hppa/decoder.m

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001, The University of Queensland
00003  *
00004  * See the file "LICENSE.TERMS" for information on usage and
00005  * redistribution of this file, and for a DISCLAIMER OF ALL
00006  * WARRANTIES.
00007  *
00008  */
00009 
00010 /*==============================================================================
00011  * FILE:       decoder.m
00012  * OVERVIEW:   Implementation of the HP pa-risc specific parts of the
00013  *             NJMCDecoder class.
00014  *============================================================================*/
00015 
00016 /* $Revision: 1.1 $
00017  *    Apr 01 - Simon: Created
00018  * 04 May 01 - Mike: Create RTLs not strings; moved addressing mode functions
00019  *                      here (from decoder_low.m)
00020  * 08 May 01 - Mike: New addressing modes for dis_addr handles "modify"
00021  * 09 May 01 - Mike: Match several logues; add idReg where needed; fixed ma
00022  *              addressing mode
00023  * 11 May 01 - Mike: Match branches as high level jumps
00024  * 13 May 01 - Mike: Fixed problems with B.l.n
00025  * 14 May 01 - Mike: Added some early code for cmpib_all
00026  * 17 May 01 - Mike: Added gcc frameless logues; handle non anulled CMPIB
00027  * 27 Jun 01 - Mike: B.l -> BL (1.1 opcode) etc; addressing modes too
00028  * 19 Jul 01 - Simon: Updated dis_addr(). Added dis_x_addr_shift().
00029  * 19 Jul 01 - Simon: Also got cmpibf working with various conditions.
00030  * 23 Jul 01 - Simon: Added cmpb_all and addr_ldisp_17_old
00031  * 01 Aug 01 - Mike: BL with no target register treated as branch, not call
00032  * 06 Aug 01 - Mike: Added ADD[I]B; removed getBump()
00033  * 07 Aug 01 - Mike: Added bare_ret, bare_ret_anulled patterns; some patterns
00034  *              are type DU now; fixed SCDAN cases
00035  * 07 Aug 01 - Simon: dis_addr() gone completely - [addr] => [xd,s,b]
00036  * 10 Aug 01 - Simon: added dis_c_bit(); added BB/BVB High Level Branches
00037  * 20 Aug 01 - Mike: Check for param_reloc1 pattern
00038  */
00039 
00040 #include "global.h"
00041 #include "proc.h"
00042 #include "prog.h"
00043 #include "decoder.h"
00044 #include "hppadecoder.h"
00045 #include "ss.h"
00046 #include "rtl.h"
00047 #include "csr.h"
00048 #include "hppa.pat.h"      // generated from `sparc.pat'
00049 #include "hppa-names.h"    // generated by 'tools -fieldnames' - has
00050                             //   arrays of names of fields
00051 #include "BinaryFile.h"     // For SymbolByAddress()
00052 
00053 
00054 static const JCOND_TYPE hl_jcond_type = {
00055     HLJCOND_JNE, // no 'jump_never' enumeration for JCOND_TYPE
00056     HLJCOND_JE,
00057     HLJCOND_JSL,
00058     HLJCOND_JSLE,
00059     HLJCOND_JUL,
00060     HLJCOND_JULE,
00061     HLJCOND_JOF,
00062     HLJCOND_JNE, // no 'jump_if_odd' enumeration for JCOND_TYPE
00063     HLJCOND_JE,
00064     HLJCOND_JNE,
00065     HLJCOND_JSGE,
00066     HLJCOND_JSG,
00067     HLJCOND_JUGE,
00068     HLJCOND_JUG,
00069     HLJCOND_JNOF,
00070     HLJCOND_JE  // no 'jump_if_even' enumeration for JCOND_TYPE
00071 };
00072 
00073 // Handle the completer for the addr addressing mode
00074 void c_addr(ADDRESS hostpc, SemStr* ssb, SemStr* ssx);
00075 
00076 bool is_null(ADDRESS hostPC)
00077 {
00078     bool res;
00079     match hostPC to
00080         | c_br_nnull() => {
00081             res = false;
00082         }
00083         | c_br_null() => {
00084             res = true;
00085         }
00086     endmatch
00087 
00088     return res;
00089 }
00090 
00091 
00092 DecodeResult& NJMCDecoder::decodeInstruction (ADDRESS pc, int delta,
00093     UserProc* proc /* = NULL */)
00094 { 
00095     static DecodeResult result;
00096     ADDRESS hostPC = pc+delta;
00097 
00098     // Clear the result structure;
00099     result.reset();
00100 
00101     // The actual list of instantiated RTs
00102     list<RT*>* RTs = NULL;
00103     preInstSem = NULL;          // No semantics before the instruction yet
00104     postInstSem = NULL;         // No semantics after the instruction yet
00105 
00106     ADDRESS nextPC;
00107 
00108     // Try matching a logue first.
00109     ADDRESS saveHostPC = hostPC;
00110     int addr, locals, libstub;
00111     Logue* logue;
00112 
00113     if ((logue = InstructionPatterns::std_call(csr,hostPC,addr)) != NULL) {
00114         /*
00115          * Ordinary call to fixed dest
00116          */
00117         HLCall* newCall = new HLCall(pc, 0, RTs);
00118         // Set the fixed destination. Note that addr is (at present!!) just
00119         // the offset in the instruction, so we have to add native pc
00120         newCall->setDest(addr + pc);
00121         result.numBytes = hostPC - saveHostPC;
00122         // See if this call is to a special symbol
00123         const char* dest = prog.pBF->SymbolByAddress((ADDRESS)(addr + pc));
00124         if (dest && (strcmp(dest, "__main") == 0)) {
00125             // Treat this as a NOP
00126         } else {
00127 
00128             result.rtl = newCall;
00129             result.type = SD;
00130 
00131             // Record the prologue of this caller
00132             newCall->setPrologue(logue);
00133 
00134             SHOW_ASM("std_call 0x" << hex << addr-delta)
00135         }
00136     }
00137 
00138     //
00139     // Callee prologues
00140     //
00141     else if ((logue = InstructionPatterns::gcc_frame(csr,hostPC, locals))
00142       != NULL) {
00143         /*
00144          * Standard prologue for gcc: sets up frame in %r3; optionally saves
00145          * several registers to the stack
00146          */
00147         if (proc != NULL) {
00148 
00149             // Record the prologue of this callee
00150             assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00151             proc->setPrologue((CalleePrologue*)logue);
00152         }
00153 
00154         result.numBytes = hostPC - saveHostPC;
00155         result.rtl = new RTL(pc,RTs);
00156         result.type = NCT;
00157         SHOW_ASM("gcc_frame " << dec << locals)
00158     }
00159     else if ((logue = InstructionPatterns::gcc_frameless(csr,hostPC, locals))
00160       != NULL) {
00161         /*
00162          * Gcc prologue where optimisation is on, and no frame pointer is needed
00163          */
00164         if (proc != NULL) {
00165 
00166             // Record the prologue of this callee
00167             assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00168             proc->setPrologue((CalleePrologue*)logue);
00169         }
00170 
00171         result.numBytes = hostPC - saveHostPC;
00172         result.rtl = new RTL(pc,RTs);
00173         result.type = NCT;
00174         SHOW_ASM("gcc_frameless " << dec << locals)
00175     }
00176     else if ((locals=8, logue = InstructionPatterns::param_reloc1(csr,hostPC,
00177       libstub, locals)) != NULL) {
00178         /*
00179          * Parameter relocation stub common when passing a double as the second
00180          * parameter to printf
00181          */
00182         if (proc != NULL) {
00183             // Record the prologue of this callee
00184             assert(logue->getType() == Logue::CALLEE_PROLOGUE);
00185             proc->setPrologue((CalleePrologue*)logue);
00186         }
00187 
00188         // The semantics of the first 3 instructions are difficult to translate
00189         // However, they boil down to these three, and the parameter analysis
00190         // should be able to use these:
00191         // *64* m[%afp + 0] = r[39];
00192         SemStr* ssSrc = new SemStr;
00193         SemStr* ssDst = new SemStr;
00194         *ssSrc << idRegOf << idIntConst << 39;
00195         *ssDst << idMemOf << idAFP;
00196         RTs = new list<RT*>;
00197         RTAssgn* pRt = new RTAssgn(ssDst, ssSrc, 64); RTs->push_back(pRt);
00198         // *32* r[23] := m[%afp    ];
00199         ssSrc = new SemStr; ssDst = new SemStr;
00200         *ssSrc << idMemOf << idAFP;
00201         *ssDst << idRegOf << idIntConst << 23;
00202         pRt = new RTAssgn(ssDst, ssSrc, 32);
00203         RTs->push_back(pRt);
00204         // *32* r[24] := m[%afp + 4];
00205         ssSrc = new SemStr; ssDst = new SemStr;
00206         *ssSrc << idMemOf << idPlus << idAFP << idIntConst << 4;
00207         *ssDst << idRegOf << idIntConst << 24;
00208         pRt = new RTAssgn(ssDst, ssSrc, 32); RTs->push_back(pRt);
00209 
00210         // Find the destination of the final jump. It starts 12 bytes later than
00211         // the pc of the whole pattern
00212         ADDRESS dest = pc + 12 + libstub;
00213         // Treat it like a call, followed by a return
00214         HLCall* newCall = new HLCall(pc, 0, RTs);
00215         // Set the fixed destination.
00216         newCall->setDest(dest);
00217         newCall->setReturnAfterCall(true);
00218         result.numBytes = hostPC - saveHostPC;
00219         result.rtl = newCall;
00220         result.type = SU;
00221 
00222         // Record the prologue of this caller (though it's the wrong type)
00223         newCall->setPrologue(logue);
00224         SHOW_ASM("param_reloc1 " << hex << dest)
00225     }
00226 
00227     //
00228     // Callee epilogues
00229     //
00230     else if ((logue = InstructionPatterns::gcc_unframe(csr, hostPC)) != NULL) {
00231         /*
00232          * Standard removal of current frame for gcc; optional restore of
00233          * several registers from stack
00234          */
00235         result.numBytes = hostPC - saveHostPC;
00236         result.rtl = new HLReturn(pc,RTs);
00237         result.type = DU;
00238 
00239         // Record the epilogue of this callee
00240         if (proc != NULL) {
00241             assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00242             proc->setEpilogue((CalleeEpilogue*)logue);
00243         }
00244     
00245         SHOW_ASM("gcc_unframe");
00246     }
00247     else if ((logue = InstructionPatterns::gcc_unframeless1(csr, hostPC)) !=
00248       NULL) {
00249         /*
00250          * Removal of current frame for gcc (where no frame pointer was used)
00251          */
00252         result.numBytes = hostPC - saveHostPC;
00253         result.rtl = new HLReturn(pc,RTs);
00254         // Although the actual return instruction is a DD (Dynamic Delayed
00255         // branch), we call it a DU so the delay slot instruction is not decoded
00256         result.type = DU;
00257 
00258         // Record the epilogue of this callee
00259         if (proc != NULL) {
00260             assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00261             proc->setEpilogue((CalleeEpilogue*)logue);
00262         }
00263     
00264         SHOW_ASM("gcc_unframeless1");
00265     }
00266     else if ((logue = InstructionPatterns::gcc_unframeless2(csr, hostPC)) !=
00267       NULL) {
00268         /*
00269          * Removal of current frame for gcc (where no frame pointer was used)
00270          */
00271         result.numBytes = hostPC - saveHostPC;
00272         result.rtl = new HLReturn(pc,RTs);
00273         result.type = DU;
00274 
00275         // Record the epilogue of this callee
00276         if (proc != NULL) {
00277             assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00278             proc->setEpilogue((CalleeEpilogue*)logue);
00279         }
00280     
00281         SHOW_ASM("gcc_unframeless2");
00282     }
00283     else if ((logue = InstructionPatterns::bare_ret(csr, hostPC)) != NULL) {
00284         /*
00285          * Just a bare (non anulled) return statement
00286          */
00287         result.numBytes = 8;        // BV and the delay slot instruction
00288         result.rtl = new HLReturn(pc, RTs);
00289         // This is a DD instruction; the front end will decode the delay slot
00290         // instruction
00291         result.type = DD;
00292 
00293         // Record the epilogue of this callee
00294         if (proc != NULL) {
00295             assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00296             proc->setEpilogue((CalleeEpilogue*)logue);
00297         }
00298     
00299         SHOW_ASM("bare_ret");
00300     }
00301     else if ((logue = InstructionPatterns::bare_ret_anulled(csr, hostPC))
00302       != NULL) {
00303         /*
00304          * Just a bare (anulled) return statement
00305          */
00306         result.numBytes = 4;        // BV only
00307         result.rtl = new HLReturn(pc, RTs);
00308         result.type = DU;       // No delay slot to decode
00309 
00310         // Record the epilogue of this callee
00311         if (proc != NULL) {
00312             assert(logue->getType() == Logue::CALLEE_EPILOGUE);
00313             proc->setEpilogue((CalleeEpilogue*)logue);
00314         }
00315     
00316         SHOW_ASM("bare_ret_anulled");
00317     }
00318 
00319     else {
00320         // Branches and other high level instructions
00321         match  hostPC to
00322         | BL (nulli, ubr_target, t_06) => {
00323             HLJump* jump;
00324             // The return registers are 2 (standard) or 31 (millicode)
00325             if ((t_06 == 2) || (t_06 == 31))
00326                 jump = new HLCall(pc, 0, RTs);
00327             if ((t_06 != 2) && (t_06 != 31))    // Can't use "else"
00328                 jump = new HLJump(pc, RTs);
00329             result.rtl = jump;
00330             bool isNull = is_null(nulli);
00331             if (isNull)
00332                 result.type = SU;
00333             if (!isNull)                        // Can't use "else"
00334                 result.type = SD;
00335             jump->setDest(ubr_target + pc);     // This may change
00336             result.numBytes = 4;
00337         }
00338         
00339         | bb_all(c_cmplt, null_cmplt, r, bit_cmplt, target) => {
00340             int condvalue;
00341             SemStr* cond_ss = c_c(c_cmplt, condvalue);
00342             HLJcond* jump = new HLJcond(pc, RTs);
00343             jump->setDest(dis_Num(target + pc + 8));
00344             SemStr* reg = dis_Reg(r);
00345             SemStr* mask = dis_c_bit(bit_cmplt);
00346             SemStr* exp = new SemStr;
00347             *exp << idBitAnd << *mask << *reg;
00348             substituteCallArgs("c_c", cond_ss, mask, reg, exp);
00349             jump->setCondExpr(cond_ss);
00350             bool isNull = is_null(null_cmplt);
00351             result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00352             result.rtl = jump;
00353             result.numBytes = 4;
00354         }
00355         
00356         | cmpib_all(c_cmplt, null_cmplt, im5_11, r_06, target) => {
00357             int condvalue;
00358             SemStr* cond_ss = c_c(c_cmplt, condvalue);
00359             HLJcond* jump = new HLJcond(pc, RTs);
00360             jump->setCondType(hl_jcond_type[condvalue]);
00361             jump->setDest(dis_Num(target + pc + 8));
00362             SemStr* imm = dis_Num(im5_11);
00363             SemStr* reg = dis_Reg(r_06);
00364             reg->prep(idRegOf);
00365             SemStr* exp = new SemStr;
00366             *exp << idMinus << *imm << *reg;
00367             substituteCallArgs("c_c", cond_ss, imm, reg, exp);
00368             jump->setCondExpr(cond_ss);
00369             bool isNull = is_null(null_cmplt);
00370             // If isNull, then taken forward or failing backwards anull
00371             result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00372             result.rtl = jump;
00373             result.numBytes = 4;
00374         }
00375 
00376         | cmpb_all(c_cmplt, null_cmplt, r1, r2, target) => {
00377             int condvalue;
00378             SemStr* cond_ss = c_c(c_cmplt, condvalue);
00379             HLJcond* jump = new HLJcond(pc, RTs);
00380             jump->setCondType(hl_jcond_type[condvalue]);
00381             jump->setDest(dis_Num(target + pc + 8));
00382             SemStr* reg1 = dis_Reg(r1);
00383             SemStr* reg2 = dis_Reg(r2);
00384             reg1->prep(idRegOf);
00385             reg2->prep(idRegOf);
00386             SemStr* exp = new SemStr;
00387             *exp << idMinus << *reg1 << *reg2;
00388             substituteCallArgs("c_c", cond_ss, reg1, reg2, exp);
00389             jump->setCondExpr(cond_ss);
00390             bool isNull = is_null(null_cmplt);
00391             // If isNull, then taken forward or failing backwards anull
00392             result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00393             result.rtl = jump;
00394             result.numBytes = 4;
00395         }
00396         | addib_all(c_cmplt, null_cmplt, im5_11, r_06, target) => {
00397             int condvalue;
00398             SemStr* cond_ss = c_c(c_cmplt, condvalue);
00399             // Get semantics for the add part (only)
00400             RTs = instantiate(pc, name, dis_Num(im5_11), dis_Reg(r_06));
00401             HLJcond* jump = new HLJcond(pc, RTs);
00402             jump->setCondType(hl_jcond_type[condvalue]);
00403             jump->setDest(dis_Num(target + pc + 8));
00404             SemStr* imm = dis_Num(im5_11);
00405             SemStr* reg = dis_Reg(r_06);
00406             reg->prep(idRegOf);
00407             SemStr* tgt = new SemStr(*reg);      // Each actual is deleted
00408             substituteCallArgs("c_c", cond_ss, imm, reg, tgt);
00409             jump->setCondExpr(cond_ss);
00410             bool isNull = is_null(null_cmplt);
00411             // If isNull, then taken forward or failing backwards anull
00412             result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00413             result.rtl = jump;
00414             result.numBytes = 4;
00415         }
00416         | MOVB (c_cmplt, null_cmplt, r1, r2, target) => {
00417             int condvalue;
00418             SemStr* cond_ss = c_c(c_cmplt, condvalue);
00419             RTs = instantiate(pc, name, dis_Reg(r1), dis_Reg(r2));
00420             HLJcond* jump = new HLJcond(pc, RTs);
00421             jump->setCondType(hl_jcond_type[condvalue]);
00422             jump->setDest(dis_Num(target + pc + 8));
00423             SemStr* reg1 = dis_Reg(r1);
00424             SemStr* reg2 = dis_Reg(r2);
00425             reg1->prep(idRegOf);
00426             reg2->prep(idRegOf);
00427             SemStr* tgt = new SemStr(*reg2);
00428             substituteCallArgs("c_c", cond_ss, reg1, reg2, tgt);
00429             jump->setCondExpr(cond_ss);
00430             bool isNull = is_null(null_cmplt);
00431             result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00432             result.rtl = jump;
00433             result.numBytes = 4;
00434         }
00435         | MOVIB (c_cmplt, null_cmplt, i, r, target) => {
00436             int condvalue;
00437             SemStr* cond_ss = c_c(c_cmplt, condvalue);
00438             RTs = instantiate(pc, name, dis_Num(i), dis_Reg(r));
00439             HLJcond* jump = new HLJcond(pc, RTs);
00440             jump->setCondType(hl_jcond_type[condvalue]);
00441             jump->setDest(dis_Num(target + pc + 8));
00442             SemStr* imm = dis_Reg(i);
00443             SemStr* reg = dis_Reg(r);
00444             imm->prep(idIntConst);
00445             reg->prep(idRegOf);
00446             SemStr* tgt = new SemStr(*reg);
00447             substituteCallArgs("c_c", cond_ss, imm, reg, tgt);
00448             jump->setCondExpr(cond_ss);
00449             bool isNull = is_null(null_cmplt);
00450             result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00451             result.rtl = jump;
00452             result.numBytes = 4;
00453         }
00454         | addb_all(c_cmplt, null_cmplt, r1, r2, target) => {
00455             int condvalue;
00456             SemStr* cond_ss = c_c(c_cmplt, condvalue);
00457             // Get semantics for the add part (only)
00458             RTs = instantiate(pc, name, dis_Reg(r1), dis_Reg(r2));
00459             HLJcond* jump = new HLJcond(pc, RTs);
00460             jump->setCondType(hl_jcond_type[condvalue]);
00461             jump->setDest(dis_Num(target + pc + 8));
00462             SemStr* reg1 = dis_Reg(r1);
00463             SemStr* reg2 = dis_Reg(r2);
00464             reg1->prep(idRegOf);
00465             reg2->prep(idRegOf);
00466             SemStr* tgt = new SemStr(*reg2);      // Each actual is deleted
00467             substituteCallArgs("c_c", cond_ss, reg1, reg2, tgt);
00468             jump->setCondExpr(cond_ss);
00469             bool isNull = is_null(null_cmplt);
00470             // If isNull, then taken forward or failing backwards anull
00471             result.type = isNull ? (((int)target >= 0) ? SCDAT : SCDAN) : SCD;
00472             result.rtl = jump;
00473             result.numBytes = 4;
00474         }
00475         // The following two groups of instructions may or may not be anulling
00476         // (NCTA). If not, let the low level decoder take care of it.
00477         | arith(cmplt, r_11, r_06, t_27) => {
00478             // Decode the instruction
00479             low_level(RTs, hostPC, pc, result, nextPC);
00480             int condvalue;
00481             c_c(cmplt, condvalue);
00482             if (condvalue != 0)
00483                 // Anulled. Need to decode the next instruction, and make each
00484                 // RTAssgn in it conditional on !r[tmpNul]
00485                 // We can't do this here, so we just make result.type equal to
00486                 // NCTA, and the front end will do this for us
00487                 result.type = NCTA;
00488             not_used(r_11); not_used(r_06); not_used(t_27);
00489         }
00490         | arith_imm(cmplt, imm11, r_06, t_11) => {
00491             // Decode the instruction
00492             low_level(RTs, hostPC, pc, result, nextPC);
00493             int condvalue;
00494             c_c(cmplt, condvalue);
00495             if (condvalue != 0)
00496                 // Anulled. Need to decode the next instruction, and make each
00497                 // RTAssgn in it conditional on !r[tmpNul]
00498                 result.type = NCTA;
00499             not_used(imm11); not_used(r_06); not_used(t_11);
00500         } 
00501         else {
00502             // Low level instruction
00503             low_level(RTs, hostPC, pc, result, nextPC);
00504         }
00505         endmatch
00506     }
00507     return result;
00508 }
00509 
00510 // Let the low level decoder handle this instruction
00511 void NJMCDecoder::low_level(list<RT*>*& RTs, ADDRESS hostPC, ADDRESS pc,
00512   DecodeResult& result, ADDRESS& nextPC)
00513 {
00514     RTs = decodeLowLevelInstruction(hostPC, pc, result);
00515     if (preInstSem && RTs)
00516         RTs->insert(RTs->begin(), preInstSem->begin(), preInstSem->end());
00517     if (postInstSem && RTs)
00518         RTs->insert(RTs->end(), postInstSem->begin(), postInstSem->end());
00519     result.rtl = new RTL(pc, RTs);
00520     nextPC = hostPC + 4;        // 4 byte instruction
00521     result.numBytes = 4;
00522 }
00523 
00524 SemStr* NJMCDecoder::dis_c_bit(ADDRESS hostpc)
00525 {
00526     SemStr* result;
00527     match hostpc to
00528         | c_bitpos_w(p) => {
00529             result = instantiateNamedParam( "bitpos_fix", dis_Num(p));
00530         }
00531         | c_bitsar() => {
00532             result = instantiateNamedParam( "bitpos_sar", dis_Num(0));
00533         }
00534     endmatch
00535     return result;
00536 }
00537 
00538 SemStr* NJMCDecoder::dis_xd(ADDRESS hostpc)
00539 {
00540     SemStr* result;
00541     match hostpc to
00542       | x_addr_nots(x)   => {
00543             result = instantiateNamedParam( "x_addr_nots"   , dis_Reg(x));
00544       }
00545       | x_addr_s_byte(x) => {
00546             result = instantiateNamedParam( "x_addr_s_byte" , dis_Reg(x));
00547       }
00548       | x_addr_s_hwrd(x) => {
00549             result = instantiateNamedParam( "x_addr_s_hwrd" , dis_Reg(x));
00550       }
00551       | x_addr_s_word(x) => {
00552             result = instantiateNamedParam( "x_addr_s_word" , dis_Reg(x));
00553       }
00554       | x_addr_s_dwrd(x) => {
00555             result = instantiateNamedParam( "x_addr_s_dwrd" , dis_Reg(x));
00556       }
00557       | s_addr_im_r(i)   => {
00558             result = instantiateNamedParam( "s_addr_im_r"   , dis_Num(i));
00559       }
00560       | s_addr_r_im(i)   => {
00561             result = instantiateNamedParam( "s_addr_r_im"   , dis_Num(i));
00562       }
00563       | l_addr_16_old(i) => {
00564             result = instantiateNamedParam( "l_addr_16_old" , dis_Num(i));
00565       }
00566       | l_addr_17_old(i) => {
00567             result = instantiateNamedParam( "l_addr_17_old" , dis_Num(i));
00568       }
00569     endmatch
00570     return result;
00571 }
00572 
00573 /*==============================================================================
00574  * FUNCTION:        c_addr
00575  * OVERVIEW:        Processes completers for various addressing modes
00576  * NOTE:            I think we need to pass the base register to this function
00577  * PARAMETERS:      hostpc - the instruction stream address of the dynamic
00578  *                    address
00579  *                  ssb - SemStr* for the base register that gets modified
00580  *                  ssx - SemStr* for the amount to be added to ssb
00581  * RETURNS:         the SemStr representation of the given address
00582  *============================================================================*/
00583 SemStr* NJMCDecoder::dis_c_addr(ADDRESS hostPC)
00584 {
00585     SemStr* result = NULL;
00586     match hostPC to
00587         | c_s_addr_mb() =>
00588          { result = instantiateNamedParam( "c_s_addr_mb" ); }
00589         | c_s_addr_ma() =>
00590          { result = instantiateNamedParam( "c_s_addr_ma" ); }
00591         | c_s_addr_notm() =>
00592          { result = instantiateNamedParam( "c_s_addr_notm" ); }
00593         | c_x_addr_m() =>
00594          { result = instantiateNamedParam( "c_x_addr_m" ); }
00595         | c_x_addr_notm() =>
00596          { result = instantiateNamedParam( "c_x_addr_notm" ); }
00597         | c_y_addr_e() =>
00598          { result = instantiateNamedParam( "c_y_addr_e" ); }
00599         | c_y_addr_m() =>
00600          { result = instantiateNamedParam( "c_y_addr_m" ); }
00601         | c_y_addr_me() =>
00602          { result = instantiateNamedParam( "c_y_addr_me" ); }
00603         | c_y_addr_none() =>
00604          { result = instantiateNamedParam( "c_y_addr_none" ); }
00605         | c_l_addr_none() =>
00606          { result = instantiateNamedParam( "c_l_addr_none" ); }
00607     endmatch
00608     return result;
00609 }
00610 
00611 SemStr* NJMCDecoder::dis_c_wcr(unsigned hostPC)
00612 {
00613     return 0;
00614 }
00615 
00616 SemStr* NJMCDecoder::dis_ct(unsigned hostPC)
00617 {
00618     return 0;
00619 }
00620 
00621 SemStr* NJMCDecoder::dis_Freg(int regNum, int fmt)
00622 {
00623     int r;          // Final register number
00624     switch (fmt) {
00625         case 0:     // SGL
00626             r = regNum + 64;
00627             break;
00628         case 1:     // DBL
00629             r = regNum + 32;
00630             break;
00631         case 2:     // QUAD
00632             r = regNum + 128;
00633             break;
00634         default:
00635             printf("Error decoding floating point register %d with format %d\n",
00636               regNum, fmt);
00637             r = 0;
00638     }
00639     SemStr* ss = new SemStr;
00640     *ss << idIntConst << r;
00641     return ss;
00642 }
00643 
00644 SemStr* NJMCDecoder::dis_Creg(int regNum)
00645 {
00646     SemStr* ss = new SemStr;
00647     *ss << idIntConst << (regNum + 256);
00648     return ss;
00649 }
00650 
00651 SemStr* NJMCDecoder::dis_Sreg(int regNum)
00652 {
00653     SemStr* ss = new SemStr;
00654     *ss << idIntConst << regNum;
00655     return ss;
00656 }
00657 
00658 /*==============================================================================
00659  * FUNCTION:      isFuncPrologue()
00660  * OVERVIEW:      Check to see if the instructions at the given offset match
00661  *                  any callee prologue, i.e. does it look like this offset
00662  *                  is a pointer to a function?
00663  * PARAMETERS:    hostPC - pointer to the code in question (native address)
00664  * RETURNS:       True if a match found
00665  *============================================================================*/
00666 bool isFuncPrologue(ADDRESS hostPC)
00667 {
00668 #if 0
00669     int hiVal, loVal, reg, locals;
00670     if ((InstructionPatterns::new_reg_win(prog.csrSrc,hostPC, locals)) != NULL)
00671             return true;
00672     if ((InstructionPatterns::new_reg_win_large(prog.csrSrc, hostPC,
00673         hiVal, loVal, reg)) != NULL)
00674             return true;
00675     if ((InstructionPatterns::same_reg_win(prog.csrSrc, hostPC, locals))
00676         != NULL)
00677             return true;
00678     if ((InstructionPatterns::same_reg_win_large(prog.csrSrc, hostPC,
00679         hiVal, loVal, reg)) != NULL)
00680             return true;
00681 #endif
00682 
00683     return false;
00684 }
00685 

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