mc68k/decoder.m

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1996, Princeton University or Owen Braun ?????
00003  * Copyright (C) 2000, The University of Queensland
00004  * Copyright (C) 2000-2001, Sun Microsystems, Inc
00005  *
00006  * See the file "LICENSE.TERMS" for information on usage and
00007  * redistribution of this file, and for a DISCLAIMER OF ALL
00008  * WARRANTIES.
00009  *
00010  */
00011 
00012 /*==============================================================================
00013  * FILE:       decoder.m
00014  * OVERVIEW:   Implementation of the higher level mc68000 specific parts of the
00015  *             NJMCDecoder class.
00016  *
00017  * (C) 2000 The University of Queensland, BT Group & Sun Microsystems, Inc.
00018  *============================================================================*/
00019 
00020 /* $Revision: 1.1 $
00021  * $Id: decoder.m,v 1.1 2002/08/08 05:59:31 quantumg Exp $
00022  * Created by Mike 15 Feb 2000
00023  * 21 Feb 2000 - Mike: support for -(an) and (an)+ (bump and bumpr)
00024  * 21 Mar 2000 - Mike: pPcDisp generates expressions with idCodeAddr
00025  * 24 Mar 2000 - Mike: Converted sizes to bits; initialise size of SemStr
00026  *  1 Aug 00 - Cristina: upgraded to support mltk version Apr 5 14:56:28
00027  *              EDT 2000.  [numBytes] renamed to nextPC as semantics of
00028  *              [numBytes] has changed.  Assignment of (nextPC - hostPC). 
00029  * 31 Jul 01 - Brian: New class HRTL replaces RTlist. Added new derived class
00030  *               RTL for low-level HRTLs.
00031  */
00032 
00033 #include "global.h"
00034 #include "decoder.h"
00035 #include "prog.h"
00036 #include "ss.h"
00037 #include "rtl.h"
00038 #include "proc.h"
00039 #include "csr.h"
00040 #include "mc68k.pat.h"
00041 
00042 /**********************************
00043  * NJMCDecoder methods.
00044  **********************************/   
00045 
00046 /*==============================================================================
00047  * FUNCTION:       NJMCDecoder::decodeInstruction
00048  * OVERVIEW:       Decodes a machine instruction and returns an RTL instance. In
00049  *                 most cases a single instruction is decoded. However, if a
00050  *                 higher level construct that may consist of multiple
00051  *                 instructions is matched, then there may be a need to return
00052  *                 more than one RTL. The caller_prologue2 is an example of such
00053  *                 a construct which encloses an abritary instruction that must
00054  *                 be decoded into its own RTL (386 example)
00055  * PARAMETERS:     pc - the native address of the pc
00056  *                 delta - the difference between the above address and the
00057  *                   host address of the pc (i.e. the address that the pc is at
00058  *                   in the loaded object file)
00059  *                 RTLDict - the dictionary of RTL templates used to instantiate
00060  *                   the RTL for the instruction being decoded
00061  *                 proc - the enclosing procedure
00062  *                 pProc - the enclosing procedure
00063  * RETURNS:        a DecodeResult structure containing all the information
00064  *                   gathered during decoding
00065  *============================================================================*/
00066 DecodeResult& NJMCDecoder::decodeInstruction (ADDRESS pc, int delta,
00067     UserProc* proc = NULL)
00068 {
00069     static DecodeResult result;
00070     ADDRESS hostPC = pc + delta;
00071 
00072     // Clear the result structure;
00073     result.reset();
00074 
00075     // The actual list of instantiated RTs
00076     list<RT*>* RTs = NULL;
00077 
00078     // Try matching a logue first
00079     int addr, locals, stackSize, d16, d32, reg;
00080     ADDRESS saveHostPC = hostPC;
00081     Logue* logue;
00082     if ((logue = InstructionPatterns::std_call(csr, hostPC, addr)) != NULL) {
00083         /*
00084          * Direct call
00085          */
00086         HLCall* newCall = new HLCall(pc, 0, RTs);
00087         result.rtl = newCall;
00088         result.numBytes = hostPC - saveHostPC;
00089 
00090         // Set the destination expression
00091         newCall->setDest(addr - delta);
00092         newCall->setPrologue(logue);
00093 
00094         // Save RTL for the latest call
00095         //lastCall = newCall;
00096         SHOW_ASM("std_call "<<addr)
00097     }
00098 
00099     else if ((logue = InstructionPatterns::near_call(csr, hostPC, addr))
00100         != NULL) {
00101         /*
00102          * Call with short displacement (16 bit instruction)
00103          */
00104         HLCall* newCall = new HLCall(pc, 0, RTs);
00105         result.rtl = newCall;
00106         result.numBytes = hostPC - saveHostPC;
00107 
00108         // Set the destination expression
00109         newCall->setDest(addr - delta);
00110         newCall->setPrologue(logue);
00111 
00112         // Save RTL for the latest call
00113         //lastCall = newCall;
00114         SHOW_ASM("near_call " << addr)
00115     }
00116 
00117     else if ((logue = InstructionPatterns::pea_pea_add_rts(csr, hostPC, d32))
00118         != NULL) {
00119         /*
00120          * pea E(pc) pea 4(pc) / addil #d32, (a7) / rts
00121          * Handle as a call
00122          */
00123         HLCall* newCall = new HLCall(pc, 0, RTs);
00124         result.rtl = newCall;
00125         result.numBytes = hostPC - saveHostPC;
00126 
00127         // Set the destination expression. It's d32 past the address of the
00128         // d32 itself, which is pc+10
00129         newCall->setDest(pc + 10 + d32);
00130         newCall->setPrologue(logue);
00131 
00132         // Save RTL for the latest call
00133         //lastCall = newCall;
00134         SHOW_ASM("pea/pea/add/rts " << pc+10+d32)
00135     }
00136 
00137     else if ((logue = InstructionPatterns::pea_add_rts(csr, hostPC, d32))
00138         != NULL) {
00139         /*
00140          * pea 4(pc) / addil #d32, (a7) / rts
00141          * Handle as a call followed by a return
00142          */
00143         HLCall* newCall = new HLCall(pc, 0, RTs);
00144         result.rtl = newCall;
00145         result.numBytes = hostPC - saveHostPC;
00146 
00147         // Set the destination expression. It's d32 past the address of the
00148         // d32 itself, which is pc+6
00149         newCall->setDest(pc + 6 + d32);
00150         newCall->setPrologue(logue);
00151 
00152         // This call effectively is followed by a return
00153         newCall->setReturnAfterCall(true);
00154 
00155         // Save RTL for the latest call
00156         //lastCall = newCall;
00157         SHOW_ASM("pea/add/rts " << pc+6+d32)
00158     }
00159 
00160     else if ((logue = InstructionPatterns::trap_syscall(csr, hostPC, d16))
00161         != NULL) {
00162         /*
00163          * trap / AXXX  (d16 set to the XXX)
00164          * Handle as a library call
00165          */
00166         HLCall* newCall = new HLCall(pc, 0, RTs);
00167         result.rtl = newCall;
00168         result.numBytes = hostPC - saveHostPC;
00169 
00170         // Set the destination expression. For now, we put AAAAA000+d16 there
00171         newCall->setDest(0xAAAAA000 + d16);
00172         newCall->setPrologue(logue);
00173 
00174         SHOW_ASM("trap/syscall " << hex << 0xA000 + d16)
00175     }
00176 
00177 /*
00178  * CALLEE PROLOGUES
00179  */
00180     else if ((logue = InstructionPatterns::link_save(csr, hostPC,
00181         locals, d16)) != NULL)
00182     {
00183         /*
00184          * Standard link with save of registers using movem
00185          */
00186         if (proc != NULL) {
00187 
00188             // Record the prologue of this callee
00189             assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00190             proc->setPrologue((CalleePrologue*)logue);
00191         }
00192         result.rtl = new RTL(pc, RTs);
00193         result.numBytes = hostPC - saveHostPC;
00194         SHOW_ASM("link_save " << locals)
00195     }
00196 
00197     else if ((logue = InstructionPatterns::link_save1(csr, hostPC,
00198         locals, reg)) != NULL)
00199     {
00200         /*
00201          * Standard link with save of 1 D register using move dn,-(a7)
00202          */
00203         if (proc != NULL) {
00204 
00205             // Record the prologue of this callee
00206             assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00207             proc->setPrologue((CalleePrologue*)logue);
00208         }
00209         result.rtl = new RTL(pc, RTs);
00210         result.numBytes = hostPC - saveHostPC;
00211         SHOW_ASM("link_save1 " << locals)
00212     }
00213 
00214     else if ((logue = InstructionPatterns::push_lea(csr, hostPC,
00215         locals, reg)) != NULL)
00216     {
00217         /*
00218          * Just save of 1 D register using move dn,-(a7);
00219          * then an lea d16(a7), a7 to allocate the stack
00220          */
00221         //locals = 0;             // No locals for this prologue
00222         if (proc != NULL) {
00223 
00224             // Record the prologue of this callee
00225             assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00226             proc->setPrologue((CalleePrologue*)logue);
00227         }
00228         result.rtl = new RTL(pc, RTs);
00229         result.numBytes = hostPC - saveHostPC;
00230         SHOW_ASM("push_lea " << locals)
00231     }
00232 
00233     else if ((logue = InstructionPatterns::std_link(csr, hostPC,
00234         locals)) != NULL)
00235     {
00236         /*
00237          * Standard link
00238          */
00239         if (proc != NULL) {
00240 
00241             // Record the prologue of this callee
00242             assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00243             proc->setPrologue((CalleePrologue*)logue);
00244         }
00245         result.rtl = new RTL(pc, RTs);
00246         result.numBytes = hostPC - saveHostPC;
00247         SHOW_ASM("std_link "<< locals)
00248     }
00249 
00250     else if ((logue = InstructionPatterns::bare_ret(csr, hostPC))
00251         != NULL)
00252     {
00253         /*
00254          * Just a bare rts instruction
00255          */
00256         if (proc != NULL) {
00257 
00258             // Record the prologue of this callee
00259             assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00260             proc->setPrologue((CalleePrologue*)logue);
00261             proc->setEpilogue(new CalleeEpilogue("__dummy",list<string>()));
00262         }
00263         result.rtl = new HLReturn(pc, RTs);
00264         result.numBytes = hostPC - saveHostPC;
00265         SHOW_ASM("bare_ret")
00266     }
00267 
00268     else if ((logue = InstructionPatterns::std_ret(csr, hostPC)) != NULL) {
00269         /*
00270          * An unlink and return
00271          */
00272         if (proc!= NULL) {
00273 
00274             // Record the epilogue of this callee
00275             assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00276             proc->setEpilogue((CalleeEpilogue*)logue);
00277         }
00278 
00279         result.rtl = new HLReturn(pc, RTs);
00280         result.numBytes = hostPC - saveHostPC;
00281         SHOW_ASM("std_ret")
00282     }
00283 
00284     else if ((logue = InstructionPatterns::rest_ret(csr, hostPC, d16)) != NULL)
00285     {
00286         /*
00287          * A restore (movem stack to registers) then return
00288          */
00289         if (proc!= NULL) {
00290 
00291             // Record the epilogue of this callee
00292             assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00293             proc->setEpilogue((CalleeEpilogue*)logue);
00294         }
00295 
00296         result.rtl = new HLReturn(pc, RTs);
00297         result.numBytes = hostPC - saveHostPC;
00298         SHOW_ASM("rest_ret")
00299     }
00300 
00301     else if ((logue = InstructionPatterns::rest1_ret(csr, hostPC, reg)) != NULL)
00302     {
00303         /*
00304          * A pop (move (a7)+ to one D register) then unlink and return
00305          */
00306         if (proc!= NULL) {
00307 
00308             // Record the epilogue of this callee
00309             assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00310             proc->setEpilogue((CalleeEpilogue*)logue);
00311         }
00312 
00313         result.rtl = new HLReturn(pc, RTs);
00314         result.numBytes = hostPC - saveHostPC;
00315         SHOW_ASM("rest1_ret")
00316     }
00317 
00318     else if ((logue = InstructionPatterns::pop_ret(csr, hostPC, reg)) != NULL)
00319     {
00320         /*
00321          * A pop (move (a7)+ to one D register) then just return
00322          */
00323         if (proc!= NULL) {
00324 
00325             // Record the epilogue of this callee
00326             assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00327             proc->setEpilogue((CalleeEpilogue*)logue);
00328         }
00329 
00330         result.rtl = new HLReturn(pc, RTs);
00331         result.numBytes = hostPC - saveHostPC;
00332         SHOW_ASM("pop_ret")
00333     }
00334 
00335     else if ((logue = InstructionPatterns::clear_stack(csr, hostPC, stackSize))
00336         != NULL)
00337     {
00338         /*
00339          * Remove parameters from the stack
00340          */
00341         RTs = instantiate(pc, "clear_stack", dis_Num(stackSize));
00342 
00343         result.rtl = new RTL(pc, RTs);
00344         result.numBytes = hostPC - saveHostPC;
00345     }
00346 
00347     else {
00348 
00349         ADDRESS nextPC;
00350         int bump = 0, bumpr;
00351         SemStr* ss;
00352 
00353         match  hostPC to
00354         
00355         | regCall(ea) =>
00356             /*
00357              * Register call
00358              */
00359             // Mike: there should probably be a HLNwayCall class for this!
00360             HLCall* newCall = new HLCall(pc, 0, RTs);
00361             // Record the fact that this is a computed call
00362             newCall->setIsComputed();
00363             // Set the destination expression
00364             newCall->setDest(cEA(ea, pc, 32));
00365             result.rtl = newCall;
00366             // Only one instruction, so size of result is size of this decode
00367             result.numBytes = nextPC - hostPC;
00368     
00369         | regJmp(ea) =>
00370             /*
00371              * Register jump
00372              */
00373             HLNwayJump* newJump = new HLNwayJump(pc, RTs);
00374             // Record the fact that this is a computed call
00375             newJump->setIsComputed();
00376             // Set the destination expression
00377             newJump->setDest(cEA(ea, pc, 32));
00378             result.rtl = newJump;
00379             // Only one instruction, so size of result is size of this decode
00380             result.numBytes = nextPC - hostPC;
00381         
00382         /*
00383          * Unconditional branches
00384          */
00385         | bra(d)          =>
00386             ss = BTA(d, result, pc);
00387             UNCOND_JUMP(name, nextPC - hostPC, ss);
00388     
00389         /*
00390          * Conditional branches
00391          */
00392         | bgt(d)  =>
00393             ss = BTA(d, result, pc);
00394             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JSG)
00395         | ble(d)  =>
00396             ss = BTA(d, result, pc);
00397             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JSLE)
00398         | bge(d)  =>
00399             ss = BTA(d, result, pc);
00400             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JSGE)
00401         | blt(d)  =>
00402             ss = BTA(d, result, pc);
00403             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JSL)
00404         | bpl(d)  =>
00405             ss = BTA(d, result, pc);
00406             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JPOS)
00407         | bmi(d)  =>
00408             ss = BTA(d, result, pc);
00409             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JMI)
00410         | bhi(d)  =>
00411             ss = BTA(d, result, pc);
00412             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JUG)
00413         | bls(d)  =>
00414             ss = BTA(d, result, pc);
00415             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JULE)
00416         | bne(d)  =>
00417             ss = BTA(d, result, pc);
00418             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JNE)
00419         | beq(d)  =>
00420             ss = BTA(d, result, pc);
00421             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JE)
00422         | bcc(d)  =>
00423             ss = BTA(d, result, pc);
00424             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JUGE)
00425         | bcs(d)  =>
00426             ss = BTA(d, result, pc);
00427             COND_JUMP(name, nextPC - hostPC, ss, HLJCOND_JUL)
00428         | bvc(d)  =>
00429             ss = BTA(d, result, pc);
00430             COND_JUMP(name, nextPC - hostPC, ss, (JCOND_TYPE)0)
00431         | bvs(d)  =>
00432             ss = BTA(d, result, pc);
00433             COND_JUMP(name, nextPC - hostPC, ss, (JCOND_TYPE)0)
00434     
00435     
00436         // MVE: I'm assuming that we won't ever see shi(-(a7)) or the like.
00437         // This would unbalance the stack, although it would be legal for
00438         // address registers other than a7. For now, we ignore the possibility
00439         // of having to bump a register
00440         | shi(ea)  =>
00441             ss = daEA(ea, pc, bump, bumpr, 1);
00442             RTs = instantiate(pc, name, ss);
00443             SETS(name, ss, HLJCOND_JSG)
00444         | sls(ea)  =>
00445             ss = daEA(ea, pc, bump, bumpr, 1);
00446             RTs = instantiate(pc, name, ss);
00447             SETS(name, ss, HLJCOND_JULE)
00448         | scc(ea)  =>
00449             ss = daEA(ea, pc, bump, bumpr, 1);
00450             RTs = instantiate(pc, name, ss);
00451             SETS(name, ss, HLJCOND_JUGE)
00452         | scs(ea)  =>
00453             ss = daEA(ea, pc, bump, bumpr, 1);
00454             RTs = instantiate(pc, name, ss);
00455             SETS(name, ss, HLJCOND_JUL)
00456         | sne(ea)  =>
00457             ss = daEA(ea, pc, bump, bumpr, 1);
00458             RTs = instantiate(pc, name, ss);
00459             SETS(name, ss, HLJCOND_JNE)
00460         | seq(ea)  =>
00461             ss = daEA(ea, pc, bump, bumpr, 1);
00462             RTs = instantiate(pc, name, ss);
00463             SETS(name, ss, HLJCOND_JE)
00464         //| svc(ea) [name] =>
00465         //  ss = daEA(ea, pc, bump, bumpr, 1);
00466         //  RTs = instantiate(pc, name, ss);
00467         //  SETS(name, ss, HLJCOND_)
00468         //| svs(ea) [name] =>
00469         //  ss = daEA(ea, pc, bump, bumpr, 1);
00470         //  RTs = instantiate(pc, name, ss);
00471         //  SETS(name, ss, HLJCOND_)
00472         | spl(ea)  =>
00473             ss = daEA(ea, pc, bump, bumpr, 1);
00474             RTs = instantiate(pc, name, ss);
00475             SETS(name, ss, HLJCOND_JPOS)
00476         | smi(ea)  =>
00477             ss = daEA(ea, pc, bump, bumpr, 1);
00478             RTs = instantiate(pc, name, ss);
00479             SETS(name, ss, HLJCOND_JMI)
00480         | sge(ea)  =>
00481             ss = daEA(ea, pc, bump, bumpr, 1);
00482             RTs = instantiate(pc, name, ss);
00483             SETS(name, ss, HLJCOND_JSGE)
00484         | slt(ea)  =>
00485             ss = daEA(ea, pc, bump, bumpr, 1);
00486             RTs = instantiate(pc, name, ss);
00487             SETS(name, ss, HLJCOND_JSL)
00488         | sgt(ea)  =>
00489             ss = daEA(ea, pc, bump, bumpr, 1);
00490             RTs = instantiate(pc, name, ss);
00491             SETS(name, ss, HLJCOND_JSG)
00492         | sle(ea)  =>
00493             ss = daEA(ea, pc, bump, bumpr, 1);
00494             RTs = instantiate(pc, name, ss);
00495             SETS(name, ss, HLJCOND_JSLE)
00496 // HACK: Still need to do .ex versions of set, jsr, jmp
00497     
00498     else
00499             result.rtl = new RTL(pc,
00500                 decodeLowLevelInstruction(hostPC, pc, result));
00501         endmatch
00502     }
00503     return result;
00504 }
00505 
00506 /*==============================================================================
00507  * These are machine specific functions used to decode instruction
00508  * operands into SemStrs.
00509  *============================================================================*/
00510 
00511 /*
00512  * Modified from the original: 
00513  *  m68k_ea.m
00514  *  written by Owen Braun
00515  *  ocbraun@princeton.edu
00516  *  created 4/7/96 11:27 pm
00517  * 
00518  * 4 Feb 2000 - Cristina, removed ObjFile reference for integration w/UQBT 
00519  * 7,9 Feb 2000 - Cristina, changed display format of addressing modes to
00520  *      comply with the Motorola assembly format.
00521  * 8 Feb 2000 - Note that the ML version of the toolkit generates
00522  *      repeated label names for procedures that have more than one
00523  *      matching statement.  Mike's program formats replaces repeated
00524  *      names by unique names.
00525  * 9 Feb 00 - Cristina.  Note that I have *not* tested the indexed 
00526  *      addressing modes as the mc68328 does not support *any* of
00527  *      such addressing modes.  The mc68000 does however. 
00528  * 20 Feb 00 - Cristina: fixed branches
00529  * 21 Feb 00 - Mike: Removed redundant delta from BTA()
00530  */
00531 
00532 
00533 // Branch target
00534 SemStr* NJMCDecoder::BTA(ADDRESS d, DecodeResult& result, ADDRESS pc)
00535 {
00536 
00537   SemStr* ret = new SemStr(32);
00538   ret->push(idIntConst);
00539 
00540   match d to
00541 
00542   | wordOffset (dsp16) => {
00543                 ret->push(pc+2 + dsp16);
00544                 result.numBytes += 2;
00545             }
00546 
00547   | byteOffset (dsp8) =>  {
00548                 // Casts needed to work around MLTK bug
00549                 ret->push(pc+2 + (int)(char)dsp8);
00550             }
00551   endmatch
00552     
00553   return ret;
00554 }
00555 
00556 
00557 void NJMCDecoder::pIllegalMode(ADDRESS pc)
00558 {
00559     ostrstream ost;
00560     ost << "Illegal addressing mode at " << hex << pc;
00561     error(str(ost));
00562 }
00563 
00564 SemStr* NJMCDecoder::pDDirect(int r2, int size)
00565 {
00566     SemStr* ret = new SemStr(size);
00567     ret->push(idRegOf);
00568     ret->push(idIntConst);
00569     ret->push(r2);
00570     return ret;
00571 }
00572 
00573 SemStr* NJMCDecoder::pADirect(int r2, int size)
00574 {
00575     SemStr* ret = new SemStr(size);
00576     ret->push(idRegOf);
00577     ret->push(idIntConst);
00578     ret->push(r2 + 8);          // First A register is r[8]
00579     return ret;
00580 }
00581 
00582 SemStr* NJMCDecoder::pIndirect(int r2, int size)
00583 {
00584     SemStr* ret = new SemStr(size);
00585     ret->push(idMemOf);
00586     ret->push(idRegOf);
00587     ret->push(idIntConst);
00588     ret->push(r2 + 8);          // First A register is r[8]
00589     return ret;
00590 }
00591 
00592 SemStr* NJMCDecoder::pPostInc(int r2, int& bump, int& bumpr, int size)
00593 {
00594     // Treat this as (an), set bump to size, and bumpr to r2+8
00595     // Note special semantics when r2 == 7 (stack pointer): if size == 1, then
00596     // the system will change it to 2 to keep the stack word aligned
00597     if ((r2 == 7) && (size == 8)) size = 16;
00598     SemStr* ret = new SemStr(size/8);
00599     ret->push(idMemOf);
00600     ret->push(idRegOf);
00601     ret->push(idIntConst);
00602     ret->push(r2 + 8);          // First A register is r[8]
00603     bump = size/8;              // Amount to bump register by
00604     bumpr = r2 + 8;             // Register to bump
00605     return ret;
00606 }
00607 
00608 SemStr* NJMCDecoder::pPreDec(int r2, int& bump, int& bumpr, int size)
00609 {
00610     // We treat this as -size(an), set bump to -size, and bumpr to r2+8
00611     // Note special semantics when r2 == 7 (stack pointer): if size == 1, then
00612     // the system will change it to 2 to keep the stack word aligned
00613     if ((r2 == 7) && (size == 8)) size = 16;
00614     SemStr* ret = new SemStr(size);
00615     ret->push(idMemOf); ret->push(idPlus);
00616     ret->push(idRegOf);
00617     ret->push(idIntConst);
00618     ret->push(r2 + 8);          // First A register is r[8]
00619     ret->push(idIntConst); ret->push(-size/8);
00620     bump = -size/8;             // Amount to bump register by
00621     bumpr = r2 + 8;             // Register to bump
00622     return ret;
00623 }
00624 
00625 SemStr* NJMCDecoder::alEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00626     int size)
00627 {
00628   SemStr* ret = new SemStr(size);
00629   match ea to
00630     | alDDirect (reg2)  => ret = pDDirect(reg2, size);
00631     | alADirect (reg2)  => ret = pADirect(reg2, size);
00632     | alIndirect (reg2) => ret = pIndirect(reg2, size);
00633     | alPostInc (reg2)  => ret = pPostInc(reg2, bump, bumpr, size);
00634     | alPreDec (reg2)   => ret = pPreDec(reg2, bump, bumpr, size);
00635     else pIllegalMode(pc);
00636   endmatch
00637   return ret;
00638 }
00639 
00640 SemStr* NJMCDecoder::amEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00641     int size)
00642 {
00643   SemStr* ret = new SemStr(size);
00644   match ea to
00645     | amDDirect (reg2)  => ret = pDDirect(reg2, size);
00646     | amADirect (reg2)  => ret = pADirect(reg2, size);
00647     | amIndirect (reg2) => ret = pIndirect(reg2, size);
00648     | amPostInc (reg2)  => ret = pPostInc(reg2, bump, bumpr, size);
00649     | amPreDec (reg2)   => ret = pPreDec(reg2, bump, bumpr, size);
00650     else pIllegalMode(pc);
00651   endmatch
00652   return ret;
00653 }
00654 
00655 SemStr* NJMCDecoder::awlEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00656     int size)
00657 {
00658   SemStr* ret = new SemStr(size);
00659   match ea to
00660     | awlDDirect (reg2)  => ret = pDDirect(reg2, size);
00661     | awlADirect (reg2)  => ret = pADirect(reg2, size);
00662     | awlIndirect (reg2) => ret = pIndirect(reg2, size);
00663     | awlPostInc (reg2)  => ret = pPostInc(reg2, bump, bumpr, size);
00664     | awlPreDec (reg2)   => ret = pPreDec(reg2, bump, bumpr, size);
00665     else pIllegalMode(pc);
00666   endmatch
00667   return ret;
00668 }
00669 
00670 SemStr* NJMCDecoder::cEA(ADDRESS ea, ADDRESS pc, int size)
00671 {
00672   SemStr* ret = new SemStr(size);
00673   match ea to
00674     | cIndirect (reg2) => ret = pIndirect(reg2, size);
00675     else pIllegalMode(pc);
00676   endmatch
00677   return ret;
00678 }
00679 
00680 SemStr* NJMCDecoder::dEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00681     int size)
00682 {
00683   SemStr* ret = new SemStr(size);
00684   match ea to
00685     | dDDirect (reg2)  => ret = pDDirect(reg2, size);
00686     | dIndirect (reg2) => ret = pIndirect(reg2, size);
00687     | dPostInc (reg2)  => ret = pPostInc(reg2, bump, bumpr, size);
00688     | dPreDec (reg2)   => ret = pPreDec(reg2, bump, bumpr, size);
00689     else pIllegalMode(pc);
00690   endmatch
00691   return ret;
00692 }
00693 
00694 SemStr* NJMCDecoder::daEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00695     int size)
00696 {
00697   SemStr* ret = new SemStr(size);
00698   match ea to
00699     | daDDirect (reg2)  => ret = pDDirect(reg2, size);
00700     | daIndirect (reg2) => ret = pIndirect(reg2, size);
00701     | daPostInc (reg2)  => ret = pPostInc(reg2, bump, bumpr, size);
00702     | daPreDec (reg2)   => ret = pPreDec(reg2, bump, bumpr, size);
00703     else pIllegalMode(pc);
00704   endmatch
00705   return ret;
00706 }
00707 
00708 SemStr* NJMCDecoder::dBEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00709     int size)
00710 {
00711   SemStr* ret = new SemStr(size);
00712   match ea to
00713     | dBDDirect (reg2)  => ret = pDDirect(reg2, size);
00714     | dBIndirect (reg2) => ret = pIndirect(reg2, size);
00715     | dBPostInc (reg2)  => ret = pPostInc(reg2, bump, bumpr, size);
00716     | dBPreDec (reg2)   => ret = pPreDec(reg2, bump, bumpr, size);
00717     else pIllegalMode(pc);
00718   endmatch
00719   return ret;
00720 }
00721 
00722 SemStr* NJMCDecoder::dWEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00723     int size)
00724 {
00725   SemStr* ret = new SemStr(size);
00726   match ea to
00727     | dWDDirect (reg2)  => ret = pDDirect(reg2, size);
00728     | dWIndirect (reg2) => ret = pIndirect(reg2, size);
00729     | dWPostInc (reg2)  => ret = pPostInc(reg2, bump, bumpr, size);
00730     | dWPreDec (reg2)   => ret = pPreDec(reg2, bump, bumpr, size);
00731     else pIllegalMode(pc);
00732   endmatch
00733   return ret;
00734 }
00735 
00736 SemStr* NJMCDecoder::maEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00737     int size)
00738 {
00739   SemStr* ret = new SemStr(size);
00740   match ea to
00741     | maIndirect (reg2) => ret = pIndirect(reg2, size);
00742     | maPostInc (reg2)  => ret = pPostInc(reg2, bump, bumpr, size);
00743     | maPreDec (reg2)   => ret = pPreDec(reg2, bump, bumpr, size);
00744     else pIllegalMode(pc);
00745   endmatch
00746   return ret;
00747 }
00748 
00749 SemStr* NJMCDecoder::msEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00750     int size)
00751 {
00752   SemStr* ret = new SemStr(size);
00753   match ea to
00754     | msDDirect (reg2)  => ret = pDDirect(reg2, size);
00755     | msADirect (reg2)  => ret = pADirect(reg2, size);
00756     | msIndirect (reg2) => ret = pIndirect(reg2, size);
00757     | msPostInc (reg2)  => ret = pPostInc(reg2, bump, bumpr, size);
00758     | msPreDec (reg2)   => ret = pPreDec(reg2, bump, bumpr, size);
00759     else pIllegalMode(pc);
00760   endmatch
00761   return ret;
00762 }
00763 
00764 SemStr* NJMCDecoder::mdEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00765     int size)
00766 {
00767   SemStr* ret = new SemStr(size);
00768   match ea to
00769     | mdDDirect (reg1)  => ret = pDDirect(reg1, size);
00770     | mdADirect (reg1)  => ret = pADirect(reg1, size);
00771     | mdIndirect (reg1) => ret = pIndirect(reg1, size);
00772     | mdPostInc (reg1)  => ret = pPostInc(reg1, bump, bumpr, size);
00773     | mdPreDec (reg1)   => ret = pPreDec(reg1, bump, bumpr, size);
00774     else pIllegalMode(pc);
00775   endmatch
00776   return ret;
00777 }
00778 
00779 SemStr* NJMCDecoder::mrEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00780     int size)
00781 {
00782   SemStr* ret = new SemStr(size);
00783   match ea to
00784     | mrIndirect (reg2) => ret = pIndirect(reg2, size);
00785     | mrPostInc (reg2)  => ret = pPostInc(reg2, bump, bumpr, size);
00786     else pIllegalMode(pc);
00787   endmatch
00788   return ret;
00789 }
00790 
00791 SemStr* NJMCDecoder::rmEA(ADDRESS ea, ADDRESS pc, int& bump, int& bumpr,
00792     int size)
00793 {
00794   SemStr* ret = new SemStr(size);
00795   match ea to
00796     | rmIndirect (reg2) => ret = pIndirect(reg2, size);
00797     | rmPreDec (reg2)   => ret = pPreDec(reg2, bump, bumpr, size);
00798     else pIllegalMode(pc);
00799   endmatch
00800   return ret;
00801 }
00802 
00803 
00804 SemStr* NJMCDecoder::pADisp(int d16, int r, int size)
00805 {
00806   SemStr* ret = new SemStr(size);
00807   // d16(Ar) -> m[ + r[ int r+8 ] int d16]
00808   ret->push(idMemOf); ret->push(idPlus); ret->push(idRegOf);
00809   ret->push(idIntConst); ret->push(r+8);
00810   ret->push(idIntConst); ret->push(d16);
00811   return ret;
00812 }
00813 
00814 SemStr* NJMCDecoder::pAIndex(int d8, int r, int iT, int iR, int iS, int size)
00815 {
00816     SemStr* ret = new SemStr(size);
00817     // d8(Ar, A/Di.[wl] ->
00818     //   m[ + + r[ int r+8 ] ! size[ 16/32 r[ int iT<<3+iR ]] int i8 ]
00819     ret->push(idMemOf); ret->push(idPlus); ret->push(idPlus);
00820     ret->push(idRegOf); ret->push(idIntConst); ret->push(r+8);
00821     ret->push(idSignExt);
00822     ret->push(idSize);  ret->push(iS == 0 ? 16 : 32);
00823     ret->push(idRegOf); ret->push(idIntConst); ret->push((iT<<3) + iR);
00824     ret->push(idIntConst); ret->push(d8);
00825     return ret;
00826 }
00827 
00828 SemStr* NJMCDecoder::pPcDisp(ADDRESS label, int delta, int size)
00829 {
00830     // Note: label is in the host address space, so need to subtract delta
00831     SemStr* ret = new SemStr(size);
00832     // d16(pc) -> m[ code pc+d16 ]
00833     // Note: we use "code" instead of "int" to flag the fact that this address
00834     // is relative to the pc, and hence needs translation before use in the
00835     // target machine
00836     ret->push(idMemOf); ret->push(idCodeAddr);
00837     ret->push(label - delta);
00838     return ret;
00839 }
00840 
00841 SemStr* NJMCDecoder::pPcIndex(int d8, int iT, int iR, int iS, ADDRESS nextPc, int size)
00842 {
00843     // Note: nextPc is expected to have +2 or +4 etc already added to it!
00844     SemStr* ret = new SemStr(size);
00845     // d8(pc, A/Di.[wl] ->
00846     //   m[ + pc+i8 ! size[ 16/32 r[ int iT<<3+iR ]]]
00847     ret->push(idMemOf); ret->push(idPlus);
00848     ret->push(idIntConst); ret->push(nextPc+d8);
00849     ret->push(idSignExt);
00850     ret->push(idSize);  ret->push(iS == 0 ? 16 : 32);
00851     ret->push(idRegOf); ret->push(idIntConst); ret->push((iT<<3) + iR);
00852     return ret;
00853 }
00854 
00855 SemStr* NJMCDecoder::pAbsW(int d16, int size)
00856 {
00857   // (d16).w  ->  size[ ss m[ int d16 ]]
00858   // Note: d16 should already have been sign extended to 32 bits
00859   SemStr* ret = new SemStr(size);
00860   ret->push(idSize); ret->push(size);
00861   ret->push(idMemOf); ret->push(idIntConst); ret->push(d16);
00862   return ret;
00863 }
00864 
00865 SemStr* NJMCDecoder::pAbsL(int d32, int size)
00866 {
00867   // (d32).w  ->  size[ ss m[ int d32 ]]
00868   SemStr* ret = new SemStr(size);
00869   ret->push(idSize); ret->push(size);
00870   ret->push(idMemOf); ret->push(idIntConst); ret->push(d32);
00871   return ret;
00872 }
00873 
00874 SemStr* NJMCDecoder::pImmB(int d8)
00875 {
00876   // #d8 -> int d8
00877   // Should already be sign extended to 32 bits
00878   SemStr* ret = new SemStr(8);
00879   ret->push(idIntConst); ret->push(d8);
00880   return ret;
00881 }
00882 
00883 SemStr* NJMCDecoder::pImmW(int d16)
00884 {
00885   // #d16 -> int d16
00886   // Should already be sign extended to 32 bits
00887   SemStr* ret = new SemStr(16);
00888   ret->push(idIntConst); ret->push(d16);
00889   return ret;
00890 }
00891 
00892 SemStr* NJMCDecoder::pImmL(int d32)
00893 {
00894   SemStr* ret = new SemStr(32);
00895   ret->push(idIntConst); ret->push(d32);
00896   return ret;
00897 }
00898 
00899 void NJMCDecoder::pNonzeroByte(ADDRESS pc)
00900 {
00901     ostrstream ost;
00902     ost << "Non zero upper byte at " << hex << pc;
00903     error(str(ost));
00904 }
00905 
00906 
00907 SemStr* NJMCDecoder::alEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
00908     ADDRESS pc, int size)
00909 {
00910   SemStr* ret;
00911   int reg2, mode;
00912 
00913   match eax to
00914     | alADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
00915     | alAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
00916     | alAbs.w ()    => { mode = 4; result.numBytes += 2;}
00917     | alAbs.l ()    => { mode = 5; result.numBytes += 4;}
00918     else pIllegalMode(pc);
00919   endmatch
00920 
00921   switch (mode) {
00922     case 0 : {
00923       match x to  
00924     | alADisp.x (d16) => ret = pADisp(d16, reg2, size);
00925       endmatch
00926       break;
00927     }
00928     case 1 : {
00929       match x to
00930     | alAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
00931       endmatch
00932       break;
00933     }
00934     case 4 : {
00935       match x to
00936     | alAbs.w.x (d16) => ret = pAbsW(d16, size);
00937       endmatch
00938       break;
00939     }
00940     case 5 : {
00941       match x to
00942     | alAbs.l.x (d32) => ret = pAbsL(d32, size);
00943       endmatch
00944       break;
00945     }
00946     default : pIllegalMode(pc); break;
00947   } 
00948   return ret;
00949 }
00950 
00951 
00952 SemStr* NJMCDecoder::amEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
00953     ADDRESS pc, int delta, int size)
00954 {
00955   SemStr* ret;
00956   int reg2, mode;
00957 
00958   match eax to
00959     | amADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
00960     | amAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
00961     | amPcDisp ()   => { mode = 2; result.numBytes += 2;}
00962     | amPcIndex ()  => { mode = 3; result.numBytes += 2;}
00963     | amAbs.w ()    => { mode = 4; result.numBytes += 2;}
00964     | amAbs.l ()    => { mode = 5; result.numBytes += 4;}
00965     | amImm.b ()    => { mode = 6; result.numBytes += 2;}
00966     | amImm.w ()    => { mode = 7; result.numBytes += 2;}
00967     | amImm.l ()    => { mode = 8; result.numBytes += 4;}
00968     else pIllegalMode(pc);
00969   endmatch
00970 
00971   switch (mode) {
00972     case 0 : {
00973       match x to  
00974     | amADisp.x (d16) => ret = pADisp(d16, reg2, size);
00975       endmatch
00976       break;
00977     }
00978     case 1 : {
00979       match x to
00980     | amAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
00981       endmatch
00982       break;
00983     }
00984     case 2 : {
00985       match x to
00986     | amPcDisp.x (d16) => ret = pPcDisp(d16, delta, size);
00987       endmatch
00988       break;
00989     }
00990     case 3 : {
00991       match x to
00992     | amPcIndex.x (iT, iR, iS, d8) =>
00993         ret = pPcIndex(d8, iT, iR, iS, pc+2, size);
00994       endmatch
00995       break;
00996     }
00997     case 4 : {
00998       match x to
00999     | amAbs.w.x (d16) => ret = pAbsW(d16, size);
01000       endmatch
01001       break;
01002     }
01003     case 5 : {
01004       match x to
01005     | amAbs.l.x (d32) => ret = pAbsL(d32, size);
01006       endmatch
01007       break;
01008     }
01009     case 6 : {
01010       match x to
01011     | amImm.b.x (d8) => ret = pImmB(d8);
01012         else pNonzeroByte(pc);
01013       endmatch
01014       break;
01015     }
01016     case 7 : {
01017       match x to
01018     | amImm.w.x (d16) => ret = pImmW(d16);
01019       endmatch
01020       break;
01021     }
01022     case 8 : {
01023       match x to
01024     | amImm.l.x (d32) => ret = pImmL(d32);
01025       endmatch
01026       break;
01027     }
01028     default : pIllegalMode(pc); break;
01029   } 
01030   return ret;
01031 }
01032 
01033 
01034 SemStr* NJMCDecoder::awlEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01035     ADDRESS pc, int delta, int size)
01036 {
01037   SemStr* ret;
01038   int reg2, mode;
01039 
01040   match eax to
01041     | awlADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
01042     | awlAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
01043     | awlPcDisp ()   => { mode = 2; result.numBytes += 2;}
01044     | awlPcIndex ()  => { mode = 3; result.numBytes += 2;}
01045     | awlAbs.w ()    => { mode = 4; result.numBytes += 2;}
01046     | awlAbs.l ()    => { mode = 5; result.numBytes += 4;}
01047     | awlImm.w ()    => { mode = 7; result.numBytes += 2;}
01048     | awlImm.l ()    => { mode = 8; result.numBytes += 4;}
01049     else pIllegalMode(pc);
01050   endmatch
01051 
01052   switch (mode) {
01053     case 0 : {
01054       match x to  
01055     | awlADisp.x (d16) => ret = pADisp(d16, reg2, size);
01056       endmatch
01057       break;
01058     }
01059     case 1 : {
01060       match x to
01061     | awlAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
01062       endmatch
01063       break;
01064     }
01065     case 2 : {
01066       match x to
01067     | awlPcDisp.x (d16) => ret = pPcDisp(d16, delta, size);
01068       endmatch
01069       break;
01070     }
01071     case 3 : {
01072       match x to
01073     | awlPcIndex.x (iT, iR, iS, d8) =>
01074         ret = pPcIndex(d8, iT, iR, iS, pc+2, size);
01075       endmatch
01076       break;
01077     }
01078     case 4 : {
01079       match x to
01080     | awlAbs.w.x (d16) => ret = pAbsW(d16, size);
01081       endmatch
01082       break;
01083     }
01084     case 5 : {
01085       match x to
01086     | awlAbs.l.x (d32) => ret = pAbsL(d32, size);
01087       endmatch
01088       break;
01089     }
01090     case 7 : {
01091       match x to
01092     | awlImm.w.x (d16) => ret = pImmW(d16);
01093       endmatch
01094       break;
01095     }
01096     case 8 : {
01097       match x to
01098     | awlImm.l.x (d32) => ret = pImmL(d32);
01099       endmatch
01100       break;
01101     }
01102     default : pIllegalMode(pc); break;
01103   } 
01104   return ret;
01105 }
01106 
01107 
01108 SemStr* NJMCDecoder::cEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01109     ADDRESS pc, int delta, int size)
01110 {
01111   SemStr* ret;
01112   int reg2, mode;
01113 
01114   match eax to
01115     | cADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
01116     | cAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
01117     | cPcDisp ()   => { mode = 2; result.numBytes += 2;}
01118     | cPcIndex ()  => { mode = 3; result.numBytes += 2;}
01119     | cAbs.w ()    => { mode = 4; result.numBytes += 2;}
01120     | cAbs.l ()    => { mode = 5; result.numBytes += 4;}
01121     else pIllegalMode(pc);
01122   endmatch
01123 
01124   switch (mode) {
01125     case 0 : {
01126       match x to  
01127     | cADisp.x (d16) => ret = pADisp(d16, reg2, size);
01128       endmatch
01129       break;
01130     }
01131     case 1 : {
01132       match x to
01133     | cAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
01134       endmatch
01135       break;
01136     }
01137     case 2 : {
01138       match x to
01139     | cPcDisp.x (label) => ret = pPcDisp(label, delta, size);
01140       endmatch
01141       break;
01142     }
01143     case 3 : {
01144       match x to
01145     | cPcIndex.x (iT, iR, iS, d8) => ret = pPcIndex(d8, iT, iR, iS, pc+2, size);
01146       endmatch
01147       break;
01148     }
01149     case 4 : {
01150       match x to
01151     | cAbs.w.x (d16) => ret = pAbsW(d16, size);
01152       endmatch
01153       break;
01154     }
01155     case 5 : {
01156       match x to
01157     | cAbs.l.x (d32) => ret = pAbsL(d32, size);
01158       endmatch
01159       break;
01160     }
01161     default : pIllegalMode(pc); break;
01162   }  
01163   return ret;
01164 }
01165 
01166 
01167 SemStr* NJMCDecoder::dEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01168     ADDRESS pc, int delta, int size)
01169 {
01170   SemStr* ret;
01171   int reg2, mode;
01172 
01173   match eax to
01174     | dADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
01175     | dAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
01176     | dPcDisp ()   => { mode = 2; result.numBytes += 2;}
01177     | dPcIndex ()  => { mode = 3; result.numBytes += 2;}
01178     | dAbs.w ()    => { mode = 4; result.numBytes += 2;}
01179     | dAbs.l ()    => { mode = 5; result.numBytes += 4;}
01180     | dImm.b ()    => { mode = 6; result.numBytes += 2;}
01181     | dImm.w ()    => { mode = 7; result.numBytes += 2;}
01182     | dImm.l ()    => { mode = 8; result.numBytes += 4;}
01183     else pIllegalMode(pc);
01184   endmatch
01185 
01186   switch (mode) {
01187     case 0 : {
01188       match x to  
01189     | dADisp.x (d16) => ret = pADisp(d16, reg2, size);
01190       endmatch
01191       break;
01192     }
01193     case 1 : {
01194       match x to
01195     | dAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
01196       endmatch
01197       break;
01198     }
01199     case 2 : {
01200       match x to
01201     | dPcDisp.x (label) => ret = pPcDisp(label, delta, size);
01202       endmatch
01203       break;
01204     }
01205     case 3 : {
01206       match x to
01207     | dPcIndex.x (iT, iR, iS, d8) => ret = pPcIndex(d8, iT, iR, iS, pc+2, size);
01208       endmatch
01209       break;
01210     }
01211     case 4 : {
01212       match x to
01213     | dAbs.w.x (d16) => ret = pAbsW(d16, size);
01214       endmatch
01215       break;
01216     }
01217     case 5 : {
01218       match x to
01219     | dAbs.l.x (d32) => ret = pAbsL(d32, size);
01220       endmatch
01221       break;
01222     }
01223     case 6 : {
01224       match x to
01225     | dImm.b.x (d8) => ret = pImmB(d8);
01226         else pNonzeroByte(pc);
01227       endmatch
01228       break;
01229     }
01230     case 7 : {
01231       match x to
01232     | dImm.w.x (d16) => ret = pImmW(d16);
01233       endmatch
01234       break;
01235     }
01236     case 8 : {
01237       match x to
01238     | dImm.l.x (d32) => ret = pImmL(d32);
01239       endmatch
01240       break;
01241     }
01242     default : pIllegalMode(pc); break;
01243   }  
01244   return ret;
01245 }
01246 
01247 
01248 SemStr* NJMCDecoder::daEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01249     ADDRESS pc, int size)
01250 {
01251   SemStr* ret;
01252   int reg2, mode;
01253 
01254   match eax to
01255     | daADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
01256     | daAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
01257     | daAbs.w ()    => { mode = 4; result.numBytes += 2;}
01258     | daAbs.l ()    => { mode = 5; result.numBytes += 4;}
01259     else pIllegalMode(pc);
01260   endmatch
01261 
01262   switch (mode) {
01263     case 0 : {
01264       match x to  
01265     | daADisp.x (d16) => ret = pADisp(d16, reg2, size);
01266       endmatch
01267       break;
01268     }
01269     case 1 : {
01270       match x to
01271     | daAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
01272       endmatch
01273       break;
01274     }
01275     case 4 : {
01276       match x to
01277     | daAbs.w.x (d16) => ret = pAbsW(d16, size);
01278       endmatch
01279       break;
01280     }
01281     case 5 : {
01282       match x to
01283     | daAbs.l.x (d32) => ret = pAbsL(d32, size);
01284       endmatch
01285       break;
01286     }
01287     default : pIllegalMode(pc); break;
01288   } 
01289   return ret;
01290 }
01291 
01292 
01293 SemStr* NJMCDecoder::dBEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01294     ADDRESS pc, int delta, int size)
01295 {
01296   SemStr* ret;
01297   int reg2, mode;
01298 
01299   match eax to
01300     | dBADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
01301     | dBAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
01302     | dBPcDisp ()   => { mode = 2; result.numBytes += 2;}
01303     | dBPcIndex ()  => { mode = 3; result.numBytes += 2;}
01304     | dBAbs.w ()    => { mode = 4; result.numBytes += 2;}
01305     | dBAbs.l ()    => { mode = 5; result.numBytes += 4;}
01306     | dBImm.b ()    => { mode = 6; result.numBytes += 2;}
01307     else pIllegalMode(pc);
01308   endmatch
01309 
01310   switch (mode) {
01311     case 0 : {
01312       match x to  
01313     | dBADisp.x (d16) => ret = pADisp(d16, reg2, size);
01314       endmatch
01315       break;
01316     }
01317     case 1 : {
01318       match x to
01319     | dBAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
01320       endmatch
01321       break;
01322     }
01323     case 2 : {
01324       match x to
01325     | dBPcDisp.x (label) => ret = pPcDisp(label, delta, size);
01326       endmatch
01327       break;
01328     }
01329     case 3 : {
01330       match x to
01331     | dBPcIndex.x (iT, iR, iS, d8) =>
01332         ret = pPcIndex(d8, iT, iR, iS, pc+2, size);
01333       endmatch
01334       break;
01335     }
01336     case 4 : {
01337       match x to
01338     | dBAbs.w.x (d16) => ret = pAbsW(d16, size);
01339       endmatch
01340       break;
01341     }
01342     case 5 : {
01343       match x to
01344     | dBAbs.l.x (d32) => ret = pAbsL(d32, size);
01345       endmatch
01346       break;
01347     }
01348     case 6 : {
01349       match x to
01350     | dImm.b.x (d8) => ret = pImmB(d8);
01351         else pNonzeroByte(pc);
01352       endmatch
01353       break;
01354     }
01355     default : pIllegalMode(pc); break;
01356   } 
01357   return ret;
01358 }
01359 
01360 
01361 SemStr* NJMCDecoder::dWEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01362     ADDRESS pc, int delta, int size)
01363 {
01364   SemStr* ret;
01365   int reg2, mode;
01366 
01367   match eax to
01368     | dWADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
01369     | dWAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
01370     | dWPcDisp ()   => { mode = 2; result.numBytes += 2;}
01371     | dWPcIndex ()  => { mode = 3; result.numBytes += 2;}
01372     | dWAbs.w ()    => { mode = 4; result.numBytes += 2;}
01373     | dWAbs.l ()    => { mode = 5; result.numBytes += 4;}
01374     | dWImm.w ()    => { mode = 7; result.numBytes += 2;}
01375     else pIllegalMode(pc);
01376   endmatch
01377 
01378   switch (mode) {
01379     case 0 : {
01380       match x to  
01381     | dWADisp.x (d16) => ret = pADisp(d16, reg2, size);
01382       endmatch
01383       break;
01384     }
01385     case 1 : {
01386       match x to
01387     | dWAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
01388       endmatch
01389       break;
01390     }
01391     case 2 : {
01392       match x to
01393     | dWPcDisp.x (label) => ret = pPcDisp(label, delta, size);
01394       endmatch
01395       break;
01396     }
01397     case 3 : {
01398       match x to
01399     | dWPcIndex.x (iT, iR, iS, d8) =>
01400         ret = pPcIndex(d8, iT, iR, iS, pc+2, size);
01401       endmatch
01402       break;
01403     }
01404     case 4 : {
01405       match x to
01406     | dWAbs.w.x (d16) => ret = pAbsW(d16, size);
01407       endmatch
01408       break;
01409     }
01410     case 5 : {
01411       match x to
01412     | dWAbs.l.x (d32) => ret = pAbsL(d32, size);
01413       endmatch
01414       break;
01415     }
01416     case 7 : {
01417       match x to
01418     | dWImm.w.x (d16) => ret = pImmW(d16);
01419       endmatch
01420       break;
01421     }
01422     default : pIllegalMode(pc); break;
01423   } 
01424   return ret;
01425 }
01426 
01427 
01428 SemStr* NJMCDecoder::maEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01429     ADDRESS pc, int size)
01430 {
01431   SemStr* ret;
01432   int reg2, mode;
01433 
01434   match eax to
01435     | maADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
01436     | maAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
01437     | maAbs.w ()    => { mode = 4; result.numBytes += 2;}
01438     | maAbs.l ()    => { mode = 5; result.numBytes += 4;}
01439     else pIllegalMode(pc);
01440   endmatch
01441 
01442   switch (mode) {
01443     case 0 : {
01444       match x to  
01445     | maADisp.x (d16) => ret = pADisp(d16, reg2, size);
01446       endmatch
01447       break;
01448     }
01449     case 1 : {
01450       match x to
01451     | maAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
01452       endmatch
01453       break;
01454     }
01455     case 4 : {
01456       match x to
01457     | maAbs.w.x (d16) => ret = pAbsW(d16, size);
01458       endmatch
01459       break;
01460     }
01461     case 5 : {
01462       match x to
01463     | maAbs.l.x (d32) => ret = pAbsL(d32, size);
01464       endmatch
01465       break;
01466     }
01467     default : pIllegalMode(pc); break;
01468   } 
01469   return ret;
01470 }
01471 
01472 
01473 SemStr* NJMCDecoder::msEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01474     ADDRESS pc, int delta, int size)
01475 {
01476   SemStr* ret;
01477   int reg2, mode;
01478 
01479   match eax to
01480     | msADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
01481     | msAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
01482     | msPcDisp ()   => { mode = 2; result.numBytes += 2;}
01483     | msPcIndex ()  => { mode = 3; result.numBytes += 2;}
01484     | msAbs.w ()    => { mode = 4; result.numBytes += 2;}
01485     | msImm.b ()    => { mode = 6; result.numBytes += 2;}
01486     | msImm.w ()    => { mode = 7; result.numBytes += 2;}
01487     else pIllegalMode(pc);
01488   endmatch
01489 
01490   switch (mode) {
01491     case 0 : {
01492       match x to  
01493     | msADisp.x (d16) => ret = pADisp(d16, reg2, size);
01494       endmatch
01495       break;
01496     }
01497     case 1 : {
01498       match x to
01499     | msAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
01500       endmatch
01501       break;
01502     }
01503     case 2 : {
01504       match x to
01505     | msPcDisp.x (label) => ret = pPcDisp(label, delta, size);
01506       endmatch
01507       break;
01508     }
01509     case 3 : {
01510       match x to
01511     | msPcIndex.x (iT, iR, iS, d8) =>
01512         ret = pPcIndex(d8, iT, iR, iS, pc+2, size);
01513       endmatch
01514       break;
01515     }
01516     case 4 : {
01517       match x to
01518     | msAbs.w.x (d16) => ret = pAbsW(d16, size);
01519       endmatch
01520       break;
01521     }
01522     case 6 : {
01523       match x to
01524     | msImm.b.x (d8) => ret = pImmB(d8);
01525         else pNonzeroByte(pc);
01526       endmatch
01527       break;
01528     }
01529     case 7 : {
01530       match x to
01531     | msImm.w.x (d16) => ret = pImmW(d16);
01532       endmatch
01533       break;
01534     }
01535     default : pIllegalMode(pc); break;
01536   } 
01537   return ret;
01538 }
01539 
01540 
01541 SemStr* NJMCDecoder::msEAXL(ADDRESS eaxl, int d32, DecodeResult& result,
01542     ADDRESS pc, int size)
01543 {
01544   SemStr* ret;
01545   int reg2, mode;
01546 
01547   match eaxl to
01548     | msAbs.l ()    => { mode = 5; result.numBytes += 4;}
01549     | msImm.l ()    => { mode = 8; result.numBytes += 4;}
01550     else pIllegalMode(pc);
01551   endmatch
01552 
01553   switch (mode) {
01554     case 5 : {
01555       ret = pAbsL(d32, size);
01556       break;
01557     }
01558     case 8 : {
01559       ret = pImmL(d32);
01560       break;
01561     }
01562     default : pIllegalMode(pc); break;
01563   } 
01564   return ret;
01565 }
01566 
01567 
01568 SemStr* NJMCDecoder::mdEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01569     ADDRESS pc, int size)
01570 {
01571   SemStr* ret;
01572   int reg1, mode;
01573 
01574   match eax to
01575     | mdADisp (r1)  => { mode = 0; reg1 = r1; result.numBytes += 2;}
01576     | mdAIndex (r1) => { mode = 1; reg1 = r1; result.numBytes += 2;}
01577     | mdAbs.w ()    => { mode = 4; result.numBytes += 2;}
01578     | mdAbs.l ()    => { mode = 5; result.numBytes += 4;}
01579     else pIllegalMode(pc);
01580   endmatch
01581 
01582   switch (mode) {
01583     case 0 : {
01584       match x to  
01585     | mdADisp.x (d16) => ret = pADisp(d16, reg1, size);
01586       endmatch
01587       break;
01588     }
01589     case 1 : {
01590       match x to
01591     | mdAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg1, iT, iR, iS, size);
01592     endmatch
01593       break;
01594     }
01595     case 4 : {
01596       match x to
01597     | mdAbs.w.x (d16) => ret = pAbsW(d16, size);
01598       endmatch
01599       break;
01600     }
01601     case 5 : {
01602       match x to
01603     | mdAbs.l.x (d32) => ret = pAbsL(d32, size);
01604       endmatch
01605       break;
01606     }
01607     default : pIllegalMode(pc); break;
01608   } 
01609   return ret;
01610 }
01611 
01612 
01613 SemStr* NJMCDecoder::mrEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01614     ADDRESS pc, int delta, int size)
01615 {
01616   SemStr* ret;
01617   int reg2, mode;
01618 
01619   match eax to
01620     | mrADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
01621     | mrAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
01622     | mrPcDisp ()   => { mode = 2; result.numBytes += 2;}
01623     | mrPcIndex ()  => { mode = 3; result.numBytes += 2;}
01624     | mrAbs.w ()    => { mode = 4; result.numBytes += 2;}
01625     | mrAbs.l ()    => { mode = 5; result.numBytes += 4;}
01626     else pIllegalMode(pc);
01627   endmatch
01628 
01629   switch (mode) {
01630     case 0 : {
01631       match x to  
01632     | mrADisp.x (d16) => ret = pADisp(d16, reg2, size);
01633       endmatch
01634       break;
01635     }
01636     case 1 : {
01637       match x to
01638     | mrAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
01639       endmatch
01640       break;
01641     }
01642     case 2 : {
01643       match x to
01644     | mrPcDisp.x (label) => ret = pPcDisp(label, delta, size);
01645       endmatch
01646       break;
01647     }
01648     case 3 : {
01649       match x to
01650     | mrPcIndex.x (iT, iR, iS, d8) =>
01651         ret = pPcIndex(d8, iT, iR, iS, pc+2, size);
01652       endmatch
01653       break;
01654     }
01655     case 4 : {
01656       match x to
01657     | mrAbs.w.x (d16) => ret = pAbsW(d16, size);
01658       endmatch
01659       break;
01660     }
01661     case 5 : {
01662       match x to
01663     | mrAbs.l.x (d32) => ret = pAbsL(d32, size);
01664       endmatch
01665       break;
01666     }
01667     default : pIllegalMode(pc); break;
01668   } 
01669   return ret;
01670 }
01671 
01672 
01673 SemStr* NJMCDecoder::rmEAX(ADDRESS eax, ADDRESS x, DecodeResult& result,
01674     ADDRESS pc, int size)
01675 {
01676   SemStr* ret;
01677   int reg2, mode;
01678 
01679   match eax to
01680     | rmADisp (r2)  => { mode = 0; reg2 = r2; result.numBytes += 2;}
01681     | rmAIndex (r2) => { mode = 1; reg2 = r2; result.numBytes += 2;}
01682     | rmAbs.w ()    => { mode = 4; result.numBytes += 2;}
01683     | rmAbs.l ()    => { mode = 5; result.numBytes += 4;}
01684     else pIllegalMode(pc);
01685   endmatch
01686 
01687   switch (mode) {
01688     case 0 : {
01689       match x to  
01690     | rmADisp.x (d16) => ret = pADisp(d16, reg2, size);
01691       endmatch
01692       break;
01693     }
01694     case 1 : {
01695       match x to
01696     | rmAIndex.x (iT, iR, iS, d8) => ret = pAIndex(d8, reg2, iT, iR, iS, size);
01697       endmatch
01698       break;
01699     }
01700     case 4 : {
01701       match x to
01702     | rmAbs.w.x (d16) => ret = pAbsW(d16, size);
01703       endmatch
01704       break;
01705     }
01706     case 5 : {
01707       match x to
01708     | rmAbs.l.x (d32) => ret = pAbsL(d32, size);
01709       endmatch
01710       break;
01711     }
01712     default : pIllegalMode(pc); break;
01713   } 
01714   return ret;
01715 }
01716 
01717 /*==============================================================================
01718  * FUNCTION:      isFuncPrologue()
01719  * OVERVIEW:      Check to see if the instructions at the given offset match
01720  *                  any callee prologue, i.e. does it look like this offset
01721  *                  is a pointer to a function?
01722  * PARAMETERS:    hostPC - pointer to the code in question (native address)
01723  * RETURNS:       True if a match found
01724  *============================================================================*/
01725 bool isFuncPrologue(ADDRESS hostPC)
01726 {
01727     int locals, reg, d16;
01728 
01729     if ((InstructionPatterns::link_save(prog.csrSrc, hostPC, locals, d16))
01730         != NULL)
01731             return true;
01732     if ((InstructionPatterns::link_save1(prog.csrSrc, hostPC, locals, reg))
01733         != NULL)
01734             return true;
01735     if ((InstructionPatterns::push_lea(prog.csrSrc, hostPC, locals, reg))
01736         != NULL)
01737             return true;
01738     if ((InstructionPatterns::std_link(prog.csrSrc, hostPC, locals)) != NULL)
01739         return true;
01740 
01741     return false;
01742 }
01743 

Generated on Tue Sep 19 21:18:16 2006 for Boomerang by  doxygen 1.4.6