sparc/decoder.m

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1996-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 SPARC specific parts of the
00013  *             SparcDecoder class.
00014  *============================================================================*/
00015 
00016 /* $Revision: 1.23 $    // 1.20.2.2
00017  *
00018  * 26 Apr 02 - Mike: Mods for boomerang
00019  * 19 May 02 - Mike: Added many (int) casts: variables from toolkit are unsgnd
00020  * 21 May 02 - Mike: SAVE and RESTORE have full semantics now
00021  * 30 Oct 02 - Mike: dis_Eaddr mode indirectA had extra memof
00022  * 22 Nov 02 - Mike: Support 32 bit V9 branches
00023  * 04 Dec 02 - Mike: r[0] -> 0 automatically (rhs only)
00024  * 30 May 02 - Mike: Also fixed r[0] -> 0 for store instructions
00025  * 03 Nov 04 - Mike: DIS_FDS was returning numbers for the double precision registers
00026 */
00027 
00028 /*==============================================================================
00029  * Dependencies.
00030  *============================================================================*/
00031 
00032 #include <assert.h>
00033 #if defined(_MSC_VER) && _MSC_VER <= 1100
00034 #include "signature.h"
00035 #endif
00036 
00037 #include "decoder.h"
00038 #include "exp.h"
00039 #include "prog.h"
00040 #include "proc.h"
00041 #include "sparcdecoder.h"
00042 #include "rtl.h"
00043 #include "BinaryFile.h"     // For SymbolByAddress()
00044 #include "boomerang.h"
00045 
00046 #define DIS_ROI     (dis_RegImm(roi))
00047 #define DIS_ADDR    (dis_Eaddr(addr))
00048 #define DIS_RD      (dis_RegLhs(rd))
00049 #define DIS_RDR     (dis_RegRhs(rd))
00050 #define DIS_RS1     (dis_RegRhs(rs1))
00051 #define DIS_FS1S    (dis_RegRhs(fs1s+32))
00052 #define DIS_FS2S    (dis_RegRhs(fs2s+32))
00053 // Note: Sparc V9 has a second set of double precision registers that have an
00054 // odd index. So far we only support V8
00055 #define DIS_FDS     (dis_RegLhs(fds+32))
00056 #define DIS_FS1D    (dis_RegRhs((fs1d>>1)+64))
00057 #define DIS_FS2D    (dis_RegRhs((fs2d>>1)+64))
00058 #define DIS_FDD     (dis_RegLhs((fdd>>1)+64))
00059 #define DIS_FDQ     (dis_RegLhs((fdq>>2)+80))
00060 #define DIS_FS1Q    (dis_RegRhs((fs1q>>2)+80))
00061 #define DIS_FS2Q    (dis_RegRhs((fs2q>>2)+80))
00062 
00063 /*==============================================================================
00064  * FUNCTION:       unused
00065  * OVERVIEW:       A dummy function to suppress "unused local variable" messages
00066  * PARAMETERS:     x: integer variable to be "used"
00067  * RETURNS:        Nothing
00068  *============================================================================*/
00069 void SparcDecoder::unused(int x)
00070 {}
00071 
00072 /*==============================================================================
00073  * FUNCTION:       createBranchRtl
00074  * OVERVIEW:       Create an RTL for a Bx instruction
00075  * PARAMETERS:     pc - the location counter
00076  *                 stmts - ptr to list of Statement pointers
00077  *                 name - instruction name (e.g. "BNE,a", or "BPNE")
00078  * RETURNS:        Pointer to newly created RTL, or NULL if invalid
00079  *============================================================================*/
00080 RTL* SparcDecoder::createBranchRtl(ADDRESS pc, std::list<Statement*>* stmts, const char* name) {
00081     RTL* res = new RTL(pc, stmts);
00082     BranchStatement* br = new BranchStatement();
00083     res->appendStmt(br);
00084     if (name[0] == 'F') {
00085         // fbranch is any of [ FBN FBNE FBLG FBUL FBL   FBUG FBG   FBU
00086         //                     FBA FBE  FBUE FBGE FBUGE FBLE FBULE FBO ],
00087         // fbranches are not the same as ibranches, so need a whole different set of tests
00088         if (name[2] == 'U')
00089             name++;             // Just ignore unordered (for now)
00090         switch (name[2]) {
00091         case 'E':                           // FBE
00092             br->setCondType(BRANCH_JE, true);
00093             break;
00094         case 'L':
00095             if (name[3] == 'G')             // FBLG
00096                 br->setCondType(BRANCH_JNE, true);
00097             else if (name[3] == 'E')        // FBLE
00098                 br->setCondType(BRANCH_JSLE, true);
00099             else                            // FBL
00100                 br->setCondType(BRANCH_JSL, true);
00101             break;
00102         case 'G':
00103             if (name[3] == 'E')             // FBGE
00104                 br->setCondType(BRANCH_JSGE, true);
00105             else                            // FBG
00106                 br->setCondType(BRANCH_JSG, true);
00107             break;
00108         case 'N':
00109             if (name[3] == 'E')             // FBNE
00110                 br->setCondType(BRANCH_JNE, true);
00111             // Else it's FBN!
00112             break;
00113         default:
00114             std::cerr << "unknown float branch " << name << std::endl;
00115             delete res;
00116             res = NULL;
00117         }
00118         return res;
00119     }   
00120 
00121     // ibranch is any of [ BN BE  BLE BL  BLEU BCS BNEG BVS
00122     //                     BA BNE BG  BGE BGU  BCC BPOS BVC ],
00123     // Note: BPN, BPE, etc handled below
00124     switch(name[1]) {
00125     case 'E':
00126         br->setCondType(BRANCH_JE);           // BE
00127         break;
00128     case 'L':
00129         if (name[2] == 'E') {
00130             if (name[3] == 'U')
00131                 br->setCondType(BRANCH_JULE); // BLEU
00132             else
00133                 br->setCondType(BRANCH_JSLE); // BLE
00134         }
00135         else
00136             br->setCondType(BRANCH_JSL);      // BL
00137         break;
00138     case 'N':
00139         // BNE, BNEG (won't see BN)
00140         if (name[3] == 'G')
00141             br->setCondType(BRANCH_JMI);      // BNEG
00142         else
00143             br->setCondType(BRANCH_JNE);      // BNE
00144         break;
00145     case 'C':
00146         // BCC, BCS
00147         if (name[2] == 'C')
00148             br->setCondType(BRANCH_JUGE);     // BCC
00149         else
00150             br->setCondType(BRANCH_JUL);      // BCS
00151         break;
00152     case 'V':
00153         // BVC, BVS; should never see these now
00154         if (name[2] == 'C')
00155             std::cerr << "Decoded BVC instruction\n";   // BVC
00156         else
00157             std::cerr << "Decoded BVS instruction\n";   // BVS
00158         break;
00159     case 'G':   
00160         // BGE, BG, BGU
00161         if (name[2] == 'E')
00162             br->setCondType(BRANCH_JSGE);     // BGE
00163         else if (name[2] == 'U')
00164             br->setCondType(BRANCH_JUG);      // BGU
00165         else
00166             br->setCondType(BRANCH_JSG);      // BG
00167         break;
00168     case 'P':   
00169         if (name[2] == 'O') {
00170             br->setCondType(BRANCH_JPOS);         // BPOS
00171             break;
00172         }
00173         // Else, it's a BPXX; remove the P (for predicted) and try again
00174         // (recurse)
00175         // B P P O S ...
00176         // 0 1 2 3 4 ...
00177         char temp;
00178         temp = 'B';
00179         strcpy(temp+1, name+2);
00180         delete res;
00181         return createBranchRtl(pc, stmts, temp);
00182     default:
00183         std::cerr << "unknown non-float branch " << name << std::endl;
00184     }   
00185     return res;
00186 }
00187 
00188 
00189 /*==============================================================================
00190  * FUNCTION:       SparcDecoder::decodeInstruction
00191  * OVERVIEW:       Attempt to decode the high level instruction at a given address and return the corresponding HL type
00192  *                  (e.g. CallStatement, GotoStatement etc). If no high level instruction exists at the given address,
00193  *                  then simply return the RTL for the low level instruction at this address. There is an option to also
00194  *                 include the low level statements for a HL instruction.
00195  * PARAMETERS:     pc - the native address of the pc
00196  *                 delta - the difference between the above address and the host address of the pc (i.e. the address
00197  *                  that the pc is at in the loaded object file)
00198  *                 proc - the enclosing procedure. This can be NULL for those of us who are using this method in an
00199  *                  interpreter
00200  * RETURNS:        a DecodeResult structure containing all the information gathered during decoding
00201  *============================================================================*/
00202 DecodeResult& SparcDecoder::decodeInstruction (ADDRESS pc, int delta) { 
00203     static DecodeResult result;
00204     ADDRESS hostPC = pc+delta;
00205 
00206     // Clear the result structure;
00207     result.reset();
00208 
00209     // The actual list of instantiated statements
00210     std::list<Statement*>* stmts = NULL;
00211 
00212     ADDRESS nextPC = NO_ADDRESS;
00213 
00214     match  hostPC to
00215 
00216     | call__(addr) =>
00217         /*
00218          * A standard call 
00219          */
00220         CallStatement* newCall = new CallStatement;
00221 
00222         // Set the destination
00223         ADDRESS nativeDest = addr - delta;
00224         newCall->setDest(nativeDest);
00225         Proc* destProc = prog->setNewProc(nativeDest);
00226         if (destProc == (Proc*)-1) destProc = NULL;
00227         newCall->setDestProc(destProc);
00228         result.rtl = new RTL(pc, stmts);
00229         result.rtl->appendStmt(newCall);
00230         result.type = SD;
00231         SHOW_ASM("call__ " << std::hex << (nativeDest))
00232         DEBUG_STMTS
00233 
00234     | call_(addr) =>
00235         /*
00236          * A JMPL with rd == %o7, i.e. a register call
00237          */
00238         CallStatement* newCall = new CallStatement;
00239 
00240         // Record the fact that this is a computed call
00241         newCall->setIsComputed();
00242 
00243         // Set the destination expression
00244         newCall->setDest(dis_Eaddr(addr));
00245         result.rtl = new RTL(pc, stmts);
00246         result.rtl->appendStmt(newCall);
00247         result.type = DD;
00248 
00249         SHOW_ASM("call_ " << dis_Eaddr(addr))
00250         DEBUG_STMTS
00251 
00252 
00253     | ret() =>
00254         /*
00255          * Just a ret (non leaf)
00256          */
00257         result.rtl = new RTL(pc, stmts);
00258         result.rtl->appendStmt(new ReturnStatement);
00259         result.type = DD;
00260         SHOW_ASM("ret_")
00261         DEBUG_STMTS
00262 
00263     | retl() =>
00264         /*
00265          * Just a ret (leaf; uses %o7 instead of %i7)
00266          */
00267         result.rtl = new RTL(pc, stmts);
00268         result.rtl->appendStmt(new ReturnStatement);
00269         result.type = DD;
00270         SHOW_ASM("retl_")
00271         DEBUG_STMTS
00272 
00273     | branch^",a" (tgt) [name] => 
00274         /*
00275          * Anulled branch
00276          */
00277 
00278         // First, check for CBxxx branches (branches that depend on co-processor instructions). These are invalid,
00279         // as far as we are concerned
00280         if (name[0] == 'C') {
00281             result.valid = false;
00282             result.rtl = new RTL;
00283             result.numBytes = 4;
00284             return result;
00285         }
00286         // Instantiate a GotoStatement for the unconditional branches, HLJconds for the rest.
00287         // NOTE: NJMC toolkit cannot handle embedded else statements!
00288         GotoStatement* jump = 0;
00289         RTL* rtl = NULL;                    // Init to NULL to suppress a warning
00290         if (strcmp(name,"BA,a") == 0 || strcmp(name,"BN,a") == 0) {
00291             jump = new GotoStatement;
00292             rtl = new RTL(pc, stmts);
00293             rtl->appendStmt(jump);
00294         } else if (strcmp(name,"BVS,a") == 0 || strcmp(name,"BVC,a") == 0) {
00295             jump = new GotoStatement;
00296             rtl = new RTL(pc, stmts);
00297             rtl->appendStmt(jump);
00298         } else {
00299             rtl = createBranchRtl(pc, stmts, name);
00300             jump = (GotoStatement*) rtl->getList().back();
00301         }
00302 
00303         // The class of this instruction depends on whether or not it is one of the 'unconditional' conditional branches
00304         // "BA,A" or "BN,A"
00305         result.type = SCDAN;
00306         if ((strcmp(name,"BA,a") == 0) || (strcmp(name, "BVC,a") == 0)) {
00307             result.type = SU;
00308         } else {
00309             result.type = SKIP;
00310         }
00311 
00312         result.rtl = rtl;
00313         jump->setDest(tgt - delta);
00314         SHOW_ASM(name << " " << std::hex << tgt-delta)
00315         DEBUG_STMTS
00316         
00317     | pbranch^",a" (cc01, tgt) [name] => 
00318         /*
00319          * Anulled , predicted branch (treat as for non predicted)
00320          */
00321 
00322         // Instantiate a GotoStatement for the unconditional branches, HLJconds for the rest.
00323         // NOTE: NJMC toolkit cannot handle embedded else statements!
00324         if (cc01 != 0) {        /* If 64 bit cc used, can't handle */
00325             result.valid = false;
00326             result.rtl = new RTL;
00327             result.numBytes = 4;
00328             return result;
00329         }
00330         GotoStatement* jump = 0;
00331         RTL* rtl = NULL;                    // Init to NULL to suppress a warning
00332         if (strcmp(name,"BPA,a") == 0 || strcmp(name,"BPN,a") == 0) {
00333             jump = new GotoStatement;
00334             rtl = new RTL(pc, stmts);
00335             rtl->appendStmt(jump);
00336         } else if (strcmp(name,"BPVS,a") == 0 || strcmp(name,"BPVC,a") == 0) {
00337             jump = new GotoStatement;
00338             rtl = new RTL(pc, stmts);
00339             rtl->appendStmt(jump);
00340         } else {
00341             rtl = createBranchRtl(pc, stmts, name);
00342             jump = (GotoStatement*) rtl->getList().back();
00343         }
00344 
00345         // The class of this instruction depends on whether or not it is one of the 'unconditional' conditional branches
00346         // "BPA,A" or "BPN,A"
00347         result.type = SCDAN;
00348         if ((strcmp(name,"BPA,a") == 0) || (strcmp(name, "BPVC,a") == 0)) {
00349             result.type = SU;
00350         } else {
00351             result.type = SKIP;
00352         }
00353 
00354         result.rtl = rtl;
00355         jump->setDest(tgt - delta);
00356         SHOW_ASM(name << " " << std::hex << tgt-delta)
00357         DEBUG_STMTS
00358         
00359     | branch (tgt)  => 
00360         /*
00361          * Non anulled branch
00362          */
00363         // First, check for CBxxx branches (branches that depend on co-processor instructions). These are invalid,
00364         // as far as we are concerned
00365         if (name[0] == 'C') {
00366             result.valid = false;
00367             result.rtl = new RTL;
00368             result.numBytes = 4;
00369             return result;
00370         }
00371         // Instantiate a GotoStatement for the unconditional branches, BranchStatement for the rest
00372         // NOTE: NJMC toolkit cannot handle embedded plain else statements! (But OK with curly bracket before the else)
00373         GotoStatement* jump = 0;
00374         RTL* rtl = NULL;
00375         if (strcmp(name,"BA") == 0 || strcmp(name,"BN") == 0) {
00376             jump = new GotoStatement;
00377             rtl = new RTL(pc, stmts);
00378             rtl->appendStmt(jump);
00379         } else if (strcmp(name,"BVS") == 0 || strcmp(name,"BVC") == 0) {
00380             jump = new GotoStatement;
00381             rtl = new RTL(pc, stmts);
00382             rtl->appendStmt(jump);
00383         } else {
00384             rtl = createBranchRtl(pc, stmts, name);
00385             jump = (BranchStatement*) rtl->getList().back();
00386         }
00387 
00388         // The class of this instruction depends on whether or not it is one of the 'unconditional' conditional branches
00389         // "BA" or "BN" (or the pseudo unconditionals BVx)
00390         result.type = SCD;
00391         if ((strcmp(name,"BA") == 0) || (strcmp(name, "BVC") == 0))
00392             result.type = SD;
00393         if ((strcmp(name,"BN") == 0) || (strcmp(name, "BVS") == 0))
00394             result.type = NCT;
00395 
00396         result.rtl = rtl;
00397         jump->setDest(tgt - delta);
00398         SHOW_ASM(name << " " << std::hex << tgt-delta)
00399         DEBUG_STMTS
00400 
00401     | BPA (cc01, tgt) =>            /* Can see bpa xcc,tgt in 32 bit code */
00402         unused(cc01);               // Does not matter because is unconditional
00403         GotoStatement* jump = new GotoStatement;
00404 
00405         result.type = SD;
00406         result.rtl = new RTL(pc, stmts);
00407         result.rtl->appendStmt(jump);
00408         jump->setDest(tgt - delta);
00409         SHOW_ASM("BPA " << std::hex << tgt-delta)
00410         DEBUG_STMTS
00411 
00412     | pbranch (cc01, tgt)  =>
00413         if (cc01 != 0) {        /* If 64 bit cc used, can't handle */
00414             result.valid = false;
00415             result.rtl = new RTL;
00416             result.numBytes = 4;
00417             return result;
00418         }
00419         GotoStatement* jump = 0;
00420         RTL* rtl = NULL;
00421         if (strcmp(name,"BPN") == 0) {
00422             jump = new GotoStatement;
00423             rtl = new RTL(pc, stmts);
00424             rtl->appendStmt(jump);
00425         } else if (strcmp(name,"BPVS") == 0 || strcmp(name,"BPVC") == 0) {
00426             jump = new GotoStatement;
00427             rtl = new RTL(pc, stmts);
00428             rtl->appendStmt(jump);
00429         } else {
00430             rtl = createBranchRtl(pc, stmts, name);
00431             // The BranchStatement will be the last Stmt of the rtl
00432             jump = (GotoStatement*)rtl->getList().back();
00433         }
00434 
00435         // The class of this instruction depends on whether or not
00436         // it is one of the 'unconditional' conditional branches
00437         // "BPN" (or the pseudo unconditionals BPVx)
00438         result.type = SCD;
00439         if (strcmp(name, "BPVC") == 0)
00440             result.type = SD;
00441         if ((strcmp(name,"BPN") == 0) || (strcmp(name, "BPVS") == 0))
00442             result.type = NCT;
00443 
00444         result.rtl = rtl;
00445         jump->setDest(tgt - delta);
00446         SHOW_ASM(name << " " << std::hex << tgt-delta)
00447         DEBUG_STMTS
00448 
00449     | JMPL (addr, rd) =>
00450         /*
00451          * JMPL, with rd != %o7, i.e. register jump
00452          * Note: if rd==%o7, then would be handled with the call_ arm
00453          */
00454         CaseStatement* jump = new CaseStatement;
00455         // Record the fact that it is a computed jump
00456         jump->setIsComputed();
00457         result.rtl = new RTL(pc, stmts);
00458         result.rtl->appendStmt(jump);
00459         result.type = DD;
00460         jump->setDest(dis_Eaddr(addr));
00461         unused(rd);
00462         SHOW_ASM("JMPL ")
00463         DEBUG_STMTS
00464 
00465 
00466     //  //  //  //  //  //  //  //
00467     //                          //
00468     //   Ordinary instructions  //
00469     //                          //
00470     //  //  //  //  //  //  //  //
00471 
00472     | SAVE (rs1, roi, rd) =>
00473         // Decided to treat SAVE as an ordinary instruction
00474         // That is, use the large list of effects from the SSL file, and
00475         // hope that optimisation will vastly help the common cases
00476         stmts = instantiate(pc, "SAVE", DIS_RS1, DIS_ROI, DIS_RD);
00477 
00478     | RESTORE (rs1, roi, rd) =>
00479         // Decided to treat RESTORE as an ordinary instruction
00480         stmts = instantiate(pc, "RESTORE", DIS_RS1, DIS_ROI, DIS_RD);
00481 
00482     | NOP  =>
00483         result.type = NOP;
00484         stmts = instantiate(pc,  name);
00485 
00486     | sethi(imm22, rd) => 
00487         stmts = instantiate(pc,  "sethi", dis_Num(imm22), DIS_RD);
00488 
00489     | load_greg(addr, rd)  => 
00490         stmts = instantiate(pc,  name, DIS_ADDR, DIS_RD);
00491 
00492     | LDF (addr, fds)  => 
00493         stmts = instantiate(pc,  name, DIS_ADDR, DIS_FDS);
00494 
00495     | LDDF (addr, fdd)  => 
00496         stmts = instantiate(pc,  name, DIS_ADDR, DIS_FDD);
00497 
00498     | load_asi (addr, asi, rd)  => 
00499         unused(asi);            // Note: this could be serious!
00500         stmts = instantiate(pc,  name, DIS_RD, DIS_ADDR);
00501 
00502     | sto_greg(rd, addr)  => 
00503         // Note: RD is on the "right hand side" only for stores
00504         stmts = instantiate(pc,  name, DIS_RDR, DIS_ADDR);
00505 
00506     | STF (fds, addr)  => 
00507         stmts = instantiate(pc,  name, DIS_FDS, DIS_ADDR);
00508 
00509     | STDF (fdd, addr)  => 
00510         stmts = instantiate(pc,  name, DIS_FDD, DIS_ADDR);
00511 
00512     | sto_asi (rd, addr, asi)  => 
00513         unused(asi);            // Note: this could be serious!
00514         stmts = instantiate(pc,  name, DIS_RDR, DIS_ADDR);
00515 
00516     | LDFSR(addr)  => 
00517         stmts = instantiate(pc,  name, DIS_ADDR);
00518 
00519     | LDCSR(addr)  => 
00520         stmts = instantiate(pc,  name, DIS_ADDR);
00521 
00522     | STFSR(addr)  => 
00523         stmts = instantiate(pc,  name, DIS_ADDR);
00524 
00525     | STCSR(addr)  => 
00526         stmts = instantiate(pc,  name, DIS_ADDR);
00527 
00528     | STDFQ(addr)  => 
00529         stmts = instantiate(pc,  name, DIS_ADDR);
00530 
00531     | STDCQ(addr)  => 
00532         stmts = instantiate(pc,  name, DIS_ADDR);
00533 
00534     | RDY(rd)  => 
00535         stmts = instantiate(pc,  name, DIS_RD);
00536 
00537     | RDPSR(rd)  => 
00538         stmts = instantiate(pc,  name, DIS_RD);
00539 
00540     | RDWIM(rd)  => 
00541         stmts = instantiate(pc,  name, DIS_RD);
00542 
00543     | RDTBR(rd)     => 
00544         stmts = instantiate(pc,  name, DIS_RD);
00545 
00546     | WRY(rs1,roi)  => 
00547         stmts = instantiate(pc,  name, DIS_RS1, DIS_ROI);
00548 
00549     | WRPSR(rs1, roi)  => 
00550         stmts = instantiate(pc,  name, DIS_RS1, DIS_ROI);
00551 
00552     | WRWIM(rs1, roi)  => 
00553         stmts = instantiate(pc,  name, DIS_RS1, DIS_ROI);
00554 
00555     | WRTBR(rs1, roi)  => 
00556         stmts = instantiate(pc,  name, DIS_RS1, DIS_ROI);
00557 
00558     | alu (rs1, roi, rd)  => 
00559         stmts = instantiate(pc,  name, DIS_RS1, DIS_ROI, DIS_RD);
00560 
00561     | float2s (fs2s, fds)  => 
00562         stmts = instantiate(pc,  name, DIS_FS2S, DIS_FDS);
00563 
00564     | float3s (fs1s, fs2s, fds)  => 
00565         stmts = instantiate(pc,  name, DIS_FS1S, DIS_FS2S, DIS_FDS);
00566  
00567     | float3d (fs1d, fs2d, fdd)  => 
00568         stmts = instantiate(pc,  name, DIS_FS1D, DIS_FS2D, DIS_FDD);
00569  
00570     | float3q (fs1q, fs2q, fdq)  => 
00571         stmts = instantiate(pc,  name, DIS_FS1Q, DIS_FS2Q, DIS_FDQ);
00572  
00573     | fcompares (fs1s, fs2s)  => 
00574         stmts = instantiate(pc,  name, DIS_FS1S, DIS_FS2S);
00575 
00576     | fcompared (fs1d, fs2d)  => 
00577         stmts = instantiate(pc,  name, DIS_FS1D, DIS_FS2D);
00578 
00579     | fcompareq (fs1q, fs2q)  => 
00580         stmts = instantiate(pc,  name, DIS_FS1Q, DIS_FS2Q);
00581 
00582     | FTOs (fs2s, fds)  =>
00583         stmts = instantiate(pc, name, DIS_FS2S, DIS_FDS);
00584 
00585     // Note: itod and dtoi have different sized registers
00586     | FiTOd (fs2s, fdd)  =>
00587         stmts = instantiate(pc, name, DIS_FS2S, DIS_FDD);
00588     | FdTOi (fs2d, fds)  =>
00589         stmts = instantiate(pc, name, DIS_FS2D, DIS_FDS);
00590 
00591     | FiTOq (fs2s, fdq)  =>
00592         stmts = instantiate(pc, name, DIS_FS2S, DIS_FDQ);
00593     | FqTOi (fs2q, fds)  =>
00594         stmts = instantiate(pc, name, DIS_FS2Q, DIS_FDS);
00595 
00596     | FsTOd (fs2s, fdd)  =>
00597         stmts = instantiate(pc, name, DIS_FS2S, DIS_FDD);
00598     | FdTOs (fs2d, fds)  =>
00599         stmts = instantiate(pc, name, DIS_FS2D, DIS_FDS);
00600 
00601     | FsTOq (fs2s, fdq)  =>
00602         stmts = instantiate(pc, name, DIS_FS2S, DIS_FDQ);
00603     | FqTOs (fs2q, fds)  =>
00604         stmts = instantiate(pc, name, DIS_FS2Q, DIS_FDS);
00605 
00606     | FdTOq (fs2d, fdq)  =>
00607         stmts = instantiate(pc, name, DIS_FS2D, DIS_FDQ);
00608     | FqTOd (fs2q, fdd)  =>
00609         stmts = instantiate(pc, name, DIS_FS2Q, DIS_FDD);
00610 
00611 
00612     | FSQRTd (fs2d, fdd)  =>
00613         stmts = instantiate(pc, name, DIS_FS2D, DIS_FDD);
00614 
00615     | FSQRTq (fs2q, fdq)  =>
00616         stmts = instantiate(pc, name, DIS_FS2Q, DIS_FDQ);
00617 
00618 
00619     // In V9, the privileged RETT becomes user-mode RETURN
00620     // It has the semantics of "ret restore" without the add part of the restore
00621     | RETURN (addr)  => 
00622         stmts = instantiate(pc, name, DIS_ADDR);
00623         result.rtl = new RTL(pc, stmts);
00624         result.rtl->appendStmt(new ReturnStatement);
00625         result.type = DD;
00626 
00627     | trap (addr)  => 
00628         stmts = instantiate(pc,  name, DIS_ADDR);
00629 
00630     | UNIMP (n) => 
00631         unused(n);
00632         stmts = NULL;
00633         result.valid = false;
00634 
00635     | inst = n => 
00636         // What does this mean?
00637         unused(n);
00638         result.valid = false;
00639         stmts = NULL;
00640 
00641     else
00642         stmts = NULL;
00643         result.valid = false;
00644         result.numBytes = 4;
00645     endmatch
00646 
00647     result.numBytes = nextPC - hostPC;
00648     if (result.valid && result.rtl == 0)    // Don't override higher level res
00649         result.rtl = new RTL(pc, stmts);
00650 
00651     return result;
00652 }
00653 
00654 
00655 /***********************************************************************
00656  * These are functions used to decode instruction operands into
00657  * expressions (Exp*s).
00658  **********************************************************************/
00659 
00660 /*==============================================================================
00661  * FUNCTION:        SparcDecoder::dis_RegLhs
00662  * OVERVIEW:        Decode the register on the LHS
00663  * PARAMETERS:      r - register (0-31)
00664  * RETURNS:         the expression representing the register
00665  *============================================================================*/
00666 Exp* SparcDecoder::dis_RegLhs(unsigned r)
00667 {
00668     return Location::regOf(r);
00669 }
00670 
00671 /*==============================================================================
00672  * FUNCTION:        SparcDecoder::dis_RegRhs
00673  * OVERVIEW:        Decode the register on the RHS
00674  * NOTE:            Replaces r[0] with const 0
00675  * NOTE:            Not used by DIS_RD since don't want 0 on LHS
00676  * PARAMETERS:      r - register (0-31)
00677  * RETURNS:         the expression representing the register
00678  *============================================================================*/
00679 Exp* SparcDecoder::dis_RegRhs(unsigned r)
00680 {
00681     if (r == 0)
00682         return new Const(0);
00683     return Location::regOf(r);
00684 }
00685 
00686 /*==============================================================================
00687  * FUNCTION:        SparcDecoder::dis_RegImm
00688  * OVERVIEW:        Decode the register or immediate at the given address.
00689  * NOTE:            Used via macro DIS_ROI
00690  * PARAMETERS:      pc - an address in the instruction stream
00691  * RETURNS:         the register or immediate at the given address
00692  *============================================================================*/
00693 Exp* SparcDecoder::dis_RegImm(unsigned pc)
00694 {
00695 
00696     match pc to
00697     | imode(i) =>
00698         Exp* expr = new Const(i);
00699         return expr;
00700     | rmode(rs2) =>
00701         return dis_RegRhs(rs2);
00702     endmatch
00703 }
00704 
00705 /*==============================================================================
00706  * FUNCTION:        SparcDecoder::dis_Eaddr
00707  * OVERVIEW:        Converts a dynamic address to a Exp* expression.
00708  *                  E.g. %o7 --> r[ 15 ]
00709  * PARAMETERS:      pc - the instruction stream address of the dynamic address
00710  *                  ignore - redundant parameter on SPARC
00711  * RETURNS:         the Exp* representation of the given address
00712  *============================================================================*/
00713 Exp* SparcDecoder::dis_Eaddr(ADDRESS pc, int ignore /* = 0 */)
00714 {
00715     Exp* expr;
00716 
00717     match pc to
00718     | indirectA(rs1) =>
00719         expr = Location::regOf(rs1);
00720     | indexA(rs1, rs2) =>
00721         expr = new Binary(opPlus,
00722             Location::regOf(rs1),
00723             Location::regOf(rs2));
00724     | absoluteA(i) =>
00725         expr = new Const((int)i);
00726     | dispA(rs1,i) =>
00727         expr = new Binary(opPlus,
00728             Location::regOf(rs1),
00729             new Const((int)i));
00730     endmatch
00731 
00732     return expr;
00733 }
00734 
00735 /*==============================================================================
00736  * FUNCTION:      isFuncPrologue()
00737  * OVERVIEW:      Check to see if the instructions at the given offset match any callee prologue, i.e. does it look
00738  *                  like this offset is a pointer to a function?
00739  * PARAMETERS:    hostPC - pointer to the code in question (host address)
00740  * RETURNS:       True if a match found
00741  *============================================================================*/
00742 bool SparcDecoder::isFuncPrologue(ADDRESS hostPC)
00743 {
00744 #if 0       // Can't do this without patterns. It was a bit of a hack anyway
00745     int hiVal, loVal, reg, locals;
00746     if ((InstructionPatterns::new_reg_win(prog.csrSrc,hostPC, locals)) != NULL)
00747             return true;
00748     if ((InstructionPatterns::new_reg_win_large(prog.csrSrc, hostPC,
00749         hiVal, loVal, reg)) != NULL)
00750             return true;
00751     if ((InstructionPatterns::same_reg_win(prog.csrSrc, hostPC, locals))
00752         != NULL)
00753             return true;
00754     if ((InstructionPatterns::same_reg_win_large(prog.csrSrc, hostPC,
00755         hiVal, loVal, reg)) != NULL)
00756             return true;
00757 #endif
00758 
00759     return false;
00760 }
00761 
00762 /*==============================================================================
00763  * FUNCTION:      isRestore()
00764  * OVERVIEW:      Check to see if the instruction at the given offset is a restore instruction
00765  * PARAMETERS:    hostPC - pointer to the code in question (host address)
00766  * RETURNS:       True if a match found
00767  *============================================================================*/
00768 bool SparcDecoder::isRestore(ADDRESS hostPC) {
00769         match hostPC to
00770         | RESTORE(a, b, c) =>
00771             unused(a);      // Suppress warning messages
00772             unused(b);
00773             unused(c);
00774             return true;
00775         else
00776             return false;
00777         endmatch
00778 }
00779 
00780  /**********************************
00781  * These are the fetch routines.
00782  **********************************/
00783 
00784 /*==============================================================================
00785  * FUNCTION:        getDword
00786  * OVERVIEW:        Returns the double starting at the given address.
00787  * PARAMETERS:      lc - address at which to decode the double
00788  * RETURNS:         the decoded double
00789  *============================================================================*/
00790 DWord SparcDecoder::getDword(ADDRESS lc)
00791 {
00792     Byte* p = (Byte*)lc;
00793     return (p[0] << 24) + (p << 16) + (p[2] << 8) + p;
00794 }
00795 
00796 /*==============================================================================
00797  * FUNCTION:       SparcDecoder::SparcDecoder
00798  * OVERVIEW:       
00799  * PARAMETERS:     None
00800  * RETURNS:        N/A
00801  *============================================================================*/
00802 SparcDecoder::SparcDecoder(Prog* prog) : NJMCDecoder(prog)
00803 {
00804     std::string file = Boomerang::get()->getProgPath() + "frontend/machine/sparc/sparc.ssl";
00805     RTLDict.readSSLFile(file.c_str());
00806 }
00807 
00808 // For now...
00809 int SparcDecoder::decodeAssemblyInstruction(unsigned, int)
00810 { return 0; }
00811 

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