ppc/decoder.m

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 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 PPC specific parts of the PPCDecoder class.
00013  *============================================================================*/
00014 
00015 /* $Revision: 1.26 $    // 1.24.2.1
00016  *
00017  * 23/Nov/04 - Jay Sweeney and Alajandro Dubrovsky: Created
00018  * 26/Sep/05 - Mike: Added Xsab_, Xsax_; DIS_INDEX uses RAZ not RA now; A2c_ -> Ac_ (does single as well as double prec)
00019  **/
00020 
00021 /*==============================================================================
00022  * Dependencies.
00023  *============================================================================*/
00024 
00025 #include <assert.h>
00026 #if defined(_MSC_VER) && _MSC_VER <= 1100
00027 #include "signature.h"
00028 #endif
00029 
00030 #include "exp.h"
00031 #include "prog.h"
00032 #include "proc.h"
00033 #include "decoder.h"
00034 #include "ppcdecoder.h"
00035 #include "rtl.h"
00036 #include "BinaryFile.h"     // For SymbolByAddress()
00037 #include "boomerang.h"
00038 #include <iostream>
00039 
00040 Exp*    crBit(int bitNum);  // Get an expression for a CR bit access
00041 
00042 #define DIS_UIMM    (new Const(uimm))
00043 #define DIS_SIMM    (new Const(simm))
00044 #define DIS_RS      (dis_Reg(rs))
00045 #define DIS_RD      (dis_Reg(rd))
00046 //#define DIS_CRFD  (dis_Reg(64/* condition registers start*/ + crfd))
00047 #define DIS_CRFD    (new Const(crfd))
00048 #define DIS_RDR     (dis_Reg(rd))
00049 #define DIS_RA      (dis_Reg(ra))
00050 #define DIS_RAZ     (dis_RAmbz(ra))     // As above, but May Be constant Zero
00051 #define DIS_RB      (dis_Reg(rb))
00052 #define DIS_D       (new Const(d))
00053 #define DIS_NZRA    (dis_Reg(ra))
00054 #define DIS_NZRB    (dis_Reg(rb))
00055 #define DIS_ADDR    (new Const(addr))
00056 #define DIS_RELADDR (new Const(reladdr - delta))
00057 #define DIS_CRBD    (crBit(crbD))
00058 #define DIS_CRBA    (crBit(crbA))
00059 #define DIS_CRBB    (crBit(crbB))
00060 #define DIS_DISP    (new Binary(opPlus, dis_RAmbz(ra), new Const(d)))
00061 #define DIS_INDEX   (new Binary(opPlus, DIS_RAZ, DIS_NZRB))
00062 #define DIS_BICR    (new Const(BIcr))
00063 #define DIS_RS_NUM  (new Const(rs))
00064 #define DIS_RD_NUM  (new Const(rd))
00065 #define DIS_BEG     (new Const(beg))
00066 #define DIS_END     (new Const(end))
00067 #define DIS_FD      (dis_Reg(fd+32))
00068 #define DIS_FS      (dis_Reg(fs+32))
00069 #define DIS_FA      (dis_Reg(fa+32))
00070 #define DIS_FB      (dis_Reg(fb+32))
00071 
00072 #define PPC_COND_JUMP(name, size, relocd, cond, BIcr) \
00073     result.rtl = new RTL(pc, stmts); \
00074     BranchStatement* jump = new BranchStatement; \
00075     result.rtl->appendStmt(jump); \
00076     result.numBytes = size; \
00077     jump->setDest(relocd-delta); \
00078     jump->setCondType(cond); \
00079     SHOW_ASM(name<<" "<<BIcr<<", 0x"<<std::hex<<relocd-delta)
00080 
00081 /*==============================================================================
00082  * FUNCTION:       unused
00083  * OVERVIEW:       A dummy function to suppress "unused local variable" messages
00084  * PARAMETERS:     x: integer variable to be "used"
00085  * RETURNS:        Nothing
00086  *============================================================================*/
00087 void PPCDecoder::unused(int x)
00088 {}
00089 void unused(char* x) {}
00090 
00091 
00092 /*==============================================================================
00093  * FUNCTION:       PPCDecoder::decodeInstruction
00094  * OVERVIEW:       Attempt to decode the high level instruction at a given
00095  *                 address and return the corresponding HL type (e.g. CallStatement,
00096  *                 GotoStatement etc). If no high level instruction exists at the
00097  *                 given address, then simply return the RTL for the low level
00098  *                 instruction at this address. There is an option to also
00099  *                 include the low level statements for a HL instruction.
00100  * PARAMETERS:     pc - the native address of the pc
00101  *                 delta - the difference between the above address and the
00102  *                   host address of the pc (i.e. the address that the pc is at
00103  *                   in the loaded object file)
00104  *                 proc - the enclosing procedure. This can be NULL for
00105  *                   those of us who are using this method in an interpreter
00106  * RETURNS:        a DecodeResult structure containing all the information
00107  *                   gathered during decoding
00108  *============================================================================*/
00109 DecodeResult& PPCDecoder::decodeInstruction (ADDRESS pc, int delta) { 
00110     static DecodeResult result;
00111     ADDRESS hostPC = pc+delta;
00112 
00113     // Clear the result structure;
00114     result.reset();
00115 
00116     // The actual list of instantiated statements
00117     std::list<Statement*>* stmts = NULL;
00118 
00119     ADDRESS nextPC = NO_ADDRESS;
00120 
00121     match  hostPC to
00122     | XO_ ( rd, ra, rb)  =>
00123         stmts = instantiate(pc,  name, DIS_RD, DIS_RA, DIS_RB);
00124     | XOb_ ( rd, ra)  =>
00125         stmts = instantiate(pc, name, DIS_RD, DIS_RA);
00126     | Xsax_^Rc (rd, ra)  =>
00127         stmts = instantiate(pc, name, DIS_RD, DIS_RA);
00128     // The number of parameters in these matcher arms has to agree with the number in core.spec
00129     // The number of parameters passed to instantiate() after pc and name has to agree with ppc.ssl
00130     // Stores and loads pass rA to instantiate twice: as part of DIS_DISP, and separately as DIS_NZRA
00131     | Dsad_ (rs, d, ra)  =>
00132         if (strcmp(name, "stmw") == 0) {
00133             // Needs the last param s, which is the register number from rs
00134             stmts = instantiate(pc, name, DIS_RS, DIS_DISP, DIS_RS_NUM);
00135         } else
00136             stmts = instantiate(pc, name, DIS_RS, DIS_DISP, DIS_NZRA);
00137         
00138     | Dsaui_ (rd, ra, uimm)  =>
00139         stmts = instantiate(pc, name, DIS_RD, DIS_RA, DIS_UIMM);
00140     | Ddasi_ (rd, ra, simm)  =>
00141         if (strcmp(name, "addi") == 0 || strcmp(name, "addis") == 0) {
00142             // Note the DIS_RAZ, since rA could be constant zero
00143             stmts = instantiate(pc, name, DIS_RD, DIS_RAZ, DIS_SIMM);
00144         } else
00145             stmts = instantiate(pc, name, DIS_RD, DIS_RA , DIS_SIMM);
00146     | Xsabx_^Rc (rd, ra, rb)  =>
00147         stmts = instantiate(pc, name, DIS_RD, DIS_RA, DIS_RB);
00148     | Xdab_ (rd, ra, rb)  =>
00149         stmts = instantiate(pc, name, DIS_RD, DIS_INDEX);
00150     | Xsab_ (rd, ra, rb)  =>
00151         stmts = instantiate(pc, name, DIS_RD, DIS_INDEX);
00152     // Load instructions
00153     | Ddad_ (rd, d, ra)  =>
00154         if (strcmp(name, "lmw") == 0) {
00155             // Needs the third param d, which is the register number from rd
00156             stmts = instantiate(pc, name, DIS_RD, DIS_DISP, DIS_RD_NUM);
00157         } else
00158             stmts = instantiate(pc, name, DIS_RD, DIS_DISP, DIS_NZRA);
00159 //  | XLb_ (b0, b1) [name] =>
00160 #if BCCTR_LONG  // Prefer to see bltctr instead of bcctr 12,0
00161                 // But also affects return instructions (bclr)
00162         /*FIXME: since this is used for returns, do a jump to LR instead (ie ignoring control registers) */
00163         stmts = instantiate(pc,  name);
00164         result.rtl = new RTL(pc, stmts);
00165         result.rtl->appendStmt(new ReturnStatement);
00166         unused(b0);
00167         unused(b1);
00168 #endif
00169     | XLc_ (crbD, crbA, crbB)  =>
00170         stmts = instantiate(pc, name, DIS_CRBD, DIS_CRBA, DIS_CRBB);
00171         
00172     | mfspr (rd, uimm)  =>
00173         stmts = instantiate(pc, name, DIS_RD, DIS_UIMM);
00174     | mtspr (uimm, rs)  =>
00175         switch (uimm) {
00176             case 1:
00177                 stmts = instantiate(pc, "MTXER" , DIS_RS); break;
00178             case 8:
00179                 stmts = instantiate(pc, "MTLR" , DIS_RS); break;
00180             case 9:
00181                 stmts = instantiate(pc, "MTCTR" , DIS_RS); break;
00182             default:
00183                 std::cerr << "ERROR: MTSPR instruction with invalid S field: " << uimm << "\n";
00184         }
00185 		::unused(name);
00186 
00187     | Xd_ (rd)  =>
00188         stmts = instantiate(pc, name, DIS_RD);
00189 
00190     | M_^Rc(ra, rs, uimm, beg, end)  =>
00191         stmts = instantiate(pc, name, DIS_RA, DIS_RS, DIS_UIMM, DIS_BEG, DIS_END);
00192 
00193 
00194     | bl (reladdr)  =>
00195         Exp* dest = DIS_RELADDR;
00196         stmts = instantiate(pc, name, dest);
00197         CallStatement* newCall = new CallStatement;
00198         // Record the fact that this is not a computed call
00199         newCall->setIsComputed(false);
00200         // Set the destination expression
00201         newCall->setDest(dest);
00202         result.rtl = new RTL(pc, stmts);
00203         result.rtl->appendStmt(newCall);
00204         Proc* destProc = prog->setNewProc(reladdr-delta);
00205         if (destProc == (Proc*)-1) destProc = NULL;
00206         newCall->setDestProc(destProc);
00207 
00208     | b (reladdr) =>
00209         unconditionalJump("b", 4, reladdr, delta, pc, stmts, result);
00210 
00211     | ball (BIcr, reladdr)  =>      // Always "conditional" branch with link, test/OSX/hello has this
00212         if (reladdr - delta - pc == 4) {    // Branch to next instr?
00213             // Effectively %LR = %pc+4, but give the actual value for %pc
00214             Assign* as = new Assign(
00215                 new IntegerType,
00216                 new Unary(opMachFtr, new Const("%LR")),
00217                 new Const(pc+4));
00218             stmts = new std::list<Statement*>;
00219             stmts->push_back(as);
00220             SHOW_ASM(name<<" "<<BIcr<<", .+4"<<" %LR = %pc+4")
00221         } else {
00222             Exp* dest = DIS_RELADDR;
00223             stmts = instantiate(pc, name, dest);
00224             CallStatement* newCall = new CallStatement;
00225             // Record the fact that this is not a computed call
00226             newCall->setIsComputed(false);
00227             // Set the destination expression
00228             newCall->setDest(dest);
00229             result.rtl = new RTL(pc, stmts);
00230             result.rtl->appendStmt(newCall);
00231         }
00232         unused(BIcr);
00233 
00234     | Xcmp_ (crfd, l, ra, rb)  =>
00235         stmts = instantiate(pc, name, DIS_CRFD, DIS_NZRA, DIS_NZRB);
00236         unused(l);
00237     | cmpi (crfd, l, ra, simm)  =>
00238         stmts = instantiate(pc, name, DIS_CRFD, DIS_NZRA, DIS_SIMM);
00239         unused(l);
00240     | cmpli (crfd, l, ra, uimm)  =>
00241         stmts = instantiate(pc, name, DIS_CRFD, DIS_NZRA, DIS_UIMM);
00242         unused(l);
00243 
00244     | Ddaf_(fd, d, ra)  =>                                  // Floating point loads (non indexed)
00245         stmts = instantiate(pc, name, DIS_FD, DIS_DISP, DIS_RA);    // Pass RA twice (needed for update)
00246 
00247     | Xdaf_(fd, ra, rb)  =>                                 // Floating point loads (indexed)
00248         stmts = instantiate(pc, name, DIS_FD, DIS_INDEX, DIS_RA);   // Pass RA twice (needed for update)
00249 
00250     | Dsaf_(fs, d, ra)  =>                                  // Floating point stores (non indexed)
00251         stmts = instantiate(pc, name, DIS_FS, DIS_DISP, DIS_RA);    // Pass RA twice (needed for update)
00252 
00253     | Xsaf_(fs, ra, rb)  =>                                 // Floating point stores (indexed)
00254         stmts = instantiate(pc, name, DIS_FS, DIS_INDEX, DIS_RA);   // Pass RA twice (needed for update)
00255 
00256 
00257     | Xcab_(crfd, fa, fb)  =>                                   // Floating point compare
00258         stmts = instantiate(pc, name, DIS_CRFD, DIS_FA, DIS_FB);
00259 
00260     | Xdbx_^Rc(fd, fb)  =>                                  // Floating point unary
00261         stmts = instantiate(pc, name, DIS_FD, DIS_FB);
00262 
00263     | Ac_^Rc(fd, fa, fb)  =>                                    // Floating point binary
00264         stmts = instantiate(pc, name, DIS_FD, DIS_FA, DIS_FB);
00265 
00266 
00267         
00268 
00269     // Conditional branches
00270     // bcc_ is blt | ble | beq | bge | bgt | bnl | bne | bng | bso | bns | bun | bnu | bal (branch always)
00271     | blt(BIcr, reladdr)  =>
00272         PPC_COND_JUMP(name, 4, reladdr, BRANCH_JSL, BIcr);
00273     | ble(BIcr, reladdr)  =>
00274         PPC_COND_JUMP(name, 4, reladdr, BRANCH_JSLE, BIcr);
00275     | beq(BIcr, reladdr)  =>
00276         PPC_COND_JUMP(name, 4, reladdr, BRANCH_JE, BIcr);
00277     | bge(BIcr, reladdr)  =>
00278         PPC_COND_JUMP(name, 4, reladdr, BRANCH_JSGE, BIcr);
00279     | bgt(BIcr, reladdr)  =>
00280         PPC_COND_JUMP(name, 4, reladdr, BRANCH_JSG, BIcr);
00281 //  | bnl(BIcr, reladdr) [name] =>                              // bnl same as bge
00282 //      PPC_COND_JUMP(name, 4, reladdr, BRANCH_JSGE, BIcr);
00283     | bne(BIcr, reladdr)  =>
00284         PPC_COND_JUMP(name, 4, reladdr, BRANCH_JNE, BIcr);
00285 //  | bng(BIcr, reladdr) [name] =>                              // bng same as blt
00286 //      PPC_COND_JUMP(name, 4, reladdr, BRANCH_JSLE, BIcr);
00287     | bso(BIcr, reladdr)  =>                                // Branch on summary overflow
00288         PPC_COND_JUMP(name, 4, reladdr, (BRANCH_TYPE)0, BIcr);  // MVE: Don't know these last 4 yet
00289     | bns(BIcr, reladdr)  =>
00290         PPC_COND_JUMP(name, 4, reladdr, (BRANCH_TYPE)0, BIcr);
00291 //  | bun(BIcr, reladdr) [name] =>
00292 //      PPC_COND_JUMP(name, 4, reladdr, (BRANCH_TYPE)0, BIcr);
00293 //  | bnu(BIcr, reladdr) [name] =>
00294 //      PPC_COND_JUMP(name, 4, reladdr, (BRANCH_TYPE)0, BIcr);
00295 
00296     | balctr(BIcr)  =>
00297         computedJump(name, 4, new Unary(opMachFtr, new Const("%CTR")), pc, stmts, result);
00298         unused(BIcr);
00299         
00300     | balctrl(BIcr)  =>
00301         computedCall(name, 4, new Unary(opMachFtr, new Const("%CTR")), pc, stmts, result);
00302         unused(BIcr);
00303         
00304     | bal(BIcr, reladdr) =>
00305         unconditionalJump("bal", 4, reladdr, delta, pc, stmts, result);
00306         unused(BIcr);
00307 
00308     // b<cond>lr: Branch conditionally to the link register. Model this as a conditional branch around a return
00309     // statement.
00310     | bltlr(BIcr)  =>
00311         PPC_COND_JUMP(name, 4, hostPC+4, BRANCH_JSGE, BIcr);
00312         result.rtl->appendStmt(new ReturnStatement);
00313 
00314     | blelr(BIcr)  =>
00315         PPC_COND_JUMP(name, 4, hostPC+4, BRANCH_JSG, BIcr);
00316         result.rtl->appendStmt(new ReturnStatement);
00317 
00318     | beqlr(BIcr)  =>
00319         PPC_COND_JUMP(name, 4, hostPC+4, BRANCH_JNE, BIcr);
00320         result.rtl->appendStmt(new ReturnStatement);
00321 
00322     | bgelr(BIcr)  =>
00323         PPC_COND_JUMP(name, 4, hostPC+4, BRANCH_JSL, BIcr);
00324         result.rtl->appendStmt(new ReturnStatement);
00325 
00326     | bgtlr(BIcr)  =>
00327         PPC_COND_JUMP(name, 4, hostPC+4, BRANCH_JSLE, BIcr);
00328         result.rtl->appendStmt(new ReturnStatement);
00329 
00330     | bnelr(BIcr)  =>
00331         PPC_COND_JUMP(name, 4, hostPC+4, BRANCH_JE, BIcr);
00332         result.rtl->appendStmt(new ReturnStatement);
00333 
00334     | bsolr(BIcr)  =>
00335         PPC_COND_JUMP(name, 4, hostPC+4, (BRANCH_TYPE)0, BIcr);
00336         result.rtl->appendStmt(new ReturnStatement);
00337 
00338     | bnslr(BIcr)  =>
00339         PPC_COND_JUMP(name, 4, hostPC+4, (BRANCH_TYPE)0, BIcr);
00340         result.rtl->appendStmt(new ReturnStatement);
00341 
00342     | ballr(BIcr)  =>
00343         result.rtl = new RTL(pc, stmts);
00344         result.rtl->appendStmt(new ReturnStatement);
00345         SHOW_ASM(name<<"\n");
00346         unused(BIcr);
00347 
00348     // Shift right arithmetic
00349     | srawi(ra, rs, uimm)  =>
00350         stmts = instantiate(pc,  name, DIS_RA, DIS_RS, DIS_UIMM);
00351     | srawiq(ra, rs, uimm)  =>
00352         stmts = instantiate(pc,  name, DIS_RA, DIS_RS, DIS_UIMM);
00353         
00354     else
00355         stmts = NULL;
00356         result.valid = false;
00357         result.numBytes = 4;      
00358     endmatch
00359 
00360     result.numBytes = nextPC - hostPC;
00361     if (result.valid && result.rtl == 0)    // Don't override higher level res
00362         result.rtl = new RTL(pc, stmts);
00363 
00364     return result;
00365 }
00366 
00367 
00368 /***********************************************************************
00369  * These are functions used to decode instruction operands into
00370  * expressions (Exp*s).
00371  **********************************************************************/
00372 
00373 /*==============================================================================
00374  * FUNCTION:        PPCDecoder::dis_Reg
00375  * OVERVIEW:        Decode the register
00376  * PARAMETERS:      r - register (0-31)
00377  * RETURNS:         the expression representing the register
00378  *============================================================================*/
00379 Exp* PPCDecoder::dis_Reg(unsigned r)
00380 {
00381     return Location::regOf(r);
00382 }
00383 
00384 /*==============================================================================
00385  * FUNCTION:        PPCDecoder::dis_RAmbz
00386  * OVERVIEW:        Decode the register rA when rA represents constant 0 if r == 0
00387  * PARAMETERS:      r - register (0-31)
00388  * RETURNS:         the expression representing the register
00389  *============================================================================*/
00390 Exp* PPCDecoder::dis_RAmbz(unsigned r)
00391 {
00392     if (r == 0)
00393         return new Const(0);
00394     return Location::regOf(r);
00395 }
00396 
00397 
00398 /*==============================================================================
00399  * FUNCTION:      isFuncPrologue()
00400  * OVERVIEW:      Check to see if the instructions at the given offset match
00401  *                  any callee prologue, i.e. does it look like this offset
00402  *                  is a pointer to a function?
00403  * PARAMETERS:    hostPC - pointer to the code in question (host address)
00404  * RETURNS:       True if a match found
00405  *============================================================================*/
00406 bool PPCDecoder::isFuncPrologue(ADDRESS hostPC)
00407 {
00408 
00409     return false;
00410 }
00411 
00412 
00413  /**********************************
00414  * These are the fetch routines.
00415  **********************************/
00416 
00417 /*==============================================================================
00418  * FUNCTION:        getDword
00419  * OVERVIEW:        Returns the double starting at the given address.
00420  * PARAMETERS:      lc - address at which to decode the double
00421  * RETURNS:         the decoded double
00422  *============================================================================*/
00423 DWord PPCDecoder::getDword(ADDRESS lc)
00424 {
00425   Byte* p = (Byte*)lc;
00426   return (p[0] << 24) + (p << 16) + (p[2] << 8) + p;
00427 }
00428 
00429 /*==============================================================================
00430  * FUNCTION:       PPCDecoder::PPCDecoder
00431  * OVERVIEW:       
00432  * PARAMETERS:     None
00433  * RETURNS:        N/A
00434  *============================================================================*/
00435 PPCDecoder::PPCDecoder(Prog* prog) : NJMCDecoder(prog)
00436 {
00437   std::string file = Boomerang::get()->getProgPath() + "frontend/machine/ppc/ppc.ssl";
00438   RTLDict.readSSLFile(file.c_str());
00439 }
00440 
00441 // For now...
00442 int PPCDecoder::decodeAssemblyInstruction(unsigned, int)
00443 { return 0; }
00444 
00445 // Get an expression for a CR bit. For example, if bitNum is 6, return r65@[2:2]
00446 // (r64 .. r71 are the %cr0 .. %cr7 flag sets)
00447 Exp* crBit(int bitNum) {
00448     int     crNum = bitNum / 4;
00449     bitNum = bitNum & 3;
00450     return new Ternary(opAt,
00451         Location::regOf(64 + crNum),
00452         new Const(bitNum),
00453         new Const(bitNum));
00454 }
00455 

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