00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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;
00045
00046
00047 bool p3enable = true;
00048
00049 bool k6_3DNow_enable = true;
00050
00051 bool k6_en_3DNow_enable = true;
00052
00053 bool athlon_enable = true;
00054
00055 #ifdef DEBUG
00056 static int mmx = 0;
00057 static int xmm = 0;
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 },
00141 { istr_rol, istr_ror, istr_rcl, istr_rcr, istr_shl, istr_shr, -1, istr_sar },
00142 { istr_test, -1, istr_not, istr_neg, istr_mul, istr_imul, istr_div, istr_idiv },
00143 { istr_inc, istr_dec, -1, -1, -1, -1, -1, -1 },
00144 { istr_inc, istr_dec, istr_call, istr_call, istr_jmp, istr_jmp, istr_push, -1 },
00145 { istr_sldt, istr_str, istr_lldt, istr_ltr, istr_verr, istr_verw, -1, -1 },
00146 { istr_sgdt, istr_sidt, istr_lgdt, istr_lidt, istr_smsw, -1, istr_lmsw,istr_invlpg },
00147 { -1, -1, -1, -1, istr_bt, istr_bts, istr_btr, istr_btc },
00148 { -1, istr_cmpxchg8b, -1, -1, -1, -1, -1, -1 },
00149 { -1, -1, -1, -1, -1, -1, -1, -1 },
00150 { -1, -1, -1, -1, -1, -1, -1, -1 },
00151 { -1, -1, istr_psrlw, -1, istr_psraw, -1, istr_psllw, -1 },
00152 { -1, -1, istr_psrld, -1, istr_psrad, -1, istr_pslld, -1 },
00153 { -1, -1, istr_psrlq, -1, -1, -1, istr_psllq, -1 },
00154 { istr_fxsave,istr_fxrstor,istr_ldmxcsr,istr_stmxcsr,-1, -1, -1, -1 },
00155 { istr_prefetchnta,istr_prefetch0,istr_prefetch1,istr_prefetch2,-1,-1, -1, -1 }
00156 };
00157
00158 static const int rm_size_invalid = 5;
00159
00160 static int over_seg = -1;
00161 static bool over_opsize = false;
00162 static bool over_adrsize = false;
00163 static bool size_large = true;
00164 static bool addr_large = true;
00165 static int size_bytes = 4;
00166 int addr_bytes = 4;
00167
00168
00169 static reg_t get_regnum(int reg)
00170 {
00171 if ( reg < 9 )
00172 return GETREGS(0,reg-1);
00173
00174 if ( reg < 17 )
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
00185 static void inst_init()
00186 {
00187 over_seg = -1;
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;
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
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
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
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 ) {
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
00360
00361
00362
00363 data_size = size_bytes;
00364
00365
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
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
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
00540
00541 reg = 1;
00542 if ( addr_large )
00543 reg = 2;
00544
00545
00546 if (over_seg == -1)
00547 {
00548 instruction.numArg = 0;
00549 return 1;
00550 }
00551
00552 switch( opcode ) {
00553 case 0xA4:
00554 case 0xA5:
00555 case 0xA6:
00556 case 0xA7:
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:
00565 case 0xAF:
00566 case 0xAA:
00567 case 0xAB:
00568 case 0x6C:
00569 case 0x6D:
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:
00576 case 0xAD:
00577 case 0x6E:
00578 case 0x6F:
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
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
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
00644
00645
00646
00647 instruction.numArg = 1;
00648
00649
00650 offset = _this->reader->ReadByte();
00651
00652
00653
00654
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
00678
00679
00680
00681 offset = _this->ReadVar( addr_large );
00682
00683
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
00705 instruction.numArg = 0;
00706 return 1;
00707 }
00708
00709 #ifdef __BORLANDC__
00710 #pragma argsused
00711 #endif
00712 INSTPROCDECL(prefix)
00713 {
00714
00715 instruction.numArg = 0;
00716 return 1;
00717 }
00718
00719
00720 #ifdef __BORLANDC__
00721 #pragma argsused
00722 #endif
00723 INSTPROCDECL(prefixf3)
00724 {
00725 while (p3enable)
00726 {
00727
00728 uint32_t byte;
00729
00730
00731 if ( _this->get_checkc( &byte ) || byte != 0xF )
00732 {
00733
00734 _this->reader->UnReadByte();
00735 break;
00736 }
00737
00738
00739 if ( _this->get_checkc( &byte ) )
00740 return 0;
00741
00742
00743 instruction.instruction = F3XMM(byte).instruction;
00744 if (instruction.instruction == -1)
00745 return 0;
00746
00747
00748
00749 int valid = mod_xmm( _this, byte, F3XMM(byte).special, instruction );
00750
00751 return valid?valid+2:valid;
00752 }
00753
00754
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;
00766
00767 save_seg = over_seg;
00768
00769
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)
00801 {
00802 size_large = !size_large;
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;
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;
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 ) {
00870
00871
00872
00873
00874
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
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
00916 if ( get_checkc( &offset ) )
00917 return -1;
00918
00919
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
00937
00938
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)
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)
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
00982 param.mem_reg2 = null_reg;
00983 param.factor = 1;
00984 if ( r_m == 4 && mod != 3 ) {
00985
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
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
01008
01009
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
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;
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
01133 _PRG_ASSERT(0);
01134 case modregMemNone:
01135 rm_size = rm_size_invalid;
01136 memType = Param::memNone;
01137 break;
01138 }
01139 }
01140
01141
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
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
01176
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
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
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
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
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
01275 if (mod != 3)
01276 return 0;
01277 break;
01278 case istr_pinsrw:
01279 _PRG_ASSERT(special == modregPqEdIub);
01280 _PRG_ASSERT(opcode == 0xC4);
01281
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
01298 if (!p3enable)
01299 return 0;
01300
01301 uint32_t mod_reg;
01302 if ( _this->get_checkc( &mod_reg ) )
01303 return 0;
01304
01305
01306 if ( (opcode|4) == 0x16 && (mod_reg & 0xC0) == 0xC0 )
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
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
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
01348 _PRG_ASSERT(0);
01349 case modregRegMem:
01350 reg_param = &instruction.Args[0];
01351 mem_param = &instruction.Args[1];
01352 break;
01353 }
01354
01355
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
01411 if (reg == 0)
01412 {
01413
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
01458 if ( (reg==3) || (reg==5) )
01459 special = modregEp;
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
01497 if ( reg == 7 )
01498 special = modregMn;
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);
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
01570 if (!p3enable && !athlon_enable)
01571 return 0;
01572
01573 if ( _this->get_checkc( &mod_reg ) )
01574 return 0;
01575
01576
01577 if ( mod_reg == 0xF8 )
01578 {
01579 instruction.instruction = istr_sfence;
01580 instruction.numArg = 0;
01581 return 2;
01582 }
01583
01584
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
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;
01604 if (reg < 2)
01605 {
01606 rm_size = rm_size_invalid;
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
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
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
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
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:
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
01694 #ifdef __BORLANDC__
01695 #pragma argsused
01696 #endif
01697 INSTPROCDECL(mov_special)
01698 {
01699
01700 uint32_t mod_reg;
01701 uchar mod;
01702 uchar r_m;
01703
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
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
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
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
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
01782 if (mod == 3)
01783 return 0;
01784
01785 if ( reg == 1 )
01786 instruction.instruction = istr_prefetchw;
01787
01788
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
01812 if ( result == 0 || _this->get_checkc( &mod_reg ) )
01813 {
01814 return 0;
01815 }
01816 _PRG_ASSERT(mod_reg < 256);
01817
01818
01819 instruction.instruction = k6_3DNow_instr[mod_reg].instruction;
01820 if ( instruction.instruction == -1 )
01821 return 0;
01822
01823
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;
01845 uchar lll;
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
01862 int escInstr = FPIM3_ISTR(esc_inst_mod3[esc_byte]);
01863 instruction.numArg = 2;
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
01880 instruction.numArg = 0;
01881
01882
01883 if (escInstr == -1)
01884 return 0;
01885
01886
01887 escInstr = esc_inst_special[escInstr][r_m];
01888
01889
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
01898 _PRG_ASSERT(0);
01899 }
01900
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
01913
01914 mem_size = FPI_TYPE(esc_inst[esc_byte]);
01915
01916 if (mem_size>fpiTypeImplicitMemory)
01917 size_needed = false;
01918
01919
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
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
01970
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
02005 instruction.instruction = num_instructions;
02006 instruction.numArg = 20;
02007
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
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
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