front68k.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2000-2001, The University of Queensland
00003  * Copyright (C) 2000-2001, Sun Microsystems, Inc
00004  *
00005  * See the file "LICENSE.TERMS" for information on usage and
00006  * redistribution of this file, and for a DISCLAIMER OF ALL
00007  * WARRANTIES.
00008  *
00009  */
00010 
00011 /*==============================================================================
00012  * FILE:       front68k.cc
00013  * OVERVIEW:   This file contains routines to manage the decoding of mc68k
00014  *             instructions and the instantiation to RTLs. These functions
00015  *             replace Frontend.cc for decoding mc68k instructions.
00016  *============================================================================*/
00017 
00018 /*
00019  * $Revision: 1.3 $
00020  * 14 Feb 00 - Mike: converted from front386.cc
00021  * 23 Feb 00 - Mike: added logic for isReturnAfterCall
00022  * 09 Nov 00 - Cristina: Added support to generate rtl code to a file
00023  * 31 Mar 01 - Mike: getFixedDest() returns NO_ADDRESS for non fixed addresses
00024  * 31 Jul 01 - Brian: New class HRTL replaces RTlist. Renamed LRTL to HRTLList.
00025 */
00026 
00027 #include "global.h"
00028 #include "frontend.h"
00029 #include "decoder.h"        // prototype for decodeInstruction()
00030 #include "rtl.h"
00031 #include "cfg.h"
00032 #include "ss.h"
00033 #include "prog.h"           // For findProc()
00034 #include "proc.h"
00035 #include "options.h"
00036 #include "BinaryFile.h"     // For SymbolByAddress()
00037 #include "csr.h"            // For class CalleeEpilogue
00038 
00039 /*==============================================================================
00040  * Forward declarations.
00041  *============================================================================*/
00042 
00043 /*==============================================================================
00044  * File globals.
00045  *============================================================================*/
00046 
00047 // Queues used by various functions
00048 queue < ADDRESS> qLabels;       // Queue of labels this procedure
00049 
00050 /*==============================================================================
00051  * Forward declarations.
00052  *============================================================================*/
00053 void initCti();             // Imp in cti68k.cc
00054 
00055 struct SemCmp
00056 { bool operator() (const SemStr& ss1, const SemStr& ss2) const; };
00057 bool SemCmp::operator() (const SemStr& ss1, const SemStr& ss2) const
00058 { return ss1 < ss2; }
00059     
00060 // A map from semantic string to integer (for identifying branch statements)
00061 static map<SemStr, int, SemCmp> condMap;
00062 
00063 int arrConds[12][7] = {
00064 { idZF},                                        // HLJCOND_JE: Z
00065 { idNot, idZF},                                 // HLJCOND_JNE: ~Z
00066 { idBitXor, idNF, idOF},                        // HLJCOND_JSL: N ^ O
00067 { idBitOr, idBitXor, idNF, idOF, idZF},         // HLJCOND_JSLE: (N ^ O) | Z
00068 { idNot, idBitXor, idNF, idOF },                // HLJCOND_JGES: ~(N ^ O)
00069 { idBitAnd, idNot, idBitXor, idNF, idOF,
00070     idNot, idZF},                               // HLJCOND_JSG: ~(N ^ O) & ~Z
00071 { idCF},                                        // HLJCOND_JUL: C
00072 { idBitOr, idCF, idZF},                         // HLJCOND_JULE: C | Z
00073 { idNot, idCF},                                 // HLJCOND_JUGE: ~C
00074 { idBitAnd, idNot, idCF, idNot, idZF},          // HLJCOND_JUG: ~C & ~Z
00075 { idNF},                                        // HLJCOND_JMI: N
00076 { idNot, idNF},                                 // HLJCOND_JPOS: ~N
00077 };
00078 
00079 // Ugly. The lengths of the above arrays.
00080 int condLengths[12] = {1, 2, 3, 5, 4, 7, 1, 3, 2, 5, 1, 2};
00081 
00082 /*==============================================================================
00083  * FUNCTION:      initFront
00084  * OVERVIEW:      Initialise the front end.
00085  * PARAMETERS:    <none>                
00086  * RETURNS:       <nothing>
00087  *============================================================================*/
00088 void initFront()
00089 {
00090     for (int i=0; i < 12; i++)
00091     {
00092         SemStr ss;
00093         ss.pushArr(condLengths[i], arrConds[i]);
00094         condMap[ss] = i;
00095     }
00096 }
00097 
00098 // Get the condition, given that it's something like %NF ^ %OF
00099 JCOND_TYPE getCond(const SemStr* pCond)
00100 {
00101     map<SemStr, int, SemCmp>::const_iterator mit;
00102 
00103     mit = condMap.find(*pCond);
00104     if (mit == condMap.end())
00105     {
00106         ostrstream os;
00107         os << "Condition ";
00108         pCond->print(os);
00109         os << " not known";
00110         error(os.str());
00111         return (JCOND_TYPE) 0;
00112     }
00113     return (JCOND_TYPE) (*mit).second;
00114 }
00115 
00116 /*==============================================================================
00117  * FUNCTION:      FrontEndSrc::processProc
00118  * OVERVIEW:      Process a procedure, given a native (source machine) address.
00119  * PARAMETERS:    address - the address at which the procedure starts
00120  *                pProc - the procedure object
00121  *                spec - true if a speculative decode
00122  *                os - output stream for rtl output
00123  * RETURNS:       True if successful decode
00124  *============================================================================*/
00125 bool FrontEndSrc::processProc(ADDRESS uAddr, UserProc* pProc, ofstream &os,
00126     bool spec /* = false */)
00127 {
00128     // Call the base class to do all of the work
00129     return FrontEnd::processProc(uAddr, pProc, os, spec);
00130 }
00131 
00132 #if 0
00133 /*==============================================================================
00134  * FUNCTION:      processProc
00135  * OVERVIEW:      Process a procedure, given a native (source machine) address.
00136  * PARAMETERS:    address - the address at which the procedure starts
00137  *                delta - the offset of the above address from the logical
00138  *                  address at which the procedure starts (i.e. the one
00139  *                  given by dis)
00140  *                uUpper - the highest address of the text segment
00141  *                pProc - the procedure object
00142  *                decoder - NJMCDecoder object
00143  * RETURNS:       <nothing>
00144  *============================================================================*/
00145 void processProc(ADDRESS uAddr, int delta, ADDRESS uUpper, UserProc* pProc,
00146     NJMCDecoder& decoder)
00147 {
00148     PBB pBB;                    // Pointer to the current basic block
00149     INSTTYPE type;              // Cfg type of instruction (e.g. IRET)
00150 
00151     // Declare a queue of targets not yet processed yet. This has to be
00152     // individual to the procedure!
00153     TARGETS targets;
00154 
00155     // Indicates whether or not the next instruction to be decoded is the
00156     // lexical successor of the current one. Will be true for all NCTs and for
00157     // CTIs with a fall through branch.
00158     bool sequentialDecode = true;
00159 
00160     Cfg* pCfg = pProc->getCFG();
00161 
00162     // Initialise the queue of control flow targets that have yet to be decoded.
00163     targets.push(uAddr);
00164 
00165     // Clear the pointer used by the caller prologue code to access the last
00166     // call rtl of this procedure
00167     //decoder.resetLastCall();
00168 
00169     while ((uAddr = nextAddress(targets, pCfg)) != 0) {
00170 
00171         // The list of RTLs for the current basic block
00172         list<HRTL*>* BB_rtls = new list<HRTL*>();
00173 
00174         // Keep decoding sequentially until a CTI without a fall through branch
00175         // is decoded
00176         ADDRESS start = uAddr;
00177         DecodeResult inst;
00178         while (sequentialDecode) {
00179 
00180             // Decode and classify the current instruction
00181             if (progOptions.trace)
00182                 cout << "*" << hex << uAddr << "\t" << flush;
00183 
00184             // Decode the inst at uAddr.
00185             inst = decoder.decodeInstruction(uAddr, delta, pProc);
00186 
00187             // Need to construct a new list of RTLs if a basic block has just
00188             // been finished but decoding is continuing from its lexical
00189             // successor
00190             if (BB_rtls == NULL)
00191                 BB_rtls = new list<HRTL*>();
00192 
00193             HRTL* pRtl = inst.rtl;
00194             if (inst.numBytes == 0)
00195             {
00196                 // An invalid instruction. Most likely because a call did
00197                 // not return (e.g. call _exit()), etc. Best thing is to
00198                 // emit a INVALID BB, and continue with valid instructions
00199                 ostrstream ost;
00200                 ost << "invalid instruction at " << hex << uAddr;
00201                 warning(str(ost));
00202                 // Emit the RTL anyway, so we have the address and maybe
00203                 // some other clues
00204                 BB_rtls->push_back(new RTL(uAddr));  
00205                 pBB = pCfg->newBB(BB_rtls, INVALID, 0);
00206                 sequentialDecode = false; BB_rtls = NULL; continue;
00207             }
00208     
00209             HLJump* rtl_jump = static_cast<HLJump*>(pRtl);
00210 
00211             // Display RTL representation if asked
00212             if (progOptions.rtl) pRtl->print();
00213     
00214             ADDRESS uDest;
00215 
00216             switch (pRtl->getKind())
00217             {
00218 
00219             case JUMP_HRTL:
00220             {
00221                 uDest = rtl_jump->getFixedDest();
00222     
00223                 // Handle one way jumps and computed jumps separately
00224                 if (uDest != NO_ADDRESS) {
00225                     BB_rtls->push_back(pRtl);
00226                     sequentialDecode = false;
00227 
00228                     pBB = pCfg->newBB(BB_rtls,ONEWAY,1);
00229 
00230                     // Exit the switch now and stop decoding sequentially if the
00231                     // basic block already existed
00232                     if (pBB == 0) {
00233                         sequentialDecode = false;
00234                         BB_rtls = NULL;
00235                         break;
00236                     }
00237 
00238                     // Add the out edge if it is to a destination within the
00239                     // procedure
00240                     if (uDest < uUpper) {
00241                         visit(pCfg, uDest, targets, pBB);
00242                         pCfg->addOutEdge(pBB, uDest, true);
00243                     }
00244                     else {
00245                         ostrstream ost;
00246                         ost << "Error: Instruction at " << hex << uAddr;
00247                         ost << " branches beyond end of section, to ";
00248                         ost << uDest;
00249                         error(str(ost)); 
00250                     }
00251                 }
00252                 break;
00253             }
00254 
00255             case NWAYJUMP_HRTL:
00256             {
00257                 BB_rtls->push_back(pRtl);
00258                 // We create the BB as a COMPJUMP type, then change
00259                 // to an NWAY if it turns out to be a switch stmt
00260                 pBB = pCfg->newBB(BB_rtls, COMPJUMP, 0);
00261                 if (isSwitch(pBB, rtl_jump->getDest(), pProc, pBF)) {
00262                     processSwitch(pBB, delta, pCfg, targets, pBF);
00263                 }
00264                 else { // Computed jump
00265                     // Not a switch statement
00266                     ostrstream ost;
00267                     string sKind("JUMP");
00268                     if (type == I_COMPCALL) sKind = "CALL";
00269                     ost << "COMPUTED " << sKind << " at "
00270                     << hex << uAddr << endl;
00271                     warning(str(ost));
00272                     BB_rtls = NULL;    // New HRTLList for next BB
00273                 }
00274                 sequentialDecode = false;
00275                 break;     
00276             }
00277 
00278 
00279 
00280             case JCOND_HRTL:
00281             {
00282                 uDest = rtl_jump->getFixedDest();
00283                 BB_rtls->push_back(pRtl);
00284                 pBB = pCfg->newBB(BB_rtls, TWOWAY, 2);
00285 
00286                 // Stop decoding sequentially if the basic block already existed
00287                 // otherwise complete the basic block
00288                 if (pBB == 0)
00289                     sequentialDecode = false;
00290                 else {
00291 
00292                     // Add the out edge if it is to a destination within the
00293                     // procedure
00294                     if (uDest < uUpper) {
00295                         visit(pCfg, uDest, targets, pBB);
00296                         pCfg->addOutEdge(pBB, uDest, true);
00297                     }
00298                     else {
00299                         ostrstream ost;
00300                         ost << "Error: Instruction at " << hex << uAddr;
00301                         ost << " branches beyond end of section, to ";
00302                         ost << uDest;
00303                         error(str(ost)); 
00304                     }
00305 
00306                     // Add the fall-through outedge
00307                     pCfg->addOutEdge(pBB, uAddr + inst.numBytes); 
00308                 }
00309 
00310                 // Create the list of RTLs for the next basic block and continue
00311                 // with the next instruction.
00312                 BB_rtls = NULL;
00313                 break;
00314             }
00315 
00316             case CALL_HRTL:
00317             {
00318                 HLCall* call = static_cast<HLCall*>(pRtl);
00319 
00320                 // Treat computed and static calls seperately
00321                 if (call->isComputed()) {
00322                     BB_rtls->push_back(pRtl);
00323                     pBB = pCfg->newBB(BB_rtls, COMPCALL, 1);
00324 
00325                     // Stop decoding sequentially if the basic block already
00326                     // existed otherwise complete the basic block
00327                     if (pBB == 0)
00328                         sequentialDecode = false;
00329                     else
00330                         pCfg->addOutEdge(pBB, uAddr + inst.numBytes);
00331 
00332                 }
00333                 else {      // Static call
00334                 
00335                     BB_rtls->push_back(pRtl);
00336 
00337                     // Find the address of the callee.
00338                     ADDRESS uNewAddr = call->getFixedDest();
00339 
00340                     // Add this non computed call site to the set of call
00341                     // sites which need to be analysed later.
00342                     pCfg->addCall(call);
00343 
00344                     // Record the called address as the start of a new
00345                     // procedure if it didn't already exist.
00346                     if ((uNewAddr != NO_ADDRESS) &&
00347                       prog.findProc(uNewAddr) == NULL) {
00348                         prog.visitProc(uNewAddr);
00349                         if (progOptions.trace)
00350                             cout << "p" << hex << uNewAddr << "\t" << flush;
00351                     }
00352 
00353                     // Check if this is the _exit function. May prevent us from
00354                     // attempting to decode invalid instructions.
00355                     char* name = prog.pBF->SymbolByAddress(uNewAddr);
00356                     if (name && strcmp(name, "_exit") == 0) {
00357                         // Create the new basic block
00358                         pBB = pCfg->newBB(BB_rtls, CALL, 0);
00359 
00360                         // Stop decoding sequentially
00361                         sequentialDecode = false;
00362                     }
00363                     else {
00364                         // Create the new basic block
00365                         pBB = pCfg->newBB(BB_rtls, CALL, 1);
00366 
00367                         if (call->isReturnAfterCall()) {
00368                             // Constuct the RTLs for the new basic block
00369                             list<HRTL*>* rtls = new list<HRTL*>();
00370                             // The only RTL in the basic block is a high level
00371                             // return that doesn't have any RTs.
00372                             rtls->push_back(new HLReturn(0, NULL));
00373         
00374                             BasicBlock* returnBB = pCfg->newBB(rtls, RET, 0);
00375                             // Add out edge from call to return
00376                             pCfg->addOutEdge(pBB, returnBB);
00377                             // Put a label on the return BB (since it's an
00378                             // orphan); a jump will be reqd
00379                             pCfg->setLabel(returnBB);
00380                             pBB->setJumpReqd();
00381                             // Give the enclosing proc a dummy callee epilogue
00382                             pProc->setEpilogue(new CalleeEpilogue("__dummy",
00383                                 list<string>()));
00384                             // Mike: do we need to set return locations?
00385                             // This ends the function
00386                             sequentialDecode = false;
00387                         }
00388                         else
00389                         {
00390                             // Add the fall through edge if the block didn't
00391                             // already exist
00392                             if (pBB != NULL)
00393                                 pCfg->addOutEdge(pBB, uAddr + inst.numBytes);
00394                         }
00395                     }
00396                 }
00397 
00398                 // Create the list of RTLs for the next basic block and continue
00399                 // with the next instruction.
00400                 BB_rtls = NULL;
00401                 break;  
00402             }
00403 
00404             case RET_HRTL:
00405                 // Stop decoding sequentially
00406                 sequentialDecode = false;
00407 
00408                 // Add the RTL to the list
00409                 BB_rtls->push_back(pRtl);
00410                 // Create the basic block
00411                 pBB = pCfg->newBB(BB_rtls, RET, 0);
00412 
00413                 // Create the list of RTLs for the next basic block and continue
00414                 // with the next instruction.
00415                 BB_rtls = NULL;    // New HRTLList for next BB
00416                 break;
00417 
00418             case SCOND_HRTL:
00419                 // This is just an ordinary instruction; no control transfer
00420                 // Fall through
00421             case LOW_LEVEL_HRTL:
00422                 // We must emit empty RTLs for NOPs, because they could be the
00423                 // destinations of jumps (and splitBB won't work)
00424                 // Just emit the current instr to the current BB
00425                 BB_rtls->push_back(pRtl);
00426                 break;
00427         
00428             } // switch (pRtl->getKind())
00429 
00430             uAddr += inst.numBytes;
00431             // Update the RTL's number of bytes for coverage analysis (only)
00432             inst.rtl->updateNumBytes(inst.numBytes);
00433 
00434             // If sequentially decoding, check if the next address happens to
00435             // be the start of an existing BB. If so, finish off the current BB
00436             // (if any RTLs) as a fallthrough, and  no need to decode again
00437             // (unless it's an incomplete BB, then we do decode it).
00438             // In fact, mustn't decode twice, because it will muck up the
00439             // coverage, but also will cause subtle problems like add a call
00440             // to the list of calls to be processed, then delete the call RTL
00441             // (e.g. Pentium 134.perl benchmark)
00442             if (sequentialDecode && pCfg->existsBB(uAddr)) {
00443                 // Create the fallthrough BB, if there are any RTLs at all
00444                 if (BB_rtls) {
00445                     PBB pBB = pCfg->newBB(BB_rtls, FALL, 1);
00446                     // Add an out edge to this address
00447                     if (pBB) {
00448                         pCfg->addOutEdge(pBB, uAddr);
00449                         BB_rtls = NULL;         // Need new list of RTLs
00450                     }
00451                 }
00452                 // Pick a new address to decode from, if the BB is complete
00453                 if (!pCfg->isIncomplete(uAddr))
00454                     sequentialDecode = false;
00455             }
00456 
00457         }   // while sequentialDecode
00458 
00459         // Add this range to the coverage
00460         pProc->addRange(start, uAddr);
00461 
00462         // Must set sequentialDecode back to true
00463         sequentialDecode = true;
00464 
00465     }   // while nextAddress()
00466 
00467     // This pass is to remove up to 3 nops between ranges.
00468     // These will be assumed to be padding for alignments of BBs
00469     // Possibly removes a lot of ranges that could otherwise be combined
00470     ADDRESS a1, a2;
00471     COV_CIT ii;
00472     Coverage temp;
00473     if (pProc->getFirstGap(a1, a2, ii)) {
00474         do {
00475             int gap = a2 - a1;
00476             if (gap < 8) {
00477                 bool allNops = true;
00478                 for (int i=0; i < gap; i+= 2) {
00479                     // Beware endianness! getWord will work properly
00480                     if (getWord(a1+i+delta) != 0x4e71) {
00481                         allNops = false;
00482                         break;
00483                     }
00484                 }
00485                 if (allNops)
00486                     // Remove this gap, by adding a range equal to the gap
00487                     // Note: it's not safe to add the range now, so we put
00488                     // the range into a temp Coverage object to be added later
00489                     temp.addRange(a1, a2);
00490             }
00491         } while (pProc->getNextGap(a1, a2, ii));
00492     }
00493     // Now add the ranges in temp
00494     pProc->addRanges(temp);
00495 
00496 }
00497 #endif
00498 
00499 

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