Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

x86dasm.cpp

Go to the documentation of this file.
00001 /*
00002 PeRdr - PE file disassembler
00003 Copyright (C) 1999-2003 Frediano Ziglio
00004 -----
00005 
00006 This program is free software; you can redistribute it and/or modify
00007 it under the terms of the GNU General Public License as published by
00008 the Free Software Foundation; either version 2 of the License, or
00009 (at your option) any later version.
00010 
00011 This program is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 GNU General Public License for more details.
00015 
00016 You should have received a copy of the GNU General Public License
00017 along with this program; if not, write to the Free Software
00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 -----
00020 
00021 INFORMATION
00022   www: https://freddy77.tripod.com/perdr/
00023   e-mail: freddy77@angelfire.com
00024 */
00025 #include "global.h"
00026 #ifdef HAVE_HDRSTOP
00027 #pragma hdrstop
00028 #endif
00029 
00030 #include <cstring>
00031 #include "x86dasm.h"
00032 #include "x86istr.h"
00033 #include "x86table.h"
00034 #include "utils/compilecheck.hpp"
00035 
00036 // some bit utils (derived from bdf)
00037 #define U8TOI(num)  (((num)^0x80)-0x80)
00038 #define U16TOI(num) (((num)^0x8000)-0x8000)
00039 
00040 #define IsRelocation(addr) \
00041   (reloc.GetRelocation(addr)!=NULL)
00042 
00043 int     segment_mode  = 386;
00044 int     segment_bytes = 4;    // 2 for 286 mode
00045 
00046 // enable PentiumIII instructions
00047 bool p3enable = true;
00048 // enable 3DNow instructions
00049 bool k6_3DNow_enable = true;
00050 // enable 3DNow enhanched instructions
00051 bool k6_en_3DNow_enable = true;
00052 // enable Athlon instructions
00053 bool athlon_enable = true;
00054 
00055 #ifdef DEBUG
00056   static int mmx = 0;
00057   static int xmm = 0; // SIMD Floating-point
00058 #endif
00059 
00060 #define SUCC(n,m) (REG(n)+1) == REG(m)
00061 COMPILE_CHECK(iRegCheck,
00062   SUCC(al,cl)     && SUCC(cl,dl)     && SUCC(dl,bl)     && SUCC(bl,ah) &&
00063   SUCC(ah,ch)     && SUCC(ch,dh)     && SUCC(dh,bh)     && SUCC(bh,ax) &&
00064   SUCC(ax,cx)     && SUCC(cx,dx)     && SUCC(dx,bx)     && SUCC(bx,sp) &&
00065   SUCC(sp,bp)     && SUCC(bp,si)     && SUCC(si,di)     && SUCC(di,eax) &&
00066   SUCC(eax,ecx)   && SUCC(ecx,edx)   && SUCC(edx,ebx)   && SUCC(ebx,esp) &&
00067   SUCC(esp,ebp)   && SUCC(ebp,esi)   && SUCC(esi,edi)   && SUCC(edi,mm0) &&
00068   SUCC(mm0,mm1)   && SUCC(mm1,mm2)   && SUCC(mm2,mm3)   && SUCC(mm3,mm4) &&
00069   SUCC(mm4,mm5)   && SUCC(mm5,mm6)   && SUCC(mm6,mm7)   && SUCC(mm7,xmm0) &&
00070   SUCC(xmm0,xmm1) && SUCC(xmm1,xmm2) && SUCC(xmm2,xmm3) && SUCC(xmm3,xmm4) &&
00071   SUCC(xmm4,xmm5) && SUCC(xmm5,xmm6) && SUCC(xmm6,xmm7)
00072 );
00073 COMPILE_CHECK(segRegCheck,
00074   SUCC(es,cs) && SUCC(cs,ss) && SUCC(ss,ds) &&
00075   SUCC(ds,fs) && SUCC(fs,gs)
00076 );
00077 COMPILE_CHECK(fpRegCheck,
00078   SUCC(st0,st1)   && SUCC(st1,st2)   && SUCC(st2,st3)   && SUCC(st3,st4) &&
00079   SUCC(st4,st5)   && SUCC(st5,st6)   && SUCC(st6,st7)
00080 );
00081 COMPILE_CHECK(controlRegCheck,
00082   SUCC(cr0,cr1)   && SUCC(cr1,cr2)   && SUCC(cr2,cr3)   && SUCC(cr3,cr4) &&
00083   SUCC(cr4,cr5)   && SUCC(cr5,cr6)   && SUCC(cr6,cr7)   && SUCC(cr7,dr0) &&
00084   SUCC(dr0,dr1)   && SUCC(dr1,dr2)   && SUCC(dr2,dr3)   && SUCC(dr3,dr4) &&
00085   SUCC(dr4,dr5)   && SUCC(dr5,dr6)   && SUCC(dr6,dr7)   && SUCC(dr7,tr0) &&
00086   SUCC(tr0,tr1)   && SUCC(tr1,tr2)   && SUCC(tr2,tr3)   && SUCC(tr3,tr4) &&
00087   SUCC(tr4,tr5)   && SUCC(tr5,tr6)   && SUCC(tr6,tr7)
00088 );
00089 #undef SUCC
00090 
00091 #define _REAL_GETREGS(n,m)     ((reg_t)(REG(al)+(((n)*8)+(m))))
00092 #define _REAL_GETSEGREGS(n)    ((reg_t)(REG(es)+(n)))
00093 #define _REAL_GETFPREGS(n)     ((reg_t)(REG(st0)+(n)))
00094 #define _REAL_GETCTRLREGS(n,m) ((reg_t)(REG(cr0)+(((n)*8)+(m))))
00095 
00096 #ifdef DEBUG
00097 static reg_t DebugGetRegs(int n,int m)
00098 {
00099   _PRG_ASSERT(n >= 0 && n < 5 && m >= 0 && m < 8);
00100   return _REAL_GETREGS(n,m);
00101 }
00102 static reg_t DebugGetSegRegs(int n)
00103 {
00104   _PRG_ASSERT(n >= 0 && n < 6);
00105   return _REAL_GETSEGREGS(n);
00106 }
00107 static reg_t DebugGetFpRegs(int n)
00108 {
00109   _PRG_ASSERT(n >= 0 && n < 8);
00110   return _REAL_GETFPREGS(n);
00111 }
00112 static reg_t DebugGetCtrlRegs(int n,int m)
00113 {
00114   _PRG_ASSERT(n >= 0 && n < 3 && m >= 0 && m < 8);
00115   return _REAL_GETCTRLREGS(n,m);
00116 }
00117 #  define GETREGS(n,m)     DebugGetRegs(n,m)
00118 #  define GETSEGREGS(n)    DebugGetSegRegs(n)
00119 #  define GETFPREGS(n)     DebugGetFpRegs(n)
00120 #  define GETCTRLREGS(n,m) DebugGetCtrlRegs(n,m)
00121 #else
00122 #  define GETREGS(n,m)     _REAL_GETREGS(n,m)
00123 #  define GETSEGREGS(n)    _REAL_GETSEGREGS(n)
00124 #  define GETFPREGS(n)     _REAL_GETFPREGS(n)
00125 #  define GETCTRLREGS(n,m) _REAL_GETCTRLREGS(n,m)
00126 #endif
00127 
00128 static const reg_t addr_mode2[8][2] = {
00129   { REG(bx),REG(si) },
00130   { REG(bx),REG(di) },
00131   { REG(bp),REG(si) },
00132   { REG(bp),REG(di) },
00133   { REG(si),null_reg },
00134   { REG(di),null_reg },
00135   { REG(bp),null_reg },
00136   { REG(bx),null_reg }
00137 };
00138 
00139 static const int op_grp[16][8] = {
00140   {  istr_add,   istr_or,  istr_adc,  istr_sbb,  istr_and,  istr_sub,  istr_xor,   istr_cmp }, // 1
00141   {  istr_rol,  istr_ror,  istr_rcl,  istr_rcr,  istr_shl,  istr_shr,        -1,   istr_sar }, // 2
00142   { istr_test,        -1,  istr_not,  istr_neg,  istr_mul, istr_imul,  istr_div,  istr_idiv }, // 3
00143   {  istr_inc,  istr_dec,        -1,        -1,        -1,        -1,        -1,         -1 }, // 4
00144   {  istr_inc,  istr_dec, istr_call, istr_call,  istr_jmp,  istr_jmp, istr_push,         -1 }, // 5
00145   { istr_sldt,  istr_str, istr_lldt,  istr_ltr, istr_verr, istr_verw,        -1,         -1 }, // 6
00146   { istr_sgdt, istr_sidt, istr_lgdt, istr_lidt, istr_smsw,        -1, istr_lmsw,istr_invlpg }, // 7
00147   {        -1,        -1,        -1,        -1,   istr_bt,  istr_bts,  istr_btr,   istr_btc }, // 8
00148   {        -1, istr_cmpxchg8b,   -1,        -1,        -1,        -1,        -1,         -1 }, // 9
00149   {        -1,        -1,        -1,        -1,        -1,        -1,        -1,         -1 }, // 10
00150   {        -1,        -1,        -1,        -1,        -1,        -1,        -1,         -1 }, // 11
00151   {        -1,        -1,  istr_psrlw,      -1,  istr_psraw,      -1,  istr_psllw,       -1 }, // 12
00152   {        -1,        -1,  istr_psrld,      -1,  istr_psrad,      -1,  istr_pslld,       -1 }, // 13
00153   {        -1,        -1,  istr_psrlq,      -1,        -1,        -1,  istr_psllq,       -1 }, // 14
00154   { istr_fxsave,istr_fxrstor,istr_ldmxcsr,istr_stmxcsr,-1,        -1,        -1,         -1 }, // 15
00155   { istr_prefetchnta,istr_prefetch0,istr_prefetch1,istr_prefetch2,-1,-1,     -1,         -1 }  // 16
00156 };
00157 
00158 static const int rm_size_invalid = 5;
00159 
00160 static int  over_seg     = -1;      /*   -1  = No overiding segment yet      */
00161 static bool over_opsize  = false;   /* false = No overiding operand size yet */
00162 static bool over_adrsize = false;   /* false = No overiding address size yet */
00163 static bool size_large   = true;
00164 static bool addr_large   = true;    /* Special Addressing Modes              */
00165 static int  size_bytes   = 4;       /* Default DWORD size                     */
00166        int  addr_bytes   = 4;       /* Default DWORD size                     */
00167 
00168 // !!! replace all entry in x86table with true registry !!!
00169 static reg_t get_regnum(int reg)
00170 {
00171   if ( reg < 9 )         /* Byte sized half register */
00172     return GETREGS(0,reg-1);
00173 
00174   if ( reg < 17 )        /* Word/DWord sized general register */
00175   {
00176     if ( size_large )
00177       return GETREGS(2,reg-9);
00178     return GETREGS(1,reg-9);
00179   }
00180 
00181   return GETSEGREGS(reg-17);
00182 }
00183 
00184 // !!! should be a class constructor
00185 static void inst_init()
00186 {
00187     over_seg     = -1;              /* Setup for the next instruction */
00188     over_opsize  = false;
00189     over_adrsize = false;
00190 
00191     if ( segment_mode == 386 ) {
00192         size_large = true;
00193         addr_large = true;
00194     } else {
00195         size_large = false;
00196         addr_large = false;
00197     }
00198     size_bytes = segment_bytes;
00199     addr_bytes = segment_bytes;
00200 }
00201 
00202 bool InstructionDecoder::get_checkc( uint32_t* offset )
00203 {
00204   if ( IsRelocation( reader->Tell() ) )
00205     return true; // Must be no labels or fixups
00206         *offset = reader->ReadByte();
00207         return false;
00208 }
00209 
00210 uint32_t InstructionDecoder::ReadVar( int flag )
00211 {
00212     if ( flag )
00213       return reader->ReadDword();;
00214                 return reader->ReadWord();
00215 }
00216 
00217 bool InstructionDecoder::getv_rel( Param& param, int flag )
00218 {
00219   uint32_t value;
00220         const Relocation *rel;
00221   if (flag)
00222   {
00223                 rel = reloc.GetRelocation(reader->Tell(),4);
00224     if (rel == &RelocationInfos::relError)
00225       return true;
00226                 value = reader->ReadDword();
00227   }
00228   else
00229   {
00230                 rel = reloc.GetRelocation(reader->Tell(),2);
00231     if (rel == &RelocationInfos::relError)
00232       return true;
00233                 value = reader->ReadWord();
00234   }
00235         param.relocation = rel;
00236   param.literal = value;
00237   return false;
00238 }
00239 
00240 #define INSTPROCDECL(name) \
00241   int InstructionDecoder::name(InstructionDecoder* _this, uchar opcode, int special, Instruction& instruction)
00242 
00243 #ifdef __BORLANDC__
00244 #pragma argsused
00245 #endif
00246 // Ritorna sempre 0, condizione di errore
00247 INSTPROCDECL(stub)
00248 {
00249   return 0;
00250 }
00251 
00252 #ifdef __BORLANDC__
00253 #pragma argsused
00254 #endif
00255 INSTPROCDECL(conv_byte)
00256 {
00257   _PRG_ASSERT( opcode == 0x98 || opcode == 0x99 );
00258         instruction.numArg = 0;
00259   if ( size_large )
00260     instruction.instruction = special;
00261   return 1;
00262 }
00263 
00264 #ifdef __BORLANDC__
00265 #pragma argsused
00266 #endif
00267 INSTPROCDECL(one_byte)
00268 {
00269         instruction.numArg = 0;
00270   if (special != regNone)
00271   {
00272         instruction.numArg = 1;
00273         instruction.Args[0] = Param(Param::Registry,get_regnum(special));
00274   }
00275   return 1;
00276 }
00277 
00278 #ifdef __BORLANDC__
00279 #pragma argsused
00280 #endif
00281 INSTPROCDECL(two_byte)
00282 {
00283   uint32_t offset;
00284 
00285   if ( _this->get_checkc( &offset ) ) {
00286     return( 0 );
00287   }
00288 
00289   instruction.numArg = 1;
00290   if (special != regNone)
00291   {
00292         instruction.numArg = 2;
00293         instruction.Args[0] = Param(Param::Registry,get_regnum(special));
00294   }
00295 
00296   // unsigned byte
00297         instruction.Args[instruction.numArg-1] = Param(Param::Literal,offset,(uchar)1);
00298 
00299   return 2;
00300 }
00301 
00302 #ifdef __BORLANDC__
00303 #pragma argsused
00304 #endif
00305 INSTPROCDECL(two_sbyte)
00306 {
00307   uint32_t offset;
00308   int num;
00309 
00310   if ( _this->get_checkc( &offset ) )
00311     return 0;
00312 
00313   num = U8TOI(offset);
00314 
00315   instruction.numArg = 1;
00316 
00317   // signed byte
00318         instruction.Args[instruction.numArg-1] = Param(Param::Literal,num,(uchar)1);
00319 
00320   return 2;
00321 }
00322 
00323 #ifdef __BORLANDC__
00324 #pragma argsused
00325 #endif
00326 INSTPROCDECL(three_byte)
00327 {
00328   instruction.numArg = 1;
00329   if (special != regNone)
00330   {
00331           instruction.numArg = 2;
00332     instruction.Args[0] =
00333         Param(Param::Registry,get_regnum(special));
00334   }
00335   Param& cParam = instruction.Args[instruction.numArg-1];
00336 
00337   bool size_tmp = size_large;
00338   if ( opcode == 0xC2 || opcode == 0xCA ) {       /* <RET jjkk>/<RETF jjkk> */
00339     size_tmp = false;
00340   }
00341   int result = (size_tmp?5:3);
00342 
00343   cParam = Param(Param::Literal,0,(uchar)(result-1) );
00344   if ( _this->getv_rel( cParam, size_tmp ) )
00345     return 0;
00346 
00347   return result;
00348 }
00349 
00350 #ifdef __BORLANDC__
00351 #pragma argsused
00352 #endif
00353 INSTPROCDECL(five_byte)
00354 {
00355   uint32_t offset;
00356   uint32_t segment;
00357   int     data_size;
00358 
00359 //  if ( over_seg != -1 ) {         // No segment overide allowed
00360 //    return(0);
00361 //  }
00362 
00363   data_size = size_bytes;
00364 
00365   // !!! check relocation
00366   offset = _this->ReadVar( size_large );
00367         segment = _this->reader->ReadWord();
00368 
00369   instruction.numArg = 1;
00370   instruction.Args[0] =
00371     Param(Param::FarLiteral,offset,(uchar)data_size,segment);
00372 
00373   return( 3 + data_size );
00374 }
00375 
00376 
00377 #ifdef __BORLANDC__
00378 #pragma argsused
00379 #endif
00380 INSTPROCDECL(one_a)
00381 {
00382         instruction.numArg = 1;
00383 
00384   instruction.Args[0] =
00385                 Param(Param::Registry,GETREGS(size_large?2:1,0));
00386   if (special != regNone)
00387   {
00388         instruction.numArg = 2;
00389         instruction.Args[1] =
00390         Param(Param::Registry,get_regnum(special));
00391   }
00392 
00393   return 1;
00394 }
00395 
00396 #ifdef __BORLANDC__
00397 #pragma argsused
00398 #endif
00399 INSTPROCDECL(two_a)
00400 {
00401   int     size;
00402   uint32_t offset;
00403 
00404   size = (opcode & 0x01);
00405   if (size && size_large)
00406     size = 2;
00407 
00408   if ( _this->get_checkc( &offset ) )
00409     return 0;
00410 
00411   instruction.numArg = 2;
00412   instruction.Args[0] = Param(Param::Literal,offset,(uchar)1);
00413   _PRG_ASSERT(0<=size && size <=2);
00414   instruction.Args[1] = Param(Param::Registry,GETREGS(size,0));
00415   return 2;
00416 }
00417 
00418 // !!! optimize fixing constants
00419 Param::MemoryTypes RegSizeToMemType(int reg_size)
00420 {
00421   switch (reg_size)
00422   {
00423   case 0: return Param::memInt8;
00424   case 1: return Param::memInt16;
00425   case 2: return Param::memInt32;
00426   case 3: return Param::memMmx;
00427   case 4: return Param::memXmm;
00428   default:
00429     _PRG_ASSERT(0);
00430     return Param::memNone;
00431   }
00432 }
00433 
00434 #ifdef __BORLANDC__
00435 #pragma argsused
00436 #endif
00437 INSTPROCDECL(three_a)
00438 {
00439   int                dir;
00440   int                reg_size;
00441   int                data_size;
00442   Param::MemoryTypes memType;
00443 
00444   instruction.numArg = 2;
00445 
00446   data_size = addr_bytes;
00447 
00448   dir  = ( opcode & 0x02 ) >> 1;
00449   reg_size = ( opcode & 0x01 );
00450 
00451   if ( reg_size == 1 && size_large )
00452     reg_size = 2;
00453 
00454   memType = RegSizeToMemType(reg_size);
00455 
00456         instruction.segOver = over_seg;
00457 
00458   if ( dir == 0 )
00459   {
00460     _PRG_ASSERT(reg_size>=0 && reg_size<=2);
00461         instruction.Args[0] =
00462         Param(Param::Registry,GETREGS(reg_size,0) );
00463         instruction.Args[1] =
00464         Param(Param::Memory,0,memType);
00465     instruction.Args[1].SetMemType(memType,false);
00466     if ( _this->getv_rel( instruction.Args[1], addr_large ) )
00467       return 0;
00468   }
00469   else
00470   {
00471         instruction.Args[0] =
00472         Param(Param::Memory,0,memType);
00473     instruction.Args[0].SetMemType(memType,false);
00474     if ( _this->getv_rel( instruction.Args[0], addr_large ) )
00475       return 0;
00476     _PRG_ASSERT(reg_size>=0 && reg_size<=2);
00477         instruction.Args[1] =
00478         Param(Param::Registry,GETREGS(reg_size,0) );
00479   }
00480 
00481   return( 1 + data_size );
00482 }
00483 
00484 
00485 #ifdef __BORLANDC__
00486 #pragma argsused
00487 #endif
00488 INSTPROCDECL(in_out)
00489 {
00490   int             dir;
00491   int             size;
00492 
00493   instruction.numArg = 2;
00494 
00495   dir  = ( opcode & 0x02 ) >> 1;
00496   size = ( opcode & 0x01 );
00497 
00498   if ( size == 1 && size_large )
00499     size = 2;
00500 
00501   if ( dir == 0 )
00502   {
00503     _PRG_ASSERT(size>=0 && size<=2);
00504         instruction.Args[0] =
00505         Param(Param::Registry,GETREGS(size,0));
00506         instruction.Args[1] =
00507         Param(Param::Registry,REG(dx));
00508   } else {
00509         instruction.Args[0] =
00510         Param(Param::Registry,REG(dx));
00511     _PRG_ASSERT(size>=0 && size<=2);
00512         instruction.Args[1] =
00513         Param(Param::Registry,GETREGS(size,0));
00514   }
00515 
00516   return 1;
00517 }
00518 
00519 #ifdef __BORLANDC__
00520 #pragma argsused
00521 #endif
00522 INSTPROCDECL(string_byte)
00523 {
00524         int                size;
00525   int                reg;
00526   Param::MemoryTypes memType;
00527 //  uchar  bytes;
00528 
00529   instruction.segOver = over_seg;
00530 
00531   size = opcode & 0x01;
00532   if ( size == 1 && size_large )
00533   {
00534     size = 2;
00535     instruction.instruction = special;
00536   }
00537 
00538   memType = RegSizeToMemType(size);
00539 //  bytes = (uchar)(1<<size);
00540 
00541   reg = 1;
00542   if ( addr_large )
00543         reg = 2;
00544 
00545   // !!! troppo legato alla stampa
00546   if (over_seg == -1)
00547   {
00548     instruction.numArg = 0;
00549     return 1;
00550   }
00551 
00552   switch( opcode ) {
00553   case 0xA4: // movsb
00554   case 0xA5: // movsw/d
00555   case 0xA6: // cmpsb
00556   case 0xA7: // cmpsw/d
00557     instruction.numArg = 2;
00558     _PRG_ASSERT(reg>=1 && reg<=2);
00559     instruction.Args[0] =
00560       Param(Param::Memory,GETREGS(reg,7),0,memType);
00561     instruction.Args[1] =
00562       Param(Param::Memory,GETREGS(reg,6),0,memType);
00563     break;
00564   case 0xAE: // scasb
00565   case 0xAF: // scasw/d
00566   case 0xAA: // stosb
00567   case 0xAB: // stosw/d
00568   case 0x6C: // insb
00569   case 0x6D: // insw/d
00570     instruction.numArg = 1;
00571     _PRG_ASSERT(reg>=1 && reg<=2);
00572     instruction.Args[0] =
00573       Param(Param::Memory,GETREGS(reg,7),0,memType);
00574     break;
00575   case 0xAC: // lodsb
00576   case 0xAD: // lodsw/d
00577   case 0x6E: // outsb
00578   case 0x6F: // outsw/d
00579     instruction.numArg = 1;
00580     _PRG_ASSERT(reg>=1 && reg<=2);
00581     instruction.Args[0] =
00582       Param(Param::Memory,GETREGS(reg,6),0,memType);
00583     break;
00584   default:
00585     _PRG_ASSERT(0);
00586     break;
00587   }
00588   return 1;
00589 }
00590 
00591 #ifdef __BORLANDC__
00592 #pragma argsused
00593 #endif
00594 INSTPROCDECL(enter)
00595 {
00596   uint32_t num_bytes;
00597   uint32_t nest_level;
00598 
00599   // !!! check for no relocation
00600         num_bytes = _this->reader->ReadWord();
00601 
00602   if ( _this->get_checkc( &nest_level) )
00603     return 0;
00604 
00605   instruction.numArg = 2;
00606   _PRG_ASSERT(instruction.instruction == istr_enter);
00607 
00608   instruction.Args[0] = Param(Param::Literal,num_bytes, (uchar)2);
00609   instruction.Args[1] = Param(Param::Literal,nest_level,(uchar)1);
00610   return 4;
00611 }
00612 
00613 #ifdef __BORLANDC__
00614 #pragma argsused
00615 #endif
00616 INSTPROCDECL(two_bcd)
00617 {
00618   uint32_t offset;
00619 
00620   // niente rilocazioni
00621   if ( _this->get_checkc( &offset ) )
00622     return 0;
00623 
00624   if ( offset == 10 )
00625   {
00626     instruction.numArg = 0;
00627     return 2;
00628   }
00629 
00630   instruction.numArg = 1;
00631   instruction.Args[0] = Param(Param::Literal,offset,(uchar)1);
00632   return 2;
00633 }
00634 
00635 #ifdef __BORLANDC__
00636 #pragma argsused
00637 #endif
00638 INSTPROCDECL(disp8)
00639 {
00640   uint32_t offset;
00641   uint32_t dest;
00642 
00643 //    if ( over_seg != -1 ) {             /* No segment overide allowed */
00644 //        return( 0 );
00645 //    }
00646 
00647   instruction.numArg = 1;
00648 
00649   // !!! check relocation
00650         offset = _this->reader->ReadByte();
00651 
00652 //    if ( offset == 0xFFFFFFFFL ) {      /* This would generate a label in  */
00653 //        return( 0 );                    /* the middle of the jmp statement */
00654 //    }                                   /* thereby preventing it anyway    */
00655 
00656   dest = _this->reader->Tell() + (signed char)offset;
00657 
00658         instruction.Args[0] =
00659         Param(Param::Literal,dest,(uchar)addr_bytes);
00660 
00661   return 2;
00662 }
00663 
00664 #ifdef __BORLANDC__
00665 #pragma argsused
00666 #endif
00667 INSTPROCDECL(disp16)
00668 {
00669   uint32_t offset;
00670   uint32_t dest;
00671   int             data_size;
00672 
00673   instruction.numArg = 1;
00674 
00675   data_size = addr_bytes;
00676 
00677 //    if ( over_seg != -1 )               /* No segment overide allowed */
00678 //        return( 0 );
00679 
00680   // !!! check relocation
00681   offset = _this->ReadVar( addr_large );
00682 
00683   // translate 16 to 32
00684   if ( !addr_large )
00685     offset = U16TOI(offset);
00686 
00687   dest = _this->reader->Tell() + offset;
00688 
00689   if ( !addr_large )
00690     dest &= 0xFFFFlu;
00691 
00692         instruction.Args[0] =
00693         Param(Param::Literal,dest,(uchar)addr_bytes);
00694 
00695   return( 1 + data_size );
00696 }
00697 
00698 
00699 #ifdef __BORLANDC__
00700 #pragma argsused
00701 #endif
00702 INSTPROCDECL(wait)
00703 {
00704   // !!! always print instruction
00705   instruction.numArg = 0;
00706   return 1;
00707 }
00708 
00709 #ifdef __BORLANDC__
00710 #pragma argsused
00711 #endif
00712 INSTPROCDECL(prefix)
00713 {
00714   // !!! should verify next instruction
00715   instruction.numArg = 0;
00716   return 1;
00717 }
00718 
00719 // special handling for Pentium III/4 instruction
00720 #ifdef __BORLANDC__
00721 #pragma argsused
00722 #endif
00723 INSTPROCDECL(prefixf3)
00724 {
00725   while (p3enable) // false loop
00726   {
00727     // see if next instruction can be 2 byte opcode
00728     uint32_t byte;
00729 
00730     // next byte must be 0xF
00731     if ( _this->get_checkc( &byte ) || byte != 0xF )
00732     {
00733       // do normal operation
00734       _this->reader->UnReadByte();
00735       break;
00736     }
00737 
00738     // read opcode
00739     if ( _this->get_checkc( &byte ) )
00740       return 0;
00741 
00742     // read next instruction
00743     instruction.instruction = F3XMM(byte).instruction;
00744     if (instruction.instruction == -1)
00745       return 0;
00746 
00747     // a small check_forward replacement
00748     // instruction ??
00749     int valid = mod_xmm( _this, byte, F3XMM(byte).special, instruction );
00750 
00751     return valid?valid+2:valid;
00752   }
00753 
00754   // !!! check forward instruction, should be a string instruction
00755   instruction.numArg = 0;
00756   return 1;
00757 }
00758 
00759 #ifdef __BORLANDC__
00760 #pragma argsused
00761 #endif
00762 INSTPROCDECL(seg_over)
00763 {
00764   int             valid;
00765   int             save_seg; // !!! serve salvarlo ??
00766 
00767   save_seg = over_seg;
00768 
00769   // puo' essere computato direttamente con special
00770   if ( opcode >= 0x64 ) {
00771     over_seg = 4 + opcode - 0x64;
00772     _PRG_ASSERT(over_seg >= 4 && over_seg < 6);
00773   } else {
00774     over_seg = (opcode & 0x18) >> 3;
00775     _PRG_ASSERT(over_seg >= 0 && over_seg < 4);
00776   }
00777 
00778   valid = _this->check_forward( instrTable, instruction );
00779 
00780   over_seg = save_seg;
00781   if ( valid )
00782     return( valid+1 );
00783   else
00784     return( 0 );
00785 }
00786 
00787 
00788 #ifdef __BORLANDC__
00789 #pragma argsused
00790 #endif
00791 INSTPROCDECL(opsize_over)
00792 {
00793   int             valid;
00794   int             save_bytes;
00795   bool            save_large;
00796 
00797   save_large = size_large;
00798   save_bytes = size_bytes;
00799 
00800   if (!over_opsize)  // already override, nothing to do
00801   {
00802     size_large = !size_large;       /* Toggle size */
00803     if ( size_bytes == 2 ) {
00804       size_bytes = 4;
00805     } else {
00806       size_bytes = 2;
00807     }
00808     over_opsize = true;
00809   }
00810 
00811   valid = _this->check_forward( instrTable, instruction );
00812 
00813   size_large = save_large;
00814   size_bytes = save_bytes;
00815   over_opsize = false;  // always set to false
00816 
00817   if ( valid )
00818     return( valid+1 );
00819   else
00820     return( 0 );
00821 }
00822 
00823 #ifdef __BORLANDC__
00824 #pragma argsused
00825 #endif
00826 INSTPROCDECL(adrsize_over)
00827 {
00828   int             valid;
00829   int             save_bytes;
00830   bool            save_large;
00831 
00832   save_large = addr_large;
00833   save_bytes = addr_bytes;
00834 
00835   if (!over_adrsize)
00836   {
00837     addr_large = !addr_large;           /* Toggle address */
00838     if ( addr_bytes == 2 ) {
00839       addr_bytes = 4;
00840     } else {
00841       addr_bytes = 2;
00842     }
00843     over_adrsize = true;
00844   }
00845 
00846   valid = _this->check_forward( instrTable, instruction );
00847 
00848   addr_large = save_large;
00849   addr_bytes = save_bytes;
00850   over_adrsize = false;
00851 
00852   if ( valid )
00853     return( valid+1 );
00854   else
00855     return( 0 );
00856 }
00857 
00858 int InstructionDecoder::do_sib( uchar* base, Param& param )
00859 {
00860     uint32_t sib_byte;
00861     int             ss;
00862     int             idx;
00863 
00864     if ( get_checkc ( &sib_byte ) )
00865       return( -1 );
00866     ss    = (int)(sib_byte & 0xC0L) >> 6;
00867     idx   = (int)(sib_byte & 0x38L) >> 3;
00868     *base = (uchar)(sib_byte & 0x07L);
00869     if ( idx == 0x04 ) {            /* For special [ESP] */
00870     // assume codifica fissa, tolto
00871 //      if ( ss != 0 ) {
00872 //        return( -1 );
00873 //      } else {
00874 //        strcpy( text, "" );
00875 //      }
00876     } else
00877     {
00878         param.mem_reg2 = GETREGS(2,idx);
00879       param.factor   = (uchar)(1<<ss);
00880     }
00881     return 1;
00882 }
00883 
00884 
00885 int InstructionDecoder::mod0( int sib_offset, uchar r_m, bool* size_known, Param& param )
00886 {
00887   int      result;
00888 
00889   if ( (r_m == 6 && !addr_large) || (r_m == 5 && addr_large) ) {
00890 
00891     // !!! segmento mettere in instruction
00892     param = Param(Param::Memory,null_reg,param.mem_reg2,0,param.factor);
00893     if ( getv_rel( param, addr_large ) )
00894       return -1;
00895 
00896     result = addr_bytes+sib_offset;
00897     *size_known = false;
00898     return( result );
00899   }
00900   if ( addr_large ) {
00901     param = Param(Param::Memory,GETREGS(2,r_m),param.mem_reg2,0,param.factor);
00902   } else {
00903         param = Param(Param::Memory,addr_mode2[r_m][0],addr_mode2[r_m][1],0,1 );
00904   }
00905   result = sib_offset;
00906   *size_known = true;
00907   return( result );
00908 }
00909 
00910 int InstructionDecoder::mod1( int sib_offset, uchar r_m, Param& param )
00911 {
00912     uint32_t offset;
00913     int      result;
00914 
00915     // read no relocation byte
00916     if ( get_checkc( &offset ) )
00917         return -1;
00918 
00919     // byte to dword
00920     offset = U8TOI(offset);
00921 
00922     if ( addr_large ) {
00923       param = Param(Param::Memory,GETREGS(2,r_m),param.mem_reg2,offset,param.factor);
00924     } else {
00925                 param = Param(Param::Memory,addr_mode2[r_m][0],addr_mode2[r_m][1],offset,1 );
00926     }
00927 
00928     result = 1 + sib_offset;
00929     return( result );
00930 }
00931 
00932 int InstructionDecoder::mod2( int sib_offset, uchar r_m, bool* size_known, Param& param )
00933 {
00934     int      result;
00935 
00936         // e chi se ne importa se l'assembler non e' ottimizzato ?
00937 //      if ( offset == 0x00000000L ) {
00938 //        return( -1 );       /* Assembler should have optimized */
00939 //      }
00940     if ( addr_large ) {
00941       param = Param(Param::Memory,GETREGS(2,r_m),param.mem_reg2,0,param.factor);
00942     } else {
00943       param = Param(Param::Memory,addr_mode2[r_m][0],addr_mode2[r_m][1],0,1 );
00944     }
00945     if ( getv_rel( param, addr_large ) )
00946       return -1;
00947     result = addr_bytes+sib_offset;
00948     *size_known = true;
00949     return( result );
00950 }
00951 
00952 
00953 static int mod3( uchar r_m, int size, Param& param )
00954 {
00955   if (unsigned(size)>4u) // 0-4 valid
00956     return -1;
00957   param = Param(Param::Registry,GETREGS(size,r_m));
00958   return 0;
00959 }
00960 
00961 int InstructionDecoder::do_mod_rm( uchar mod, uchar r_m, int reg_size, Param::MemoryTypes memType, bool size_needed, Param& param )
00962 {
00963     bool            size_known;
00964     int             sib_offset;
00965     int             result;
00966 
00967     _PRG_ASSERT(reg_size != 3 || mmx);
00968     _PRG_ASSERT(reg_size != 4 || xmm);
00969 
00970     if (mod == 3) // registry case
00971     {
00972         return mod3( r_m, reg_size, param );
00973     }
00974 
00975     size_known = false;
00976 
00977     sib_offset = 0;
00978 
00979     if ( addr_large )
00980     {
00981         // set default value for sib
00982         param.mem_reg2 = null_reg;
00983       param.factor = 1;
00984       if ( r_m == 4 && mod != 3 ) {
00985         /* Get result and new r_m */
00986         sib_offset = do_sib( &r_m, param );
00987         if ( sib_offset == -1 ) {
00988           return( -1 );
00989         }
00990       }
00991     }
00992     switch( mod ) {
00993         case 0: result = mod0( sib_offset, r_m, &size_known, param );
00994                 break;
00995         case 1: result = mod1( sib_offset, r_m, param );
00996                 size_known = true;
00997                 break;
00998         default:
00999                 // no warning and a bit optimized
01000                 _PRG_ASSERT(0);
01001         case 2: result = mod2( sib_offset, r_m, &size_known, param );
01002                 break;
01003     }
01004 
01005     if ( result != -1 ) {
01006         /*
01007         ** If the size is already known, then we don't need 'xxxx' ptr text
01008         */
01009 //        if ( !size_known || size_needed )
01010         {
01011                 param.SetMemType( memType, size_needed );
01012         }
01013     }
01014     return( result );
01015 }
01016 
01017 #ifdef __BORLANDC__
01018 #pragma argsused
01019 #endif
01020 int InstructionDecoder::mod_reg2 ( uchar opcode, int special, int mod_reg, Instruction& instruction)
01021 {
01022   uchar              mod;
01023   uchar              r_m;
01024   uchar              reg;
01025   int                reg_size;
01026   int                rm_size;
01027   int                additional = 0;
01028         Param              *reg_param;
01029   Param              *mem_param;
01030   Param::MemoryTypes memType;
01031 
01032   mod = (uchar)((mod_reg & 0xC0) >> 6);
01033   reg = (uchar)((mod_reg & 0x38) >> 3);
01034   r_m = (uchar)((mod_reg & 0x07) >> 0);
01035 
01036   reg_size = special & modregSize;
01037   COMPILE_CHECK(varTypes,(modregVar == 1) && (modregMmx == 3) && (modregXmm == 4));
01038   if (reg_size == modregVar && size_large )
01039     reg_size = 2;
01040 #ifdef DEBUG
01041   _PRG_ASSERT(mmx == 0 && xmm == 0);
01042   if (reg_size == modregMmx)
01043     ::mmx = 1;
01044   if (reg_size == modregXmm)
01045     ::xmm = 1;
01046 #endif
01047 
01048   // !!! se size_needed e punta a registro errore (es LDS)
01049   bool size_needed = false;
01050 
01051   if ( (special&modregMemType) == 0 )
01052   {
01053     rm_size = reg_size;
01054     memType = RegSizeToMemType(reg_size);
01055   }
01056   else
01057   {
01058     size_needed = true;
01059     switch (special&modregMemType)
01060     {
01061     case modregMemByte:
01062       rm_size = 0;
01063       memType  = Param::memInt8;
01064       break;
01065     case modregMemWord:
01066       rm_size = 1;
01067       memType  = Param::memInt16;
01068       break;
01069     case modregMemDword:
01070       _PRG_ASSERT( (::mmx && reg_size == modregMmx) 
01071         || (::xmm && reg_size == modregXmm) );
01072       rm_size = 2;
01073       memType  = Param::memInt32;
01074       break;
01075     case modregMemQword:
01076       _PRG_ASSERT(::xmm == 0);
01077       _PRG_ASSERT(instruction.instruction==istr_cmpxchg8b);
01078       rm_size = rm_size_invalid;
01079       memType  = Param::memInt64;
01080       break;
01081     case modregMemFPacket:
01082 #ifdef DEBUG
01083       ::xmm = 1;
01084 #endif
01085       rm_size = 4;
01086       memType = Param::memFPFloat32;
01087       break;
01088     case modregMem2FPacket:
01089 #ifdef DEBUG
01090       ::xmm = 1;
01091 #endif
01092       rm_size = 4;
01093       memType = Param::memSemiXmm;
01094       break;
01095     case modregMem4FPacket:
01096 #ifdef DEBUG
01097       ::xmm = 1;
01098 #endif
01099       rm_size = 4;
01100       memType = Param::memXmm;
01101       break;
01102     case modregMemPacket:
01103       _PRG_ASSERT(instruction.instruction==istr_pextrw 
01104                           || instruction.instruction==istr_pmovmskb 
01105         || instruction.instruction==istr_cvtpi2ps);
01106 #ifdef DEBUG
01107       if (instruction.instruction==istr_cvtpi2ps) ::xmm = 1; else ::mmx = 1;
01108 #endif
01109       rm_size = (instruction.instruction==istr_cvtpi2ps)?4:3;
01110       memType  = Param::memMmx;
01111       break;
01112     case modregMemPacketDword:
01113       _PRG_ASSERT(::mmx && reg_size == modregMmx);
01114       rm_size = (mod==3)?3:2;
01115       memType  = Param::memInt32;
01116       break;
01117     case modregMemDescriptor: 
01118             rm_size = rm_size_invalid; 
01119             memType = Param::memDescriptor;
01120             break; // 16&32 bit
01121     case modregMemPointer:
01122       _PRG_ASSERT(::xmm == 0);
01123       rm_size = rm_size_invalid;
01124       memType  = size_large?Param::memFarPointer32:Param::memFarPointer16;
01125       break;
01126     case modregMemBound:
01127       _PRG_ASSERT(::xmm == 0);
01128       rm_size = rm_size_invalid;
01129       memType  = size_large?Param::memBound32:Param::memBound32;
01130       break;
01131     default:
01132       // no warning and small optimization
01133       _PRG_ASSERT(0);
01134     case modregMemNone:
01135       rm_size = rm_size_invalid;
01136       memType  = Param::memNone;
01137       break;
01138     }
01139   }
01140 
01141   // write first 2 arguments
01142   switch ( special&modregType )
01143   {
01144   case modregMemReg:
01145         instruction.numArg = 2;
01146         mem_param = &instruction.Args[0];
01147         reg_param = &instruction.Args[1];
01148     break;
01149   case modregRegMem:
01150         instruction.numArg = 2;
01151         reg_param = &instruction.Args[0];
01152         mem_param = &instruction.Args[1];
01153     break;
01154   case modregMem:
01155         instruction.numArg = 1;
01156         mem_param = &instruction.Args[0];
01157     reg_param = NULL;
01158     break;
01159   default:
01160     // non dovrebbe capitare ma non si sa mai
01161     _PRG_ASSERT(0);
01162   case modregReg:
01163         instruction.numArg = 1;
01164         reg_param = &instruction.Args[0];
01165     mem_param = NULL;
01166     break;
01167   }
01168 
01169   if ( reg_param != NULL )
01170   {
01171     _PRG_ASSERT(reg_size>=0 && reg_size<=4);
01172         *reg_param = Param(Param::Registry,GETREGS(reg_size,reg));
01173   }
01174   else
01175     // !!! non sempre la dimensione serve se non c'e' un registro, a volte
01176     // e' implicita nell' operazione
01177     size_needed = true;
01178 
01179   if ( mem_param != NULL )
01180   {
01181     instruction.segOver = over_seg;
01182     additional = do_mod_rm( mod, r_m, rm_size, memType, size_needed, *mem_param );
01183 #ifdef DEBUG
01184     ::mmx = 0;
01185     ::xmm = 0;
01186 #endif
01187     if ( additional == -1 )
01188       return 0;
01189   }
01190 #ifdef DEBUG
01191   ::mmx = 0;
01192   ::xmm = 0;
01193 #endif
01194 
01195   // process third parameters (if one)
01196   if ( special&modregThird )
01197   {
01198         uint32_t data;
01199     Param& tParam = instruction.Args[instruction.numArg];
01200     switch ( special&modregThird )
01201     {
01202     case modregIsb:
01203       // check no relocation
01204         if ( get_checkc( &data ) )
01205         return 0;
01206       data = U8TOI(data);
01207       ++additional;
01208       tParam = Param(Param::Literal,data,(uchar)1);
01209       break;
01210     case modregIub:
01211       // check no relocation
01212         if ( get_checkc( &data ) )
01213         return 0;
01214       ++additional;
01215       tParam = Param(Param::Literal,data,(uchar)1);
01216       break;
01217     case modregIv:
01218       _PRG_ASSERT( size_bytes == (size_large?4:2) );
01219         tParam = Param(Param::Literal,0,(uchar)size_bytes);
01220       if ( getv_rel( tParam, size_large ) )
01221         return 0;
01222       additional += size_bytes;
01223       break;
01224     case modreg1:
01225         tParam = Param(Param::Literal,1,(uchar)1);
01226       break;
01227     case modregCL:
01228         tParam = Param(Param::Registry,REG(cl));
01229       break;
01230     }
01231     ++instruction.numArg;
01232   }
01233 
01234   return 2+additional;
01235 }
01236 
01237 #ifdef __BORLANDC__
01238 #pragma argsused
01239 #endif
01240 INSTPROCDECL(mod_reg)
01241 {
01242   uint32_t mod_reg;
01243   if ( _this->get_checkc( &mod_reg ) )
01244     return 0;
01245 
01246   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01247 }
01248 
01249 #ifdef __BORLANDC__
01250 #pragma argsused
01251 #endif
01252 INSTPROCDECL(mod_reg_p3)
01253 {
01254   uint32_t mod_reg;
01255   uchar mod;
01256 
01257   // verify PentiumIII or Athlon
01258   if (!p3enable && !athlon_enable)
01259     return 0;
01260 
01261   if ( _this->get_checkc( &mod_reg ) )
01262     return 0;
01263 
01264   mod = (uchar)((mod_reg & 0xC0) >> 6);
01265 
01266   switch (instruction.instruction)
01267   {
01268   case istr_pextrw:
01269     _PRG_ASSERT(opcode == 0xC5);
01270   case istr_pmovmskb:
01271     _PRG_ASSERT(instruction.instruction != istr_pmovmskb || opcode == 0xD7);
01272   case istr_maskmovq:
01273     _PRG_ASSERT(instruction.instruction != istr_maskmovq || opcode == 0xF7);
01274     // solo registri
01275     if (mod != 3)
01276       return 0;
01277     break;
01278   case istr_pinsrw:
01279     _PRG_ASSERT(special == modregPqEdIub);
01280     _PRG_ASSERT(opcode == 0xC4);
01281     // memoria , in questo caso i parametri sono diversi
01282     if (mod != 3)
01283       special = modregPqEwIub;
01284     break;
01285   }
01286 
01287   return _this->mod_reg2 (opcode,special,mod_reg, instruction);
01288 }
01289 
01290 #ifdef __BORLANDC__
01291 #pragma argsused
01292 #endif
01293 INSTPROCDECL(mod_xmm)
01294 {
01295   _PRG_ASSERT(instruction.instruction != -1);
01296 
01297   // verifica PentiumIII abilitato
01298   if (!p3enable)
01299     return 0;
01300 
01301   uint32_t mod_reg;
01302   if ( _this->get_checkc( &mod_reg ) )
01303     return 0;
01304 
01305   // movhlps and movlhps renaming
01306   if ( (opcode|4) == 0x16 && (mod_reg & 0xC0) == 0xC0 ) // 0x12 or 0x16 and registry
01307   {
01308     instruction.instruction = istr_movlhps;
01309     if (opcode == 0x12) 
01310       instruction.instruction = istr_movhlps;
01311   }
01312 
01313   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01314 }
01315 
01316 // mov seg_reg,reg/mem  mov reg/mem,seg_reg
01317 #ifdef __BORLANDC__
01318 #pragma argsused
01319 #endif
01320 INSTPROCDECL(seg_reg)
01321 {
01322   uint32_t mod_reg;
01323   uchar  mod;
01324   uchar  r_m;
01325   uchar  reg;
01326   int    additional;
01327         Param *reg_param;
01328   Param *mem_param;
01329 
01330   if ( _this->get_checkc( &mod_reg ) )
01331     return 0;
01332 
01333   instruction.numArg = 2;
01334 
01335   mod = (uchar)((mod_reg & 0xC0) >> 6);
01336   reg = (uchar)((mod_reg & 0x38) >> 3);
01337   r_m = (uchar)((mod_reg & 0x07) >> 0);
01338 
01339   // write first 2 arguments
01340   switch ( special&modregType )
01341   {
01342   case modregMemReg:
01343         mem_param = &instruction.Args[0];
01344         reg_param = &instruction.Args[1];
01345     break;
01346   default:
01347        // no warning and small optimization
01348     _PRG_ASSERT(0);
01349   case modregRegMem:
01350         reg_param = &instruction.Args[0];
01351         mem_param = &instruction.Args[1];
01352     break;
01353   }
01354 
01355   // check reg value
01356   if (reg >=6)
01357         return 0;
01358 
01359   *reg_param = Param(Param::Registry,GETSEGREGS(reg));
01360 
01361   instruction.segOver = over_seg;
01362   additional = _this->do_mod_rm( mod, r_m, 1, Param::memInt16,false, *mem_param );
01363   if ( additional == -1 )
01364     return 0;
01365 
01366   return 2+additional;
01367 }
01368 
01369 #ifdef __BORLANDC__
01370 #pragma argsused
01371 #endif
01372 INSTPROCDECL(group1)
01373 {
01374   uint32_t mod_reg;
01375   if ( _this->get_checkc( &mod_reg ) )
01376     return 0;
01377 
01378   instruction.instruction = op_grp[0][(uchar)((mod_reg & 0x38) >> 3)];
01379   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01380 }
01381 
01382 #ifdef __BORLANDC__
01383 #pragma argsused
01384 #endif
01385 INSTPROCDECL(group2)
01386 {
01387   uint32_t mod_reg;
01388   if ( _this->get_checkc( &mod_reg ) )
01389     return 0;
01390 
01391   instruction.instruction = op_grp[1][(uchar)(((int)mod_reg & 0x38) >> 3)];
01392   if (instruction.instruction == -1)
01393     return 0;
01394 
01395   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01396 }
01397 
01398 #ifdef __BORLANDC__
01399 #pragma argsused
01400 #endif
01401 INSTPROCDECL(group3)
01402 {
01403   uint32_t mod_reg;
01404   uchar reg;
01405 
01406   if ( _this->get_checkc( &mod_reg ) )
01407     return 0;
01408   reg = (uchar)(((int)mod_reg & 0x38) >> 3);
01409 
01410   // verifica istruzione test
01411   if (reg == 0)
01412   {
01413     // test
01414     if ( (special&modregSize) == modregByte )
01415       special |= modregIub;
01416     else
01417     {
01418       _PRG_ASSERT( (special&modregSize) == modregVar );
01419       special |= modregIv;
01420     }
01421   }
01422   instruction.instruction = op_grp[2][reg];
01423   if (instruction.instruction == -1)
01424     return 0;
01425 
01426   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01427 }
01428 
01429 #ifdef __BORLANDC__
01430 #pragma argsused
01431 #endif
01432 INSTPROCDECL(group4)
01433 {
01434   uint32_t mod_reg;
01435   if ( _this->get_checkc( &mod_reg ) )
01436     return 0;
01437 
01438   instruction.instruction = op_grp[3][(uchar)(((int)mod_reg & 0x38) >> 3)];
01439   if (instruction.instruction == -1)
01440     return 0;
01441 
01442   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01443 }
01444 
01445 #ifdef __BORLANDC__
01446 #pragma argsused
01447 #endif
01448 INSTPROCDECL(group5)
01449 {
01450   uint32_t mod_reg;
01451   uchar reg;
01452 
01453   if ( _this->get_checkc( &mod_reg ) )
01454     return 0;
01455   reg = (uchar)(((int)mod_reg & 0x38) >> 3);
01456 
01457   // verifica istruzione test
01458   if ( (reg==3) || (reg==5) )
01459     special = modregEp; // !!! Mp
01460 
01461   instruction.instruction = op_grp[4][reg];
01462   if (instruction.instruction == -1)
01463     return 0;
01464 
01465   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01466 }
01467 
01468 #ifdef __BORLANDC__
01469 #pragma argsused
01470 #endif
01471 INSTPROCDECL(group6)
01472 {
01473   uint32_t mod_reg;
01474   if ( _this->get_checkc( &mod_reg ) )
01475     return 0;
01476 
01477   instruction.instruction = op_grp[5][(uchar)(((int)mod_reg & 0x38) >> 3)];
01478   if (instruction.instruction == -1)
01479     return 0;
01480 
01481   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01482 }
01483 
01484 #ifdef __BORLANDC__
01485 #pragma argsused
01486 #endif
01487 INSTPROCDECL(group7)
01488 {
01489   uint32_t mod_reg;
01490   uchar reg;
01491 
01492   if ( _this->get_checkc( &mod_reg ) )
01493     return 0;
01494   reg = (uchar)(((int)mod_reg & 0x38) >> 3);
01495 
01496   // calcola parametri
01497   if ( reg == 7 )
01498     special = modregMn; // pointer to no memory
01499   else if (reg >= 4)
01500     special = modregEw;
01501 
01502   instruction.instruction = op_grp[6][reg];
01503   if (instruction.instruction == -1)
01504     return 0;
01505 
01506   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01507 }
01508 
01509 #ifdef __BORLANDC__
01510 #pragma argsused
01511 #endif
01512 INSTPROCDECL(group8)
01513 {
01514   uint32_t mod_reg;
01515   if ( _this->get_checkc( &mod_reg ) )
01516     return 0;
01517 
01518   instruction.instruction = op_grp[7][(uchar)(((int)mod_reg & 0x38) >> 3)];
01519   if (instruction.instruction == -1)
01520     return 0;
01521 
01522   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01523 }
01524 
01525 INSTPROCDECL(group9)
01526 {
01527   uint32_t mod_reg;
01528   if ( _this->get_checkc( &mod_reg ) )
01529     return 0;
01530 
01531   instruction.instruction = op_grp[8][(uchar)(((int)mod_reg & 0x38) >> 3)];
01532   if (instruction.instruction == -1)
01533     return 0;
01534 
01535   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01536 }
01537 
01538 #ifdef __BORLANDC__
01539 #pragma argsused
01540 #endif
01541 INSTPROCDECL(groupA)
01542 {
01543   _PRG_ASSERT( opcode >= 0x71 && opcode <= 0x73 );
01544   uint32_t mod_reg;
01545   int size = opcode - (0x71 - 11);
01546   _PRG_ASSERT( size >= 11 && size <= 13); // dal gruppo 12 al 14
01547   uchar reg;
01548 
01549   if ( _this->get_checkc( &mod_reg ) )
01550     return 0;
01551   reg = (uchar)(((int)mod_reg & 0x38) >> 3);
01552 
01553   if ( (instruction.instruction=op_grp[size][reg]) == -1 )
01554     return 0;
01555 
01556   return _this->mod_reg2( opcode,special,mod_reg, instruction);
01557 }
01558 
01559 #ifdef __BORLANDC__
01560 #pragma argsused
01561 #endif
01562 INSTPROCDECL(group15)
01563 {
01564   uint32_t mod_reg;
01565   uchar reg;
01566   uchar mod;
01567   uchar r_m;
01568 
01569   // check PentiumIII or Athlon enabled
01570   if (!p3enable && !athlon_enable)
01571     return 0;
01572 
01573   if ( _this->get_checkc( &mod_reg ) )
01574     return 0;
01575 
01576   // check for sfence
01577   if ( mod_reg == 0xF8 )
01578   {
01579     instruction.instruction = istr_sfence;
01580     instruction.numArg = 0;
01581     return 2;
01582   }
01583 
01584   // Athlon support only sfence
01585   if (!p3enable)
01586     return 0;
01587 
01588   mod = (uchar)((mod_reg & 0xC0) >> 6);
01589   reg = (uchar)((mod_reg & 0x38) >> 3);
01590   r_m = (uchar)((mod_reg & 0x07) >> 0);
01591 
01592   // not registry operands
01593   if (mod == 3)
01594     return 0;
01595 
01596   if ( (instruction.instruction=op_grp[14][reg]) == -1 )
01597     return 0;
01598   _PRG_ASSERT(reg <= 3);
01599 
01600   instruction.numArg = 1;
01601 
01602   Param::MemoryTypes memType = Param::memInt32;
01603   int rm_size = 2; // !!! is registry alright ??
01604   if (reg < 2)
01605   {
01606     rm_size = rm_size_invalid; // invalid registry
01607     memType = Param::memXStatus;
01608   }
01609 
01610   int additional = _this->do_mod_rm( mod, r_m, rm_size, memType, false, instruction.Args[0] );
01611   if ( additional == -1 )
01612     return 0;
01613 
01614   return 2+additional;
01615 }
01616 
01617 #ifdef __BORLANDC__
01618 #pragma argsused
01619 #endif
01620 INSTPROCDECL(group16)
01621 {
01622   uint32_t mod_reg;
01623   uchar reg;
01624   uchar mod;
01625   uchar r_m;
01626 
01627   // verifica PentiumIII abilitato
01628   if (!p3enable)
01629     return 0;
01630 
01631   if ( _this->get_checkc( &mod_reg ) )
01632     return 0;
01633 
01634   mod = (uchar)((mod_reg & 0xC0) >> 6);
01635   reg = (uchar)((mod_reg & 0x38) >> 3);
01636   r_m = (uchar)((mod_reg & 0x07) >> 0);
01637 
01638   // solo memoria
01639   if (mod == 3)
01640     return 0;
01641 
01642   if ( (instruction.instruction=op_grp[15][reg]) == -1 )
01643     return 0;
01644   _PRG_ASSERT(reg <= 3);
01645 
01646   instruction.numArg = 1;
01647 
01648   // !!! memNone ??
01649   int additional = _this->do_mod_rm( mod, r_m, rm_size_invalid, Param::memInt8, false, instruction.Args[0] );
01650   if ( additional == -1 )
01651     return 0;
01652 
01653   return 2+additional;
01654 }
01655 
01656 #ifdef __BORLANDC__
01657 #pragma argsused
01658 #endif
01659 INSTPROCDECL(mov_creg)
01660 {
01661   _PRG_ASSERT(special>=0 && special<=5);
01662   int type = special>>1;
01663 //  int b;
01664   uint32_t mod_reg;
01665   uchar creg,reg;
01666   Param *reg_param;
01667   Param *creg_param;
01668 
01669   if ( _this->get_checkc( &mod_reg ) )
01670     return 0;
01671 
01672   creg = (uchar)(((int)mod_reg & 0x38) >> 3);
01673   reg  = (uchar)(((int)mod_reg & 0x07) >> 0);
01674 
01675   instruction.numArg = 2;
01676   switch(special&1)
01677   {
01678   case 0:
01679     reg_param  = &instruction.Args[0];
01680     creg_param = &instruction.Args[1];
01681     break;
01682   default: // no silly warning
01683   case 1:
01684     creg_param = &instruction.Args[0];
01685     reg_param  = &instruction.Args[1];
01686     break;
01687   }
01688   *creg_param = Param(Param::Registry,GETCTRLREGS(type,creg));
01689   *reg_param  = Param(Param::Registry,GETREGS(2,reg));
01690   return 2;
01691 }
01692 
01693 // serve davvero ??
01694 #ifdef __BORLANDC__
01695 #pragma argsused
01696 #endif
01697 INSTPROCDECL(mov_special)
01698 {
01699 //  int    b;
01700   uint32_t mod_reg;
01701   uchar  mod;
01702   uchar  r_m;
01703 //  uchar  reg;
01704   int    reg_size;
01705   int    rm_size;
01706   int    additional;
01707   bool   size_needed;
01708 
01709   instruction.segOver = over_seg;
01710   instruction.numArg = 2;
01711 
01712   if ( _this->get_checkc( &mod_reg ) )
01713     return 0;
01714 
01715   mod = (uchar)(((int)mod_reg & 0xC0) >> 6);
01716 //  reg = (uchar)(((int)mod_reg & 0x38) >> 3);
01717   r_m = (uchar)(((int)mod_reg & 0x07) >> 0);
01718 
01719   size_needed = true;
01720 
01721   reg_size = opcode & 1;
01722   if (reg_size && size_large)
01723     reg_size = 2;
01724 
01725   rm_size = reg_size;
01726 
01727   _PRG_ASSERT(rm_size>=0 && rm_size<=2);
01728   additional = _this->do_mod_rm( mod, r_m, rm_size, RegSizeToMemType(rm_size), size_needed, instruction.Args[0] );
01729   if ( additional == -1 )
01730     return 0;
01731 
01732   // leggi secondo parametro
01733   uint32_t offset;
01734   if (reg_size == 0)
01735   {
01736                 offset = _this->reader->ReadByte();
01737     instruction.Args[1] = Param(Param::Literal,offset,(uchar)1);
01738 
01739     additional++;
01740   }
01741   else
01742   {
01743         instruction.Args[1] = Param(Param::Literal,0,(uchar)size_bytes);
01744     if ( _this->getv_rel( instruction.Args[1], size_large ) )
01745       return 0;
01746     additional += size_bytes;
01747   }
01748 
01749   return 2+additional;
01750 }
01751 
01752 // K6 3D Now! instruction
01753 INSTPROCDECL(one_byte_k63d)
01754 {
01755   if (!k6_3DNow_enable)
01756     return 0;
01757 
01758   return one_byte( _this, opcode,special,instruction);
01759 }
01760 
01761 INSTPROCDECL(prefetch_k63d)
01762 {
01763   _PRG_ASSERT( opcode == 0x0E && special == 0 );
01764 
01765   // verifica 3DNow abilitato
01766   if (!k6_3DNow_enable)
01767     return 0;
01768 
01769   uint32_t mod_reg;
01770   uchar reg;
01771   uchar mod;
01772   uchar r_m;
01773 
01774   if ( _this->get_checkc( &mod_reg ) )
01775     return 0;
01776 
01777   mod = (uchar)((mod_reg & 0xC0) >> 6);
01778   reg = (uchar)((mod_reg & 0x38) >> 3);
01779   r_m = (uchar)((mod_reg & 0x07) >> 0);
01780 
01781   // solo memoria
01782   if (mod == 3)
01783     return 0;
01784 
01785   if ( reg == 1 )
01786     instruction.instruction = istr_prefetchw;
01787 
01788   // !!! usare mod_reg2 ?? e modregEb
01789 
01790   instruction.numArg = 1;
01791 
01792   int additional = _this->do_mod_rm( mod, r_m, rm_size_invalid, Param::memInt8, false, instruction.Args[0] );
01793   if ( additional == -1 )
01794     return 0;
01795 
01796   return 2+additional;
01797 }
01798 
01799 INSTPROCDECL(k6_3dnow)
01800 {
01801   _PRG_ASSERT(special == modregPqQq);
01802   if (!k6_3DNow_enable)
01803     return 0;
01804 
01805   uint32_t mod_reg;
01806   if ( _this->get_checkc( &mod_reg ) )
01807     return 0;
01808 
01809   int result = _this->mod_reg2( opcode,special,mod_reg, instruction);
01810 
01811   // read opcode suffix
01812   if ( result == 0 || _this->get_checkc( &mod_reg ) )
01813   {
01814     return 0;
01815   }
01816   _PRG_ASSERT(mod_reg < 256);
01817   
01818   // get instruction
01819   instruction.instruction = k6_3DNow_instr[mod_reg].instruction;
01820   if ( instruction.instruction == -1 )
01821     return 0;
01822 
01823   // check for enhanched enabled
01824   if ( mod_reg == 0xBB || (mod_reg&0xF) == 0xC || (mod_reg&0xF9) == 0x80 )
01825   {
01826     _PRG_ASSERT( mod_reg==0xBB || mod_reg==0x8A || mod_reg==0x8E || mod_reg==0x0C || mod_reg==0x1C );
01827     if (!k6_en_3DNow_enable)
01828       return 0;
01829   }
01830 
01831   return 1+result;
01832 }
01833 
01834 #ifdef __BORLANDC__
01835 #pragma argsused
01836 #endif
01837 INSTPROCDECL(esc)
01838 {
01839   uint32_t mod_reg;
01840   int  additional;
01841   int  mem_size;
01842   bool size_needed = true;
01843   uchar mod;
01844   uchar ttt;        // Described as TTT in 80386 Prog Ref Man.
01845   uchar lll;        // Described as LLL in 80386 Prog Ref Man.
01846   uchar r_m;
01847   uchar esc_byte;
01848 
01849   if ( _this->get_checkc( &mod_reg ) )
01850     return 0;
01851 
01852   mod = (uchar)((mod_reg & 0xC0) >> 6);
01853   lll = (uchar)(((int)mod_reg & 0x38) >> 3);
01854   r_m = (uchar)(((int)mod_reg & 0x07) >> 0);
01855 
01856   ttt = (uchar)(opcode & 0x07);
01857   esc_byte = (uchar)((ttt << 3) + lll);
01858 
01859   if ( mod == 0x03 )
01860   {
01861     // instruction or special escape group
01862           int escInstr = FPIM3_ISTR(esc_inst_mod3[esc_byte]);
01863     instruction.numArg = 2; // default
01864     switch(FPIM3_PARAM(esc_inst_mod3[esc_byte]))
01865     {
01866     case fpiParamStNSt:
01867       instruction.Args[0] = Param(Param::Registry,GETFPREGS(r_m));
01868       instruction.Args[1] = Param(Param::Registry,REG(st0));
01869       break;
01870     case fpiParamStStN:
01871       instruction.Args[0] = Param(Param::Registry,REG(st0));
01872       instruction.Args[1] = Param(Param::Registry,GETFPREGS(r_m));
01873       break;
01874     case fpiParamStN:
01875       instruction.numArg = 1;
01876       instruction.Args[0] = Param(Param::Registry,GETFPREGS(r_m));
01877       break;
01878     case fpiParamNone:
01879       // escInstr is a special escape group
01880       instruction.numArg = 0;
01881 
01882       // is a valid group ?
01883       if (escInstr == -1)
01884         return 0;
01885 
01886       // get instruction
01887       escInstr = esc_inst_special[escInstr][r_m];
01888 
01889       // unico caso speciale, ax come parametro
01890       if (escInstr == istr_fstsw)
01891       {
01892         instruction.numArg = 1;
01893         instruction.Args[0] = Param(Param::Registry,REG(ax));
01894       }
01895       break;
01896     default:
01897       // non dovrebbe capitare
01898       _PRG_ASSERT(0);
01899     }
01900     // nessuna istruzione
01901     if (escInstr == -1)
01902       return 0;
01903                 instruction.instruction = escInstr;
01904     return 2;
01905   }
01906 
01907   if ( (instruction.instruction=FPI_ISTR(esc_inst[esc_byte])) == -1 )
01908     return 0;
01909 
01910   instruction.numArg = 1;
01911 
01912   // calcola dimensione
01913   // !!! per ora non c'e' il tipo, solo la dimensione
01914   mem_size = FPI_TYPE(esc_inst[esc_byte]);
01915 
01916   if (mem_size>fpiTypeImplicitMemory)
01917     size_needed = false;
01918 
01919   // !!! eliminare switch
01920   Param::MemoryTypes memType;
01921   switch(mem_size)
01922   {
01923   case fpiTypeWord:
01924   case fpiTypeWInt:
01925     memType = Param::memInt16;
01926     break;
01927   case fpiTypeSInt:
01928     memType = Param::memInt32;
01929     break;
01930   case fpiTypeLInt:
01931     memType = Param::memInt64;
01932     break;
01933   case fpiTypeSingle:
01934     memType = Param::memFPFloat32;
01935     break;
01936   case fpiTypeDouble:
01937     memType = Param::memFPFloat64;
01938     break;
01939   case fpiTypeExtended:
01940     memType = Param::memFPFloat80;
01941     break;
01942   case fpiTypeBCD:
01943     memType = Param::memFPBCD;
01944     break;
01945   case fpiTypeEnv:
01946     memType = size_large? Param::memFPEnv32 : Param::memFPEnv16;
01947     break;
01948   default:
01949     // no warning and small optimization
01950     _PRG_ASSERT(0);
01951   case fpiTypeStatus:
01952     memType = size_large? Param::memFPStatus32 : Param::memFPStatus16;
01953     break;
01954   }
01955 
01956   additional = _this->do_mod_rm( mod, r_m, rm_size_invalid, memType, size_needed, instruction.Args[0] );
01957   if ( additional == -1 )
01958     return 0;
01959 
01960   return 2+additional;
01961 }
01962 
01963 int InstructionDecoder::check_forward( const InstTable* inst_table, Instruction& instruction )
01964 {
01965     uint32_t byte;
01966     int      data;
01967     int      valid;
01968 
01969     // !!! too different ??
01970     // the next byte must be a valid instruction
01971     if ( get_checkc( &byte ) )
01972       return 0;
01973     data = (uchar)byte;
01974 
01975    instruction.instruction = inst_table[data].instruction;
01976    valid = inst_table[data].rtn(
01977               this,
01978               (uchar)data,
01979               inst_table[data].special,
01980               instruction );
01981 
01982     return valid;
01983 }
01984 
01985 #ifdef __BORLANDC__
01986 #pragma argsused
01987 #endif
01988 INSTPROCDECL(extra)
01989 {
01990   int result;
01991 
01992   result = _this->check_forward( exInstrTable, instruction);
01993 
01994   if ( result == 0 )
01995     return 0;
01996   else
01997     return( result+1 );
01998 }
01999 
02000 int InstructionDecoder::Decode(Instruction& instruction,ObjectModule::DataReader& reader)
02001 {
02002         this->reader = &reader;
02003 #ifdef DEBUG
02004   // marca istruzione con valori invalidi
02005   instruction.instruction = num_instructions;
02006   instruction.numArg = 20;
02007   // testa valori
02008   for(int i = 0; i<3; ++i)
02009   {
02010     _PRG_ASSERT(instruction.Args[i].relocation == NULL);
02011     instruction.Args[i].InitInvalid();
02012   }
02013 #endif
02014         try
02015   {
02016         int result;
02017           uint32_t c;
02018         if ( get_checkc( &c ) )
02019         return 0;
02020                 instruction.instruction = instrTable[c].instruction;
02021         result =
02022         instrTable[c].rtn( this, (uchar)c,instrTable[c].special,instruction);
02023 #ifdef DEBUG
02024         // testa valori
02025         if (result != 0 )
02026         {
02027         _PRG_ASSERT(instruction.instruction>=0);
02028         _PRG_ASSERT(instruction.instruction<num_instructions);
02029         _PRG_ASSERT(instruction.numArg != 20);
02030         for(int i = 0; i<instruction.numArg; ++i)
02031         {
02032         instruction.Args[i].CheckValid();
02033         if ( instruction.Args[i].type == Param::t_memory )
02034         {
02035                 if (instruction.instruction != istr_lea && instruction.instruction != istr_invlpg)
02036                 _PRG_ASSERT(instruction.Args[i].GetMemSize() != 0);
02037         }
02038         }
02039         }
02040 #endif
02041         return result;
02042         }
02043   catch(const ObjectModule::OutOfAddress&)
02044   {
02045                 /* reset to default */
02046                 over_seg = -1;
02047                 if (over_opsize) 
02048                 {
02049         size_large = !size_large;
02050         size_bytes = 6 - size_bytes;
02051                 }
02052                 if (over_adrsize)
02053                 {
02054         addr_large = !addr_large;
02055         addr_bytes = 6 - addr_bytes;
02056                 }
02057     return 0;
02058   }
02059 }
02060 
02061 // vim:tabstop=2:

Generated on Mon Jan 13 22:20:34 2003 for perdr by doxygen1.2.15