Make your own free website on Tripod.com
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: http://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