/*++ Copyright (c) 2000 Microsoft Corporation Module Name: 86dis.cpp Abstract: Used to find out how long (in bytes) an instruction is: X86 only Notes: This is largely undocumented since it's based entirely on the original implementation by Gerd Immeyer. History: 10/19/1989 Gerd Immeyer Original version 01/09/2000 linstev Dumbed down for a shim --*/ #include "precomp.h" IMPLEMENT_SHIM_BEGIN(IgnoreException) #include "ShimHookMacro.h" #ifdef _X86_ #pragma pack(1) #define BIT20(b) (b & 0x07) #define BIT53(b) (b >> 3 & 0x07) #define BIT76(b) (b >> 6 & 0x03) #define MRM 0x40 #define COM 0x80 #define END 0xc0 #define SECTAB_OFFSET_1 256 #define SECTAB_OFFSET_2 236 #define SECTAB_OFFSET_3 227 #define SECTAB_OFFSET_4 215 #define SECTAB_OFFSET_5 199 #define SECTAB_OFFSET_UNDEF 260 #define O_DoDB 0 #define O_NoOperands 0 #define O_NoOpAlt5 O_NoOperands+1 #define O_NoOpAlt4 O_NoOpAlt5+2 #define O_NoOpAlt3 O_NoOpAlt4+2 #define O_NoOpAlt1 O_NoOpAlt3+2 #define O_NoOpAlt0 O_NoOpAlt1+2 #define O_NoOpStrSI O_NoOpAlt0+2 #define O_NoOpStrDI O_NoOpStrSI+2 #define O_NoOpStrSIDI O_NoOpStrDI+2 #define O_bModrm_Reg O_NoOpStrSIDI+2 #define O_vModrm_Reg O_bModrm_Reg+3 #define O_Modrm_Reg O_vModrm_Reg+3 #define O_bReg_Modrm O_Modrm_Reg+3 #define O_fReg_Modrm O_bReg_Modrm+3 #define O_Reg_Modrm O_fReg_Modrm+3 #define O_AL_Ib O_Reg_Modrm+3 #define O_AX_Iv O_AL_Ib+2 #define O_sReg2 O_AX_Iv+2 #define O_oReg O_sReg2+1 #define O_DoBound O_oReg+1 #define O_Iv O_DoBound+3 #define O_wModrm_Reg O_Iv+1 #define O_Ib O_wModrm_Reg+3 #define O_Imulb O_Ib+1 #define O_Imul O_Imulb+4 #define O_Rel8 O_Imul+4 #define O_bModrm_Ib O_Rel8+1 #define O_Modrm_Ib O_bModrm_Ib+3 #define O_Modrm_Iv O_Modrm_Ib+3 #define O_Modrm_sReg3 O_Modrm_Iv+3 #define O_sReg3_Modrm O_Modrm_sReg3+3 #define O_Modrm O_sReg3_Modrm+3 #define O_FarPtr O_Modrm+2 #define O_AL_Offs O_FarPtr+1 #define O_Offs_AL O_AL_Offs+2 #define O_AX_Offs O_Offs_AL+2 #define O_Offs_AX O_AX_Offs+2 #define O_oReg_Ib O_Offs_AX+2 #define O_oReg_Iv O_oReg_Ib+2 #define O_Iw O_oReg_Iv+2 #define O_Enter O_Iw+1 #define O_Ubyte_AL O_Enter+2 #define O_Ubyte_AX O_Ubyte_AL+2 #define O_AL_Ubyte O_Ubyte_AX+2 #define O_AX_Ubyte O_AL_Ubyte+2 #define O_DoInAL O_AX_Ubyte+2 #define O_DoInAX O_DoInAL+3 #define O_DoOutAL O_DoInAX+3 #define O_DoOutAX O_DoOutAL+3 #define O_Rel16 O_DoOutAX+3 #define O_ADR_OVERRIDE O_Rel16+1 #define O_OPR_OVERRIDE O_ADR_OVERRIDE+1 #define O_SEG_OVERRIDE O_OPR_OVERRIDE+1 #define O_DoInt3 O_SEG_OVERRIDE+1 #define O_DoInt 117 #define O_OPC0F O_DoInt+1 #define O_GROUP11 O_OPC0F+1 #define O_GROUP13 O_GROUP11+5 #define O_GROUP12 O_GROUP13+5 #define O_GROUP21 O_GROUP12+5 #define O_GROUP22 O_GROUP21+5 #define O_GROUP23 O_GROUP22+5 #define O_GROUP24 O_GROUP23+6 #define O_GROUP25 O_GROUP24+6 #define O_GROUP26 O_GROUP25+6 #define O_GROUP4 O_GROUP26+6 #define O_GROUP6 O_GROUP4+4 #define O_GROUP8 O_GROUP6+4 #define O_GROUP31 O_GROUP8+5 #define O_GROUP32 O_GROUP31+3 #define O_GROUP5 O_GROUP32+3 #define O_GROUP7 O_GROUP5+3 #define O_x87_ESC O_GROUP7+3 #define O_bModrm O_x87_ESC+2 #define O_wModrm O_bModrm+2 #define O_dModrm O_wModrm+2 #define O_fModrm O_dModrm+2 #define O_vModrm O_fModrm+2 #define O_vModrm_Iv O_vModrm+2 #define O_Reg_bModrm O_vModrm_Iv+3 #define O_Reg_wModrm O_Reg_bModrm+3 #define O_Modrm_Reg_Ib O_Reg_wModrm+3 #define O_Modrm_Reg_CL O_Modrm_Reg_Ib+4 #define O_ST_iST O_Modrm_Reg_CL+5 #define O_iST O_ST_iST+2 #define O_iST_ST O_iST+2 #define O_qModrm O_iST_ST+2 #define O_tModrm O_qModrm+2 #define O_DoRep O_tModrm+2 #define O_Modrm_CReg O_DoRep+1 #define O_CReg_Modrm O_Modrm_CReg+3 #define O_AX_oReg O_CReg_Modrm+3 #define O_MmReg_qModrm O_AX_oReg+2 #define O_qModrm_MmReg O_MmReg_qModrm+3 #define O_MmReg_dModrm O_qModrm_MmReg+3 #define O_dModrm_MmReg O_MmReg_dModrm+3 #define O_qModrm_Ib O_dModrm_MmReg+3 #define O_PSHimw O_qModrm_Ib+3 #define O_PSHimd O_PSHimw+5 #define O_PSHimq O_PSHimd+5 #define O_length O_PSHimq+5 typedef unsigned short ActionIndex; typedef struct Tdistbl { ActionIndex opr; } Tdistbl; typedef struct _ADDR { USHORT type; USHORT seg; ULONG off; union { ULONG flat; ULONGLONG flat64; }; } ADDR, *PADDR; typedef struct _DECODEDATA { int mod; // mod of mod/rm byte int rm; // rm of mod/rm byte int ttt; // return reg value (of mod/rm) unsigned char *pMem; // current position in instruction ADDR EAaddr[2]; // offset of effective address int EAsize[2]; // size of effective address item BOOL fMovX; // indicates a MOVSX or MOVZX BOOL fMmRegEa; // Use mm? registers in reg-only EA. } DECODEDATA; enum oprtyp { ADDRP, ADR_OVR, ALSTR, ALT, AXSTR, BOREG, BREG, BRSTR, xBYTE, CHR, CREG, xDWORD, EDWORD, EGROUPT, FARPTR, GROUP, GROUPT, IB, IST, IST_ST, IV, IW, LMODRM, MODRM, NOP, OFFS, OPC0F, OPR_OVR, QWORD, REL16, REL8, REP, SEG_OVR, SREG2, SREG3, ST_IST, STROP, xTBYTE, UBYTE, VAR, VOREG, VREG, xWORD, WREG, WRSTR, MMWREG, MMQWORD }; unsigned char actiontbl[] = { /* NoOperands */ NOP+END, /* NoOpAlt5 */ ALT+END, 5, /* NoOpAlt4 */ ALT+END, 4, /* NoOpAlt3 */ ALT+END, 3, /* NoOpAlt1 */ ALT+END, 1, /* NoOpAlt0 */ ALT+END, 0, /* NoOpStrSI */ STROP+END, 1, /* NoOpStrDI */ STROP+END, 2, /* NoOpStrSIDI */ STROP+END, 3, /* bModrm_Reg */ xBYTE+MRM, MODRM+COM, BREG+END, /* vModrm_Reg */ VAR+MRM, LMODRM+COM, BREG+END, /* Modrm_Reg */ VAR+MRM, MODRM+COM, VREG+END, /* bReg_Modrm */ xBYTE+MRM, BREG+COM, MODRM+END, /* fReg_Modrm */ FARPTR+MRM,VREG+COM, MODRM+END, /* Reg_Modrm */ VAR+MRM, VREG+COM, MODRM+END, /* AL_Ib */ ALSTR+COM, IB+END, /* AX_Iv */ AXSTR+COM, IV+END, /* sReg2 */ SREG2+END, /* oReg */ VOREG+END, /* DoBound */ VAR+MRM, VREG+COM, MODRM+END, /* Iv */ IV+END, /* wModrm_Reg */ xWORD+MRM, LMODRM+COM, WREG+END, /* Ib */ IB+END, /* Imulb */ VAR+MRM, VREG+COM, MODRM+COM, IB+END, /* Imul */ VAR+MRM, VREG+COM, MODRM+COM, IV+END, /* REL8 */ REL8+END, /* bModrm_Ib */ xBYTE+MRM, LMODRM+COM, IB+END, /* Modrm_Ib */ VAR+MRM, LMODRM+COM, IB+END, /* Modrm_Iv */ VAR+MRM, LMODRM+COM, IV+END, /* Modrm_sReg3 */ xWORD+MRM, MODRM+COM, SREG3+END, /* sReg3_Modrm */ xWORD+MRM, SREG3+COM, MODRM+END, /* Modrm */ VAR+MRM, MODRM+END, /* FarPtr */ ADDRP+END, /* AL_Offs */ ALSTR+COM, OFFS+END, /* Offs_AL */ OFFS+COM, ALSTR+END, /* AX_Offs */ AXSTR+COM, OFFS+END, /* Offs_AX */ OFFS+COM, AXSTR+END, /* oReg_Ib */ BOREG+COM, IB+END, /* oReg_Iv */ VOREG+COM, IV+END, /* Iw */ IW+END, /* enter */ IW+COM, IB+END, /* Ubyte_AL */ UBYTE+COM, ALSTR+END, /* Ubyte_AX */ UBYTE+COM, AXSTR+END, /* AL_Ubyte */ ALSTR+COM, UBYTE+END, /* AX_Ubyte */ AXSTR+COM, UBYTE+END, /* DoInAL */ ALSTR+COM, WRSTR+END, 2, /* DoInAX */ AXSTR+COM, WRSTR+END, 2, /* DoOutAL */ WRSTR+COM, 2, ALSTR+END, /* DoOutAX */ WRSTR+COM, 2, AXSTR+END, /* REL16 */ REL16+END, /* ADR_OVERRIDE*/ ADR_OVR, /* OPR_OVERRIDE*/ OPR_OVR, /* SEG_OVERRIDE*/ SEG_OVR, /* DoInt3 */ CHR+END, '3', /* DoInt */ UBYTE+END, /* Opcode0F */ OPC0F, /* group1_1 */ xBYTE+MRM, GROUP, 0, LMODRM+COM, IB+END, /* group1_3 */ VAR+MRM, GROUP, 0, LMODRM+COM, IB+END, /* group1_2 */ VAR+MRM, GROUP, 0, LMODRM+COM, IV+END, /* group2_1 */ xBYTE+MRM, GROUP, 1, LMODRM+COM, IB+END, /* group2_2 */ VAR+MRM, GROUP, 1, LMODRM+COM, IB+END, /* group2_3 */ xBYTE+MRM, GROUP, 1, LMODRM+COM, CHR+END, '1', /* group2_4 */ VAR+MRM, GROUP, 1, LMODRM+COM, CHR+END, '1', /* group2_5 */ xBYTE+MRM, GROUP, 1, LMODRM+COM, BRSTR+END, 1, /* group2_6 */ VAR+MRM, GROUP, 1, LMODRM+COM, BRSTR+END, 1, /* group4 */ xBYTE+MRM, GROUP, 2, LMODRM+END, /* group6 */ xWORD+MRM, GROUP, 3, LMODRM+END, /* group8 */ xWORD+MRM, GROUP, 4, LMODRM+COM, IB+END, /* group3_1 */ xBYTE+MRM, GROUPT, 20, /* group3_2 */ VAR+MRM, GROUPT, 21, /* group5 */ VAR+MRM, GROUPT, 22, /* group7 */ NOP+MRM, GROUPT, 23, /* x87_ESC */ NOP+MRM, EGROUPT, /* bModrm */ xBYTE+MRM, LMODRM+END, /* wModrm */ xWORD+MRM, LMODRM+END, /* dModrm */ xDWORD+MRM,LMODRM+END, /* fModrm */ FARPTR+MRM,LMODRM+END, /* vModrm */ VAR+MRM, LMODRM+END, /* vModrm_Iv */ VAR+MRM, LMODRM+COM, IV+END, /* reg_bModrm */ xBYTE+MRM, VREG+COM, LMODRM+END, /* reg_wModrm */ xWORD+MRM, VREG+COM, LMODRM+END, /* Modrm_Reg_Ib*/ VAR+MRM, MODRM+COM, VREG+COM, IB+END, /* Modrm_Reg_CL*/ VAR+MRM, MODRM+COM, VREG+COM, BRSTR+END, 1, /* ST_iST */ NOP+MRM, ST_IST+END, /* iST */ NOP+MRM, IST+END, /* iST_ST */ NOP+MRM, IST_ST+END, /* qModrm */ QWORD+MRM, LMODRM+END, /* tModrm */ xTBYTE+MRM, LMODRM+END, /* REP */ REP, /* Modrm_CReg */ EDWORD+MRM,MODRM+COM, CREG+END, /* CReg_Modrm */ EDWORD+MRM,CREG+COM, MODRM+END, /* AX_oReg */ AXSTR+COM, VOREG+END, /* MmReg_qModrm*/ MMQWORD+MRM, MMWREG+COM, LMODRM+END, /* qModrm_MmReg*/ MMQWORD+MRM, MODRM+COM, MMWREG+END, /* MmReg_dModrm*/ xDWORD+MRM, MMWREG+COM,LMODRM+END, /* dModrm_MmReg*/ xDWORD+MRM, MODRM+COM, MMWREG+END, /* qModrm_Ib */ MMQWORD+MRM, MODRM+COM,IB+END, /* PSHimw */ MMQWORD+MRM, GROUP, 5, LMODRM+COM, IB+END, /* PSHimd */ MMQWORD+MRM, GROUP, 6, LMODRM+COM, IB+END, /* PSHimq */ MMQWORD+MRM, GROUP, 7, LMODRM+COM, IB+END, }; Tdistbl distbl[] = { O_bModrm_Reg, /* 00 ADD mem/reg, reg (byte) */ O_Modrm_Reg, /* 01 ADD mem/reg, reg (word) */ O_bReg_Modrm, /* 02 ADD reg, mem/reg (byte) */ O_Reg_Modrm, /* 03 ADD reg, mem/reg (word) */ O_AL_Ib, /* 04 ADD AL, I */ O_AX_Iv, /* 05 ADD AX, I */ O_sReg2, /* 06 PUSH ES */ O_sReg2, /* 07 POP ES */ O_bModrm_Reg, /* 08 OR mem/reg, reg (byte) */ O_Modrm_Reg, /* 09 OR mem/reg, reg (word) */ O_bReg_Modrm, /* 0A OR reg, mem/reg (byte) */ O_Reg_Modrm, /* 0B OR reg, mem/reg (word) */ O_AL_Ib, /* 0C OR AL, I */ O_AX_Iv, /* 0D OR AX, I */ O_sReg2, /* 0E PUSH CS */ O_OPC0F, /* 0F CLTS & protection ctl(286) */ O_bModrm_Reg, /* 10 ADC mem/reg, reg (byte) */ O_Modrm_Reg, /* 11 ADC mem/reg, reg (word) */ O_bReg_Modrm, /* 12 ADC reg, mem/reg (byte) */ O_Reg_Modrm, /* 13 ADC reg, mem/reg (word) */ O_AL_Ib, /* 14 ADC AL, I */ O_AX_Iv, /* 15 ADC AX, I */ O_sReg2, /* 16 PUSH SS */ O_sReg2, /* 17 POP SS */ O_bModrm_Reg, /* 18 SBB mem/reg, reg (byte) */ O_Modrm_Reg, /* 19 SBB mem/reg, reg (word) */ O_bReg_Modrm, /* 1A SBB reg, mem/reg (byte) */ O_Reg_Modrm, /* 1B SBB reg, mem/reg (word) */ O_AL_Ib, /* 1C SBB AL, I */ O_AX_Iv, /* 1D SBB AX, I */ O_sReg2, /* 1E PUSH DS */ O_sReg2, /* 1F POP DS */ O_bModrm_Reg, /* 20 AND mem/reg, reg (byte) */ O_Modrm_Reg, /* 21 AND mem/reg, reg (word) */ O_bReg_Modrm, /* 22 AND reg, mem/reg (byte) */ O_Reg_Modrm, /* 23 AND reg, mem/reg (word) */ O_AL_Ib, /* 24 AND AL, I */ O_AX_Iv, /* 25 AND AX, I */ O_SEG_OVERRIDE, /* 26 SEG ES: */ O_NoOperands, /* 27 DAA */ O_bModrm_Reg, /* 28 SUB mem/reg, reg (byte) */ O_Modrm_Reg, /* 29 SUB mem/reg, reg (word) */ O_bReg_Modrm, /* 2A SUB reg, mem/reg (byte) */ O_Reg_Modrm, /* 2B SUB reg, mem/reg (word) */ O_AL_Ib, /* 2C SUB AL, I */ O_AX_Iv, /* 2D SUB AX, I */ O_SEG_OVERRIDE, /* 2E SEG CS: */ O_NoOperands, /* 2F DAS */ O_bModrm_Reg, /* 30 XOR mem/reg, reg (byte) */ O_Modrm_Reg, /* 31 XOR mem/reg, reg (word) */ O_bReg_Modrm, /* 32 XOR reg, mem/reg (byte) */ O_Reg_Modrm, /* 33 XOR reg, mem/reg (word) */ O_AL_Ib, /* 34 XOR AL, I */ O_AX_Iv, /* 35 XOR AX, I */ O_SEG_OVERRIDE, /* 36 SEG SS: */ O_NoOperands, /* 37 AAA */ O_bModrm_Reg, /* 38 CMP mem/reg, reg (byte) */ O_Modrm_Reg, /* 39 CMP mem/reg, reg (word) */ O_bReg_Modrm, /* 3A CMP reg, mem/reg (byte) */ O_Reg_Modrm, /* 3B CMP reg, mem/reg (word) */ O_AL_Ib, /* 3C CMP AL, I */ O_AX_Iv, /* 3D CMP AX, I */ O_SEG_OVERRIDE, /* 3E SEG DS: */ O_NoOperands, /* 3F AAS */ O_oReg, /* 40 INC AX */ O_oReg, /* 41 INC CX */ O_oReg, /* 42 INC DX */ O_oReg, /* 43 INC BX */ O_oReg, /* 44 INC SP */ O_oReg, /* 45 INC BP */ O_oReg, /* 46 INC SI */ O_oReg, /* 47 INC DI */ O_oReg, /* 48 DEC AX */ O_oReg, /* 49 DEC CX */ O_oReg, /* 4A DEC DX */ O_oReg, /* 4B DEC BX */ O_oReg, /* 4C DEC SP */ O_oReg, /* 4D DEC BP */ O_oReg, /* 4E DEC SI */ O_oReg, /* 4F DEC DI */ O_oReg, /* 50 PUSH AX */ O_oReg, /* 51 PUSH CX */ O_oReg, /* 52 PUSH DX */ O_oReg, /* 53 PUSH BX */ O_oReg, /* 54 PUSH SP */ O_oReg, /* 55 PUSH BP */ O_oReg, /* 56 PUSH SI */ O_oReg, /* 57 PUSH DI */ O_oReg, /* 58 POP AX */ O_oReg, /* 59 POP CX */ O_oReg, /* 5A POP DX */ O_oReg, /* 5B POP BX */ O_oReg, /* 5C POP SP */ O_oReg, /* 5D POP BP */ O_oReg, /* 5E POP SI */ O_oReg, /* 5F POP DI */ O_NoOpAlt5, /* 60 PUSHA (286) / PUSHAD (386) */ O_NoOpAlt4, /* 61 POPA (286) / POPAD (286) */ O_DoBound, /* 62 BOUND reg, Modrm (286) */ O_Modrm_Reg, /* 63 ARPL Modrm, reg (286) */ O_SEG_OVERRIDE, /* 64 */ O_SEG_OVERRIDE, /* 65 */ O_OPR_OVERRIDE, /* 66 */ O_ADR_OVERRIDE, /* 67 */ O_Iv, /* 68 PUSH word (286) */ O_Imul, /* 69 IMUL (286) */ O_Ib, /* 6A PUSH byte (286) */ O_Imulb, /* 6B IMUL (286) */ O_NoOperands, /* 6C INSB (286) */ O_NoOpAlt3, /* 6D INSW (286) / INSD (386) */ O_NoOperands, /* 6E OUTSB (286) */ O_NoOpAlt4, /* 6F OUTSW (286) / OUTSD (386) */ O_Rel8, /* 70 JO */ O_Rel8, /* 71 JNO */ O_Rel8, /* 72 JB or JNAE or JC */ O_Rel8, /* 73 JNB or JAE or JNC */ O_Rel8, /* 74 JE or JZ */ O_Rel8, /* 75 JNE or JNZ */ O_Rel8, /* 76 JBE or JNA */ O_Rel8, /* 77 JNBE or JA */ O_Rel8, /* 78 JS */ O_Rel8, /* 79 JNS */ O_Rel8, /* 7A JP or JPE */ O_Rel8, /* 7B JNP or JPO */ O_Rel8, /* 7C JL or JNGE */ O_Rel8, /* 7D JNL or JGE */ O_Rel8, /* 7E JLE or JNG */ O_Rel8, /* 7F JNLE or JG */ O_GROUP11, /* 80 */ O_GROUP12, /* 81 */ O_DoDB, /* 82 */ O_GROUP13, /* 83 */ O_bModrm_Reg, /* 84 TEST reg, mem/reg (byte) */ O_Modrm_Reg, /* 85 TEST reg, mem/reg (word) */ O_bModrm_Reg, /* 86 XCHG reg, mem/reg (byte) */ O_Modrm_Reg, /* 87 XCHG reg, mem/reg (word) */ O_bModrm_Reg, /* 88 MOV mem/reg, reg (byte) */ O_Modrm_Reg, /* 89 MOV mem/reg, reg (word) */ O_bReg_Modrm, /* 8A MOV reg, mem/reg (byte) */ O_Reg_Modrm, /* 8B MOV reg, mem/reg (word) */ O_Modrm_sReg3, /* 8C MOV mem/reg, segreg */ O_Reg_Modrm, /* 8D LEA reg, mem */ O_sReg3_Modrm, /* 8E MOV segreg, mem/reg */ O_Modrm, /* 8F POP mem/reg */ O_NoOperands, /* 90 NOP */ O_AX_oReg, /* 91 XCHG AX,CX */ O_AX_oReg, /* 92 XCHG AX,DX */ O_AX_oReg, /* 93 XCHG AX,BX */ O_AX_oReg, /* 94 XCHG AX,SP */ O_AX_oReg, /* 95 XCHG AX,BP */ O_AX_oReg, /* 96 XCHG AX,SI */ O_AX_oReg, /* 97 XCHG AX,DI */ O_NoOpAlt0, /* 98 CBW / CWDE (386) */ O_NoOpAlt1, /* 99 CWD / CDQ (386) */ O_FarPtr, /* 9A CALL seg:off */ O_NoOperands, /* 9B WAIT */ O_NoOpAlt5, /* 9C PUSHF / PUSHFD (386) */ O_NoOpAlt4, /* 9D POPF / POPFD (386) */ O_NoOperands, /* 9E SAHF */ O_NoOperands, /* 9F LAHF */ O_AL_Offs, /* A0 MOV AL, mem */ O_AX_Offs, /* A1 MOV AX, mem */ O_Offs_AL, /* A2 MOV mem, AL */ O_Offs_AX, /* A3 MOV mem, AX */ O_NoOpStrSIDI, /* A4 MOVSB */ O_NoOpStrSIDI, /* A5 MOVSW / MOVSD (386) */ O_NoOpStrSIDI, /* A6 CMPSB */ O_NoOpStrSIDI, /* A7 CMPSW / CMPSD (386) */ O_AL_Ib, /* A8 TEST AL, I */ O_AX_Iv, /* A9 TEST AX, I */ O_NoOpStrDI, /* AA STOSB */ O_NoOpStrDI, /* AB STOSW / STOSD (386) */ O_NoOpStrSI, /* AC LODSB */ O_NoOpStrSI, /* AD LODSW / LODSD (386) */ O_NoOpStrDI, /* AE SCASB */ O_NoOpStrDI, /* AF SCASW / SCASD (386) */ O_oReg_Ib, /* B0 MOV AL, I */ O_oReg_Ib, /* B1 MOV CL, I */ O_oReg_Ib, /* B2 MOV DL, I */ O_oReg_Ib, /* B3 MOV BL, I */ O_oReg_Ib, /* B4 MOV AH, I */ O_oReg_Ib, /* B5 MOV CH, I */ O_oReg_Ib, /* B6 MOV DH, I */ O_oReg_Ib, /* B7 MOV BH, I */ O_oReg_Iv, /* B8 MOV AX, I */ O_oReg_Iv, /* B9 MOV CX, I */ O_oReg_Iv, /* BA MOV DX, I */ O_oReg_Iv, /* BB MOV BX, I */ O_oReg_Iv, /* BC MOV SP, I */ O_oReg_Iv, /* BD MOV BP, I */ O_oReg_Iv, /* BE MOV SI, I */ O_oReg_Iv, /* BF MOV DI, I */ O_GROUP21, /* C0 shifts & rotates (286) */ O_GROUP22, /* C1 shifts & rotates (286) */ O_Iw, /* C2 RET Rel16 */ O_NoOperands, /* C3 RET */ O_fReg_Modrm, /* C4 LES reg, mem */ O_fReg_Modrm, /* C5 LDS reg, mem */ O_bModrm_Ib, /* C6 MOV mem/reg, I(byte) */ O_Modrm_Iv, /* C7 MOV mem/reg, I(word) */ O_Enter, /* C8 ENTER (286) */ O_NoOperands, /* C9 LEAVE (286) */ O_Iw, /* CA RETF I(word) */ O_NoOperands, /* CB RETF */ O_DoInt3, /* CC INT 3 */ O_DoInt, /* CD INT */ O_NoOperands, /* CE INTO */ O_NoOpAlt4, /* CF IRET / IRETD (386) */ O_GROUP23, /* D0 shifts & rotates,1 (byte) */ O_GROUP24, /* D1 shifts & rotates,1 (word) */ O_GROUP25, /* D2 shifts & rotates,CL (byte) */ O_GROUP26, /* D3 shifts & rotates,CL (word) */ O_Ib, /* D4 AAM */ O_Ib, /* D5 AAD */ O_DoDB, /* D6 */ O_NoOperands, /* D7 XLAT */ O_x87_ESC, /* D8 ESC */ O_x87_ESC, /* D9 ESC */ O_x87_ESC, /* DA ESC */ O_x87_ESC, /* DB ESC */ O_x87_ESC, /* DC ESC */ O_x87_ESC, /* DD ESC */ O_x87_ESC, /* DE ESC */ O_x87_ESC, /* DF ESC */ O_Rel8, /* E0 LOOPNE or LOOPNZ */ O_Rel8, /* E1 LOOPE or LOOPZ */ O_Rel8, /* E2 LOOP */ O_Rel8, /* E3 JCXZ / JECXZ (386) */ O_AL_Ubyte, /* E4 IN AL, I */ O_AX_Ubyte, /* E5 IN AX, I */ O_Ubyte_AL, /* E6 OUT I, AL */ O_Ubyte_AX, /* E7 OUT I, AX */ O_Rel16, /* E8 CALL Rel16 */ O_Rel16, /* E9 JMP Rel16 */ O_FarPtr, /* EA JMP seg:off */ O_Rel8, /* EB JMP Rel8 */ O_DoInAL, /* EC IN AL, DX */ O_DoInAX, /* ED IN AX, DX */ O_DoOutAL, /* EE OUT DX, AL */ O_DoOutAX, /* EF OUT DX, AX */ O_DoRep, /* F0 LOCK */ O_DoDB, /* F1 */ O_DoRep, /* F2 REPNE or REPNZ */ O_DoRep, /* F3 REP or REPE or REPZ */ O_NoOperands, /* F4 HLT */ O_NoOperands, /* F5 CMC */ O_GROUP31, /* F6 TEST, NOT, NEG, MUL, IMUL, */ O_GROUP32, /* F7 DIv, IDIv F6=Byte F7=Word */ O_NoOperands, /* F8 CLC */ O_NoOperands, /* F9 STC */ O_NoOperands, /* FA CLI */ O_NoOperands, /* FB STI */ O_NoOperands, /* FC CLD */ O_NoOperands, /* FD STD */ O_GROUP4, /* FE INC, DEC mem/reg (byte) */ O_GROUP5, /* FF INC, DEC, CALL, JMP, PUSH */ // secondary opcode table begins. Only "filled" locations are stored // to compress the secondary table. Hence while disassembling // opcode needs to be displaced appropriately to account for the. // The displacements are defined in 86dis.c and need to be reevaluated // if new opcodes are added here. O_GROUP6, /* 0 MULTI */ O_GROUP7, /* 1 MULTI */ O_Reg_Modrm, /* 2 LAR */ O_Reg_Modrm, /* 3 LSL */ O_DoDB, /* 4 */ O_NoOperands, /* 5 LOADALL */ O_NoOperands, /* 6 CLTS */ O_GROUP7, /* 7 MULTI */ O_NoOperands, /* 8 INVD */ O_NoOperands, /* 9 WBINVD */ O_DoDB, /* A */ O_NoOperands, /* B UD2 undefined */ O_Modrm_CReg, /* 20 MOV Rd,Cd */ O_Modrm_CReg, /* 21 MOV Rd,Dd */ O_CReg_Modrm, /* 22 MOV Cd,Rd */ O_CReg_Modrm, /* 23 MOV Dd,Rd */ O_Modrm_CReg, /* 24 MOV Rd,Td */ O_DoDB, /* 25 */ O_CReg_Modrm, /* 26 MOV Td,Rd */ O_NoOperands, /* 30 WRMSR */ O_NoOperands, /* 31 RDTSC */ O_NoOperands, /* 32 RDMSR */ O_NoOperands, /* 33 RDPMC */ O_Reg_Modrm, /* 40 CMOVO */ O_Reg_Modrm, /* 41 CMOVNO */ O_Reg_Modrm, /* 42 CMOVB */ O_Reg_Modrm, /* 43 CMOVNB */ O_Reg_Modrm, /* 44 CMOVE */ O_Reg_Modrm, /* 45 CMOVNE */ O_Reg_Modrm, /* 46 CMOVBE */ O_Reg_Modrm, /* 47 CMOVNBE */ O_Reg_Modrm, /* 48 CMOVS */ O_Reg_Modrm, /* 49 CMOVNS */ O_Reg_Modrm, /* 4A CMOVP */ O_Reg_Modrm, /* 4B CMOVNP */ O_Reg_Modrm, /* 4C CMOVL */ O_Reg_Modrm, /* 4D CMOVGE */ O_Reg_Modrm, /* 4E CMOVLE */ O_Reg_Modrm, /* 4F CMOVNLE */ O_MmReg_qModrm, /* 60 PUNPCKLBW */ O_MmReg_qModrm, /* 61 PUNPCKLWD */ O_MmReg_qModrm, /* 62 PUNPCKLDQ */ O_MmReg_qModrm, /* 63 PACKSSWB */ O_MmReg_qModrm, /* 64 PCMPGTB */ O_MmReg_qModrm, /* 65 PCMPGTW */ O_MmReg_qModrm, /* 66 PCMPGTD */ O_MmReg_qModrm, /* 67 PACKUSWB */ O_MmReg_qModrm, /* 68 PUNPCKHBW */ O_MmReg_qModrm, /* 69 PUNPCKHWD */ O_MmReg_qModrm, /* 6A PUNPCKHDQ */ O_MmReg_qModrm, /* 6B PACKSSDW */ O_DoDB, /* 6C */ O_DoDB, /* 6D */ O_MmReg_dModrm, /* 6E MOVD */ O_MmReg_qModrm, /* 6F MOVQ */ O_DoDB, /* 70 */ O_PSHimw, /* 71 PS[LR][AL]W immediate */ O_PSHimd, /* 72 PS[LR][AL]D immediate */ O_PSHimq, /* 73 PS[LR]LQ immediate */ O_MmReg_qModrm, /* 74 PCMPEQB */ O_MmReg_qModrm, /* 75 PCMPEQW */ O_MmReg_qModrm, /* 76 PCMPEQD */ O_NoOperands, /* 77 EMMS */ O_DoDB, /* 78 */ O_DoDB, /* 79 */ O_DoDB, /* 7A */ O_DoDB, /* 7B */ O_DoDB, /* 7C */ O_bModrm, /* 7D SETNL */ O_dModrm_MmReg, /* 7E MOVD */ O_qModrm_MmReg, /* 7F MOVQ */ O_Rel16, /* 80 JO */ O_Rel16, /* 81 JNO */ O_Rel16, /* 82 JB */ O_Rel16, /* 83 JNB */ O_Rel16, /* 84 JE */ O_Rel16, /* 85 JNE */ O_Rel16, /* 86 JBE */ O_Rel16, /* 87 JNBE */ O_Rel16, /* 88 JS */ O_Rel16, /* 89 JNS */ O_Rel16, /* 8A JP */ O_Rel16, /* 8B JNP */ O_Rel16, /* 8C JL */ O_Rel16, /* 8D JNL */ O_Rel16, /* 8E JLE */ O_Rel16, /* 8F JNLE */ O_bModrm, /* 90 SETO */ O_bModrm, /* 91 SETNO */ O_bModrm, /* 92 SETB */ O_bModrm, /* 93 SETNB */ O_bModrm, /* 94 SETE */ O_bModrm, /* 95 SETNE */ O_bModrm, /* 96 SETBE */ O_bModrm, /* 97 SETNBE */ O_bModrm, /* 98 SETS */ O_bModrm, /* 99 SETNS */ O_bModrm, /* 9A SETP */ O_bModrm, /* 9B SETNP */ O_bModrm, /* 9C SETL */ O_bModrm, /* 9D SETGE */ O_bModrm, /* 9E SETLE */ O_bModrm, /* 9F SETNLE */ O_sReg2, /* A0 PUSH FS */ O_sReg2, /* A1 POP FS */ O_NoOperands, /* A2 CPUID */ O_Modrm_Reg, /* A3 BT */ O_Modrm_Reg_Ib, /* A4 SHLD */ O_Modrm_Reg_CL, /* A5 SHLD */ O_DoDB, /* A6 */ O_DoDB, /* A7 */ O_sReg2, /* A8 PUSH GS */ O_sReg2, /* A9 POP GS */ O_NoOperands, /* AA RSM */ O_vModrm_Reg, /* AB BTS */ O_Modrm_Reg_Ib, /* AC SHRD */ O_Modrm_Reg_CL, /* AD SHRD */ O_DoDB, /* AE */ O_Reg_Modrm, /* AF IMUL */ O_bModrm_Reg, /* B0 CMPXCH */ O_Modrm_Reg, /* B1 CMPXCH */ O_fReg_Modrm, /* B2 LSS */ O_Modrm_Reg, /* B3 BTR */ O_fReg_Modrm, /* B4 LFS */ O_fReg_Modrm, /* B5 LGS */ O_Reg_bModrm, /* B6 MOVZX */ O_Reg_wModrm, /* B7 MOVZX */ O_DoDB, /* B8 */ O_DoDB, /* B9 */ O_GROUP8, /* BA MULTI */ O_Modrm_Reg, /* BB BTC */ O_Reg_Modrm, /* BC BSF */ O_Reg_Modrm, /* BD BSR */ O_Reg_bModrm, /* BE MOVSX */ O_Reg_wModrm, /* BF MOVSX */ O_bModrm_Reg, /* C0 XADD */ O_Modrm_Reg, /* C1 XADD */ O_DoDB, /* C2 */ O_DoDB, /* C3 */ O_DoDB, /* C4 */ O_DoDB, /* C5 */ O_DoDB, /* C6 */ O_qModrm, /* C7 CMPXCHG8B */ O_oReg, /* C8 BSWAP */ O_oReg, /* C9 BSWAP */ O_oReg, /* CA BSWAP */ O_oReg, /* CB BSWAP */ O_oReg, /* CC BSWAP */ O_oReg, /* CD BSWAP */ O_oReg, /* CE BSWAP */ O_oReg, /* CF BSWAP */ O_DoDB, /* D0 */ O_MmReg_qModrm, /* D1 PSRLW */ O_MmReg_qModrm, /* D2 PSRLD */ O_MmReg_qModrm, /* D3 PSRLQ */ O_DoDB, /* D4 */ O_MmReg_qModrm, /* D5 PMULLW */ O_DoDB, /* D6 */ O_DoDB, /* D7 */ O_MmReg_qModrm, /* D8 PSUBUSB */ O_MmReg_qModrm, /* D9 PSUBUSW */ O_DoDB, /* DA */ O_MmReg_qModrm, /* DB PAND */ O_MmReg_qModrm, /* DC PADDUSB */ O_MmReg_qModrm, /* DD PADDUSW */ O_DoDB, /* DE */ O_MmReg_qModrm, /* DF PANDN */ O_DoDB, /* E0 */ O_MmReg_qModrm, /* E1 PSRAW */ O_MmReg_qModrm, /* E2 PSRAD */ O_DoDB, /* E3 */ O_DoDB, /* E4 */ O_MmReg_qModrm, /* E5 PMULHW */ O_DoDB, /* E6 */ O_DoDB, /* E7 */ O_MmReg_qModrm, /* E8 PSUBSB */ O_MmReg_qModrm, /* E9 PSUBSW */ O_DoDB, /* EA */ O_MmReg_qModrm, /* EB POR */ O_MmReg_qModrm, /* EC PADDSB */ O_MmReg_qModrm, /* ED PADDSW */ O_DoDB, /* EE */ O_MmReg_qModrm, /* EF PXOR */ O_DoDB, /* F0 */ O_MmReg_qModrm, /* F1 PSLLW */ O_MmReg_qModrm, /* F2 PSLLD */ O_MmReg_qModrm, /* F3 PSLLQ */ O_DoDB, /* F4 */ O_MmReg_qModrm, /* F5 PMADDWD */ O_DoDB, /* F6 */ O_DoDB, /* F7 */ O_MmReg_qModrm, /* F8 PSUBB */ O_MmReg_qModrm, /* F9 PSUBW */ O_MmReg_qModrm, /* FA PSUBD */ O_DoDB, /* FB */ O_MmReg_qModrm, /* FC PADDB */ O_MmReg_qModrm, /* FD PADDW */ O_MmReg_qModrm, /* FE PADDD */ }; Tdistbl groupt[][8] = { /* 00 00 x87-D8-1 */ { O_dModrm, /* D8-0 FADD */ O_dModrm, /* D8-1 FMUL */ O_dModrm, /* D8-2 FCOM */ O_dModrm, /* D8-3 FCOMP */ O_dModrm, /* D8-4 FSUB */ O_dModrm, /* D8-5 FSUBR */ O_dModrm, /* D8-6 FDIV */ O_dModrm }, /* D8-7 FDIVR */ /* 01 x87-D8-2 */ { O_ST_iST, /* D8-0 FADD */ O_ST_iST, /* D8-1 FMUL */ O_iST, /* D8-2 FCOM */ O_iST, /* D8-3 FCOMP */ O_ST_iST, /* D8-4 FSUB */ O_ST_iST, /* D8-5 FSUBR */ O_ST_iST, /* D8-6 FDIV */ O_ST_iST }, /* D8-7 FDIVR */ /* 02 01 x87-D9-1 */ { O_dModrm, /* D9-0 FLD */ O_DoDB, /* D9-1 */ O_dModrm, /* D9-2 FST */ O_dModrm, /* D9-3 FSTP */ O_Modrm, /* D9-4 FLDENV */ O_Modrm, /* D9-5 FLDCW */ O_Modrm, /* D9-6 FSTENV */ O_Modrm }, /* D9-7 FSTCW */ /* 03 01 x87-D9-2 TTT=0,1,2,3 */ { O_iST, /* D9-0 FLD */ O_iST, /* D9-1 FXCH */ O_NoOperands, /* D9-2 FNOP */ O_iST, /* D9-3 FSTP */ O_DoDB, /* D9-4 */ O_DoDB, /* D9-5 */ O_DoDB, /* D9-6 */ O_DoDB }, /* D9-7 */ /* 04 02 x89-DA-1 */ { O_dModrm, /* DA-0 FIADD */ O_dModrm, /* DA-1 FIMUL */ O_dModrm, /* DA-2 FICOM */ O_dModrm, /* DA-3 FICOMP */ O_dModrm, /* DA-4 FISUB */ O_dModrm, /* DA-5 FISUBR */ O_dModrm, /* DA-6 FIDIV */ O_dModrm }, /* DA-7 FIDIVR */ /* 05 x87-DA-2 */ { O_ST_iST, /* DA-0 FCMOVB */ O_ST_iST, /* DA-1 FCMOVE */ O_ST_iST, /* DA-2 FCMOVBE */ O_ST_iST, /* DA-3 FCMOVU */ O_DoDB, /* DA-4 */ O_NoOperands, /* DA-5 */ O_DoDB, /* DA-6 */ O_DoDB }, /* DA-7 */ /* 06 03 x87-DB-1 */ { O_dModrm, /* DB-0 FILD */ O_DoDB, /* DB-1 */ O_dModrm, /* DB-2 FIST */ O_dModrm, /* DB-3 FISTP */ O_DoDB, /* DB-4 */ O_tModrm, /* DB-5 FLD */ O_DoDB, /* DB-6 */ O_tModrm }, /* DB-7 FSTP */ /* 07 x87-DB-2 ttt=4 */ { O_NoOperands, /* DB-0 FENI */ O_NoOperands, /* DB-1 FDISI */ O_NoOperands, /* DB-2 FCLEX */ O_NoOperands, /* DB-3 FINIT */ O_DoDB, /* DB-4 FSETPM */ O_DoDB, /* DB-5 */ O_DoDB, /* DB-6 */ O_DoDB }, /* DB-7 */ /* 08 04 x87-DC-1 */ { O_qModrm, /* DC-0 FADD */ O_qModrm, /* DC-1 FMUL */ O_qModrm, /* DC-2 FCOM */ O_qModrm, /* DC-3 FCOMP */ O_qModrm, /* DC-4 FSUB */ O_qModrm, /* DC-5 FSUBR */ O_qModrm, /* DC-6 FDIV */ O_qModrm }, /* DC-7 FDIVR */ /* 09 x87-DC-2 */ { O_iST_ST, /* DC-0 FADD */ O_iST_ST, /* DC-1 FMUL */ O_iST, /* DC-2 FCOM */ O_iST, /* DC-3 FCOMP */ O_iST_ST, /* DC-4 FSUB */ O_iST_ST, /* DC-5 FSUBR */ O_iST_ST, /* DC-6 FDIVR */ O_iST_ST }, /* DC-7 FDIV */ /* 10 05 x87-DD-1 */ { O_qModrm, /* DD-0 FLD */ O_DoDB, /* DD-1 */ O_qModrm, /* DD-2 FST */ O_qModrm, /* DD-3 FSTP */ O_Modrm, /* DD-4 FRSTOR */ O_DoDB, /* DD-5 */ O_Modrm, /* DD-6 FSAVE */ O_Modrm }, /* DD-7 FSTSW */ /* 11 x87-DD-2 */ { O_iST, /* DD-0 FFREE */ O_iST, /* DD-1 FXCH */ O_iST, /* DD-2 FST */ O_iST, /* DD-3 FSTP */ O_iST, /* DD-4 FUCOM */ O_iST, /* DD-5 FUCOMP */ O_DoDB, /* DD-6 */ O_DoDB }, /* DD-7 */ /* 12 06 x87-DE-1 */ { O_wModrm, /* DE-0 FIADD */ O_wModrm, /* DE-1 FIMUL */ O_wModrm, /* DE-2 FICOM */ O_wModrm, /* DE-3 FICOMP */ O_wModrm, /* DE-4 FISUB */ O_wModrm, /* DE-5 FISUBR */ O_wModrm, /* DE-6 FIDIV */ O_wModrm }, /* DE-7 FIDIVR */ /* 13 x87-DE-2 */ { O_iST_ST, /* DE-0 FADDP */ O_iST_ST, /* DE-1 FMULP */ O_iST, /* DE-2 FCOMP */ O_NoOperands, /* DE-3 FCOMPP */ O_iST_ST, /* DE-4 FSUBP */ O_iST_ST, /* DE-5 FSUBRP */ O_iST_ST, /* DE-6 FDIVP */ O_iST_ST }, /* DE-7 FDIVRP */ /* 14 07 x87-DF-1 */ { O_wModrm, /* DF-0 FILD */ O_DoDB, /* DF-1 */ O_wModrm, /* DF-2 FIST */ O_wModrm, /* DF-3 FISTP */ O_tModrm, /* DF-4 FBLD */ O_qModrm, /* DF-5 FILD */ O_tModrm, /* DF-6 FBSTP */ O_qModrm }, /* DF-7 FISTP */ /* 15 x87-DF-2 */ { O_iST, /* DF-0 FFREE */ O_iST, /* DF-1 FXCH */ O_iST, /* DF-2 FST */ O_iST, /* DF-3 FSTP */ O_NoOperands, /* DF-4 FSTSW */ O_ST_iST, /* DF-5 FUCOMIP */ O_ST_iST, /* DF-6 FCOMIP */ O_DoDB }, /* DF-7 */ /* 16 01 x87-D9 Mod=3 TTT=4 */ { O_NoOperands, /* D9-0 FCHS */ O_NoOperands, /* D9-1 FABS */ O_DoDB, /* D9-2 */ O_DoDB, /* D9-3 */ O_NoOperands, /* D9-4 FTST */ O_NoOperands, /* D9-5 FXAM */ O_DoDB, /* D9-6 */ O_DoDB }, /* D9-7 */ /* 17 01 x87-D9 Mod=3 TTT=5 */ { O_NoOperands, /* D9-0 FLD1 */ O_NoOperands, /* D9-1 FLDL2T */ O_NoOperands, /* D9-2 FLDL2E */ O_NoOperands, /* D9-3 FLDPI */ O_NoOperands, /* D9-4 FLDLG2 */ O_NoOperands, /* D9-5 FLDLN2 */ O_NoOperands, /* D9-6 FLDZ */ O_DoDB }, /* D9-7 */ /* 18 01 x87-D9 Mod=3 TTT=6 */ { O_NoOperands, /* D9-0 F2XM1 */ O_NoOperands, /* D9-1 FYL2X */ O_NoOperands, /* D9-2 FPTAN */ O_NoOperands, /* D9-3 FPATAN */ O_NoOperands, /* D9-4 FXTRACT */ O_NoOperands, /* D9-5 FPREM1 */ O_NoOperands, /* D9-6 FDECSTP */ O_NoOperands }, /* D9-7 FINCSTP */ /* 19 01 x87-D9 Mod=3 TTT=7 */ { O_NoOperands, /* D9-0 FPREM */ O_NoOperands, /* D9-1 FYL2XP1 */ O_NoOperands, /* D9-2 FSQRT */ O_NoOperands, /* D9-3 FSINCOS */ O_NoOperands, /* D9-4 FRNDINT */ O_NoOperands, /* D9-5 FSCALE */ O_NoOperands, /* D9-6 FSIN */ O_NoOperands }, /* D9-7 FCOS */ /* 20 group 3 */ { O_bModrm_Ib, /* F6-0 TEST */ O_DoDB, /* F6-1 */ O_bModrm, /* F6-2 NOT */ O_bModrm, /* F6-3 NEG */ O_bModrm, /* F6-4 MUL */ O_bModrm, /* F6-5 IMUL */ O_bModrm, /* F6-6 DIV */ O_bModrm }, /* F6-7 IDIV */ /* 21 group 3 */ { O_vModrm_Iv, /* F7-0 TEST */ O_DoDB, /* F7-1 */ O_vModrm, /* F7-2 NOT */ O_vModrm, /* F7-3 NEG */ O_vModrm, /* F7-4 MUL */ O_vModrm, /* F7-5 IMUL */ O_vModrm, /* F7-6 DIV */ O_vModrm }, /* F7-7 IDIV */ /* 22 group 5 */ { O_vModrm, /* FF-0 INC */ O_vModrm, /* FF-1 DEC */ O_vModrm, /* FF-2 CALL */ O_fModrm, /* FF-3 CALL */ O_vModrm, /* FF-4 JMP */ O_fModrm, /* FF-5 JMP */ O_vModrm, /* FF-6 PUSH */ O_DoDB }, /* FF-7 */ /* 23 group 7 */ { O_Modrm, /* 0F-0 SGDT */ O_Modrm, /* 0F-1 SIDT */ O_Modrm, /* 0F-2 LGDT */ O_Modrm, /* 0F-3 LIDT */ O_wModrm, /* 0F-4 MSW */ O_DoDB, /* 0F-5 */ O_wModrm, /* 0F-6 LMSW */ O_Modrm }, /* 0F-7 INVLPG */ /* 24 x87-DB Mod=3 TTT != 4 */ { O_ST_iST, /* DB-0 FCMOVNB */ O_ST_iST, /* DB-1 FCMOVNE */ O_ST_iST, /* DB-2 FCMOVNBE */ O_ST_iST, /* DB-3 FCMOVNU */ O_DoDB, /* DB-4 */ O_ST_iST, /* DB-5 FUCOMI */ O_ST_iST, /* DB-6 FCOMI */ O_DoDB } /* DB-7 */ }; DWORD GetInstructionLengthFromAddress(LPBYTE pEip) { int G_mode_32; int mode_32; // local addressing mode indicator int opsize_32; // operand size flag int opcode; // current opcode int olen = 2; // operand length int alen = 2; // address length int end = FALSE; // end of instruction flag int mrm = FALSE; // indicator that modrm is generated unsigned char *action; // action for operand interpretation long tmp; // temporary storage field int indx; // temporary index int action2; // secondary action int instlen; // instruction length int segOvr = 0; // segment override opcode unsigned char BOPaction; int subcode; // bop subcode DECODEDATA decodeData; decodeData.mod = 0; decodeData.rm = 0; decodeData.ttt = 0; decodeData.fMovX = FALSE; decodeData.fMmRegEa = FALSE; decodeData.EAsize[0] = decodeData.EAsize[1] = 0; // no effective address G_mode_32 = 1; mode_32 = opsize_32 = (G_mode_32 == 1); // local addressing mode olen = alen = (1 + mode_32) << 1; // set operand/address lengths // 2 for 16-bit and 4 for 32-bit decodeData.pMem = pEip; // point to begin of instruction opcode = *(decodeData.pMem)++; // get opcode if (opcode == 0xc4 && *(decodeData.pMem) == 0xC4) { (decodeData.pMem)++; action = &BOPaction; BOPaction = IB | END; subcode = *(decodeData.pMem); if (subcode == 0x50 || subcode == 0x52 || subcode == 0x53 || subcode == 0x54 || subcode == 0x57 || subcode == 0x58 || subcode == 0x58) { BOPaction = IW | END; } } else { action = actiontbl + distbl[opcode].opr; /* get operand action */ } // loop through all operand actions do { action2 = (*action) & 0xc0; switch((*action++) & 0x3f) { case ALT: // alter the opcode if 32-bit if (opsize_32) { indx = *action++; } break; case STROP: // compute size of operands in indx // also if dword operands, change fifth // opcode letter from 'w' to 'd'. if (opcode & 1) { if (opsize_32) { indx = 4; } else { indx = 2; } } else { indx = 1; } break; case CHR: // insert a character action++; break; case CREG: // set debug, test or control reg break; case SREG2: // segment register // Handle special case for fs/gs (OPC0F adds SECTAB_OFFSET_5 // to these codes) if (opcode > 0x7e) { decodeData.ttt = BIT53((opcode-SECTAB_OFFSET_5)); } else { decodeData.ttt = BIT53(opcode); // set value to fall through } case SREG3: // segment register break; case BRSTR: // get index to register string decodeData.ttt = *action++; // from action table goto BREGlabel; case BOREG: // byte register (in opcode) decodeData.ttt = BIT20(opcode); // register is part of opcode goto BREGlabel; case ALSTR: decodeData.ttt = 0; // point to AL register BREGlabel: case BREG: // general register break; case WRSTR: // get index to register string decodeData.ttt = *action++; // from action table goto WREGlabel; case VOREG: // register is part of opcode decodeData.ttt = BIT20(opcode); goto VREGlabel; case AXSTR: decodeData.ttt = 0; // point to eAX register VREGlabel: case VREG: // general register WREGlabel: case WREG: // register is word size break; case MMWREG: break; case IST_ST: break; case ST_IST: ; case IST: ; break; case xBYTE: // set instruction to byte only decodeData.EAsize[0] = 1; break; case VAR: if (opsize_32) goto DWORDlabel; case xWORD: decodeData.EAsize[0] = 2; break; case EDWORD: opsize_32 = 1; // for control reg move, use eRegs case xDWORD: DWORDlabel: decodeData.EAsize[0] = 4; break; case MMQWORD: decodeData.fMmRegEa = TRUE; case QWORD: decodeData.EAsize[0] = 8; break; case xTBYTE: decodeData.EAsize[0] = 10; break; case FARPTR: if (opsize_32) { decodeData.EAsize[0] = 6; } else { decodeData.EAsize[0] = 4; } break; case LMODRM: // output modRM data type if (decodeData.mod != 3) ; else decodeData.EAsize[0] = 0; case MODRM: // output modrm string if (segOvr) // in case of segment override 0; break; case ADDRP: // address pointer decodeData.pMem += olen + 2; break; case REL8: // relative address 8-bit tmp = (long)*(char *)(decodeData.pMem)++; // get the 8-bit rel offset goto DoRelDispl; case REL16: // relative address 16-/32-bit tmp = 0; if (mode_32) MoveMemory(&tmp,decodeData.pMem,sizeof(long)); else MoveMemory(&tmp,decodeData.pMem,sizeof(short)); decodeData.pMem += alen; // skip over offset DoRelDispl: break; case UBYTE: // unsigned byte for int/in/out decodeData.pMem++; break; case IB: // operand is immediate byte if ((opcode & ~1) == 0xd4) { // postop for AAD/AAM is 0x0a if (*(decodeData.pMem)++ != 0x0a) // test post-opcode byte 0; break; } olen = 1; // set operand length goto DoImmed; case IW: // operand is immediate word olen = 2; // set operand length case IV: // operand is word or dword DoImmed: decodeData.pMem += olen; break; case OFFS: // operand is offset decodeData.EAsize[0] = (opcode & 1) ? olen : 1; if (segOvr) // in case of segment override 0; decodeData.pMem += alen; break; case GROUP: // operand is of group 1,2,4,6 or 8 action++; // output opcode symbol break; case GROUPT: // operand is of group 3,5 or 7 indx = *action; // get indx into group from action goto doGroupT; case EGROUPT: // x87 ESC (D8-DF) group index indx = BIT20(opcode) * 2; // get group index from opcode if (decodeData.mod == 3) { // some operand variations exists // for x87 and mod == 3 ++indx; // take the next group table entry if (indx == 3) { // for x87 ESC==D9 and mod==3 if (decodeData.ttt > 3) { // for those D9 instructions indx = 12 + decodeData.ttt; // offset index to table by 12 decodeData.ttt = decodeData.rm; // set secondary index to rm } } else if (indx == 7) { // for x87 ESC==DB and mod==3 if (decodeData.ttt == 4) { decodeData.ttt = decodeData.rm; // set secondary group table index } else if ((decodeData.ttt<4)||(decodeData.ttt>4 && decodeData.ttt<7)) { // adjust for pentium pro opcodes indx = 24; // offset index to table by 24 } } } doGroupT: // handle group with different types of operands action = actiontbl + groupt[indx][decodeData.ttt].opr; // get new action break; // // The secondary opcode table has been compressed in the // original design. Hence while disassembling the 0F sequence, // opcode needs to be displaced by an appropriate amount depending // on the number of "filled" entries in the secondary table. // These displacements are used throughout the code. // case OPC0F: // secondary opcode table (opcode 0F) opcode = *(decodeData.pMem)++; // get real opcode decodeData.fMovX = (BOOL)(opcode == 0xBF || opcode == 0xB7); if (opcode < 12) // for the first 12 opcodes opcode += SECTAB_OFFSET_1; // point to begin of sec op tab else if (opcode > 0x1f && opcode < 0x27) opcode += SECTAB_OFFSET_2; // adjust for undefined opcodes else if (opcode > 0x2f && opcode < 0x34) opcode += SECTAB_OFFSET_3; // adjust for undefined opcodes else if (opcode > 0x3f && opcode < 0x50) opcode += SECTAB_OFFSET_4; // adjust for undefined opcodes else if (opcode > 0x5f && opcode < 0xff) opcode += SECTAB_OFFSET_5; // adjust for undefined opcodes else opcode = SECTAB_OFFSET_UNDEF; // all non-existing opcodes goto getNxtByte1; case ADR_OVR: // address override mode_32 = !G_mode_32; // override addressing mode alen = (mode_32 + 1) << 1; // toggle address length goto getNxtByte; case OPR_OVR: // operand size override opsize_32 = !G_mode_32; // override operand size olen = (opsize_32 + 1) << 1; // toggle operand length goto getNxtByte; case SEG_OVR: // handle segment override segOvr = opcode; // save segment override opcode goto getNxtByte; case REP: // handle rep/lock prefixes getNxtByte: opcode = *(decodeData.pMem)++; // next byte is opcode getNxtByte1: action = actiontbl + distbl[opcode].opr; default: // opcode has no operand break; } switch (action2) { // secondary action case MRM: // generate modrm for later use if (!mrm) { // ignore if it has been generated //DIdoModrm(segOvr, &decodeData); int newmrm; // modrm byte int sib = 0; int ss; int ind; int oldrm; newmrm = *(decodeData.pMem)++; // get the mrm byte from instruction decodeData.mod = BIT76(newmrm); // get mod decodeData.ttt = BIT53(newmrm); // get reg - used outside routine decodeData.rm = BIT20(newmrm); // get rm if (decodeData.mod == 3) { // register only mode decodeData.EAsize[0] = 0; // no EA value to output } else { // 32-bit addressing mode oldrm = decodeData.rm; if (decodeData.rm == 4) { // rm == 4 implies sib byte sib = *(decodeData.pMem)++; // get s_i_b byte decodeData.rm = BIT20(sib); // return base } if (decodeData.mod == 0 && decodeData.rm == 5) { decodeData.pMem += 4; } if (oldrm == 4) { // finish processing sib ind = BIT53(sib); if (ind != 4) { ss = 1 << BIT76(sib); } } // output any displacement if (decodeData.mod == 1) { decodeData.pMem++; } else if (decodeData.mod == 2) { decodeData.pMem += 4; } } mrm = TRUE; // remember its generation } break; case COM: // insert a comma after operand break; case END: // end of instruction end = TRUE; break; } } while (!end); // loop til end of instruction instlen = (decodeData.pMem) - pEip; return instlen; } #endif IMPLEMENT_SHIM_END