Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4201 lines
108 KiB

/***********************************************************************
* Microsoft Puma
*
* Microsoft Confidential. Copyright 1994-1996 Microsoft Corporation.
*
* Component:
*
* File: x86dis.cpp
*
* File Comments:
*
*
***********************************************************************/
#include "pumap.h"
#include "x86.h"
#include <ctype.h>
#include <iomanip.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strstrea.h>
const unsigned char iregAL = 0;
const unsigned char iregCL = 1;
const unsigned char iregDL = 2;
const unsigned char iregBL = 3;
const unsigned char iregAH = 4;
const unsigned char iregCH = 5;
const unsigned char iregDH = 6;
const unsigned char iregBH = 7;
const char rgszReg8[8][4] =
{
"al",
"cl",
"dl",
"bl",
"ah",
"ch",
"dh",
"bh"
};
const unsigned char iregAX = 0;
const unsigned char iregCX = 1;
const unsigned char iregDX = 2;
const unsigned char iregBX = 3;
const unsigned char iregSP = 4;
const unsigned char iregBP = 5;
const unsigned char iregSI = 6;
const unsigned char iregDI = 7;
const char rgszReg16[8][4] =
{
"ax",
"cx",
"dx",
"bx",
"sp",
"bp",
"si",
"di"
};
const char rgszReg32[8][4] =
{
"eax",
"ecx",
"edx",
"ebx",
"esp",
"ebp",
"esi",
"edi"
};
const unsigned char iregES = 0;
const unsigned char iregCS = 1;
const unsigned char iregSS = 2;
const unsigned char iregDS = 3;
const unsigned char iregFS = 4;
const unsigned char iregGS = 5;
const char rgszSReg[8][4] =
{
"es",
"cs",
"ss",
"ds",
"fs",
"gs",
"??",
"??"
};
const char rgszBase16[8][8] =
{
"bx+si",
"bx+di",
"bp+si",
"bp+di",
"si",
"di",
"bp",
"bx"
};
const TRMT mptrmtx86trmt[] =
{
trmtUnknown, // trmtx86Unknown
trmtFallThrough, // trmtx86FallThrough
trmtTrap, // trmtx86Trap
trmtTrapCc, // trmtx86TrapCc
trmtBra, // trmtx86JmpShort
trmtBra, // trmtx86JmpNear
trmtBra, // trmtx86JmpFar
trmtBraInd, // trmtx86JmpInd
trmtBraInd, // trmtx86Ret
trmtBraInd, // trmtx86Iret
trmtBraCc, // trmtx86JmpCcShort
trmtBraCc, // trmtx86JmpCcNear
trmtBraCc, // trmtx86Loop
trmtBraCc, // trmtx86Jcxz
trmtCall, // trmtx86CallNear16
trmtCall, // trmtx86CallNear32
trmtCall, // trmtx86CallFar
trmtCallInd, // trmtx86CallInd
};
enum MODRMT // MODRM type
{
modrmtNo, // Not present
modrmtYes, // Present
modrmtMem, // Memory only
modrmtReg, // Register only
};
enum ICB // Immediate byte count
{
icbNil, // No immediate value
icbAP, // Far pointer
icbIb, // Immediate byte
icbIv, // Immediate operand size value
icbIw, // Immediate word
icbIw_Ib, // Immediate word and immediate byte
icbJb, // Byte displacement
icbJv, // Address size displacement
icbO, // Address size value
};
enum OPRNDT // Operand type
{
oprndtNil, // No operand
oprndtAP, // Far address
oprndtCd, // CRx register from MODRM reg
oprndtConst, // Constant from bValue
oprndtDd, // DRx register from MODRM reg
oprndtGvOp, // General register (operand size) from opcode
oprndtIb, // Immediate byte
oprndtIb2, // Immediate byte following word
oprndtIv, // Immediate operand size value
oprndtIw, // Immediate word
oprndtJb, // Relative address byte
oprndtJv, // Relative address operand size value
oprndtMmModrm, // Memory/MM register references from MODRM (MMX)
oprndtMmModrmReg, // MM register from MODRM reg (MMX)
oprndtModrm, // Memory/register references from MODRM
oprndtModrmReg, // General register from MODRM reg
oprndtModrmSReg, // Segment register from MODRM reg
oprndtOffset, // Address size immediate offset
oprndtRb, // General register (byte) from bValue
oprndtRv, // General register (operand size) from bValue
oprndtRw, // General register (word) from bValue
oprndtST, // Floating point top of stack
oprndtSTi, // Floating point register from MODRM reg
oprndtSw, // Segment register (word) from bValue
oprndtTd, // TRx register from MODRM reg
oprndtX, // DS:[eSI] for string instruction
oprndtY, // ES:[eDI] for string instruction
oprndtZ, // DS:[eBX] for XLAT
};
enum OPREFT // Operand reference type
{
opreftNil, // Operand not referenced (e.g. INVLPG)
opreftRd, // Operand is read
opreftRw, // Operand is read and written
opreftWr // Operand is written
};
struct OPRND // Operand
{
unsigned char opreft : 2;
unsigned char oprndt : 6;
unsigned char bValue;
};
struct OPS // Instruction operands
{
MODRMT modrmt;
ICB icb;
OPRND rgoprnd[3];
};
struct OPCD
{
const void *pvMnemonic;
const OPS *pops;
unsigned char trmtx86;
};
#if 1
// UNDONE: Work around problem initializing with const structs
#define DEFOPRND(name, opreft_, oprndt_, b) \
const unsigned char oprnd ## name ## _opreft = opreft ## opreft_; \
const unsigned char oprnd ## name ## _oprndt = oprndt ## oprndt_; \
const unsigned char oprnd ## name ## _b = b;
#else
#define DEFOPRND(name, opreft_, oprndt_, b) \
const OPRND oprnd ## name = \
{ \
opreft ## opreft_, \
oprndt ## oprndt_, \
b \
};
#endif
DEFOPRND(1, Nil, Const, 1 )
DEFOPRND(3, Nil, Const, 3 )
DEFOPRND(AP, Nil, AP, 0 )
DEFOPRND(Ib, Nil, Ib, 1 )
DEFOPRND(Ib2, Nil, Ib2, 1 )
DEFOPRND(Iv, Nil, Iv, 0 )
DEFOPRND(Iw, Nil, Iw, 2 )
DEFOPRND(Jb, Nil, Jb, 1 )
DEFOPRND(Jv, Nil, Jv, 0 )
DEFOPRND(M, Nil, Modrm, 0 )
DEFOPRND(Nil, Nil, Nil, 0 )
DEFOPRND(RdCd, Rd, Cd, 4 )
DEFOPRND(RdDd, Rd, Dd, 4 )
DEFOPRND(RdEb, Rd, Modrm, 1 )
DEFOPRND(RdEv, Rd, Modrm, 0 )
DEFOPRND(RdEw, Rd, Modrm, 2 )
DEFOPRND(RdGb, Rd, ModrmReg, 1 )
DEFOPRND(RdGv, Rd, ModrmReg, 0 )
DEFOPRND(RdGvOp, Rd, GvOp, 0 )
DEFOPRND(RdGw, Rd, ModrmReg, 2 )
DEFOPRND(RdMa, Rd, Modrm, 0 )
DEFOPRND(RdMd, Rd, Modrm, 4 )
DEFOPRND(RdMenv, Rd, Modrm, 0 )
DEFOPRND(RdMmd, Rd, MmModrm, 4 )
DEFOPRND(RdMmq, Rd, MmModrm, 8 )
DEFOPRND(RdMp, Rd, Modrm, 0 )
DEFOPRND(RdMq, Rd, Modrm, 8 )
DEFOPRND(RdMs, Rd, Modrm, 6 )
DEFOPRND(RdMsta, Rd, Modrm, 0 )
DEFOPRND(RdMt, Rd, Modrm, 10 )
DEFOPRND(RdMv, Rd, MmModrmReg, 0 )
DEFOPRND(RdMw, Rd, Modrm, 2 )
DEFOPRND(RdOb, Rd, Offset, 1 )
DEFOPRND(RdOv, Rd, Offset, 0 )
DEFOPRND(RdRbAL, Rd, Rb, iregAL )
DEFOPRND(RdRbCL, Rd, Rb, iregCL )
DEFOPRND(RdRd, Rd, Modrm, 4 )
DEFOPRND(RdRvAX, Rd, Rv, iregAX )
DEFOPRND(RdRwDX, Rd, Rw, iregDX )
DEFOPRND(RdSw, Rd, ModrmSReg, 2 )
DEFOPRND(RdSwCS, Rd, Sw, iregCS )
DEFOPRND(RdSwDS, Rd, Sw, iregDS )
DEFOPRND(RdSwES, Rd, Sw, iregES )
DEFOPRND(RdSwFS, Rd, Sw, iregFS )
DEFOPRND(RdSwGS, Rd, Sw, iregGS )
DEFOPRND(RdSwSS, Rd, Sw, iregSS )
DEFOPRND(RdTd, Rd, Td, 4 )
DEFOPRND(RdXb, Rd, X, 1 )
DEFOPRND(RdXv, Rd, X, 0 )
DEFOPRND(RdYb, Rd, Y, 1 )
DEFOPRND(RdYv, Rd, Y, 0 )
DEFOPRND(RdZb, Rd, Z, 1 )
DEFOPRND(RwEb, Rw, Modrm, 1 )
DEFOPRND(RwEv, Rw, Modrm, 0 )
DEFOPRND(RwEw, Rw, Modrm, 2 )
DEFOPRND(RwGb, Rw, ModrmReg, 1 )
DEFOPRND(RwGdOp, Rw, GvOp, 4 )
DEFOPRND(RwGv, Rw, ModrmReg, 0 )
DEFOPRND(RwGvOp, Rw, GvOp, 0 )
DEFOPRND(RwMq, Rw, Modrm, 8 )
DEFOPRND(RwMv, Wr, MmModrmReg, 0 )
DEFOPRND(RwRbAL, Rw, Rb, iregAL )
DEFOPRND(RwRvAX, Rw, Rv, iregAX )
DEFOPRND(ST, Nil, ST, 0 )
DEFOPRND(STi, Nil, STi, 0 )
DEFOPRND(WrCd, Wr, Cd, 4 )
DEFOPRND(WrDd, Wr, Dd, 4 )
DEFOPRND(WrEb, Wr, Modrm, 1 )
DEFOPRND(WrEv, Wr, Modrm, 0 )
DEFOPRND(WrEw, Wr, Modrm, 2 )
DEFOPRND(WrGb, Wr, ModrmReg, 1 )
DEFOPRND(WrGbOp, Wr, GvOp, 1 )
DEFOPRND(WrGd, Wr, ModrmReg, 4 )
DEFOPRND(WrGv, Wr, ModrmReg, 0 )
DEFOPRND(WrGvOp, Wr, GvOp, 0 )
DEFOPRND(WrMcache, Wr, Modrm, 32 ) // UNDONE: Really cache line
DEFOPRND(WrMd, Wr, Modrm, 4 )
DEFOPRND(WrMenv, Wr, Modrm, 0 )
DEFOPRND(WrMmd, Wr, MmModrm, 4 )
DEFOPRND(WrMmq, Wr, MmModrm, 8 )
DEFOPRND(WrMq, Wr, Modrm, 8 )
DEFOPRND(WrMs, Wr, Modrm, 6 )
DEFOPRND(WrMsta, Wr, Modrm, 0 )
DEFOPRND(WrMt, Wr, Modrm, 10 )
DEFOPRND(WrMv, Wr, MmModrmReg, 0 )
DEFOPRND(WrMw, Wr, Modrm, 2 )
DEFOPRND(WrOb, Wr, Offset, 1 )
DEFOPRND(WrOv, Wr, Offset, 0 )
DEFOPRND(WrRbAL, Wr, Rb, iregAL )
DEFOPRND(WrRd, Wr, Modrm, 4 )
DEFOPRND(WrRwAX, Wr, Rw, iregAX )
DEFOPRND(WrRvAX, Wr, Rv, iregAX )
DEFOPRND(WrSw, Wr, ModrmSReg, 0 )
DEFOPRND(WrSwDS, Wr, Sw, iregDS )
DEFOPRND(WrSwES, Wr, Sw, iregES )
DEFOPRND(WrSwFS, Wr, Sw, iregFS )
DEFOPRND(WrSwGS, Wr, Sw, iregGS )
DEFOPRND(WrSwSS, Wr, Sw, iregSS )
DEFOPRND(WrTd, Wr, Td, 4 )
DEFOPRND(WrYb, Wr, Y, 1 )
DEFOPRND(WrYv, Wr, Y, 0 )
// The following are default operand sets. These are sets of three
// operands that form the base for all possible instructions. The
// operand definitions may be incomplete and require information
// to be filled in by the instruction decoding process.
#if 1
// UNDONE: Work around problem initializing with const structs
#define REFOPRND(oprnd_) \
{ \
oprnd ## oprnd_ ## _opreft, \
oprnd ## oprnd_ ## _oprndt, \
oprnd ## oprnd_ ## _b \
}
#else
#define REFOPRND(oprnd_) \
oprnd ## oprnd_
#endif
#define DEFOPS(name, modrmt_, icb_, oprnd1, oprnd2, oprnd3) \
const OPS ops ## name = \
{ \
modrmt ## modrmt_, \
icb ## icb_, \
{ \
REFOPRND(oprnd1), \
REFOPRND(oprnd2), \
REFOPRND(oprnd3) \
} \
};
// name, modrmt, icb, oprnd1, oprnd2, oprnd3
DEFOPS(Nil, No, Nil, Nil, Nil, Nil ) // AAA
DEFOPS(3, No, Nil, 3, Nil, Nil ) // INT 3
DEFOPS(AP, No, AP, AP, Nil, Nil ) // CALL ptr16:16/32
DEFOPS(Ib, No, Ib, Ib, Nil, Nil ) // INT imm8
DEFOPS(Ib_RdRbAL, No, Ib, Ib, RdRbAL, Nil ) // OUT imm8,AL
DEFOPS(Ib_RdRvAX, No, Ib, Ib, RdRvAX, Nil ) // OUT imm8,eAX
DEFOPS(Iv, No, Iv, Iv, Nil, Nil ) // PUSH imm
DEFOPS(Iw, No, Iw, Iw, Nil, Nil ) // RET imm16
DEFOPS(Iw_Ib, No, Iw_Ib, Iw, Ib2, Nil ) // ENTER imm16,imm8
DEFOPS(Jb, No, Jb, Jb, Nil, Nil ) // JA rel8
DEFOPS(Jv, No, Jv, Jv, Nil, Nil ) // CALL rel
DEFOPS(M, No, Nil, M, Nil, Nil ) // INVLPG m
DEFOPS(RdEb, Yes, Nil, RdEb, Nil, Nil ) // IDIV r/m8
DEFOPS(RdEb_Ib, Yes, Ib, RdEb, Ib, Nil ) // CMP r/m8,imm8
DEFOPS(RdEb_RdGb, Yes, Nil, RdEb, RdGb, Nil ) // CMP r/m8,r8
DEFOPS(RdEv, Yes, Nil, RdEv, Nil, Nil ) // CALL r/m
DEFOPS(RdEv_Ib, Yes, Ib, RdEv, Ib, Nil ) // BT r/m,imm8
DEFOPS(RdEv_Iv, Yes, Iv, RdEv, Iv, Nil ) // CMP r/m,imm
DEFOPS(RdEv_RdGv, Yes, Nil, RdEv, RdGv, Nil ) // BT r/m,r
DEFOPS(RdEw, Yes, Nil, RdEw, Nil, Nil ) // LLDT r/m16
DEFOPS(RdGb_RdEb, Yes, Nil, RdGb, RdEb, Nil ) // CMP r8,r/m8
DEFOPS(RdGv_RdEv, Yes, Nil, RdGv, RdEv, Nil ) // CMP r,r/m
DEFOPS(RdGv_RdMa, Mem, Nil, RdGv, RdMa, Nil ) // BOUND r,m
DEFOPS(RdGvOp, No, Nil, RdGvOp, Nil, Nil ) // PUSH r
DEFOPS(RdMd, Mem, Nil, RdMd, Nil, Nil ) // FADD m32
DEFOPS(RdMenv, Mem, Nil, RdMenv, Nil, Nil ) // FLDENV m14/28
DEFOPS(RdMp, Mem, Nil, RdMp, Nil, Nil ) // CALL m16:16/32
DEFOPS(RdMq, Mem, Nil, RdMq, Nil, Nil ) // FADD m64
DEFOPS(RdMs, Mem, Nil, RdMs, Nil, Nil ) // LGDT m48
DEFOPS(RdMsta, Mem, Nil, RdMsta, Nil, Nil ) // FRSTOR m94/108
DEFOPS(RdMt, Mem, Nil, RdMt, Nil, Nil ) // FBLD m80
DEFOPS(RdMw, Mem, Nil, RdMw, Nil, Nil ) // FIADD m16
DEFOPS(RdRbAL_Ib, No, Ib, RdRbAL, Ib, Nil ) // CMP AL,imm8
DEFOPS(RdRvAX_Iv, No, Iv, RdRvAX, Iv, Nil ) // CMP eAX,imm
DEFOPS(RdRwDX_RdRbAL, No, Nil, RdRwDX, RdRbAL, Nil ) // OUT DX,AL
DEFOPS(RdRwDX_RdRvAX, No, Nil, RdRwDX, RdRvAX, Nil ) // OUT DX,eAX
DEFOPS(RdRwDX_RdXb, No, Nil, RdRwDX, RdXb, Nil ) // OUTS m8
DEFOPS(RdRwDX_RdXv, No, Nil, RdRwDX, RdXv, Nil ) // OUTS m
DEFOPS(RdSwCS, No, Nil, RdSwCS, Nil, Nil ) // PUSH CS
DEFOPS(RdSwDS, No, Nil, RdSwDS, Nil, Nil ) // PUSH DS
DEFOPS(RdSwES, No, Nil, RdSwES, Nil, Nil ) // PUSH ES
DEFOPS(RdSwFS, No, Nil, RdSwFS, Nil, Nil ) // PUSH FS
DEFOPS(RdSwGS, No, Nil, RdSwGS, Nil, Nil ) // PUSH GS
DEFOPS(RdSwSS, No, Nil, RdSwSS, Nil, Nil ) // PUSH SS
DEFOPS(RdXb, No, Nil, RdXb, Nil, Nil ) // LODS m8
DEFOPS(RdXb_RdYb, No, Nil, RdXb, RdYb, Nil ) // CMPS m8,m8
DEFOPS(RdXv, No, Nil, RdXv, Nil, Nil ) // LODS m
DEFOPS(RdXv_RdYv, No, Nil, RdXv, RdYv, Nil ) // CMPS m,m
DEFOPS(RdYb, No, Nil, RdYb, Nil, Nil ) // SCAS m8
DEFOPS(RdYv, No, Nil, RdYv, Nil, Nil ) // SCAS m
DEFOPS(RdZb, No, Nil, RdZb, Nil, Nil ) // XLAT m
DEFOPS(RwEb, Yes, Nil, RwEb, Nil, Nil ) // DEC r/m8
DEFOPS(RwEb_1, Yes, Nil, RwEb, 1, Nil ) // RCL r/m8,1
DEFOPS(RwEb_Ib, Yes, Ib, RwEb, Ib, Nil ) // RCL r/m8,imm8
DEFOPS(RwEb_RdGb, Yes, Nil, RwEb, RdGb, Nil ) // ADC r/m8,r8
DEFOPS(RwEb_RdRbCL, Yes, Nil, RwEb, RdRbCL, Nil ) // RCL r/m8,CL
DEFOPS(RwEb_RwGb, Yes, Nil, RwEb, RwGb, Nil ) // CMPXCHG r/m8,r8
DEFOPS(RwEv, Yes, Nil, RwEv, Nil, Nil ) // DEC r/m
DEFOPS(RwEv_1, Yes, Nil, RwEv, 1, Nil ) // RCL r/m,1
DEFOPS(RwEv_Ib, Yes, Ib, RwEv, Ib, Nil ) // ADC r/m,imm8
DEFOPS(RwEv_Iv, Yes, Iv, RwEv, Iv, Nil ) // ADC r/m,imm
DEFOPS(RwEv_RdGv, Yes, Nil, RwEv, RdGv, Nil ) // ADC r/m,r
DEFOPS(RwEv_RdGv_Ib, Yes, Ib, RwEv, RdGv, Ib, ) // SHLD r/m,r,imm8
DEFOPS(RwEv_RdGv_RdRbCL, Yes, Nil, RwEv, RdGv, RdRbCL ) // SHLD r/m,r,CL
DEFOPS(RwEv_RdRbCL, Yes, Nil, RwEv, RdRbCL, Nil ) // RCL r/m,CL
DEFOPS(RwEv_RwGv, Yes, Nil, RwEv, RwGv, Nil ) // CMPXCHG r/m,r
DEFOPS(RwEw_RdGw, Yes, Nil, RwEw, RdGw, Nil ) // ARPL r/m16,r16
DEFOPS(RwGb_RdEb, Yes, Nil, RwGb, RdEb, Nil ) // ADC r8,r/m8
DEFOPS(RwGb_RwEb, Yes, Nil, RwGb, RwEb, Nil ) // XCHG r8,r/m8
DEFOPS(RwGdOp, No, Nil, RwGdOp, Nil, Nil ) // BSWAP r32
DEFOPS(RwGv_RdEv, Yes, Nil, RwGv, RdEv, Nil ) // ADC r,r/m
DEFOPS(RwGv_RwEv, Yes, Nil, RwGv, RwEv, Nil ) // XCHG r,r/m
DEFOPS(RwGvOp, No, Nil, RwGvOp, Nil, Nil ) // DEC r
DEFOPS(RwMq, Mem, Nil, RwMq, Nil, Nil ) // CMPXCHG8B m64
DEFOPS(RwMv_Ib, Yes, Nil, RwMv, Ib, Nil ) // PSLLW mm,imm8
DEFOPS(RwMv_RdMmq, Yes, Nil, RwMv, RdMmq, Nil ) // PACKSSWB mm,mm/m64
DEFOPS(RwRbAL_Ib, No, Ib, RwRbAL, Ib, Nil ) // ADC AL,imm8
DEFOPS(RwRbAL_RdEb, Yes, Nil, RwRbAL, RdEb, Nil ) // DIV AL,r/m8
DEFOPS(RwRvAX_Iv, No, Iv, RwRvAX, Iv, Nil ) // ADC eAX,imm
DEFOPS(RwRvAX_RdEv, Yes, Nil, RwRvAX, RdEv, Nil ) // DIV eAX,r/m
DEFOPS(RwRvAX_RwGvOp, No, Nil, RwRvAX, RwGvOp, Nil ) // XCHG eAX,r
DEFOPS(ST_STi, Yes, Nil, ST, STi, Nil ) // FADD ST,ST(i)
DEFOPS(STi, Yes, Nil, STi, Nil, Nil ) // FCOM ST(i)
DEFOPS(STi_ST, Yes, Nil, STi, ST, Nil ) // FADD ST(i),ST
DEFOPS(WrCd_RdRd, Reg, Nil, WrCd, RdRd, Nil ) // MOV CRn,r
DEFOPS(WrDd_RdRd, Reg, Nil, WrDd, RdRd, Nil ) // MOV DRn,r
DEFOPS(WrEb, Yes, Nil, WrEb, Nil, Nil ) // SETA r/m8
DEFOPS(WrEb_Ib, Yes, Ib, WrEb, Ib, Nil ) // MOV r/m8,imm8
DEFOPS(WrEb_RdGb, Yes, Nil, WrEb, RdGb, Nil ) // MOV r/m8,r8
DEFOPS(WrEv, Yes, Nil, WrEv, Nil, Nil ) // POP r/m
DEFOPS(WrEv_Iv, Yes, Iv, WrEv, Iv, Nil ) // MOV r/m,imm
DEFOPS(WrEv_RdGv, Yes, Nil, WrEv, RdGv, Nil ) // MOV r/m,r
DEFOPS(WrEvReg_RdGv, Reg, Nil, WrEv, RdGv, Nil ) // CMOV r,r
DEFOPS(WrEw, Yes, Nil, WrEw, Nil, Nil ) // SLDT r/m16
DEFOPS(WrEw_RdSw, Yes, Nil, WrEw, RdSw, Nil ) // MOV r/m16,sreg
DEFOPS(WrGb_RdEb, Yes, Nil, WrGb, RdEb, Nil ) // MOV r8,r/m8
DEFOPS(WrGbOp_Ib, No, Ib, WrGbOp, Ib, Nil ) // MOV r8,imm8
DEFOPS(WrGd_RdEw, Yes, Nil, WrGd, RdEw, Nil ) // MOVSZ r32,r/m16
DEFOPS(WrGv_M, Mem, Nil, WrGv, M, Nil ) // LEA r,m
DEFOPS(WrGv_RdEb, Yes, Nil, WrGv, RdEb, Nil ) // MOVSX r,r/m8
DEFOPS(WrGv_RdEv, Yes, Nil, WrGv, RdEv, Nil ) // BSF r,r/m
DEFOPS(WrGv_RdEv_Ib, Yes, Ib, WrGv, RdEv, Ib ) // IMUL r,r/m,imm8
DEFOPS(WrGv_RdEv_Iv, Yes, Iv, WrGv, RdEv, Ib ) // IMUL r,r/m,imm
DEFOPS(WrGv_RdEw, Yes, Nil, WrGv, RdEw, Nil ) // MOVSX r,r/m16
DEFOPS(WrGv_RdMp, Mem, Nil, WrGv, RdMp, Nil ) // LDS r,m16:16/32
DEFOPS(WrGvOp, No, Nil, WrGvOp, Nil, Nil ) // POP r
DEFOPS(WrGvOp_Iv, No, Iv, WrGvOp, Iv, Nil ) // MOV r,imm
DEFOPS(WrMcache, Mem, Nil, WrMcache, Nil, Nil ) // ZALLOC m
DEFOPS(WrMd, Mem, Nil, WrMd, Nil, Nil ) // FST m32
DEFOPS(WrMenv, Mem, Nil, WrMenv, Nil, Nil ) // FSTENV m14/28
DEFOPS(WrMmd_RdMv, Yes, Nil, WrMmd, RdMv, Nil ) // MOVD mm,r/m32
DEFOPS(WrMmq_RdMv, Yes, Nil, WrMmq, RdMv, Nil ) // MOVQ mm,r/m64
DEFOPS(WrMq, Mem, Nil, WrMq, Nil, Nil ) // FST m64
DEFOPS(WrMs, Mem, Nil, WrMs, Nil, Nil ) // SGDT m48
DEFOPS(WrMsta, Mem, Nil, WrMsta, Nil, Nil ) // FNSAVE m94/108
DEFOPS(WrMt, Mem, Nil, WrMt, Nil, Nil ) // FBSTP m80
DEFOPS(WrMt_RdSw, Mem, Nil, WrMt, RdSw, Nil ) // SVDC m80,sreg
DEFOPS(WrMv_RdMmd, Yes, Nil, WrMv, RdMmd, Nil ) // MOVD r/m32,mm
DEFOPS(WrMv_RdMmq, Yes, Nil, WrMv, RdMmq, Nil ) // MOVQ r/m64,mm
DEFOPS(WrMw, Mem, Nil, WrMw, Nil, Nil ) // FNSTCW m16
DEFOPS(WrOb_RdRbAL, No, O, WrOb, RdRbAL, Nil ) // MOV moffs8,AL
DEFOPS(WrOv_RdRvAX, No, O, WrOv, RdRvAX, Nil ) // MOV moffs,eAX
DEFOPS(WrRbAL_Ib, No, Ib, WrRbAL, Ib, Nil ) // IN AL,imm8
DEFOPS(WrRbAL_RdOb, No, O, WrRbAL, RdOb, Nil ) // MOV AL,moffs8
DEFOPS(WrRbAL_RdRwDX, No, Nil, WrRbAL, RdRwDX, Nil ) // IN AL,DX
DEFOPS(WrRd_RdCd, Reg, Nil, WrRd, RdCd, Nil ) // MOV r,CRn
DEFOPS(WrRd_RdDd, Reg, Nil, WrRd, RdDd, Nil ) // MOV r,DRn
DEFOPS(WrRd_RdTd, Reg, Nil, WrRd, RdTd, Nil ) // MOV r,TRn
DEFOPS(WrRwAX, Yes, Nil, WrRwAX, Nil, Nil ) // FNSTSW AX
DEFOPS(WrRvAX_Ib, No, Ib, WrRvAX, Ib, Nil ) // IN eAX,imm8
DEFOPS(WrRvAX_RdOv, No, O, WrRvAX, RdOv, Nil ) // MOV eAX,moffs
DEFOPS(WrRvAX_RdRwDX, No, Nil, WrRvAX, RdRwDX, Nil ) // IN eAX,DX
DEFOPS(WrSw_RdEw, Yes, Nil, WrSw, RdEw, Nil ) // MOV sreg,r/m16,r16
DEFOPS(WrSw_RdMt, Mem, Nil, WrSw, RdMt, Nil ) // RSDC sreg,m80
DEFOPS(WrSwDS, No, Nil, WrSwDS, Nil, Nil ) // POP DS
DEFOPS(WrSwES, No, Nil, WrSwES, Nil, Nil ) // POP ES
DEFOPS(WrSwFS, No, Nil, WrSwFS, Nil, Nil ) // POP FS
DEFOPS(WrSwGS, No, Nil, WrSwGS, Nil, Nil ) // POP GS
DEFOPS(WrSwSS, No, Nil, WrSwSS, Nil, Nil ) // POP SS
DEFOPS(WrTd_RdRd, Reg, Nil, WrTd, RdRd, Nil ) // MOV TRn,r
DEFOPS(WrYb, No, Nil, WrYb, Nil, Nil ) // STOS m8
DEFOPS(WrYb_RdRwDX, No, Nil, WrYb, RdRwDX, Nil ) // INS m8,DX
DEFOPS(WrYb_RdXb, No, Nil, WrYb, RdXb, Nil ) // MOVS m8,m8
DEFOPS(WrYv, No, Nil, WrYv, Nil, Nil ) // STOS m
DEFOPS(WrYv_RdRwDX, No, Nil, WrYv, RdRwDX, Nil ) // INS m,DX
DEFOPS(WrYv_RdXv, No, Nil, WrYv, RdXv, Nil ) // MOVS m,m
#define DEFOPCD(pvMnemonic, ops_, trmtx86_) \
{ \
pvMnemonic, \
&ops ## ops_, \
trmtx86 ## trmtx86_ \
}
#define DEFOGRP(name) \
{ \
&rgopcd ## name, \
NULL, \
trmtx86Unknown \
}
const OPCD rgopcd80[8] = // Grp 1
{
// Mnemonic Operands trmtx86
DEFOPCD("add", RwEb_Ib, FallThrough ), // 00
DEFOPCD("or", RwEb_Ib, FallThrough ), // 01
DEFOPCD("adc", RwEb_Ib, FallThrough ), // 02
DEFOPCD("sbb", RwEb_Ib, FallThrough ), // 03
DEFOPCD("and", RwEb_Ib, FallThrough ), // 04
DEFOPCD("sub", RwEb_Ib, FallThrough ), // 05
DEFOPCD("xor", RwEb_Ib, FallThrough ), // 06
DEFOPCD("cmp", RdEb_Ib, FallThrough ), // 07
};
const OPCD rgopcd81[8] = // Grp 1
{
// Mnemonic Operands trmtx86
DEFOPCD("add", RwEv_Iv, FallThrough ), // 00
DEFOPCD("or", RwEv_Iv, FallThrough ), // 01
DEFOPCD("adc", RwEv_Iv, FallThrough ), // 02
DEFOPCD("sbb", RwEv_Iv, FallThrough ), // 03
DEFOPCD("and", RwEv_Iv, FallThrough ), // 04
DEFOPCD("sub", RwEv_Iv, FallThrough ), // 05
DEFOPCD("xor", RwEv_Iv, FallThrough ), // 06
DEFOPCD("cmp", RdEv_Iv, FallThrough ), // 07
};
const OPCD rgopcd83[8] = // Grp 1
{
// Mnemonic Operands trmtx86
DEFOPCD("add", RwEv_Ib, FallThrough ), // 00
DEFOPCD("or", RwEv_Ib, FallThrough ), // 01
DEFOPCD("adc", RwEv_Ib, FallThrough ), // 02
DEFOPCD("sbb", RwEv_Ib, FallThrough ), // 03
DEFOPCD("and", RwEv_Ib, FallThrough ), // 04
DEFOPCD("sub", RwEv_Ib, FallThrough ), // 05
DEFOPCD("xor", RwEv_Ib, FallThrough ), // 06
DEFOPCD("cmp", RdEv_Ib, FallThrough ), // 07
};
const OPCD rgopcdC0[8] = // Grp 2
{
// Mnemonic Operands trmtx86
DEFOPCD("rol", RwEb_Ib, FallThrough ), // 00
DEFOPCD("ror", RwEb_Ib, FallThrough ), // 01
DEFOPCD("rcl", RwEb_Ib, FallThrough ), // 02
DEFOPCD("rcr", RwEb_Ib, FallThrough ), // 03
DEFOPCD("shl", RwEb_Ib, FallThrough ), // 04
DEFOPCD("shr", RwEb_Ib, FallThrough ), // 05
DEFOPCD("sal", RwEb_Ib, FallThrough ), // 06
DEFOPCD("sar", RwEb_Ib, FallThrough ), // 07
};
const OPCD rgopcdC1[8] = // Grp 2
{
// Mnemonic Operands trmtx86
DEFOPCD("rol", RwEv_Ib, FallThrough ), // 00
DEFOPCD("ror", RwEv_Ib, FallThrough ), // 01
DEFOPCD("rcl", RwEv_Ib, FallThrough ), // 02
DEFOPCD("rcr", RwEv_Ib, FallThrough ), // 03
DEFOPCD("shl", RwEv_Ib, FallThrough ), // 04
DEFOPCD("shr", RwEv_Ib, FallThrough ), // 05
DEFOPCD("sal", RwEv_Ib, FallThrough ), // 06
DEFOPCD("sar", RwEv_Ib, FallThrough ), // 07
};
const OPCD rgopcdD0[8] = // Grp 2
{
// Mnemonic Operands trmtx86
DEFOPCD("rol", RwEb_1, FallThrough ), // 00
DEFOPCD("ror", RwEb_1, FallThrough ), // 01
DEFOPCD("rcl", RwEb_1, FallThrough ), // 02
DEFOPCD("rcr", RwEb_1, FallThrough ), // 03
DEFOPCD("shl", RwEb_1, FallThrough ), // 04
DEFOPCD("shr", RwEb_1, FallThrough ), // 05
DEFOPCD("sal", RwEb_1, FallThrough ), // 06
DEFOPCD("sar", RwEb_1, FallThrough ), // 07
};
const OPCD rgopcdD1[8] = // Grp 2
{
// Mnemonic Operands trmtx86
DEFOPCD("rol", RwEv_1, FallThrough ), // 00
DEFOPCD("ror", RwEv_1, FallThrough ), // 01
DEFOPCD("rcl", RwEv_1, FallThrough ), // 02
DEFOPCD("rcr", RwEv_1, FallThrough ), // 03
DEFOPCD("shl", RwEv_1, FallThrough ), // 04
DEFOPCD("shr", RwEv_1, FallThrough ), // 05
DEFOPCD("sal", RwEv_1, FallThrough ), // 06
DEFOPCD("sar", RwEv_1, FallThrough ), // 07
};
const OPCD rgopcdD2[8] = // Grp 2
{
// Mnemonic Operands trmtx86
DEFOPCD("rol", RwEb_RdRbCL, FallThrough ), // 00
DEFOPCD("ror", RwEb_RdRbCL, FallThrough ), // 01
DEFOPCD("rcl", RwEb_RdRbCL, FallThrough ), // 02
DEFOPCD("rcr", RwEb_RdRbCL, FallThrough ), // 03
DEFOPCD("shl", RwEb_RdRbCL, FallThrough ), // 04
DEFOPCD("shr", RwEb_RdRbCL, FallThrough ), // 05
DEFOPCD("sal", RwEb_RdRbCL, FallThrough ), // 06
DEFOPCD("sar", RwEb_RdRbCL, FallThrough ), // 07
};
const OPCD rgopcdD3[8] = // Grp 2
{
// Mnemonic Operands trmtx86
DEFOPCD("rol", RwEv_RdRbCL, FallThrough ), // 00
DEFOPCD("ror", RwEv_RdRbCL, FallThrough ), // 01
DEFOPCD("rcl", RwEv_RdRbCL, FallThrough ), // 02
DEFOPCD("rcr", RwEv_RdRbCL, FallThrough ), // 03
DEFOPCD("shl", RwEv_RdRbCL, FallThrough ), // 04
DEFOPCD("shr", RwEv_RdRbCL, FallThrough ), // 05
DEFOPCD("sal", RwEv_RdRbCL, FallThrough ), // 06
DEFOPCD("sar", RwEv_RdRbCL, FallThrough ), // 07
};
const OPCD rgopcdF6[8] = // Grp 3
{
// Mnemonic Operands trmtx86
DEFOPCD("test", RdEb_Ib, FallThrough ), // 00
DEFOPCD("test", RdEb_Ib, FallThrough ), // 01
DEFOPCD("not", RwEb, FallThrough ), // 02
DEFOPCD("neg", RwEb, FallThrough ), // 03
DEFOPCD("mul", RwRbAL_RdEb, FallThrough ), // 04
DEFOPCD("imul", RdEb, FallThrough ), // 05
DEFOPCD("div", RwRbAL_RdEb, TrapCc ), // 06
DEFOPCD("idiv", RdEb, TrapCc ), // 07
};
const OPCD rgopcdF7[8] = // Grp 3
{
// Mnemonic Operands trmtx86
DEFOPCD("test", RdEv_Iv, FallThrough ), // 00
DEFOPCD("test", RdEv_Iv, FallThrough ), // 01
DEFOPCD("not", RwEv, FallThrough ), // 02
DEFOPCD("neg", RwEv, FallThrough ), // 03
DEFOPCD("mul", RwRvAX_RdEv, FallThrough ), // 04
DEFOPCD("imul", RdEv, FallThrough ), // 05
DEFOPCD("div", RwRvAX_RdEv, TrapCc ), // 06
DEFOPCD("idiv", RwRvAX_RdEv, TrapCc ), // 07
};
const OPCD rgopcdFE[8] = // Grp 4
{
// Mnemonic Operands trmtx86
DEFOPCD("inc", RwEb, FallThrough ), // 00
DEFOPCD("dec", RwEb, FallThrough ), // 01
DEFOPCD(NULL, Nil, Unknown ), // 02
DEFOPCD(NULL, Nil, Unknown ), // 03
DEFOPCD(NULL, Nil, Unknown ), // 04
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD(NULL, Nil, Unknown ), // 06
DEFOPCD(NULL, Nil, Unknown ), // 07
};
const OPCD rgopcdFF[8] = // Grp 5
{
// Mnemonic Operands trmtx86
DEFOPCD("inc", RwEv, FallThrough ), // 00
DEFOPCD("dec", RwEv, FallThrough ), // 01
DEFOPCD("call", RdEv, CallInd ), // 02
DEFOPCD("call", RdMp, CallInd ), // 03
DEFOPCD("jmp", RdEv, JmpInd ), // 04
DEFOPCD("jmp", RdMp, JmpInd ), // 05
DEFOPCD("push", RdEv, FallThrough ), // 06
DEFOPCD(NULL, Nil, Unknown ), // 07
};
const OPCD rgopcd0F00[8] = // Grp 6
{
// Mnemonic Operands trmtx86
DEFOPCD("sldt", WrEw, FallThrough ), // 00
DEFOPCD("str", WrEw, FallThrough ), // 01
DEFOPCD("lldt", RdEw, FallThrough ), // 02
DEFOPCD("ltr", RdEw, FallThrough ), // 03
DEFOPCD("verr", RdEw, FallThrough ), // 04
DEFOPCD("verw", RdEw, FallThrough ), // 05
DEFOPCD(NULL, Nil, Unknown ), // 06
DEFOPCD(NULL, Nil, Unknown ), // 07
};
const OPCD rgopcd0F01[8] = // Grp 7
{
// Mnemonic Operands trmtx86
DEFOPCD("sgdt", WrMs, FallThrough ), // 00
DEFOPCD("sidt", WrMs, FallThrough ), // 01
DEFOPCD("lgdt", RdMs, FallThrough ), // 02
DEFOPCD("lidt", RdMs, FallThrough ), // 03
DEFOPCD("smsw", WrEw, FallThrough ), // 04
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD("lmsw", RdEw, FallThrough ), // 06
DEFOPCD("invlpg", M, FallThrough ), // 07
};
const OPCD rgopcd0F71[8] =
{
// Mnemonic Operands trmtx86
DEFOPCD(NULL, Nil, Unknown ), // 00
DEFOPCD(NULL, Nil, Unknown ), // 01
DEFOPCD("psrlw", RwMv_Ib, FallThrough ), // 02 MMX
DEFOPCD(NULL, Nil, Unknown ), // 03
DEFOPCD("psraw", RwMv_Ib, FallThrough ), // 04 MMX
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD("psllw", RwMv_Ib, FallThrough ), // 06 MMX
DEFOPCD(NULL, Nil, Unknown ), // 07
};
const OPCD rgopcd0F72[8] =
{
// Mnemonic Operands trmtx86
DEFOPCD(NULL, Nil, Unknown ), // 00
DEFOPCD(NULL, Nil, Unknown ), // 01
DEFOPCD("psrld", RwMv_Ib, FallThrough ), // 02 MMX
DEFOPCD(NULL, Nil, Unknown ), // 03
DEFOPCD("psrad", RwMv_Ib, FallThrough ), // 04 MMX
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD("pslld", RwMv_Ib, FallThrough ), // 06 MMX
DEFOPCD(NULL, Nil, Unknown ), // 07
};
const OPCD rgopcd0F73[8] =
{
// Mnemonic Operands trmtx86
DEFOPCD(NULL, Nil, Unknown ), // 00
DEFOPCD(NULL, Nil, Unknown ), // 01
DEFOPCD("psrlq", RwMv_Ib, FallThrough ), // 02 MMX
DEFOPCD(NULL, Nil, Unknown ), // 03
DEFOPCD(NULL, Nil, Unknown ), // 04
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD("psllq", RwMv_Ib, FallThrough ), // 06 MMX
DEFOPCD(NULL, Nil, Unknown ), // 07
};
const OPCD rgopcd0FBA[8] = // Grp 8
{
// Mnemonic Operands trmtx86
DEFOPCD(NULL, Nil, Unknown ), // 00
DEFOPCD(NULL, Nil, Unknown ), // 01
DEFOPCD(NULL, Nil, Unknown ), // 02
DEFOPCD(NULL, Nil, Unknown ), // 03
DEFOPCD("bt", RdEv_Ib, FallThrough ), // 04
DEFOPCD("bts", RwEv_Ib, FallThrough ), // 05
DEFOPCD("btr", RwEv_Ib, FallThrough ), // 06
DEFOPCD("btc", RwEv_Ib, FallThrough ), // 07
};
const OPCD rgopcd0FC7[8] =
{
// Mnemonic Operands trmtx86
DEFOPCD(NULL, Nil, Unknown ), // 00
DEFOPCD("cmpxchg8b", RwMq, FallThrough ), // 01
DEFOPCD(NULL, Nil, Unknown ), // 02
DEFOPCD(NULL, Nil, Unknown ), // 03
DEFOPCD(NULL, Nil, Unknown ), // 04
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD(NULL, Nil, Unknown ), // 06
DEFOPCD(NULL, Nil, Unknown ), // 07
};
const OPCD rgopcdD8[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fadd", RdMd, FallThrough ), // 00
DEFOPCD("fmul", RdMd, FallThrough ), // 01
DEFOPCD("fcom", RdMd, FallThrough ), // 02
DEFOPCD("fcomp", RdMd, FallThrough ), // 03
DEFOPCD("fsub", RdMd, FallThrough ), // 04
DEFOPCD("fsubr", RdMd, FallThrough ), // 05
DEFOPCD("fdiv", RdMd, FallThrough ), // 06
DEFOPCD("fdivr", RdMd, FallThrough ), // 07
};
const OPCD rgopcdD9[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fld", RdMd, FallThrough ), // 00
DEFOPCD(NULL, Nil, Unknown ), // 01
DEFOPCD("fst", WrMd, FallThrough ), // 02
DEFOPCD("fstp", WrMd, FallThrough ), // 03
DEFOPCD("fldenv", RdMenv, FallThrough ), // 04
DEFOPCD("fldcw", RdMw, FallThrough ), // 05
DEFOPCD("fnstenv", WrMenv, FallThrough ), // 06
DEFOPCD("fnstcw", WrMw, FallThrough ), // 07
};
const OPCD rgopcdDA[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fiadd", RdMd, FallThrough ), // 00
DEFOPCD("fimul", RdMd, FallThrough ), // 01
DEFOPCD("ficom", RdMd, FallThrough ), // 02
DEFOPCD("ficomp", RdMd, FallThrough ), // 03
DEFOPCD("fisub", RdMd, FallThrough ), // 04
DEFOPCD("fisubr", RdMd, FallThrough ), // 05
DEFOPCD("fidiv", RdMd, FallThrough ), // 06
DEFOPCD("fidivr", RdMd, FallThrough ), // 07
};
const OPCD rgopcdDB[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fild", RdMd, FallThrough ), // 00
DEFOPCD(NULL, Nil, Unknown ), // 01
DEFOPCD("fist", WrMd, FallThrough ), // 02
DEFOPCD("fistp", WrMd, FallThrough ), // 03
DEFOPCD(NULL, Nil, Unknown ), // 04
DEFOPCD("fld", RdMt, FallThrough ), // 05
DEFOPCD(NULL, Nil, Unknown ), // 06
DEFOPCD("fstp", WrMt, FallThrough ), // 07
};
const OPCD rgopcdDC[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fadd", RdMq, FallThrough ), // 00
DEFOPCD("fmul", RdMq, FallThrough ), // 01
DEFOPCD("fcom", RdMq, FallThrough ), // 02
DEFOPCD("fcomp", RdMq, FallThrough ), // 03
DEFOPCD("fsub", RdMq, FallThrough ), // 04
DEFOPCD("fsubr", RdMq, FallThrough ), // 05
DEFOPCD("fdiv", RdMq, FallThrough ), // 06
DEFOPCD("fdivr", RdMq, FallThrough ), // 07
};
const OPCD rgopcdDD[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fld", RdMq, FallThrough ), // 00
DEFOPCD(NULL, Nil, Unknown ), // 01
DEFOPCD("fst", WrMq, FallThrough ), // 02
DEFOPCD("fstp", WrMq, FallThrough ), // 03
DEFOPCD("frstor", RdMsta, FallThrough ), // 04
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD("fnsave", WrMsta, FallThrough ), // 06
DEFOPCD("fnstsw", WrMw, FallThrough ), // 07
};
const OPCD rgopcdDE[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fiadd", RdMw, FallThrough ), // 00
DEFOPCD("fimul", RdMw, FallThrough ), // 01
DEFOPCD("ficom", RdMw, FallThrough ), // 02
DEFOPCD("ficomp", RdMw, FallThrough ), // 03
DEFOPCD("fisub", RdMw, FallThrough ), // 04
DEFOPCD("fisubr", RdMw, FallThrough ), // 05
DEFOPCD("fidiv", RdMw, FallThrough ), // 06
DEFOPCD("fidivr", RdMw, FallThrough ), // 07
};
const OPCD rgopcdDF[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fild", RdMq, FallThrough ), // 00
DEFOPCD(NULL, Nil, Unknown ), // 01
DEFOPCD("fist", WrMq, FallThrough ), // 02
DEFOPCD("fistp", WrMq, FallThrough ), // 03
DEFOPCD("fbld", RdMt, FallThrough ), // 04
DEFOPCD("fild", RdMq, FallThrough ), // 05
DEFOPCD("fbstp", WrMt, FallThrough ), // 06
DEFOPCD("fistp", WrMq, FallThrough ), // 07
};
const OPCD rgopcdD8_[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fadd", ST_STi, FallThrough ), // 00
DEFOPCD("fmul", ST_STi, FallThrough ), // 01
DEFOPCD("fcom", STi, FallThrough ), // 02
DEFOPCD("fcomp", STi, FallThrough ), // 03
DEFOPCD("fsub", ST_STi, FallThrough ), // 04
DEFOPCD("fsubr", ST_STi, FallThrough ), // 05
DEFOPCD("fdiv", ST_STi, FallThrough ), // 06
DEFOPCD("fdivr", ST_STi, FallThrough ), // 07
};
const OPCD rgopcdD9_[64] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fld", STi, FallThrough ), // 00
DEFOPCD("fld", STi, FallThrough ), // 01
DEFOPCD("fld", STi, FallThrough ), // 02
DEFOPCD("fld", STi, FallThrough ), // 03
DEFOPCD("fld", STi, FallThrough ), // 04
DEFOPCD("fld", STi, FallThrough ), // 05
DEFOPCD("fld", STi, FallThrough ), // 06
DEFOPCD("fld", STi, FallThrough ), // 07
DEFOPCD("fxch", STi, FallThrough ), // 08
DEFOPCD("fxch", STi, FallThrough ), // 09
DEFOPCD("fxch", STi, FallThrough ), // 0A
DEFOPCD("fxch", STi, FallThrough ), // 0B
DEFOPCD("fxch", STi, FallThrough ), // 0C
DEFOPCD("fxch", STi, FallThrough ), // 0D
DEFOPCD("fxch", STi, FallThrough ), // 0E
DEFOPCD("fxch", STi, FallThrough ), // 0F
DEFOPCD("fnop", Nil, FallThrough ), // 10
DEFOPCD(NULL, Nil, Unknown ), // 11
DEFOPCD(NULL, Nil, Unknown ), // 12
DEFOPCD(NULL, Nil, Unknown ), // 13
DEFOPCD(NULL, Nil, Unknown ), // 14
DEFOPCD(NULL, Nil, Unknown ), // 15
DEFOPCD(NULL, Nil, Unknown ), // 16
DEFOPCD(NULL, Nil, Unknown ), // 17
DEFOPCD(NULL, Nil, Unknown ), // 18
DEFOPCD(NULL, Nil, Unknown ), // 19
DEFOPCD(NULL, Nil, Unknown ), // 1A
DEFOPCD(NULL, Nil, Unknown ), // 1B
DEFOPCD(NULL, Nil, Unknown ), // 1C
DEFOPCD(NULL, Nil, Unknown ), // 1D
DEFOPCD(NULL, Nil, Unknown ), // 1E
DEFOPCD(NULL, Nil, Unknown ), // 1F
DEFOPCD("fchs", Nil, FallThrough ), // 20
DEFOPCD("fabs", Nil, FallThrough ), // 21
DEFOPCD(NULL, Nil, Unknown ), // 22
DEFOPCD(NULL, Nil, Unknown ), // 23
DEFOPCD("ftst", Nil, FallThrough ), // 24
DEFOPCD("fxam", Nil, FallThrough ), // 25
DEFOPCD(NULL, Nil, Unknown ), // 26
DEFOPCD(NULL, Nil, Unknown ), // 27
DEFOPCD("fld1", Nil, FallThrough ), // 28
DEFOPCD("fldl2t", Nil, FallThrough ), // 29
DEFOPCD("fldl2e", Nil, FallThrough ), // 2A
DEFOPCD("fldpi", Nil, FallThrough ), // 2B
DEFOPCD("fldlg2", Nil, FallThrough ), // 2C
DEFOPCD("fldln2", Nil, FallThrough ), // 2D
DEFOPCD("fldz", Nil, FallThrough ), // 2E
DEFOPCD(NULL, Nil, Unknown ), // 2F
DEFOPCD("f2xm1", Nil, FallThrough ), // 30
DEFOPCD("fyl2x", Nil, FallThrough ), // 31
DEFOPCD("fptan", Nil, FallThrough ), // 32
DEFOPCD("fpatan", Nil, FallThrough ), // 33
DEFOPCD("fxtract", Nil, FallThrough ), // 34
DEFOPCD("fprem1", Nil, FallThrough ), // 35
DEFOPCD("fdecstp", Nil, FallThrough ), // 36
DEFOPCD("fincstp", Nil, FallThrough ), // 37
DEFOPCD("fprem", Nil, FallThrough ), // 38
DEFOPCD("fyl2xp1", Nil, FallThrough ), // 39
DEFOPCD("fsqrt", Nil, FallThrough ), // 3A
DEFOPCD("fsincos", Nil, FallThrough ), // 3B
DEFOPCD("frndint", Nil, FallThrough ), // 3C
DEFOPCD("fscale", Nil, FallThrough ), // 3D
DEFOPCD("fsin", Nil, FallThrough ), // 3E
DEFOPCD("fcos", Nil, FallThrough ), // 3F
};
const OPCD opcdDAE9 =
DEFOPCD("fucompp", Nil, FallThrough );
const OPCD rgopcdDA_[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fcmovb", ST_STi, FallThrough ), // 00
DEFOPCD("fcmove", ST_STi, FallThrough ), // 01
DEFOPCD("fcmovbe", ST_STi, FallThrough ), // 02
DEFOPCD("fcmovu", ST_STi, FallThrough ), // 03
DEFOPCD(NULL, Nil, Unknown ), // 04
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD(NULL, Nil, Unknown ), // 06
DEFOPCD(NULL, Nil, Unknown ), // 07
};
const OPCD rgopcdDB__[17] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("feni", Nil, FallThrough ), // 00
DEFOPCD("fdisi", Nil, FallThrough ), // 01
DEFOPCD("fnclex", Nil, FallThrough ), // 02
DEFOPCD("fninit", Nil, FallThrough ), // 03
DEFOPCD("fsetpm", Nil, FallThrough ), // 04
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD(NULL, Nil, Unknown ), // 06
DEFOPCD(NULL, Nil, Unknown ), // 07
DEFOPCD("fucomi", ST_STi, Unknown ), // 08
DEFOPCD(NULL, Nil, Unknown ), // 09
DEFOPCD(NULL, Nil, Unknown ), // 0A
DEFOPCD(NULL, Nil, Unknown ), // 0B
DEFOPCD(NULL, Nil, Unknown ), // 0C
DEFOPCD(NULL, Nil, Unknown ), // 0D
DEFOPCD(NULL, Nil, Unknown ), // 0E
DEFOPCD(NULL, Nil, Unknown ), // 0F
DEFOPCD("fcomi", ST_STi, Unknown ), // 10
};
const OPCD rgopcdDB_[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fcmovnb", ST_STi, FallThrough ), // 00
DEFOPCD("fcmovne", ST_STi, FallThrough ), // 01
DEFOPCD("fcmovnbe", ST_STi, FallThrough ), // 02
DEFOPCD("fcmovnu", ST_STi, FallThrough ), // 03
DEFOPCD(NULL, Nil, Unknown ), // 04
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD(NULL, Nil, Unknown ), // 06
DEFOPCD(NULL, Nil, Unknown ), // 07
};
const OPCD rgopcdDC_[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fadd", STi_ST, FallThrough ), // 00
DEFOPCD("fmul", STi_ST, FallThrough ), // 01
DEFOPCD(NULL, Nil, Unknown ), // 02
DEFOPCD(NULL, Nil, Unknown ), // 03
DEFOPCD("fsubr", STi_ST, FallThrough ), // 04
DEFOPCD("fsub", STi_ST, FallThrough ), // 05
DEFOPCD("fdivr", STi_ST, FallThrough ), // 06
DEFOPCD("fdiv", STi_ST, FallThrough ), // 07
};
const OPCD rgopcdDD_[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("ffree", STi, FallThrough ), // 00
DEFOPCD(NULL, Nil, Unknown ), // 01
DEFOPCD("fst", STi, FallThrough ), // 02
DEFOPCD("fstp", STi, FallThrough ), // 03
DEFOPCD("fucom", STi, FallThrough ), // 04
DEFOPCD("fucomp", STi, FallThrough ), // 05
DEFOPCD(NULL, Nil, Unknown ), // 06
DEFOPCD(NULL, Nil, Unknown ), // 07
};
const OPCD rgopcdDE_[8] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("faddp", STi_ST, FallThrough ), // 00
DEFOPCD("fmulp", STi_ST, FallThrough ), // 01
DEFOPCD(NULL, Nil, Unknown ), // 02
DEFOPCD(NULL, Nil, Unknown ), // 03
DEFOPCD("fsubrp", STi_ST, FallThrough ), // 04
DEFOPCD("fsubp", STi_ST, FallThrough ), // 05
DEFOPCD("fdivrp", STi_ST, FallThrough ), // 06
DEFOPCD("fdivp", STi_ST, FallThrough ), // 07
};
const OPCD opcdDED9 =
DEFOPCD("fcompp", Nil, FallThrough );
const OPCD rgopcdDF__[17] = // Floating point
{
// Mnemonic Operands trmtx86
DEFOPCD("fnstsw", WrRwAX, FallThrough ), // 00
DEFOPCD(NULL, Nil, Unknown ), // 01
DEFOPCD(NULL, Nil, Unknown ), // 02
DEFOPCD(NULL, Nil, Unknown ), // 03
DEFOPCD(NULL, Nil, Unknown ), // 04
DEFOPCD(NULL, Nil, Unknown ), // 05
DEFOPCD(NULL, Nil, Unknown ), // 06
DEFOPCD(NULL, Nil, Unknown ), // 07
DEFOPCD("fucomip", ST_STi, Unknown ), // 08
DEFOPCD(NULL, Nil, Unknown ), // 09
DEFOPCD(NULL, Nil, Unknown ), // 0A
DEFOPCD(NULL, Nil, Unknown ), // 0B
DEFOPCD(NULL, Nil, Unknown ), // 0C
DEFOPCD(NULL, Nil, Unknown ), // 0D
DEFOPCD(NULL, Nil, Unknown ), // 0E
DEFOPCD(NULL, Nil, Unknown ), // 0F
DEFOPCD("fcomip", ST_STi, Unknown ), // 10
};
const OPCD rgopcd[256] =
{
// Mnemonic Operands trmtx86
DEFOPCD("add", RwEb_RdGb, FallThrough ), // 00
DEFOPCD("add", RwEv_RdGv, FallThrough ), // 01
DEFOPCD("add", RwGb_RdEb, FallThrough ), // 02
DEFOPCD("add", RwGv_RdEv, FallThrough ), // 03
DEFOPCD("add", RwRbAL_Ib, FallThrough ), // 04
DEFOPCD("add", RwRvAX_Iv, FallThrough ), // 05
DEFOPCD("push", RdSwES, FallThrough ), // 06
DEFOPCD("pop", WrSwES, FallThrough ), // 07
DEFOPCD("or", RwEb_RdGb, FallThrough ), // 08
DEFOPCD("or", RwEv_RdGv, FallThrough ), // 09
DEFOPCD("or", RwGb_RdEb, FallThrough ), // 0A
DEFOPCD("or", RwGv_RdEv, FallThrough ), // 0B
DEFOPCD("or", RwRbAL_Ib, FallThrough ), // 0C
DEFOPCD("or", RwRvAX_Iv, FallThrough ), // 0D
DEFOPCD("push", RdSwCS, FallThrough ), // 0E
DEFOPCD(NULL, Nil, FallThrough ), // 0F Two byte opcode
DEFOPCD("adc", RwEb_RdGb, FallThrough ), // 10
DEFOPCD("adc", RwEv_RdGv, FallThrough ), // 11
DEFOPCD("adc", RwGb_RdEb, FallThrough ), // 12
DEFOPCD("adc", RwGv_RdEv, FallThrough ), // 13
DEFOPCD("adc", RwRbAL_Ib, FallThrough ), // 14
DEFOPCD("adc", RwRvAX_Iv, FallThrough ), // 15
DEFOPCD("push", RdSwSS, FallThrough ), // 16
DEFOPCD("pop", WrSwSS, FallThrough ), // 17
DEFOPCD("sbb", RwEb_RdGb, FallThrough ), // 18
DEFOPCD("sbb", RwEv_RdGv, FallThrough ), // 19
DEFOPCD("sbb", RwGb_RdEb, FallThrough ), // 1A
DEFOPCD("sbb", RwGv_RdEv, FallThrough ), // 1B
DEFOPCD("sbb", RwRbAL_Ib, FallThrough ), // 1C
DEFOPCD("sbb", RwRvAX_Iv, FallThrough ), // 1D
DEFOPCD("push", RdSwDS, FallThrough ), // 1E
DEFOPCD("pop", WrSwDS, FallThrough ), // 1F
DEFOPCD("and", RwEb_RdGb, FallThrough ), // 20
DEFOPCD("and", RwEv_RdGv, FallThrough ), // 21
DEFOPCD("and", RwGb_RdEb, FallThrough ), // 22
DEFOPCD("and", RwGv_RdEv, FallThrough ), // 23
DEFOPCD("and", RwRbAL_Ib, FallThrough ), // 24
DEFOPCD("and", RwRvAX_Iv, FallThrough ), // 25
DEFOPCD(NULL, Nil, FallThrough ), // 26 ES:
DEFOPCD("daa", Nil, FallThrough ), // 27
DEFOPCD("sub", RwEb_RdGb, FallThrough ), // 28
DEFOPCD("sub", RwEv_RdGv, FallThrough ), // 29
DEFOPCD("sub", RwGb_RdEb, FallThrough ), // 2A
DEFOPCD("sub", RwGv_RdEv, FallThrough ), // 2B
DEFOPCD("sub", RwRbAL_Ib, FallThrough ), // 2C
DEFOPCD("sub", RwRvAX_Iv, FallThrough ), // 2D
DEFOPCD(NULL, Nil, FallThrough ), // 2E CS:
DEFOPCD("das", Nil, FallThrough ), // 2F
DEFOPCD("xor", RwEb_RdGb, FallThrough ), // 30
DEFOPCD("xor", RwEv_RdGv, FallThrough ), // 31
DEFOPCD("xor", RwGb_RdEb, FallThrough ), // 32
DEFOPCD("xor", RwGv_RdEv, FallThrough ), // 33
DEFOPCD("xor", RwRbAL_Ib, FallThrough ), // 34
DEFOPCD("xor", RwRvAX_Iv, FallThrough ), // 35
DEFOPCD(NULL, Nil, FallThrough ), // 36 SS:
DEFOPCD("aaa", Nil, FallThrough ), // 37
DEFOPCD("cmp", RdEb_RdGb, FallThrough ), // 38
DEFOPCD("cmp", RdEv_RdGv, FallThrough ), // 39
DEFOPCD("cmp", RdGb_RdEb, FallThrough ), // 3A
DEFOPCD("cmp", RdGv_RdEv, FallThrough ), // 3B
DEFOPCD("cmp", RdRbAL_Ib, FallThrough ), // 3C
DEFOPCD("cmp", RdRvAX_Iv, FallThrough ), // 3D
DEFOPCD(NULL, Nil, FallThrough ), // 3E DS:
DEFOPCD("aas", Nil, FallThrough ), // 3F
DEFOPCD("inc", RwGvOp, FallThrough ), // 40
DEFOPCD("inc", RwGvOp, FallThrough ), // 41
DEFOPCD("inc", RwGvOp, FallThrough ), // 42
DEFOPCD("inc", RwGvOp, FallThrough ), // 43
DEFOPCD("inc", RwGvOp, FallThrough ), // 44
DEFOPCD("inc", RwGvOp, FallThrough ), // 45
DEFOPCD("inc", RwGvOp, FallThrough ), // 46
DEFOPCD("inc", RwGvOp, FallThrough ), // 47
DEFOPCD("dec", RwGvOp, FallThrough ), // 48
DEFOPCD("dec", RwGvOp, FallThrough ), // 49
DEFOPCD("dec", RwGvOp, FallThrough ), // 4A
DEFOPCD("dec", RwGvOp, FallThrough ), // 4B
DEFOPCD("dec", RwGvOp, FallThrough ), // 4C
DEFOPCD("dec", RwGvOp, FallThrough ), // 4D
DEFOPCD("dec", RwGvOp, FallThrough ), // 4E
DEFOPCD("dec", RwGvOp, FallThrough ), // 4F
DEFOPCD("push", RdGvOp, FallThrough ), // 50
DEFOPCD("push", RdGvOp, FallThrough ), // 51
DEFOPCD("push", RdGvOp, FallThrough ), // 52
DEFOPCD("push", RdGvOp, FallThrough ), // 53
DEFOPCD("push", RdGvOp, FallThrough ), // 54
DEFOPCD("push", RdGvOp, FallThrough ), // 55
DEFOPCD("push", RdGvOp, FallThrough ), // 56
DEFOPCD("push", RdGvOp, FallThrough ), // 57
DEFOPCD("pop", WrGvOp, FallThrough ), // 58
DEFOPCD("pop", WrGvOp, FallThrough ), // 59
DEFOPCD("pop", WrGvOp, FallThrough ), // 5A
DEFOPCD("pop", WrGvOp, FallThrough ), // 5B
DEFOPCD("pop", WrGvOp, FallThrough ), // 5C
DEFOPCD("pop", WrGvOp, FallThrough ), // 5D
DEFOPCD("pop", WrGvOp, FallThrough ), // 5E
DEFOPCD("pop", WrGvOp, FallThrough ), // 5F
DEFOPCD("pusha", Nil, FallThrough ), // 60
DEFOPCD("popa", Nil, FallThrough ), // 61
DEFOPCD("bound", RdGv_RdMa, TrapCc ), // 62
DEFOPCD("arpl", RwEw_RdGw, FallThrough ), // 63
DEFOPCD(NULL, Nil, FallThrough ), // 64 FS:
DEFOPCD(NULL, Nil, FallThrough ), // 65 GS:
DEFOPCD(NULL, Nil, FallThrough ), // 66 Operand Size Override
DEFOPCD(NULL, Nil, FallThrough ), // 67 Address Size Override
DEFOPCD("push", Iv, FallThrough ), // 68
DEFOPCD("imul", WrGv_RdEv_Iv, FallThrough ), // 69
DEFOPCD("push", Ib, FallThrough ), // 6A
DEFOPCD("imul", WrGv_RdEv_Ib, FallThrough ), // 6B
DEFOPCD("ins", WrYb_RdRwDX, FallThrough ), // 6C
DEFOPCD("ins", WrYv_RdRwDX, FallThrough ), // 6D
DEFOPCD("outs", RdRwDX_RdXb, FallThrough ), // 6E
DEFOPCD("outs", RdRwDX_RdXv, FallThrough ), // 6F
DEFOPCD("jo", Jb, JmpCcShort ), // 70
DEFOPCD("jno", Jb, JmpCcShort ), // 71
DEFOPCD("jb", Jb, JmpCcShort ), // 72
DEFOPCD("jae", Jb, JmpCcShort ), // 73
DEFOPCD("je", Jb, JmpCcShort ), // 74
DEFOPCD("jne", Jb, JmpCcShort ), // 75
DEFOPCD("jbe", Jb, JmpCcShort ), // 76
DEFOPCD("ja", Jb, JmpCcShort ), // 77
DEFOPCD("js", Jb, JmpCcShort ), // 78
DEFOPCD("jns", Jb, JmpCcShort ), // 79
DEFOPCD("jp", Jb, JmpCcShort ), // 7A
DEFOPCD("jnp", Jb, JmpCcShort ), // 7B
DEFOPCD("jl", Jb, JmpCcShort ), // 7C
DEFOPCD("jge", Jb, JmpCcShort ), // 7D
DEFOPCD("jle", Jb, JmpCcShort ), // 7E
DEFOPCD("jg", Jb, JmpCcShort ), // 7F
DEFOGRP(80), // 80
DEFOGRP(81), // 81
DEFOPCD("mov", WrRbAL_Ib, FallThrough ), // 82
DEFOGRP(83), // 83
DEFOPCD("test", RdEb_RdGb, FallThrough ), // 84
DEFOPCD("test", RdEv_RdGv, FallThrough ), // 85
DEFOPCD("xchg", RwGb_RwEb, FallThrough ), // 86
DEFOPCD("xchg", RwGv_RwEv, FallThrough ), // 87
DEFOPCD("mov", WrEb_RdGb, FallThrough ), // 88
DEFOPCD("mov", WrEv_RdGv, FallThrough ), // 89
DEFOPCD("mov", WrGb_RdEb, FallThrough ), // 8A
DEFOPCD("mov", WrGv_RdEv, FallThrough ), // 8B
DEFOPCD("mov", WrEw_RdSw, FallThrough ), // 8C
DEFOPCD("lea", WrGv_M, FallThrough ), // 8D
DEFOPCD("mov", WrSw_RdEw, FallThrough ), // 8E
DEFOPCD("pop", WrEv, FallThrough ), // 8F
DEFOPCD("nop", Nil, FallThrough ), // 90
DEFOPCD("xchg", RwRvAX_RwGvOp, FallThrough ), // 91
DEFOPCD("xchg", RwRvAX_RwGvOp, FallThrough ), // 92
DEFOPCD("xchg", RwRvAX_RwGvOp, FallThrough ), // 93
DEFOPCD("xchg", RwRvAX_RwGvOp, FallThrough ), // 94
DEFOPCD("xchg", RwRvAX_RwGvOp, FallThrough ), // 95
DEFOPCD("xchg", RwRvAX_RwGvOp, FallThrough ), // 96
DEFOPCD("xchg", RwRvAX_RwGvOp, FallThrough ), // 97
DEFOPCD("cbw", Nil, FallThrough ), // 98
DEFOPCD("cwd", Nil, FallThrough ), // 99
DEFOPCD("call", AP, CallFar ), // 9A
DEFOPCD("wait", Nil, FallThrough ), // 9B
DEFOPCD("pushf", Nil, FallThrough ), // 9C
DEFOPCD("popf", Nil, FallThrough ), // 9D
DEFOPCD("sahf", Nil, FallThrough ), // 9E
DEFOPCD("lahf", Nil, FallThrough ), // 9F
DEFOPCD("mov", WrRbAL_RdOb, FallThrough ), // A0
DEFOPCD("mov", WrRvAX_RdOv, FallThrough ), // A1
DEFOPCD("mov", WrOb_RdRbAL, FallThrough ), // A2
DEFOPCD("mov", WrOv_RdRvAX, FallThrough ), // A3
DEFOPCD("movs", WrYb_RdXb, FallThrough ), // A4
DEFOPCD("movs", WrYv_RdXv, FallThrough ), // A5
DEFOPCD("cmps", RdXb_RdYb, FallThrough ), // A6
DEFOPCD("cmps", RdXv_RdYv, FallThrough ), // A7
DEFOPCD("test", RdRbAL_Ib, FallThrough ), // A8
DEFOPCD("test", RdRvAX_Iv, FallThrough ), // A9
DEFOPCD("stos", WrYb, FallThrough ), // AA
DEFOPCD("stos", WrYv, FallThrough ), // AB
DEFOPCD("lods", RdXb, FallThrough ), // AC
DEFOPCD("lods", RdXv, FallThrough ), // AD
DEFOPCD("scas", RdYb, FallThrough ), // AE
DEFOPCD("scas", RdYv, FallThrough ), // AF
DEFOPCD("mov", WrGbOp_Ib, FallThrough ), // B0
DEFOPCD("mov", WrGbOp_Ib, FallThrough ), // B1
DEFOPCD("mov", WrGbOp_Ib, FallThrough ), // B2
DEFOPCD("mov", WrGbOp_Ib, FallThrough ), // B3
DEFOPCD("mov", WrGbOp_Ib, FallThrough ), // B4
DEFOPCD("mov", WrGbOp_Ib, FallThrough ), // B5
DEFOPCD("mov", WrGbOp_Ib, FallThrough ), // B6
DEFOPCD("mov", WrGbOp_Ib, FallThrough ), // B7
DEFOPCD("mov", WrGvOp_Iv, FallThrough ), // B8
DEFOPCD("mov", WrGvOp_Iv, FallThrough ), // B9
DEFOPCD("mov", WrGvOp_Iv, FallThrough ), // BA
DEFOPCD("mov", WrGvOp_Iv, FallThrough ), // BB
DEFOPCD("mov", WrGvOp_Iv, FallThrough ), // BC
DEFOPCD("mov", WrGvOp_Iv, FallThrough ), // BD
DEFOPCD("mov", WrGvOp_Iv, FallThrough ), // BE
DEFOPCD("mov", WrGvOp_Iv, FallThrough ), // BF
DEFOGRP(C0), // C0
DEFOGRP(C1), // C1
DEFOPCD("ret", Iw, Ret ), // C2
DEFOPCD("ret", Nil, Ret ), // C3
DEFOPCD("les", WrGv_RdMp, FallThrough ), // C4
DEFOPCD("lds", WrGv_RdMp, FallThrough ), // C5
DEFOPCD("mov", WrEb_Ib, FallThrough ), // C6
DEFOPCD("mov", WrEv_Iv, FallThrough ), // C7
DEFOPCD("enter", Iw_Ib, FallThrough ), // C8
DEFOPCD("leave", Nil, FallThrough ), // C9
DEFOPCD("retf", Iw, Ret ), // CA
DEFOPCD("retf", Nil, Ret ), // CB
DEFOPCD("int", 3, Trap ), // CC
DEFOPCD("int", Ib, Trap ), // CD
DEFOPCD("into", Nil, TrapCc ), // CE
DEFOPCD("iret", Nil, Iret ), // CF
DEFOGRP(D0), // D0
DEFOGRP(D1), // D1
DEFOGRP(D2), // D2
DEFOGRP(D3), // D3
DEFOPCD("aam", Nil, FallThrough ), // D4
DEFOPCD("aad", Nil, FallThrough ), // D5
DEFOPCD(NULL, Nil, Unknown ), // D6
DEFOPCD("xlat", RdZb, FallThrough ), // D7
DEFOGRP(D8), // D8 ESC
DEFOGRP(D9), // D9 ESC
DEFOGRP(DA), // DA ESC
DEFOGRP(DB), // DB ESC
DEFOGRP(DC), // DC ESC
DEFOGRP(DD), // DD ESC
DEFOGRP(DE), // DE ESC
DEFOGRP(DF), // DF ESC
DEFOPCD("loopne", Jb, Loop ), // E0
DEFOPCD("loope", Jb, Loop ), // E1
DEFOPCD("loop", Jb, Loop ), // E2
DEFOPCD("jcxz", Jb, Jcxz ), // E3
DEFOPCD("in", WrRbAL_Ib, FallThrough ), // E4
DEFOPCD("in", WrRvAX_Ib, FallThrough ), // E5
DEFOPCD("out", Ib_RdRbAL, FallThrough ), // E6
DEFOPCD("out", Ib_RdRvAX, FallThrough ), // E7
DEFOPCD("call", Jv, CallNear32 ), // E8
DEFOPCD("jmp", Jv, JmpNear ), // E9
DEFOPCD("jmp", AP, JmpFar ), // EA
DEFOPCD("jmp", Jb, JmpShort ), // EB
DEFOPCD("in", WrRbAL_RdRwDX, FallThrough ), // EC
DEFOPCD("in", WrRvAX_RdRwDX, FallThrough ), // ED
DEFOPCD("out", RdRwDX_RdRbAL, FallThrough ), // EE
DEFOPCD("out", RdRwDX_RdRvAX, FallThrough ), // EF
DEFOPCD(NULL, Nil, Unknown ), // F0 Prefix: LOCK
DEFOPCD(NULL, Nil, Unknown ), // F1
DEFOPCD(NULL, Nil, Unknown ), // F2 Prefix: REPNE
DEFOPCD(NULL, Nil, Unknown ), // F3 Prefix: REP
DEFOPCD("hlt", Nil, CallInd ), // F4
DEFOPCD("cmc", Nil, FallThrough ), // F5
DEFOGRP(F6), // F6
DEFOGRP(F7), // F7
DEFOPCD("clc", Nil, FallThrough ), // F8
DEFOPCD("stc", Nil, FallThrough ), // F9
DEFOPCD("cli", Nil, FallThrough ), // FA
DEFOPCD("sti", Nil, FallThrough ), // FB
DEFOPCD("cld", Nil, FallThrough ), // FC
DEFOPCD("std", Nil, FallThrough ), // FD
DEFOGRP(FE), // FE
DEFOGRP(FF), // FF
};
const OPCD rgopcd0F[256] =
{
// Mnemonic Operands trmtx86
DEFOGRP(0F00), // 00
DEFOGRP(0F01), // 01
DEFOPCD("lar", WrGv_RdEw, FallThrough ), // 02
DEFOPCD("lsl", WrGv_RdEw, FallThrough ), // 03
DEFOPCD(NULL, Nil, Unknown ), // 04
DEFOPCD("loadall", Nil, FallThrough ), // 05
DEFOPCD("clts", Nil, FallThrough ), // 06
DEFOPCD("loadall", RdXv, FallThrough ), // 07
DEFOPCD("invd", Nil, FallThrough ), // 08
DEFOPCD("wbinvd", Nil, FallThrough ), // 09
DEFOPCD("cflsh", Nil, FallThrough ), // 0A UNDONE: Does P6 still have this?
DEFOPCD(NULL, Nil, Unknown ), // 0B
DEFOPCD(NULL, Nil, Unknown ), // 0C
DEFOPCD(NULL, Nil, Unknown ), // 0D
DEFOPCD(NULL, Nil, Unknown ), // 0E
DEFOPCD(NULL, Nil, Unknown ), // 0F
DEFOPCD(NULL, Nil, Unknown ), // 10
DEFOPCD(NULL, Nil, Unknown ), // 11
DEFOPCD(NULL, Nil, Unknown ), // 12
DEFOPCD(NULL, Nil, Unknown ), // 13
DEFOPCD(NULL, Nil, Unknown ), // 14
DEFOPCD(NULL, Nil, Unknown ), // 15
DEFOPCD(NULL, Nil, Unknown ), // 16
DEFOPCD(NULL, Nil, Unknown ), // 17
DEFOPCD(NULL, Nil, Unknown ), // 18
DEFOPCD(NULL, Nil, Unknown ), // 19
DEFOPCD(NULL, Nil, Unknown ), // 1A
DEFOPCD(NULL, Nil, Unknown ), // 1B
DEFOPCD(NULL, Nil, Unknown ), // 1C
DEFOPCD(NULL, Nil, Unknown ), // 1D
DEFOPCD(NULL, Nil, Unknown ), // 1E
DEFOPCD(NULL, Nil, Unknown ), // 1F
DEFOPCD("mov", WrRd_RdCd, FallThrough ), // 20
DEFOPCD("mov", WrRd_RdDd, FallThrough ), // 21
DEFOPCD("mov", WrCd_RdRd, FallThrough ), // 22
DEFOPCD("mov", WrDd_RdRd, FallThrough ), // 23
DEFOPCD("mov", WrTd_RdRd, FallThrough ), // 24
DEFOPCD(NULL, Nil, Unknown ), // 25
DEFOPCD("mov", WrRd_RdTd, FallThrough ), // 26
DEFOPCD(NULL, Nil, Unknown ), // 27
DEFOPCD(NULL, Nil, Unknown ), // 28
DEFOPCD(NULL, Nil, Unknown ), // 29
DEFOPCD(NULL, Nil, Unknown ), // 2A
DEFOPCD(NULL, Nil, Unknown ), // 2B
DEFOPCD(NULL, Nil, Unknown ), // 2C
DEFOPCD(NULL, Nil, Unknown ), // 2D
DEFOPCD(NULL, Nil, Unknown ), // 2E
DEFOPCD(NULL, Nil, Unknown ), // 2F
DEFOPCD("wrmsr", Nil, FallThrough ), // 30
DEFOPCD("rdtsc", Nil, FallThrough ), // 31
DEFOPCD("rdmsr", Nil, FallThrough ), // 32
DEFOPCD("rdpmc", Nil, FallThrough ), // 33
DEFOPCD("wrecr", Nil, FallThrough ), // 34 UNDONE: Does P6 still have this?
DEFOPCD(NULL, Nil, Unknown ), // 35
DEFOPCD("rdecr", Nil, FallThrough ), // 36 UNDONE: Does P6 still have this?
DEFOPCD(NULL, Nil, Unknown ), // 37
DEFOPCD(NULL, Nil, Unknown ), // 38
DEFOPCD(NULL, Nil, Unknown ), // 39
DEFOPCD(NULL, Nil, Unknown ), // 3A
DEFOPCD(NULL, Nil, Unknown ), // 3B
DEFOPCD(NULL, Nil, Unknown ), // 3C
DEFOPCD(NULL, Nil, Unknown ), // 3D
DEFOPCD(NULL, Nil, Unknown ), // 3E
DEFOPCD(NULL, Nil, Unknown ), // 3F
DEFOPCD("cmovo", WrEvReg_RdGv, FallThrough ), // 40
DEFOPCD("cmovno", WrEvReg_RdGv, FallThrough ), // 41
DEFOPCD("cmovb", WrEvReg_RdGv, FallThrough ), // 42
DEFOPCD("cmovae", WrEvReg_RdGv, FallThrough ), // 43
DEFOPCD("cmove", WrEvReg_RdGv, FallThrough ), // 44
DEFOPCD("cmovne", WrEvReg_RdGv, FallThrough ), // 45
DEFOPCD("cmovbe", WrEvReg_RdGv, FallThrough ), // 46
DEFOPCD("cmova", WrEvReg_RdGv, FallThrough ), // 47
DEFOPCD("cmovs", WrEvReg_RdGv, FallThrough ), // 48
DEFOPCD("cmovns", WrEvReg_RdGv, FallThrough ), // 49
DEFOPCD("cmovp", WrEvReg_RdGv, FallThrough ), // 4A
DEFOPCD("cmovnp", WrEvReg_RdGv, FallThrough ), // 4B
DEFOPCD("cmovl", WrEvReg_RdGv, FallThrough ), // 4C
DEFOPCD("cmovge", WrEvReg_RdGv, FallThrough ), // 4D
DEFOPCD("cmovle", WrEvReg_RdGv, FallThrough ), // 4E
DEFOPCD("cmovg", WrEvReg_RdGv, FallThrough ), // 4F
DEFOPCD(NULL, Nil, Unknown ), // 50
DEFOPCD(NULL, Nil, Unknown ), // 51
DEFOPCD(NULL, Nil, Unknown ), // 52
DEFOPCD(NULL, Nil, Unknown ), // 53
DEFOPCD(NULL, Nil, Unknown ), // 54
DEFOPCD(NULL, Nil, Unknown ), // 55
DEFOPCD(NULL, Nil, Unknown ), // 56
DEFOPCD(NULL, Nil, Unknown ), // 57
DEFOPCD(NULL, Nil, Unknown ), // 58
DEFOPCD(NULL, Nil, Unknown ), // 59
DEFOPCD(NULL, Nil, Unknown ), // 5A
DEFOPCD(NULL, Nil, Unknown ), // 5B
DEFOPCD(NULL, Nil, Unknown ), // 5C
DEFOPCD(NULL, Nil, Unknown ), // 5D
DEFOPCD(NULL, Nil, Unknown ), // 5E
DEFOPCD(NULL, Nil, Unknown ), // 5F
DEFOPCD("punpcklbw", RwMv_RdMmq, FallThrough ), // 60 MMX
DEFOPCD("punpcklbd", RwMv_RdMmq, FallThrough ), // 61 MMX
DEFOPCD("punpcklbq", RwMv_RdMmq, FallThrough ), // 62 MMX
DEFOPCD("packsswb", RwMv_RdMmq, FallThrough ), // 63 MMX
DEFOPCD("pcmpgtb", RwMv_RdMmq, Unknown ), // 64 MMX
DEFOPCD("pcmpgtw", RwMv_RdMmq, Unknown ), // 65 MMX
DEFOPCD("pcmpgtd", RwMv_RdMmq, Unknown ), // 66 MMX
DEFOPCD("packuswb", RwMv_RdMmq, FallThrough ), // 67 MMX
DEFOPCD("punpckhbw", RwMv_RdMmq, FallThrough ), // 68 MMX
DEFOPCD("punpckhbd", RwMv_RdMmq, FallThrough ), // 69 MMX
DEFOPCD("punpckhbq", RwMv_RdMmq, FallThrough ), // 6A MMX
DEFOPCD("packssdw", RwMv_RdMmq, FallThrough ), // 6B MMX
DEFOPCD(NULL, Nil, Unknown ), // 6C
DEFOPCD(NULL, Nil, Unknown ), // 6D
DEFOPCD("movd", WrMmd_RdMv, FallThrough ), // 6E MMX
DEFOPCD("movq", WrMmq_RdMv, FallThrough ), // 6F MMX
DEFOPCD(NULL, Nil, Unknown ), // 70
DEFOGRP(0F71), // 71
DEFOGRP(0F72), // 72
DEFOGRP(0F73), // 73
DEFOPCD("pcmpeqb", RwMv_RdMmq, Unknown ), // 74 MMX
DEFOPCD("pcmpeqw", RwMv_RdMmq, Unknown ), // 75 MMX
DEFOPCD("pcmpeqd", RwMv_RdMmq, Unknown ), // 76 MMX
DEFOPCD("emms", Nil, FallThrough ), // 77 MMX
DEFOPCD(NULL, Nil, Unknown ), // 78
DEFOPCD(NULL, Nil, Unknown ), // 79
DEFOPCD(NULL, Nil, Unknown ), // 7A
DEFOPCD(NULL, Nil, Unknown ), // 7B
DEFOPCD(NULL, Nil, Unknown ), // 7C
DEFOPCD(NULL, Nil, Unknown ), // 7D
DEFOPCD("movd", WrMv_RdMmd, FallThrough ), // 7E MMX
DEFOPCD("movq", WrMv_RdMmq, FallThrough ), // 7F MMX
// DEFOPCD("svdc", WrMt_RdSw, FallThrough ), // 78 IBM BL486DX
// DEFOPCD("rsdc", WrSw_RdMt, FallThrough ), // 79 IBM BL486DX
// DEFOPCD("svldt", WrMt, FallThrough ), // 7A IBM BL486DX
// DEFOPCD("rsldt", RdMt, FallThrough ), // 7B IBM BL486DX
// DEFOPCD("svts", WrMt, FallThrough ), // 7C IBM BL486DX
// DEFOPCD("rsts", RdMt, FallThrough ), // 7D IBM BL486DX
// DEFOPCD("smint", Nil, FallThrough ), // 7E IBM BL486DX
// DEFOPCD(NULL, Nil, Unknown ), // 7F
DEFOPCD("jo", Jv, JmpCcNear ), // 80
DEFOPCD("jno", Jv, JmpCcNear ), // 81
DEFOPCD("jb", Jv, JmpCcNear ), // 82
DEFOPCD("jae", Jv, JmpCcNear ), // 83
DEFOPCD("je", Jv, JmpCcNear ), // 84
DEFOPCD("jne", Jv, JmpCcNear ), // 85
DEFOPCD("jbe", Jv, JmpCcNear ), // 86
DEFOPCD("ja", Jv, JmpCcNear ), // 87
DEFOPCD("js", Jv, JmpCcNear ), // 88
DEFOPCD("jns", Jv, JmpCcNear ), // 89
DEFOPCD("jp", Jv, JmpCcNear ), // 8A
DEFOPCD("jnp", Jv, JmpCcNear ), // 8B
DEFOPCD("jl", Jv, JmpCcNear ), // 8C
DEFOPCD("jge", Jv, JmpCcNear ), // 8D
DEFOPCD("jle", Jv, JmpCcNear ), // 8E
DEFOPCD("jg", Jv, JmpCcNear ), // 8F
DEFOPCD("seto", WrEb, FallThrough ), // 90
DEFOPCD("setno", WrEb, FallThrough ), // 91
DEFOPCD("setb", WrEb, FallThrough ), // 92
DEFOPCD("setae", WrEb, FallThrough ), // 93
DEFOPCD("sete", WrEb, FallThrough ), // 94
DEFOPCD("setne", WrEb, FallThrough ), // 95
DEFOPCD("setbe", WrEb, FallThrough ), // 96
DEFOPCD("seta", WrEb, FallThrough ), // 97
DEFOPCD("sets", WrEb, FallThrough ), // 98
DEFOPCD("setns", WrEb, FallThrough ), // 99
DEFOPCD("setp", WrEb, FallThrough ), // 9A
DEFOPCD("setnp", WrEb, FallThrough ), // 9B
DEFOPCD("setl", WrEb, FallThrough ), // 9C
DEFOPCD("setge", WrEb, FallThrough ), // 9D
DEFOPCD("setle", WrEb, FallThrough ), // 9E
DEFOPCD("setg", WrEb, FallThrough ), // 9F
DEFOPCD("push", RdSwFS, FallThrough ), // A0
DEFOPCD("pop", WrSwFS, FallThrough ), // A1
DEFOPCD("cpuid", Nil, FallThrough ), // A2
DEFOPCD("bt", RdEv_RdGv, FallThrough ), // A3
DEFOPCD("shld", RwEv_RdGv_Ib, FallThrough ), // A4
DEFOPCD("shld", RwEv_RdGv_RdRbCL, FallThrough ), // A5
DEFOPCD("xbts", WrGv_RdEv, FallThrough ), // A6 Invalid instruction
DEFOPCD("ibts", RwEv_RdGv, FallThrough ), // A7 Invalid instruction
DEFOPCD("push", RdSwGS, FallThrough ), // A8
DEFOPCD("pop", WrSwGS, FallThrough ), // A9
DEFOPCD("rsm", Nil, JmpInd ), // AA
DEFOPCD("bts", RwEv_RdGv, FallThrough ), // AB
DEFOPCD("shrd", RwEv_RdGv_Ib, FallThrough ), // AC
DEFOPCD("shrd", RwEv_RdGv_RdRbCL, FallThrough ), // AD
DEFOPCD("zalloc", WrMcache, FallThrough ), // AE UNDONE: Does P6 still have this?
DEFOPCD("imul", RwGv_RdEv, FallThrough ), // AF
DEFOPCD("cmpxchg", RwEb_RwGb, FallThrough ), // B0
DEFOPCD("cmpxchg", RwEv_RwGv, FallThrough ), // B1
DEFOPCD("lss", WrGv_RdMp, FallThrough ), // B2
DEFOPCD("btr", RwEv_RdGv, FallThrough ), // B3
DEFOPCD("lfs", WrGv_RdMp, FallThrough ), // B4
DEFOPCD("lgs", WrGv_RdMp, FallThrough ), // B5
DEFOPCD("movzx", WrGv_RdEb, FallThrough ), // B6
DEFOPCD("movzx", WrGd_RdEw, FallThrough ), // B7
DEFOPCD(NULL, Nil, Unknown ), // B8
DEFOPCD(NULL, Nil, Unknown ), // B9
DEFOGRP(0FBA), // BA
DEFOPCD("btc", RwEv_RdGv, FallThrough ), // BB
DEFOPCD("bsf", WrGv_RdEv, FallThrough ), // BC
DEFOPCD("bsr", WrGv_RdEv, FallThrough ), // BD
DEFOPCD("movsx", WrGv_RdEb, FallThrough ), // BE
DEFOPCD("movsx", WrGd_RdEw, FallThrough ), // BF
DEFOPCD("xadd", RwEb_RwGb, FallThrough ), // C0
DEFOPCD("xadd", RwEv_RwGv, FallThrough ), // C1
DEFOPCD(NULL, Nil, Unknown ), // C2
DEFOPCD(NULL, Nil, Unknown ), // C3
DEFOPCD(NULL, Nil, Unknown ), // C4
DEFOPCD(NULL, Nil, Unknown ), // C5
DEFOPCD(NULL, Nil, Unknown ), // C6
DEFOGRP(0FC7), // C7
DEFOPCD("bswap", RwGdOp, FallThrough ), // C8
DEFOPCD("bswap", RwGdOp, FallThrough ), // C9
DEFOPCD("bswap", RwGdOp, FallThrough ), // CA
DEFOPCD("bswap", RwGdOp, FallThrough ), // CB
DEFOPCD("bswap", RwGdOp, FallThrough ), // CC
DEFOPCD("bswap", RwGdOp, FallThrough ), // CD
DEFOPCD("bswap", RwGdOp, FallThrough ), // CE
DEFOPCD("bswap", RwGdOp, FallThrough ), // CF
DEFOPCD(NULL, Nil, Unknown ), // D0
DEFOPCD("psrlw", RwMv_RdMmq, FallThrough ), // D1 MMX
DEFOPCD("psrld", RwMv_RdMmq, FallThrough ), // D2 MMX
DEFOPCD("psrlq", RwMv_RdMmq, FallThrough ), // D3 MMX
DEFOPCD(NULL, Nil, Unknown ), // D4
DEFOPCD("pmull", RwMv_RdMmq, FallThrough ), // D5 MMX
DEFOPCD(NULL, Nil, Unknown ), // D6
DEFOPCD(NULL, Nil, Unknown ), // D7
DEFOPCD("psubusb", RwMv_RdMmq, FallThrough ), // D8 MMX
DEFOPCD("psubusw", RwMv_RdMmq, FallThrough ), // D9 MMX
DEFOPCD(NULL, Nil, Unknown ), // DA
DEFOPCD("pand", RwMv_RdMmq, FallThrough ), // DB
DEFOPCD("paddusb", RwMv_RdMmq, FallThrough ), // DC MMX
DEFOPCD("paddusw", RwMv_RdMmq, FallThrough ), // DD MMX
DEFOPCD(NULL, Nil, Unknown ), // DE
DEFOPCD("pandn", RwMv_RdMmq, FallThrough ), // DF
DEFOPCD(NULL, Nil, Unknown ), // E0
DEFOPCD("psraw", RwMv_RdMmq, FallThrough ), // E1 MMX
DEFOPCD("psrad", RwMv_RdMmq, FallThrough ), // E2 MMX
DEFOPCD(NULL, Nil, Unknown ), // E3
DEFOPCD(NULL, Nil, Unknown ), // E4
DEFOPCD("pmulh", RwMv_RdMmq, FallThrough ), // E5 MMX
DEFOPCD(NULL, Nil, Unknown ), // E6
DEFOPCD(NULL, Nil, Unknown ), // E7
DEFOPCD("psubsb", RwMv_RdMmq, FallThrough ), // E8 MMX
DEFOPCD("psubsw", RwMv_RdMmq, FallThrough ), // E9 MMX
DEFOPCD(NULL, Nil, Unknown ), // EA
DEFOPCD("por", RwMv_RdMmq, FallThrough ), // EB MMX
DEFOPCD("paddsb", RwMv_RdMmq, FallThrough ), // EC MMX
DEFOPCD("paddsw", RwMv_RdMmq, FallThrough ), // ED MMX
DEFOPCD(NULL, Nil, Unknown ), // EE
DEFOPCD("pxor", RwMv_RdMmq, FallThrough ), // EF MMX
DEFOPCD(NULL, Nil, Unknown ), // F0
DEFOPCD("psllw", RwMv_RdMmq, FallThrough ), // F1 MMX
DEFOPCD("pslld", RwMv_RdMmq, FallThrough ), // F2 MMX
DEFOPCD("psllq", RwMv_RdMmq, FallThrough ), // F3 MMX
DEFOPCD(NULL, Nil, Unknown ), // F4
DEFOPCD("pmaddwd", RwMv_RdMmq, FallThrough ), // F5 MMX
DEFOPCD(NULL, Nil, Unknown ), // F6
DEFOPCD(NULL, Nil, Unknown ), // F7
DEFOPCD("psubb", RwMv_RdMmq, FallThrough ), // F8 MMX
DEFOPCD("psubw", RwMv_RdMmq, FallThrough ), // F9 MMX
DEFOPCD("psubd", RwMv_RdMmq, FallThrough ), // FA MMX
DEFOPCD(NULL, Nil, Unknown ), // FB
DEFOPCD("paddb", RwMv_RdMmq, FallThrough ), // FC MMX
DEFOPCD("paddw", RwMv_RdMmq, FallThrough ), // FD MMX
DEFOPCD("paddd", RwMv_RdMmq, FallThrough ), // FE MMX
DEFOPCD(NULL, Nil, Unknown ), // FF
};
inline const OPCD *PopcdFloatingPoint(BYTE bOpcd, BYTE bModrm);
DISX86::DISX86(ARCHT archt) : DIS(archt)
{
}
// -----------------------------------------------------------------
// Public Methods
// -----------------------------------------------------------------
ADDR DISX86::AddrAddress() const
{
size_t ibDisp = 0;
const OPS *pops = m_popcd->pops;
for (unsigned ioprnd = 0; ioprnd < 3; ioprnd++)
{
if (pops->rgoprnd[ioprnd].oprndt == oprndtNil)
{
break;
}
switch ((OPRNDT) pops->rgoprnd[ioprnd].oprndt)
{
case oprndtModrm : // Memory/register references from MODRM
if (m_fAddress32)
{
ibDisp = IbDispModrm32();
}
else
{
ibDisp = IbDispModrm16();
}
break;
case oprndtOffset : // Address size immediate offset
ibDisp = IbDispOffset();
break;
default :
continue;
}
break;
}
if (ibDisp == 0)
{
return(addrNil);
}
return(m_addr + ibDisp);
}
ADDR DISX86::AddrJumpTable() const
{
if (m_trmtx86 != trmtx86JmpInd)
{
// This isn't a reference to a jump table
return(addrNil);
}
ADDR addr;
if (m_fAddress32)
{
addr = AddrJumpTable32();
}
else
{
addr = AddrJumpTable16();
}
return(addr);
}
ADDR DISX86::AddrOperand(size_t ioperand) const
{
if (m_pfndwgetreg == 0)
{
return(addrNil);
}
if (ioperand == 0)
{
// Implicit operand if any
return(addrNil);
}
if (!FValidOperand(ioperand))
{
return(addrNil);
}
const OPS *pops = m_popcd->pops;
ADDR addr = addrNil;
OPRNDT oprndt = (OPRNDT) pops->rgoprnd[ioperand].oprndt;
switch ((OPRNDT) pops->rgoprnd[ioperand].oprndt)
{
case oprndtModrm : // Memory/register references from MODRM
if (m_fAddress32)
{
addr = AddrOperandModrm32();
}
else
{
addr = AddrOperandModrm16();
}
break;
case oprndtOffset : // Address size immediate offset
if (m_fAddress32)
{
addr = (ADDR) *(DWORD UNALIGNED *) (m_rgbInstr + m_ibImmed);
}
else
{
addr = (ADDR) *(WORD UNALIGNED *) (m_rgbInstr + m_ibImmed);
}
break;
case oprndtX : // DS:[eSI] for string instruction
addr = (ADDR) (*m_pfndwgetreg)(this, regEsi);
break;
case oprndtY : // ES:[eDI] for string instruction
addr = (ADDR) (*m_pfndwgetreg)(this, regEdi);
break;
case oprndtZ : // DS:[eBX] for XLAT
addr = (ADDR) (*m_pfndwgetreg)(this, regEbx);
break;
}
if (!m_fAddress32)
{
addr &= 0x0000FFFF;
}
return(addr);
}
ADDR DISX86::AddrOperandModrm16() const
{
BYTE b = m_rgbInstr[m_ibModrm];
if ((b & 0xC0) == 0xC0)
{
// Operand is a register
return(addrNil);
}
bool fDisp16 = false;
int ireg = -1;
const char *szReg = NULL;
if ((b & 0xC7) == 0x06)
{
// Special case of [disp16] operand
fDisp16 = true;
}
else
{
ireg = (int) (b & 0x07);
}
WORD wDisp;
switch (b & 0xC0)
{
case 0x40 :
wDisp = m_rgbInstr[m_ibModrm + 1];
if ((wDisp & 0x80) != 0)
{
wDisp |= 0xFF00;
}
break;
case 0x80 :
fDisp16 = true;
break;
}
if (fDisp16)
{
wDisp = *(WORD UNALIGNED *) (m_rgbInstr + m_ibModrm + 1);
}
ADDR addr = (ADDR) wDisp;
if (ireg != -1)
{
addr += (*m_pfndwgetreg)(this, ireg);
}
addr &= 0x0000FFFF;
return(addr);
}
ADDR DISX86::AddrOperandModrm32() const
{
BYTE b = m_rgbInstr[m_ibModrm];
if ((b & 0xC0) == 0xC0)
{
// Operand is a register
return(addrNil);
}
bool fDisp32 = false;
int iregIndex = -1;
unsigned uScale;
const BYTE *pbDisp = m_rgbInstr + m_ibModrm + 1;
int ireg = (b & 0x07);
if (ireg != 4)
{
// There is no SIB byte
if ((b & 0xC7) == 0x05)
{
// Special case of [disp32] operand
fDisp32 = true;
ireg = -1;
}
}
else
{
// This MODRM is followed by a SIB
BYTE bSib = *pbDisp++;
int iregBase = (bSib & 0x07);
if ((iregBase != 5) || ((b & 0xC0) != 0x00))
{
ireg = iregBase;
}
else
{
ireg = -1;
}
iregIndex = ((bSib >> 3) & 0x07);
if (iregIndex != 4)
{
uScale = 1 << (bSib >> 6);
}
else
{
iregIndex = -1;
}
if ((iregBase == 5) && ((b & 0xC0) == 0x00))
{
fDisp32 = true;
}
}
DWORD dwDisp;
switch (b & 0xC0)
{
case 0x40 :
dwDisp = *pbDisp;
if ((dwDisp & 0x80) != 0)
{
dwDisp |= 0xFFFFFF00;
}
break;
case 0x80 :
fDisp32 = true;
break;
}
if (fDisp32)
{
dwDisp = *(DWORD UNALIGNED *) (m_addr + m_ibModrm + 1);
}
ADDR addr = (ADDR) dwDisp;
if (ireg != -1)
{
addr += (*m_pfndwgetreg)(this, ireg);
}
if (iregIndex != -1)
{
addr += (*m_pfndwgetreg)(this, ireg) * uScale;
}
return(addr);
}
ADDR DISX86::AddrTarget() const
{
ADDR addr;
switch (m_trmtx86)
{
case trmtx86Unknown :
case trmtx86FallThrough :
case trmtx86Trap :
case trmtx86TrapCc :
case trmtx86JmpInd :
case trmtx86Ret :
case trmtx86Iret :
case trmtx86CallInd :
addr = addrNil;
break;
case trmtx86JmpShort :
case trmtx86JmpCcShort :
case trmtx86Loop :
case trmtx86Jcxz :
addr = m_addr + m_cb + *(signed char *) (m_rgbInstr + m_ibImmed);
break;
case trmtx86JmpNear :
case trmtx86JmpCcNear :
case trmtx86CallNear16 :
case trmtx86CallNear32 :
if (m_fOperand32)
{
addr = m_addr + m_cb + *(signed long UNALIGNED *) (m_rgbInstr + m_ibImmed);
}
else
{
addr = m_addr + m_cb + *(signed short UNALIGNED *) (m_rgbInstr + m_ibImmed);
}
if (m_archt == archtX8616)
{
// For 16 bit segments, don't change the segment portion.
addr = (m_addr & 0xFFFF0000) | (addr & 0x0000FFFF);
}
break;
case trmtx86JmpFar :
case trmtx86CallFar :
addr = *(ADDR UNALIGNED *) (m_rgbInstr + m_ibImmed);
break;
}
return(addr);
}
size_t DISX86::Cb() const
{
return(m_cb);
}
size_t DISX86::CbDisassemble(ADDR addr, const BYTE *pb, size_t cbMax)
{
m_addr = addr;
m_pbCur = pb;
m_cbMax = cbMax;
m_cb = 0;
m_fAddress32 = (m_archt != archtX8616);
m_fOperand32 = (m_archt != archtX8616);
m_bSegOverride = 0x00;
m_bPrefix = 0x00;
m_fOperOverride = false;
m_fAddrOverride = false;
Restart:
m_ibOp = m_cb;
if (m_cb == m_cbMax)
{
return(0);
}
BYTE bOpcd = *m_pbCur++;
m_cb++;
m_popcd = rgopcd + bOpcd;
if (m_popcd->pvMnemonic == NULL)
{
// This is not a normal instruction entry
switch (bOpcd)
{
case 0x0F : // Two byte instruction prefix
if (m_cb == m_cbMax)
{
return(0);
}
bOpcd = *m_pbCur++;
m_cb++;
m_popcd = rgopcd0F + bOpcd;
if (m_popcd->pvMnemonic == NULL)
{
// This is an invalid instruction
return(0);
}
break;
case 0x26 : // ES:
case 0x2E : // CS:
case 0x36 : // SS:
case 0x3E : // DS:
case 0x64 : // FS:
case 0x65 : // GS:
if (m_bSegOverride != 0)
{
// Multiple overrides
return(0);
}
m_bSegOverride = bOpcd;
goto Restart;
case 0x66 : // Operand Size Override
if (m_fOperOverride)
{
// Multiple overrides
return(0);
}
m_fOperOverride = true;
m_fOperand32 = !m_fOperand32;
goto Restart;
case 0x67 : // Address Size Override
if (m_fAddrOverride)
{
// Multiple overrides
return(0);
}
m_fAddrOverride = true;
m_fAddress32 = !m_fAddress32;
goto Restart;
case 0xF0 : // LOCK
case 0xF2 : // REPNE
case 0xF3 : // REP
if (m_bPrefix != 0)
{
// Multiple prefixes
return(0);
}
m_bPrefix = bOpcd;
goto Restart;
default :
// This is an invalid instruction
return(0);
}
}
MODRMT modrmt;
if (m_popcd->pops != NULL)
{
// Get the MODRM type from the instruction operand definition
modrmt = m_popcd->pops->modrmt;
}
else
{
// This is a group entry. All grouped instructions have a MODRM.
modrmt = modrmtYes;
}
BYTE bModrm;
if (modrmt != modrmtNo)
{
m_ibModrm = m_cb;
if (m_cb == m_cbMax)
{
return(0);
}
bModrm = *m_pbCur++;
m_cb++;
if (m_fAddress32)
{
if (!FDisassembleModrm32(bModrm))
{
// Invalid instruction
return(0);
}
}
else
{
if (!FDisassembleModrm16(bModrm))
{
// Invalid instruction
return(0);
}
}
m_cbModrm = m_cb - m_ibModrm;
}
if (m_popcd->pops == NULL)
{
// This is a group entry. Get the opcode from the MODRM byte.
if (((bOpcd & 0xF8) == 0xD8) && ((bModrm & 0xC0) == 0xC0))
{
// This is a floating point instruction with MOD == 11.
// Note: There are no 0F Dx instructions to be misidentified.
m_popcd = PopcdFloatingPoint(bOpcd, bModrm);
if (m_popcd == NULL)
{
return(0);
}
}
else
{
m_popcd = (OPCD *) m_popcd->pvMnemonic + ((bModrm >> 3) & 0x07);
}
if (m_popcd->pvMnemonic == NULL)
{
// This is an invalid instruction
return(0);
}
modrmt = m_popcd->pops->modrmt;
}
m_trmtx86 = (TRMTX86) m_popcd->trmtx86;
if (!m_fAddress32 && (m_trmtx86 == trmtx86CallNear32))
{
// We distinguish between 16 bit and 32 bit near calls in order to
// support mixed 16 and 32 bit code in NE images.
m_trmtx86 = trmtx86CallNear16;
}
// UNDONE: Check for invalid prefix bytes (e.g. REP JE Target)
if (modrmt == modrmtMem)
{
// This instruction only allows memory operands via MODRM
if ((bModrm & 0xC0) == 0xC0)
{
// Operand is a register
return(0);
}
}
else if (modrmt == modrmtReg)
{
// This instruction only allows register operands via MODRM
if ((bModrm & 0xC0) != 0xC0)
{
// Operand is not a register
return(0);
}
}
// Check for immediate bytes
m_ibImmed = m_cb;
size_t cbImmed;
switch (m_popcd->pops->icb)
{
case icbNil : // No immediate value
cbImmed = 0;
break;
case icbAP : // Far pointer
cbImmed = m_fOperand32 ? 6 : 4;
break;
case icbIb : // Immediate byte
cbImmed = 1;
break;
case icbIv : // Immediate operand size value
case icbJv : // Operand size displacement
cbImmed = m_fOperand32 ? 4 : 2;
break;
case icbIw : // Immediate word
cbImmed = 2;
break;
case icbIw_Ib : // Immediate word and immediate byte
cbImmed = 3;
break;
case icbJb : // Byte displacement
cbImmed = 1;
break;
case icbO : // Address size value
cbImmed = m_fAddress32 ? 4 : 2;
break;
}
m_cb += cbImmed;
if ((m_cb > m_cbMax) || (m_cb > 15))
{
return(0);
}
memcpy(m_rgbInstr, pb, m_cb);
return(m_cb);
}
size_t DISX86::CbGenerateLoadAddress(BYTE *pb, size_t cbBuf, size_t *pibAddress) const
{
if (m_bSegOverride != 0x00)
{
// There is a segment override
return(0);
}
size_t cb = 0;
// UNDONE: PUSH and POP instructions are not recognized as having an
// UNDONE: implicit memory reference. Should they?
const OPS *pops = m_popcd->pops;
for (unsigned ioprnd = 0; ioprnd < 3; ioprnd++)
{
if (pops->rgoprnd[ioprnd].oprndt == oprndtNil)
{
break;
}
if (pops->rgoprnd[ioprnd].opreft == opreftNil)
{
continue;
}
switch ((OPRNDT) pops->rgoprnd[ioprnd].oprndt)
{
case oprndtModrm : // Memory/register references from MODRM
cb = CbGenerateLea(pb, cbBuf, pibAddress);
break;
case oprndtOffset : // Address size immediate offset
cb = CbGenerateMovOffset(pb, cbBuf, pibAddress);
break;
case oprndtX : // DS:[eSI] for string instruction
cb = CbGenerateMovXSi(pb, cbBuf);
break;
case oprndtY : // ES:[eDI] for string instruction
cb = CbGenerateMovXDi(pb, cbBuf);
break;
default :
continue;
}
break;
}
return(cb);
}
size_t DISX86::CbJumpEntry() const
{
return(m_fAddress32 ? sizeof(DWORD) : sizeof(WORD));
}
size_t DISX86::CbMemoryReference() const
{
size_t cb = 0;
// UNDONE: PUSH and POP instructions are not recognized as having an
// UNDONE: implicit memory reference. Should they?
const OPS *pops = m_popcd->pops;
for (unsigned ioprnd = 0; ioprnd < 3; ioprnd++)
{
if (pops->rgoprnd[ioprnd].oprndt == oprndtNil)
{
break;
}
if (pops->rgoprnd[ioprnd].opreft == opreftNil)
{
continue;
}
switch ((OPRNDT) pops->rgoprnd[ioprnd].oprndt)
{
case oprndtModrm : // Memory/register references from MODRM
if ((m_rgbInstr[m_ibModrm] & 0xC0) == 0xC0)
{
continue;
}
break;
case oprndtOffset : // Address size immediate offset
case oprndtX : // DS:[eSI] for string instruction
case oprndtY : // ES:[eDI] for string instruction
break;
case oprndtZ : // DS:[eBX] for XLAT
return(1);
default :
continue;
}
cb = pops->rgoprnd[ioprnd].bValue;
if (cb == 0)
{
cb = m_fOperand32 ? sizeof(DWORD) : sizeof(WORD);
// Check for special cases
if (pops == &opsRdGv_RdMa)
{
// BOUND instruction reads two operand size values
cb *= 2;
}
else if ((pops == &opsRdMp) || (pops == &opsWrGv_RdMp))
{
// Operand sized offset plus WORD segment/selector
cb += sizeof(WORD);
}
else if ((pops == &opsRdMenv) || (pops == &opsWrMenv))
{
// FRSTOR and FNSAVE
cb = m_fOperand32 ? 28 : 14;
}
else if ((pops == &opsRdMsta) || (pops == &opsWrMsta))
{
// FLDENV and FNSTENV
cb = m_fOperand32 ? 108 : 94;
}
}
break;
}
return(cb);
}
size_t DISX86::CchFormatAddr(ADDR addr, char *sz, size_t cchMax) const
{
if (cchMax > INT_MAX)
{
cchMax = INT_MAX;
}
ostrstream ostr(sz, (int) cchMax);
FormatAddr(ostr, addr);
ostr << ends;
if (ostr.fail())
{
return(0);
}
return((size_t) ostr.pcount());
}
size_t DISX86::CchFormatBytes(char *sz, size_t cchMax) const
{
// UNDONE: Consider grouping immediates as WORDs and DWORDs
if (cchMax < (3 * m_cb))
{
// Caller's buffer is too small
return(0);
}
for (size_t ib = 0; ib < m_cb; ib++)
{
if (ib != 0)
{
sz[-1] = ' ';
}
sprintf(sz, "%02X", m_rgbInstr[ib]);
sz += 3;
}
return(3 * m_cb - 1);
}
size_t DISX86::CchFormatBytesMax() const
{
return(44); // 3 * 15 - 1
}
size_t DISX86::CchFormatInstr(char *sz, size_t cchMax) const
{
if (cchMax > INT_MAX)
{
cchMax = INT_MAX;
}
ostrstream ostr(sz, (int) cchMax);
FormatInstr(ostr);
ostr << ends;
if (ostr.fail())
{
return(0);
}
return((size_t) ostr.pcount());
}
size_t DISX86::Coperand() const
{
const OPS *pops = m_popcd->pops;
for (size_t ioprnd = 0; ioprnd < 3; ioprnd++)
{
if (pops->rgoprnd[ioprnd].oprndt == oprndtNil)
{
break;
}
}
return(ioprnd);
}
void DISX86::FormatAddr(ostream& ostr, ADDR addr) const
{
long lFlags = ostr.setf(ios::uppercase);
char chFill = ostr.fill('0');
if (m_archt == archtX8616)
{
unsigned addrSeg = (unsigned) ((addr & 0xFFFF0000) >> 16);
unsigned addrOff = (unsigned) (addr & 0x0000FFFF);
ostr << hex << setw(4) << addrSeg << ':' << hex << setw(4) << addrOff;
}
else
{
ostr << hex << setw(8) << addr;
}
ostr.fill(chFill);
ostr.flags(lFlags);
}
void DISX86::FormatInstr(ostream& ostr) const
{
long lFlags = ostr.setf(ios::uppercase);
char chFill = ostr.fill('0');
size_t cch = 0;
if (m_bPrefix != 0x00)
{
switch (m_bPrefix)
{
case 0xF0 :
ostr << "lock ";
cch = 5;
break;
case 0xF2 :
ostr << "repne ";
cch = 6;
break;
case 0xF3 :
ostr << "rep ";
cch = 4;
break;
}
}
ostr << (char *) m_popcd->pvMnemonic;
cch += strlen((char *) m_popcd->pvMnemonic);
const OPS *pops = m_popcd->pops;
for (unsigned ioprnd = 0; ioprnd < 3; ioprnd++)
{
if (pops->rgoprnd[ioprnd].oprndt == oprndtNil)
{
break;
}
if (ioprnd == 0)
{
// Pad opcode field to 12 characters
do
{
ostr << ' ';
}
while (++cch < 12);
}
else
{
ostr << ',';
}
FormatOperand(ostr, (OPRNDT) pops->rgoprnd[ioprnd].oprndt, pops->rgoprnd[ioprnd].bValue);
}
ostr.fill(chFill);
ostr.flags(lFlags);
}
DIS::MEMREFT DISX86::Memreft() const
{
switch (m_bPrefix)
{
case 0xF2 : // repne
case 0xF3 : // rep
return(memreftOther);
}
MEMREFT memreft = memreftNone;
// UNDONE: Instructions with implicit spack references are not recognized
// UNDONE: as memory references. This includes PUSH, POP, CALL, RET, IRET,
// UNDONE: ENTER, and LEAVE. Should they?
const OPS *pops = m_popcd->pops;
for (unsigned ioprnd = 0; ioprnd < 3; ioprnd++)
{
if (pops->rgoprnd[ioprnd].oprndt == oprndtNil)
{
break;
}
if (pops->rgoprnd[ioprnd].opreft == opreftNil)
{
continue;
}
switch ((OPRNDT) pops->rgoprnd[ioprnd].oprndt)
{
case oprndtModrm : // Memory/register references from MODRM
if ((m_rgbInstr[m_ibModrm] & 0xC0) == 0xC0)
{
continue;
}
break;
case oprndtOffset : // Address size immediate offset
break;
case oprndtX : // DS:[eSI] for string instruction
case oprndtY : // ES:[eDI] for string instruction
case oprndtZ : // DS:[eBX] for XLAT
// UNDONE: Should these be Other or Read, Write, Read?
return(memreftOther);
default :
continue;
}
if (memreft != memreftNone)
{
// Multiple memory references
return(memreftOther);
}
switch ((OPREFT) pops->rgoprnd[ioprnd].opreft)
{
case opreftRd : // Operand is read
memreft = memreftRead;
break;
case opreftRw : // Operand is read and written
memreft = memreftRdWr;
break;
case opreftWr : // Operand is written
memreft = memreftWrite;
break;
}
}
return(memreft);
}
TRMT DISX86::Trmt() const
{
return(mptrmtx86trmt[m_trmtx86]);
}
TRMTA DISX86::Trmta() const
{
return((TRMTA) m_trmtx86);
}
// -----------------------------------------------------------------
// Private Methods
// -----------------------------------------------------------------
inline ADDR DISX86::AddrJumpTable32() const
{
BYTE b = m_rgbInstr[m_ibModrm];
const BYTE *pb = m_rgbInstr + m_ibModrm + 1;
if ((b & 0x07) == 0x04)
{
// This MODRM is followed by a SIB
pb++;
if ((b & 0xC0) == 0x00)
{
BYTE bSib = m_rgbInstr[m_ibModrm+1];
if ((bSib & 0x07) != 0x05)
{
// Operand is not [XX+disp32]
return(addrNil);
}
return(*(ADDR UNALIGNED *) pb);
}
}
if ((b & 0xC0) != 0x80)
{
// Operand is not [XX+disp32]
return(addrNil);
}
return(*(ADDR UNALIGNED *) pb);
}
inline ADDR DISX86::AddrJumpTable16() const
{
BYTE b = m_rgbInstr[m_ibModrm];
if (m_bSegOverride != 0x2E)
{
// No CS override
return(addrNil);
}
if ((b & 0xC0) != 0x80)
{
// Operand is not [XX+disp16]
return(addrNil);
}
WORD w = *(WORD UNALIGNED *) (m_rgbInstr + m_ibModrm + 1);
ADDR addr = (m_addr & 0xFFFF0000) | w;
return(addr);
}
inline size_t DISX86::CbGenerateLea(BYTE *pb, size_t cbBuf, size_t *pibAddress) const
{
BYTE b = m_rgbInstr[m_ibModrm];
if ((b & 0xC0) == 0xC0)
{
// Operand is a register
return(0);
}
// Calculate size of generated instruction starting with opcode byte
size_t cb = 1;
if (m_fAddrOverride)
{
// If the source had an address override, we need one too
cb++;
}
if (pibAddress != NULL)
{
size_t ibDisp;
if (m_fAddress32)
{
ibDisp = IbDispModrm32();
}
else
{
ibDisp = IbDispModrm16();
}
*pibAddress = cb + (ibDisp - m_ibModrm);
}
cb += m_cbModrm;
if (cb > cbBuf)
{
// The generated instruction won't fit
return(0);
}
// Generate the instruction
// UNDONE: We always generate an LEA when a MOV may be sufficient
if (m_fAddrOverride)
{
*pb++ = 0x67;
}
*pb++ = 0x8D;
memcpy(pb, m_rgbInstr + m_ibModrm, m_cbModrm);
// UNDONE: Force the target register to be EAX
*pb = (BYTE) (*pb & 0xC7);
return(cb);
}
inline size_t DISX86::CbGenerateMovOffset(BYTE *pb, size_t cbBuf, size_t *pibAddress) const
{
// Calculate size of generated instruction starting with opcode byte
size_t cb = 1;
bool fNeedOperOverride = (m_fAddress32 ^ (m_archt != archtX8616));
if (fNeedOperOverride)
{
// If the source had an address override, we need an operand override
cb++;
}
if (pibAddress != NULL)
{
// If there is an immediate displacement, it follows the MODRM byte
*pibAddress = cb;
}
size_t cbOffset = m_fAddress32 ? sizeof(DWORD) : sizeof(WORD);
cb += cbOffset;
if (cb > cbBuf)
{
// The generated instruction won't fit
return(0);
}
if (fNeedOperOverride)
{
*pb++ = 0x66;
}
// UNDONE: The target register is always AX/EAX
*pb++ = 0xb8;
memcpy(pb, m_rgbInstr + m_ibImmed, cbOffset);
return(cb);
}
inline size_t DISX86::CbGenerateMovXDi(BYTE *pb, size_t cbBuf) const
{
bool fNeedOperOverride = (m_fAddress32 ^ (m_archt != archtX8616));
size_t cb = fNeedOperOverride + 2;
if (cb > cbBuf)
{
// The generated instruction won't fit
return(0);
}
if (fNeedOperOverride)
{
*pb++ = 0x66;
}
// UNDONE: The target register is always AX/EAX
*pb++ = 0x8b;
*pb++ = 0xc7;
return(cb);
}
inline size_t DISX86::CbGenerateMovXSi(BYTE *pb, size_t cbBuf) const
{
bool fNeedOperOverride = (m_fAddress32 ^ (m_archt != archtX8616));
size_t cb = fNeedOperOverride + 2;
if (cb > cbBuf)
{
// The generated instruction won't fit
return(0);
}
if (fNeedOperOverride)
{
*pb++ = 0x66;
}
// UNDONE: The target register is always AX/EAX
*pb++ = 0x8b;
*pb++ = 0xc6;
return(cb);
}
inline bool DISX86::FDisassembleModrm32(BYTE b)
{
if (((b & 0x07) == 0x04) && ((b & 0xC0) != 0xC0))
{
// This MODRM is followed by a SIB
if (m_cb == m_cbMax)
{
return(false);
}
BYTE bSib = *m_pbCur++;
m_cb++;
if ((bSib & 0x38) == 0x20)
{
// No index register selected. SS must be 0.
if ((bSib & 0xC0) != 0x00)
{
return(false);
}
}
if ((bSib & 0x07) == 0x05)
{
// Base register is EBP. Check for special case of disp32.
if ((b & 0xC0) == 0x00)
{
// Operand is [disp32]
m_cb += sizeof(DWORD);
if (m_cb > m_cbMax)
{
return(false);
}
}
}
}
switch (b & 0xC0)
{
case 0x00 :
if ((b & 0x07) == 0x05)
{
// Operand is [disp32]
m_cb += sizeof(DWORD);
if (m_cb > m_cbMax)
{
return(false);
}
}
break;
case 0x40 :
// Operand is [XX+disp8]
m_cb += sizeof(BYTE);
if (m_cb > m_cbMax)
{
return(false);
}
break;
case 0x80 :
// Operand is [XX+disp32]
m_cb += sizeof(DWORD);
if (m_cb > m_cbMax)
{
return(false);
}
break;
case 0xC0 :
// Operand is REG
break;
}
return(true);
}
inline bool DISX86::FDisassembleModrm16(BYTE b)
{
switch (b & 0xC0)
{
case 0x00 :
if ((b & 0x07) == 0x06)
{
// Operand is [disp16]
m_cb += sizeof(WORD);
if (m_cb > m_cbMax)
{
return(false);
}
}
break;
case 0x40 :
// Operand is [XX+disp8]
m_cb += sizeof(BYTE);
if (m_cb > m_cbMax)
{
return(false);
}
break;
case 0x80 :
// Operand is [XX+disp16]
m_cb += sizeof(WORD);
if (m_cb > m_cbMax)
{
return(false);
}
break;
case 0xC0 :
// Operand is REG
break;
}
return(true);
}
void DISX86::FormatHex(ostream& ostr, DWORD dw) const
{
if (dw <= 9)
{
ostr << dw;
return;
}
char szHex[11];
sprintf(szHex, "%lX", dw);
if (!isdigit(szHex[0]))
{
ostr << '0';
}
ostr << szHex << 'h';
}
void DISX86::FormatModrm16(ostream& ostr, unsigned cb, bool fMm) const
{
BYTE b = m_rgbInstr[m_ibModrm];
if ((b & 0xC0) == 0xC0)
{
// Operand is a register
if (fMm)
{
ostr << "mm" << (unsigned) (b & 0x07);
}
else
{
FormatRegister(ostr, b & 0x07, cb);
}
return;
}
bool fDisp16 = false;
const char *szReg = NULL;
if ((b & 0xC7) == 0x06)
{
// Special case of [disp16] operand
fDisp16 = true;
}
else
{
szReg = rgszBase16[b & 0x07];
}
char chDisp = '\0';
DWORD dwDisp;
switch (b & 0xC0)
{
BYTE bDisp;
case 0x40 :
bDisp = m_rgbInstr[m_ibModrm + 1];
if ((bDisp & 0x80) == 0x00)
{
chDisp = '+';
dwDisp = bDisp;
}
else
{
chDisp = '-';
dwDisp = -bDisp & 0xFF;
}
break;
case 0x80 :
fDisp16 = true;
break;
}
size_t cchSymbol = 0;
char szSymbol[1024];
if (fDisp16)
{
if (m_pfncchfixup != 0)
{
cchSymbol = (*m_pfncchfixup)(this, m_addr + m_ibModrm + 1, sizeof(WORD), szSymbol, sizeof(szSymbol), &dwDisp);
}
if (cchSymbol != 0)
{
fDisp16 = false;
if (dwDisp != 0)
{
chDisp = '+';
}
}
}
FormatOpSize(ostr, cb);
FormatSegOverride(ostr);
if ((m_bSegOverride == 0x00) && (cchSymbol == 0) && (szReg == NULL))
{
// Add default DS: override for MASM compatibility if there is no symbol or register
ostr << "ds:";
}
// If there is a symbol and a register than the symbol preceeds the brackets
if ((cchSymbol != 0) && (szReg != NULL))
{
if (m_bSegOverride != 0x00)
{
ostr << '[';
}
ostr << szSymbol;
if (m_bSegOverride != 0x00)
{
ostr << ']';
}
}
ostr << '[';
if (szReg != NULL)
{
ostr << szReg;
}
else if (cchSymbol != 0)
{
ostr << szSymbol;
}
if (fDisp16)
{
// This may be an address w/o fixup information. Format as flat address.
if (szReg != NULL)
{
ostr << '+';
}
ostr << hex
<< setw(4)
<< *(WORD UNALIGNED *) (m_rgbInstr + m_ibModrm + 1)
<< 'h';
}
else if (chDisp != '\0')
{
ostr << chDisp;
FormatHex(ostr, dwDisp);
}
ostr << ']';
}
void DISX86::FormatModrm32(ostream& ostr, unsigned cb, bool fMm) const
{
BYTE b = m_rgbInstr[m_ibModrm];
if ((b & 0xC0) == 0xC0)
{
// Operand is a register
if (fMm)
{
ostr << "mm" << (unsigned) (b & 0x07);
}
else
{
FormatRegister(ostr, b & 0x07, cb);
}
return;
}
bool fDisp32 = false;
int iregIndex = -1;
unsigned uScale;
const BYTE *pbDisp = m_rgbInstr + m_ibModrm + 1;
int ireg = (b & 0x07);
if (ireg != 4)
{
// There is no SIB byte
if ((b & 0xC7) == 0x05)
{
// Special case of [disp32] operand
fDisp32 = true;
ireg = -1;
}
}
else
{
// This MODRM is followed by a SIB
BYTE bSib = *pbDisp++;
int iregBase = (bSib & 0x07);
if ((iregBase != 5) || ((b & 0xC0) != 0x00))
{
ireg = iregBase;
}
else
{
ireg = -1;
}
iregIndex = ((bSib >> 3) & 0x07);
if (iregIndex != 4)
{
uScale = 1 << (bSib >> 6);
}
else
{
iregIndex = -1;
}
if ((iregBase == 5) && ((b & 0xC0) == 0x00))
{
fDisp32 = true;
}
}
bool fDisp = false;
DWORD dwDisp = 0;
switch (b & 0xC0)
{
case 0x40 :
fDisp = true;
dwDisp = *pbDisp;
if ((dwDisp & 0x80) != 0)
{
dwDisp |= 0xFFFFFF00;
}
break;
case 0x80 :
fDisp32 = true;
break;
}
size_t cchSymbol = 0;
char szSymbol[1024];
if (fDisp32)
{
DWORD dw;
if (m_pfncchfixup != 0)
{
cchSymbol = (*m_pfncchfixup)(this, m_addr + m_ibModrm + 1, sizeof(DWORD), szSymbol, sizeof(szSymbol), &dw);
}
if (cchSymbol != 0)
{
fDisp32 = false;
fDisp = (dw != 0);
dwDisp = dw;
}
else
{
dwDisp = *(DWORD UNALIGNED *) pbDisp;
}
}
if ((cchSymbol == 0) && (m_pfncchregrel != 0))
{
DWORD dw;
if (ireg != -1)
{
cchSymbol = (*m_pfncchregrel)(this, ireg, dwDisp, szSymbol, sizeof(szSymbol), &dw);
}
if (cchSymbol != 0)
{
ireg = -1;
}
else if ((iregIndex != -1) && (uScale == 1))
{
cchSymbol = (*m_pfncchregrel)(this, iregIndex, dwDisp, szSymbol, sizeof(szSymbol), &dw);
if (cchSymbol != 0)
{
iregIndex = -1;
}
}
if (cchSymbol != 0)
{
fDisp32 = false;
fDisp = (dw != 0);
dwDisp = dw;
}
}
FormatOpSize(ostr, cb);
FormatSegOverride(ostr);
bool fReg = (ireg != -1) || (iregIndex != -1);
if ((m_bSegOverride == 0x00) && (cchSymbol == 0) && !fReg)
{
// Add default DS: override for MASM compatibility if there is no symbol or register
ostr << "ds:";
}
// If there is a symbol and a register than the symbol preceeds the brackets
if ((cchSymbol != 0) && fReg)
{
if (m_bSegOverride != 0x00)
{
ostr << '[';
}
ostr << szSymbol;
if (m_bSegOverride != 0x00)
{
ostr << ']';
}
}
ostr << '[';
if (fReg)
{
if (ireg != -1)
{
ostr << rgszReg32[ireg];
}
if (iregIndex != -1)
{
if (ireg != -1)
{
ostr << '+';
}
ostr << rgszReg32[iregIndex];
if (uScale != 1)
{
ostr << '*' << uScale;
}
}
}
else if (cchSymbol != 0)
{
ostr << szSymbol;
}
if (fDisp32)
{
// This may be an address w/o fixup information. Format as flat address.
if (fReg)
{
ostr << '+';
}
ostr << hex
<< setw(8)
<< dwDisp
<< 'h';
}
else if (fDisp)
{
if (dwDisp & 0x80000000)
{
ostr << '-';
dwDisp = 0 - dwDisp;
}
else
{
ostr << '+';
}
FormatHex(ostr, dwDisp);
}
ostr << ']';
}
void DISX86::FormatOperand(ostream &ostr, OPRNDT oprndt, unsigned bValue) const
{
size_t cch;
char szSymbol[1024];
DWORD dwDisp;
int ireg;
switch (oprndt)
{
case oprndtAP : // Far address
if (m_pfncchfixup != 0)
{
size_t cbFixup = (m_fOperand32 ? sizeof(DWORD) : sizeof(WORD)) + sizeof(WORD);
cch = (*m_pfncchfixup)(this, m_addr + m_ibImmed, cbFixup, szSymbol, sizeof(szSymbol), &dwDisp);
}
else
{
cch = 0;
}
if ((cch == 0) && (m_pfncchaddr != 0) && !m_fOperand32)
{
cch = (*m_pfncchaddr)(this, AddrTarget(), szSymbol, sizeof(szSymbol), &dwDisp);
}
if (cch != 0)
{
ostr << szSymbol;
if (dwDisp != 0)
{
ostr << '+';
FormatHex(ostr, dwDisp);
}
}
else if (m_fOperand32)
{
ostr << hex
<< setw(4)
<< *(WORD UNALIGNED *) (m_rgbInstr + m_ibImmed + sizeof(DWORD))
<< ':'
<< hex
<< setw(8)
<< *(DWORD UNALIGNED *) (m_rgbInstr + m_ibImmed);
}
else
{
ostr << hex
<< setw(4)
<< *(WORD UNALIGNED *) (m_rgbInstr + m_ibImmed + sizeof(WORD))
<< ':'
<< hex
<< setw(4)
<< *(WORD UNALIGNED *) (m_rgbInstr + m_ibImmed);
}
break;
case oprndtCd : // CRx register from MODRM reg
ireg = (m_rgbInstr[m_ibModrm] >> 3) & 0x07;
ostr << "cr" << ireg;
break;
case oprndtConst : // Constant from bValue
ostr << bValue;
break;
case oprndtDd : // DRx register from MODRM reg
ireg = (m_rgbInstr[m_ibModrm] >> 3) & 0x07;
ostr << "dr" << ireg;
break;
case oprndtGvOp : // General register (operand size) from opcode
ireg = m_rgbInstr[m_ibOp] & 0x07;
FormatRegister(ostr, ireg, bValue);
break;
case oprndtIb : // Immediate byte
FormatHex(ostr, m_rgbInstr[m_ibImmed]);
break;
case oprndtIb2 : // Immediate byte
FormatHex(ostr, m_rgbInstr[m_ibImmed + 2]);
break;
case oprndtIv : // Immediate operand size value
if (m_pfncchfixup != 0)
{
size_t cbFixup = m_fOperand32 ? sizeof(DWORD) : sizeof(WORD);
cch = (*m_pfncchfixup)(this, m_addr + m_ibImmed, cbFixup, szSymbol, sizeof(szSymbol), &dwDisp);
}
else
{
cch = 0;
}
if (cch != 0)
{
ostr << "offset " << szSymbol;
if (dwDisp != 0)
{
ostr << '+';
FormatHex(ostr, dwDisp);
}
}
else if (m_fOperand32)
{
FormatHex(ostr, *(DWORD UNALIGNED *) (m_rgbInstr + m_ibImmed));
}
else
{
FormatHex(ostr, *(WORD UNALIGNED *) (m_rgbInstr + m_ibImmed));
}
break;
case oprndtIw : // Immediate word
FormatHex(ostr, *(WORD UNALIGNED *) (m_rgbInstr + m_ibImmed));
break;
case oprndtJb : // Relative address byte
case oprndtJv : // Relative address operand size value
if ((oprndt == oprndtJv) && (m_pfncchfixup != 0))
{
size_t cbFixup = m_fOperand32 ? sizeof(DWORD) : sizeof(WORD);
cch = (*m_pfncchfixup)(this, m_addr + m_ibImmed, cbFixup, szSymbol, sizeof(szSymbol), &dwDisp);
}
else
{
cch = 0;
}
if ((cch == 0) && (m_pfncchaddr != 0))
{
cch = (*m_pfncchaddr)(this, AddrTarget(), szSymbol, sizeof(szSymbol), &dwDisp);
}
if (cch != 0)
{
ostr << szSymbol;
if (dwDisp != 0)
{
ostr << '+';
FormatHex(ostr, dwDisp);
}
}
else if (m_fAddress32)
{
ostr << hex << setw(8) << AddrTarget();
}
else
{
ostr << hex << setw(4) << (AddrTarget() & 0xFFFF);
}
break;
case oprndtMmModrm : // Memory/MM register references from MODRM (MMX)
if (m_fAddress32)
{
FormatModrm32(ostr, bValue, true);
}
else
{
FormatModrm16(ostr, bValue, true);
}
break;
case oprndtMmModrmReg : // MM register from MODRM reg (MMX)
ireg = (m_rgbInstr[m_ibModrm] >> 3) & 0x07;
ostr << "mm" << ireg;
break;
case oprndtModrm : // Memory references from MODRM
if (m_fAddress32)
{
FormatModrm32(ostr, bValue, false);
}
else
{
FormatModrm16(ostr, bValue, false);
}
break;
case oprndtModrmReg : // General register from MODRM reg
ireg = (m_rgbInstr[m_ibModrm] >> 3) & 0x07;
FormatRegister(ostr, ireg, bValue);
break;
case oprndtModrmSReg : // Segment register from MODRM reg
ireg = (m_rgbInstr[m_ibModrm] >> 3) & 0x07;
ostr << rgszSReg[ireg];
break;
case oprndtOffset : // Address size immediate offset
FormatSegOverride(ostr);
if (m_pfncchfixup != 0)
{
size_t cbFixup = m_fAddress32 ? sizeof(DWORD) : sizeof(WORD);
cch = (*m_pfncchfixup)(this, m_addr + m_ibImmed, cbFixup, szSymbol, sizeof(szSymbol), &dwDisp);
}
else
{
cch = 0;
}
if (cch != 0)
{
ostr << '[' << szSymbol;
if (dwDisp != 0)
{
ostr << '+';
FormatHex(ostr, dwDisp);
}
ostr << ']';
}
else if (m_fAddress32)
{
ostr << '['
<< hex
<< setw(8)
<< *(DWORD UNALIGNED *) (m_rgbInstr + m_ibImmed)
<< ']';
}
else
{
ostr << '['
<< hex
<< setw(4)
<< *(WORD UNALIGNED *) (m_rgbInstr + m_ibImmed)
<< ']';
}
break;
case oprndtRb : // General register (byte) from bValue
ostr << rgszReg8[bValue];
break;
case oprndtRv : // General register (operand size) from bValue
FormatRegister(ostr, (int) bValue, 0);
break;
case oprndtRw : // General register (word) from bValue
ostr << rgszReg16[bValue];
break;
case oprndtST : // Floating point top of stack
ostr << "st";
break;
case oprndtSTi : // Floating point register from MODRM reg
ireg = m_rgbInstr[m_ibModrm] & 0x07;
ostr << "st(" << ireg << ')';
break;
case oprndtSw : // Segment register (word) from bValue
ostr << rgszSReg[bValue];
break;
case oprndtTd : // TRx register from MODRM reg
ireg = (m_rgbInstr[m_ibModrm] >> 3) & 0x07;
ostr << "tr" << ireg;
break;
case oprndtX : // DS:[eSI] for string instruction
FormatOpSize(ostr, bValue);
FormatSegOverride(ostr);
if (m_fAddress32)
{
ostr << "[esi]";
}
else
{
ostr << "[si]";
}
break;
case oprndtY : // ES:[eDI] for string instruction
FormatOpSize(ostr, bValue);
if (m_fAddress32)
{
ostr << "es:[edi]";
}
else
{
ostr << "es:[di]";
}
break;
case oprndtZ : // DS:[eBX] for XLAT
FormatOpSize(ostr, 1);
FormatSegOverride(ostr);
if (m_fAddress32)
{
ostr << "[ebx]";
}
else
{
ostr << "[bx]";
}
break;
default :
AssertSz(false, "Invalid operand type");
break;
}
}
void DISX86::FormatOpSize(ostream& ostr, unsigned cb) const
{
const char *szSize;
if (cb == 1)
{
szSize = "byte";
}
else if (cb == 2)
{
szSize = "word";
}
else if (cb == 4)
{
szSize = "dword";
}
else if (m_fOperand32)
{
szSize = "dword";
}
else
{
szSize = "word";
}
ostr << szSize << " ptr ";
}
void DISX86::FormatRegister(ostream& ostr, int ireg, unsigned cb) const
{
const char *szReg;
if (cb == 1)
{
szReg = rgszReg8[ireg];
}
else if (cb == 2)
{
szReg = rgszReg16[ireg];
}
else if (cb == 4)
{
szReg = rgszReg32[ireg];
}
else if (m_fOperand32)
{
szReg = rgszReg32[ireg];
}
else
{
szReg = rgszReg16[ireg];
}
ostr << szReg;
}
void DISX86::FormatSegOverride(ostream& ostr) const
{
const char *szSeg;
switch (m_bSegOverride)
{
case 0x00 : // None
return;
case 0x26 : // ES:
szSeg = "es:";
break;
case 0x2E : // CS:
szSeg = "cs:";
break;
case 0x36 : // SS:
szSeg = "ss:";
break;
case 0x3E : // DS:
szSeg = "ds:";
break;
case 0x64 : // FS:
szSeg = "fs:";
break;
case 0x65 : // GS:
szSeg = "gs:";
break;
default :
AssertSz(false, "Invalid segment override byte");
return;
}
ostr << szSeg;
}
bool DISX86::FValidOperand(size_t ioperand) const
{
if (ioperand == 0)
{
// Implicit operand if any
return(true);
}
if (ioperand > 3)
{
return(false);
}
const OPS *pops = m_popcd->pops;
OPRNDT oprndt = (OPRNDT) pops->rgoprnd[ioperand].oprndt;
return(oprndt != oprndtNil);
}
inline size_t DISX86::IbDispModrm16() const
{
BYTE b = m_rgbInstr[m_ibModrm];
if ((b & 0xC0) == 0xC0)
{
// Operand is a register
return(0);
}
size_t ibDisp = m_ibModrm + 1;
if ((b & 0xC7) == 0x06)
{
// Special case of [disp16] operand
return(ibDisp);
}
switch (b & 0xC0)
{
case 0x40 :
case 0x80 :
return(ibDisp);
}
return(0);
}
inline size_t DISX86::IbDispModrm32() const
{
BYTE b = m_rgbInstr[m_ibModrm];
if ((b & 0xC0) == 0xC0)
{
// Operand is a register
return(0);
}
size_t ibDisp = m_ibModrm + 1;
if ((b & 0x07) != 0x04)
{
// There is no SIB byte
if ((b & 0xC7) == 0x05)
{
// Special case of [disp32] operand
return(ibDisp);
}
}
else
{
// This MODRM is followed by a SIB
// If there is an immediate displacement, it follows the SIB byte
ibDisp++;
BYTE bSib = m_rgbInstr[m_ibModrm + 1];
// Special case base == EBP, mod == 0, means _no_ EBP, but disp32.
// Normally, mod == 0 with SIB means no disp32.
if (((bSib & 0x07) == 0x05) && ((b & 0xC0) == 0x00))
{
return(ibDisp);
}
}
switch (b & 0xC0)
{
case 0x40 :
case 0x80 :
return(ibDisp);
}
return(0);
}
inline size_t DISX86::IbDispOffset() const
{
return(m_ibImmed);
}
inline const OPCD *PopcdFloatingPoint(BYTE bOpcd, BYTE bModrm)
{
switch (bOpcd & 0x07)
{
case 0x00 : // D8
return(rgopcdD8_ + ((bModrm >> 3) & 0x07));
case 0x01 : // D9
return(rgopcdD9_ + (bModrm & 0x3F));
case 0x02 : // DA
if (bModrm == 0xE9)
{
return(&opcdDAE9);
}
return(rgopcdDA_ + ((bModrm >> 3) & 0x07));
case 0x03 : // DB
if ((bModrm >= 0xE0) && (bModrm <= 0xF0))
{
return(rgopcdDB__ + (bModrm - 0xE0));
}
return(rgopcdDB_ + ((bModrm >> 3) & 0x07));
case 0x04 : // DC
return(rgopcdDC_ + ((bModrm >> 3) & 0x07));
case 0x05 : // DD
return(rgopcdDD_ + ((bModrm >> 3) & 0x07));
case 0x06 : // DE
if ((bModrm & 0x38) != 0x18)
{
return(rgopcdDE_ + ((bModrm >> 3) & 0x07));
}
if (bModrm == 0xD9)
{
return(&opcdDED9);
}
break;
case 0x07 : // DF
if ((bModrm >= 0xE0) && (bModrm <= 0xF0))
{
return(rgopcdDF__ + (bModrm - 0xE0));
}
break;
}
return(NULL);
}