ucdisasm.cc

Go to the documentation of this file.
00001 /*
00002  *  ucdisasm.cc - Disassembled usecode trace
00003  *
00004  *  Copyright (C) 1999  Jeffrey S. Freedman
00005  *  Copyright (C) 2000-2002  The Exult Team
00006  *
00007  *  This program is free software; you can redistribute it and/or modify
00008  *  it under the terms of the GNU General Public License as published by
00009  *  the Free Software Foundation; either version 2 of the License, or
00010  *  (at your option) any later version.
00011  *
00012  *  This program is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *  GNU General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU General Public License
00018  *  along with this program; if not, write to the Free Software
00019  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020  */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #  include <config.h>
00024 #endif
00025 
00026 
00027 #include <cstring>
00028 #include <cstdio>
00029 #include <iostream>
00030 
00031 #ifndef UNDER_CE
00032 using std::strlen;
00033 using std::cout;
00034 #endif
00035 
00036 #include "ucinternal.h"
00037 #include "uctools.h"
00038 #include "utils.h"
00039 #include "useval.h"
00040 #include "game.h"
00041 #include "stackframe.h"
00042 
00043 int Usecode_internal::get_opcode_length(int opcode)
00044 {
00045   if (opcode >=0 &&
00046     opcode < (sizeof(opcode_table)/sizeof(opcode_table[0]))) {
00047 
00048       return opcode_table[opcode].nbytes + 1;
00049   } else {
00050     return 0;
00051   }
00052 }
00053 
00054 void Usecode_internal::uc_trace_disasm(Stack_frame* frame)
00055 {
00056   uc_trace_disasm(frame->locals,
00057           frame->num_args + frame->num_vars,
00058           frame->data,
00059           frame->externs,
00060           frame->code,
00061           frame->ip);
00062 }
00063 
00064 void Usecode_internal::uc_trace_disasm(Usecode_value* locals, int num_locals,
00065              uint8* data, uint8* externals, uint8* code,
00066              uint8* ip)
00067 {
00068   int func_ip = (int)(ip - code);
00069   int opcode = *ip++;
00070   uint8* param_ip = ip;
00071   _opcode_desc* pdesc;
00072 
00073   if (opcode >=0 && opcode < (sizeof(opcode_table)/sizeof(opcode_table[0])))
00074     pdesc = &(opcode_table[opcode]);
00075   signed short immed;
00076   unsigned short varref;
00077   unsigned short func;
00078   int immed32;
00079   int offset;
00080 
00081   std::printf("      %04X: ", func_ip);
00082 
00083   if (pdesc && pdesc->mnemonic) {
00084     std::printf("%s", pdesc->mnemonic);
00085     if (strlen(pdesc->mnemonic) < 4)
00086       std::printf("\t");
00087   } else {
00088     std::printf("<unknown>");
00089   }
00090 
00091   if (pdesc && pdesc->nbytes > 0) {
00092     switch( pdesc->type )
00093       {
00094       case BYTE:
00095         std::printf("\t%02x", *ip++);
00096         break;
00097       case IMMED:
00098         // Print immediate operand
00099         immed = Read2(ip);
00100         std::printf("\t%04hXH\t\t; %d", immed, immed);
00101         break;
00102       case IMMED32:
00103         immed32 = (sint32)Read4(ip);
00104         std::printf("\t%04hXH\t\t; %d", immed32, immed32);
00105         break;
00106       case DATA_STRING:
00107       case DATA_STRING32:
00108         {
00109           char* pstr;
00110           int len;
00111           // Print data string operand
00112           if (pdesc->type == DATA_STRING)
00113             offset = Read2(ip);
00114           else
00115             offset = (sint32)Read4(ip);
00116 
00117           pstr = (char*)data + offset;
00118           len = strlen(pstr);
00119           if( len > 20 )
00120             len = 20 - 3;
00121           std::printf("\tL%04X\t\t; ", offset);
00122           for(int i = 0; i < len; i++ )
00123             std::printf("%c", pstr[i]);
00124           if( len < strlen(pstr) )
00125             // String truncated
00126             std::printf("...");
00127         }
00128         break;
00129       case RELATIVE_JUMP:
00130         // Print jump desination
00131         offset = Read2(ip);
00132         std::printf("\t%04X",
00133               (offset + func_ip+1+pdesc->nbytes)&0xFFFF);
00134         break;
00135       case RELATIVE_JUMP32:
00136         offset = (sint32)Read4(ip);
00137         std::printf("\t%04X", offset + func_ip+1+pdesc->nbytes);
00138         break;        
00139       case SLOOP:
00140         if (pdesc->nbytes == 11)
00141           ip++;
00142         Read2(ip);
00143         Read2(ip);
00144         Read2(ip);
00145         varref = Read2(ip);
00146         offset = Read2(ip);
00147         std::printf("\t[%04X], %04X\t= ", varref, 
00148              (offset +func_ip+1+pdesc->nbytes)&0xFFFF);
00149         locals[varref].print(cout, true); // print value (short format)
00150         break;
00151       case SLOOP32:
00152         if (pdesc->nbytes == 13)
00153           ip++;
00154         Read2(ip);
00155         Read2(ip);
00156         Read2(ip);
00157         varref = Read2(ip);
00158         offset = (sint32)Read4(ip);
00159         std::printf("\t[%04X], %04X\t= ", varref, 
00160              offset +func_ip+1+pdesc->nbytes);
00161         locals[varref].print(cout, true); // print value (short format)
00162         break;
00163       case IMMED_AND_RELATIVE_JUMP:
00164         immed = Read2(ip);
00165         offset = Read2(ip);
00166         std::printf("\t%04hXH, %04X", immed, 
00167              (offset + func_ip+1+pdesc->nbytes)&0xFFFF);
00168         break;
00169       case IMMED_RELJUMP32:
00170         immed = Read2(ip);
00171         offset = (sint32)Read4(ip);
00172         std::printf("\t%04hXH, %04X", immed, 
00173              offset + func_ip+1+pdesc->nbytes);
00174         break;        
00175       case CALL:
00176         {
00177           func = Read2(ip);
00178           immed = *ip++;
00179           const char **func_table = bg_intrinsic_table;
00180           if (Game::get_game_type() == SERPENT_ISLE)
00181             func_table = si_intrinsic_table;
00182           std::printf("\t_%s@%d\t; %04X", func_table[func], immed, func);
00183         }
00184         break;
00185       case EXTCALL:
00186         {
00187           // Print extern call
00188           offset = Read2(ip);
00189           std::printf("\t[%04X]\t\t; %04XH", offset,
00190                externals[2*offset] + 256*externals[2*offset + 1]);
00191         }
00192         break;
00193       case VARREF:
00194         // Print variable reference
00195         varref = Read2(ip);
00196         std::printf("\t[%04X]\t\t= ", varref);
00197         locals[varref].print(cout, true); // print value (short)
00198         break;
00199       case FLGREF:
00200         // Print global flag reference
00201         offset = Read2(ip);
00202         std::printf("\tflag:[%04X]\t= ", offset);
00203         if (gflags[offset])
00204           std::printf("set");
00205         else
00206           std::printf("unset");
00207         break;
00208       default:
00209         // Unknown type
00210         break;
00211       }
00212   }
00213   ip = param_ip; //restore IP back to opcode parameters
00214 
00215   // special cases:
00216   switch (opcode) {
00217   case 0x05:    // JNE.
00218     {
00219       Usecode_value val;
00220       if (sp <= stack)
00221         val = Usecode_value(0);
00222       else
00223         val = *(sp - 1); 
00224 
00225       if (val.is_false())
00226         std::printf("\t\t(jump taken)");
00227       else
00228         std::printf("\t\t(jump not taken)");
00229       break;
00230     }
00231 
00232     /*
00233       maybe predict this?
00234   case 0x07:    // CMPS.
00235     {
00236       int cnt = Read2(ip);  // # strings.
00237       offset = (short) Read2(ip);
00238       bool matched = false;
00239       
00240       // only try to match if we haven't found an answer yet
00241       while (!matched && !found_answer && cnt-- > 0) {
00242         Usecode_value s = pop();
00243         const char *str = s.get_str_value();
00244         if (str && strcmp(str, user_choice) == 0) {
00245           matched = true;
00246           found_answer = true;
00247         }
00248       }
00249       while (cnt-- > 0) // Pop rest of stack.
00250         pop();
00251       if (!matched)   // Jump if no match.
00252         ip += offset;
00253     }
00254     break;
00255     */
00256   }
00257 
00258   std::printf("\n");
00259 }

Generated on Mon Jul 9 14:42:52 2007 for ExultEngine by  doxygen 1.5.1