st20/decoder.m

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2005 Mike Van Emmerik
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:   This file contains the high level decoding functionality, for matching ST-20 instructions.
00013  *============================================================================*/ 
00014 /*
00015  * $Revision: 1.3 $ // 1.2.2.2
00016  *
00017  * 10 Mar 05 - Mike: Created.
00018 */
00019 
00020 #include <assert.h>
00021 
00022 #include "rtl.h"
00023 #include "decoder.h"
00024 #include "st20decoder.h"
00025 #include "exp.h"
00026 #include "proc.h"
00027 #include "boomerang.h"
00028 #include "statement.h"
00029 
00030 /**********************************
00031  * ST20Decoder methods.
00032  **********************************/   
00033 
00034 /*==============================================================================
00035  * FUNCTION:       unused
00036  * OVERVIEW:       A dummy function to suppress "unused local variable" messages
00037  * PARAMETERS:     x: integer variable to be "used"
00038  * RETURNS:        Nothing
00039  *============================================================================*/
00040 void ST20Decoder::unused(int x)
00041 {}
00042 
00043 /*==============================================================================
00044  * FUNCTION:       ST20Decoder::decodeInstruction
00045  * OVERVIEW:       Decodes a machine instruction and returns an RTL instance. In all cases a single instruction is decoded.
00046  * PARAMETERS:     pc - the native address of the pc
00047  *                 delta - the difference between the above address and the host address of the pc (i.e. the address that
00048                     the pc is at in the loaded object file)
00049  *                 RTLDict - the dictionary of RTL templates used to instantiate the RTL for the instruction being decoded
00050  *                 proc - the enclosing procedure
00051  * RETURNS:        a DecodeResult structure containing all the information gathered during decoding
00052  *============================================================================*/
00053 static  DecodeResult result;
00054 DecodeResult& ST20Decoder::decodeInstruction (ADDRESS pc, int delta) {
00055     result.reset();                         // Clear the result structure (numBytes = 0 etc)
00056     ADDRESS hostPC = pc + delta;
00057     std::list<Statement*>* stmts = NULL;    // The actual list of instantiated Statements
00058     unsigned total = 0;                     // Total value from all prefixes
00059 
00060     while (1) {
00061         match hostPC+result.numBytes++ to
00062 
00063         | pfix(oper) =>
00064             total = (total + oper) << 4;
00065             continue;
00066                     
00067         | nfix(oper) =>
00068             total = (total + ~oper) << 4;
00069             continue;
00070 
00071         | primary(oper)  =>
00072             stmts = instantiate(pc, name, new Const(total+oper));
00073 
00074         | j (oper) =>
00075             unconditionalJump("j", result.numBytes, hostPC+result.numBytes+total+oper, delta, pc, stmts, result);
00076 
00077         | call (oper) =>
00078             total += oper;
00079             stmts = instantiate(pc, "call" , new Const(total));
00080             CallStatement* newCall = new CallStatement;
00081             newCall->setIsComputed(false);
00082             newCall->setDest(pc+result.numBytes+total);
00083             result.rtl = new RTL(pc, stmts);
00084             result.rtl->appendStmt(newCall);
00085 
00086         | cj (oper) =>
00087             BranchStatement* br = new BranchStatement();
00088             //br->setCondType(BRANCH_JE);
00089             br->setDest(pc+result.numBytes+total+oper);
00090             //br->setCondExpr(dis_Reg(0));
00091             br->setCondExpr(new Binary(opEquals,dis_Reg(0),new Const(0)));
00092             result.rtl = new RTL(pc, stmts);
00093             result.rtl->appendStmt(br);
00094 
00095         | opr (oper) =>
00096             total |= oper;
00097             char* name = NULL;
00098             bool isRet = false;
00099             if (total >= 0) {
00100                 switch (total) {
00101                     case 0x00:  name = "rev";   break;
00102                     case 0x01: name = "lb";     break;
00103                     case 0x02: name = "bsub";   break;
00104                     case 0x03: name = "endp";   break;
00105                     case 0x04: name = "diff";   break;
00106                     case 0x05: name = "add";    break;
00107                     case 0x06: name = "gcall";  break;
00108                     case 0x07: name = "in";     break;
00109                     case 0x08: name = "prod";   break;
00110                     case 0x09: name = "gt";     break;
00111                     case 0x0A: name = "wsub";   break;
00112                     case 0x0B: name = "out";    break;
00113                     case 0x0C: name = "sub";    break;
00114                     case 0x0D: name = "startp"; break;
00115                     case 0x0E: name = "outbyte";break;
00116                     case 0x0F: name = "outword";break;
00117                     case 0x10: name = "seterr"; break;
00118                     case 0x12: name = "resetch";break;
00119                     case 0x13: name = "csub0";  break;
00120                     case 0x15: name = "stopp";  break;
00121                     case 0x16: name = "ladd";   break;
00122                     case 0x17: name = "stlb";   break;
00123                     case 0x18: name = "sthf";   break;
00124                     case 0x19: name = "norm";   break;
00125                     case 0x1A: name = "ldiv";   break;
00126                     case 0x1B: name = "ldpi";   break;
00127                     case 0x1C: name = "stlf";   break;
00128                     case 0x1D: name = "xdble";  break;
00129                     case 0x1E: name = "ldpri";  break;
00130                     case 0x1F: name = "rem";    break;
00131                     case 0x20: name = "ret"; isRet = true; break;
00132                     case 0x21: name = "lend";   break;
00133                     case 0x22: name = "ldtimer";break;
00134                     case 0x29: name = "testerr";break;
00135                     case 0x2A: name = "testpranal";break;
00136                     case 0x2B: name = "tin";    break;
00137                     case 0x2C: name = "div";    break;
00138                     case 0x2E: name = "dist";   break;
00139                     case 0x2F: name = "disc";   break;
00140                     case 0x30: name = "diss";   break;
00141                     case 0x31: name = "lmul";   break;
00142                     case 0x32: name = "not";    break;
00143                     case 0x33: name = "xor";    break;
00144                     case 0x34: name = "bcnt";   break;
00145                     case 0x35: name = "lshr";   break;
00146                     case 0x36: name = "lshl";   break;
00147                     case 0x37: name = "lsum";   break;
00148                     case 0x38: name = "lsub";   break;
00149                     case 0x39: name = "runp";   break;
00150                     case 0x3A: name = "xword";  break;
00151                     case 0x3B: name = "sb";     break;
00152                     case 0x3C: name = "gajw";   break;
00153                     case 0x3D: name = "savel";  break;
00154                     case 0x3E: name = "saveh";  break;
00155                     case 0x3F: name = "wcnt";   break;
00156                     case 0x40: name = "shr";    break;
00157                     case 0x41: name = "shl";    break;
00158                     case 0x42: name = "mint";   break;
00159                     case 0x43: name = "alt";    break;
00160                     case 0x44: name = "altwt";  break;
00161                     case 0x45: name = "altend"; break;
00162                     case 0x46: name = "and";    break;
00163                     case 0x47: name = "enbt";   break;
00164                     case 0x48: name = "enbc";   break;
00165                     case 0x49: name = "enbs";   break;
00166                     case 0x4A: name = "move";   break;
00167                     case 0x4B: name = "or";     break;
00168                     case 0x4C: name = "csngl";  break;
00169                     case 0x4D: name = "ccnt1";  break;
00170                     case 0x4E: name = "talt";   break;
00171                     case 0x4F: name = "ldiff";  break;
00172                     case 0x50: name = "sthb";   break;
00173                     case 0x51: name = "taltwt"; break;
00174                     case 0x52: name = "sum";    break;
00175                     case 0x53: name = "mul";    break;
00176                     case 0x54: name = "sttimer";break;
00177                     case 0x55: name = "stoperr";break;
00178                     case 0x56: name = "cword";  break;
00179                     case 0x57: name = "clrhalterr"; break;
00180                     case 0x58: name = "sethalterr"; break;
00181                     case 0x59: name = "testhalterr";break;
00182                     case 0x5A: name = "dup";        break;
00183                     case 0x5B: name = "move2dinit"; break;
00184                     case 0x5C: name = "move2dall";  break;
00185                     case 0x5D: name = "move2dnonzero";break;
00186                     case 0x5E: name = "move2dzero"; break;
00187                     case 0x5F: name = "gtu";        break;
00188                     case 0x63: name = "unpacksn";   break;
00189                     case 0x64: name = "slmul";      break;
00190                     case 0x65: name = "sulmul";     break;
00191                     case 0x68: name = "satadd";     break;
00192                     case 0x69: name = "satsub";     break;
00193                     case 0x6A: name = "satmul";     break;
00194                     case 0x6C: name = "postnormsn"; break;
00195                     case 0x6D: name = "roundsn";    break;
00196                     case 0x6E: name = "ldtraph";    break;
00197                     case 0x6F: name = "sttraph";    break;
00198                     case 0x71: name = "ldinf";      break;
00199                     case 0x72: name = "fmul";       break;
00200                     case 0x73: name = "cflerr";     break;
00201                     case 0x74: name = "crcword";    break;
00202                     case 0x75: name = "crcbyte";    break;
00203                     case 0x76: name = "bitcnt";     break;
00204                     case 0x77: name = "bitrevword"; break;
00205                     case 0x78: name = "bitrevnbits";break;
00206                     case 0x79: name = "pop";        break;
00207                     case 0x7E: name = "ldmemstartval";break;
00208                     case 0x81: name = "wsubdb";     break;
00209                     case 0x9C: name = "fptesterr";  break;
00210                     case 0xB0: name = "settimeslice";break;
00211                     case 0xB8: name = "xbword";     break;
00212                     case 0xB9: name = "lbx";        break;
00213                     case 0xBA: name = "cb";         break;
00214                     case 0xBB: name = "cbu";        break;
00215                     case 0xC1: name = "ssub";       break;
00216                     case 0xC4: name = "intdis";     break;
00217                     case 0xC5: name = "intenb";     break;
00218                     case 0xC6: name = "ldtrapped";  break;
00219                     case 0xC7: name = "cir";        break;
00220                     case 0xC8: name = "ss";         break;
00221                     case 0xCA: name = "ls";         break;
00222                     case 0xCB: name = "sttrapped";  break;
00223                     case 0xCC: name = "ciru";       break;
00224                     case 0xCD: name = "gintdis";    break;
00225                     case 0xCE: name = "gintenb";    break;
00226                     case 0xF0: name = "devlb";      break;
00227                     case 0xF1: name = "devsb";      break;
00228                     case 0xF2: name = "devls";      break;
00229                     case 0xF3: name = "devss";      break;
00230                     case 0xF4: name = "devlw";      break;
00231                     case 0xF5: name = "devsw";      break;
00232                     case 0xF6: name = "null";       break;
00233                     case 0xF7: name = "null";       break;
00234                     case 0xF8: name = "xsword";     break;
00235                     case 0xF9: name = "lsx";        break;
00236                     case 0xFA: name = "cs";         break;
00237                     case 0xFB: name = "csu";        break;
00238                     case 0x17C:name = "lddevid";    break;
00239                 }
00240             } else {
00241                 // Total is negative, as a result of nfixes
00242                 total = (~total & ~0xF) | (total & 0xF);        // 1's complement the upper nibbles
00243                 switch (total) {
00244                     case 0x00: name = "swapqueue";  break;
00245                     case 0x01: name = "swaptimer";  break;
00246                     case 0x02: name = "insertqueue";break;
00247                     case 0x03: name = "timeslice";  break;
00248                     case 0x04: name = "signal";     break;
00249                     case 0x05: name = "wait";       break;
00250                     case 0x06: name = "trapdis";    break;
00251                     case 0x07: name = "trapenb";    break;
00252                     case 0x0B: name = "tret"; isRet = true; break;
00253                     case 0x0C: name = "ldshadow";   break;
00254                     case 0x0D: name = "stshadow";   break;
00255                     case 0x1F: name = "iret"; isRet = true; break;
00256                     case 0x24: name = "devmove";    break;
00257                     case 0x2E: name = "restart";    break;
00258                     case 0x2F: name = "causeerror"; break;
00259                     case 0x30: name = "nop";        break;
00260                     case 0x4C: name = "stclock";    break;
00261                     case 0x4D: name = "ldclock";    break;
00262                     case 0x4E: name = "clockdis";   break;
00263                     case 0x4F: name = "clockenb";   break;
00264                     case 0x8C: name = "ldprodid";   break;
00265                     case 0x8D: name = "reboot";     break;
00266                 }
00267             }
00268             if (name) {
00269                 stmts = instantiate(pc, name);
00270                 if (isRet) {
00271                     result.rtl = new RTL(pc, stmts);
00272                     result.rtl->appendStmt(new ReturnStatement);
00273                 }
00274             } else {
00275                 result.valid = false;       // Invalid instruction
00276                 result.rtl = NULL;
00277                 result.numBytes = 0;
00278                 return result;
00279             }
00280 
00281 
00282         endmatch
00283         break;
00284     }
00285 
00286     if (result.rtl == 0)
00287         result.rtl = new RTL(pc, stmts);
00288     return result;
00289 }
00290 
00291 /*==============================================================================
00292  * These are machine specific functions used to decode instruction operands into Exp*s.
00293  *============================================================================*/
00294 
00295 /**********************************
00296  * These are the fetch routines.
00297  **********************************/   
00298 
00299 /*==============================================================================
00300  * FUNCTION:        getWord
00301  * OVERVIEW:        Returns the word starting at the given address.
00302  * PARAMETERS:      lc - address at which to decode the double
00303  * RETURNS:         the decoded double
00304  *============================================================================*/
00305 Byte ST20Decoder::getByte (unsigned lc)
00306 /* getByte - returns next byte from image pointed to by lc.  */
00307 {
00308     return *(Byte *)lc;
00309 }
00310 
00311 /*==============================================================================
00312  * FUNCTION:        getWord
00313  * OVERVIEW:        Returns the word starting at the given address.
00314  * PARAMETERS:      lc - address at which to decode the double
00315  * RETURNS:         the decoded double
00316  *============================================================================*/
00317 SWord ST20Decoder::getWord (unsigned lc)
00318 /* get2Bytes - returns next 2-Byte from image pointed to by lc.  */
00319 {
00320     return (SWord)(*(Byte *)lc + (*(Byte *)(lc+1) << 8));
00321 }
00322 
00323 /*==============================================================================
00324  * FUNCTION:        getDword
00325  * OVERVIEW:        Returns the double starting at the given address.
00326  * PARAMETERS:      lc - address at which to decode the double
00327  * RETURNS:         the decoded double
00328  *============================================================================*/
00329 DWord ST20Decoder::getDword (unsigned lc)
00330 /* get4Bytes - returns the next 4-Byte word from image pointed to by lc. */
00331 {
00332     return (DWord)(*(Byte *)lc + (*(Byte *)(lc+1) << 8) +
00333         (*(Byte *)(lc+2) << 16) + (*(Byte *)(lc+3) << 24));
00334 }
00335 
00336 
00337 /*==============================================================================
00338  * FUNCTION:       ST20Decoder::ST20Decoder
00339  * OVERVIEW:       Constructor. The code won't work without this (not sure why the default constructor won't do...)
00340  * PARAMETERS:     None
00341  * RETURNS:        N/A
00342  *============================================================================*/
00343 ST20Decoder::ST20Decoder() : NJMCDecoder(prog)
00344 {
00345     std::string file = Boomerang::get()->getProgPath() + "frontend/machine/st20/st20.ssl";
00346     RTLDict.readSSLFile(file.c_str());
00347 }
00348 
00349 // For now...
00350 int ST20Decoder::decodeAssemblyInstruction(unsigned, int)
00351 { return 0; }
00352 

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