2003-12-24 23:32:59 +03:00
|
|
|
#ifndef _BX_DISASM_H_
|
|
|
|
#define _BX_DISASM_H_
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
#undef BX_SUPPORT_X86_64
|
|
|
|
|
2004-10-18 02:05:17 +04:00
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
# define DISASM_REGISTERS 16
|
|
|
|
#else
|
|
|
|
# define DISASM_REGISTERS 8
|
|
|
|
#endif
|
|
|
|
|
2003-12-24 23:32:59 +03:00
|
|
|
#define BX_DECODE_MODRM(modrm_byte, mod, opcode, rm) { \
|
|
|
|
mod = (modrm_byte >> 6) & 0x03; \
|
|
|
|
opcode = (modrm_byte >> 3) & 0x07; \
|
|
|
|
rm = modrm_byte & 0x07; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define BX_DECODE_SIB(sib_byte, scale, index, base) { \
|
|
|
|
scale = sib >> 6; \
|
|
|
|
index = (sib >> 3) & 0x07; \
|
|
|
|
base = sib & 0x07; \
|
|
|
|
}
|
|
|
|
|
2004-10-18 02:05:17 +04:00
|
|
|
// will be used in future
|
2004-12-08 21:54:15 +03:00
|
|
|
#define IA_8086 0x00000000 /* 8086 instruction */
|
|
|
|
#define IA_286 0x00000000 /* 286+ instruction */
|
|
|
|
#define IA_386 0x00000000 /* 386+ instruction */
|
|
|
|
#define IA_FPU 0x00000000
|
|
|
|
#define IA_486 0x00000000 /* 486+ instruction */
|
|
|
|
#define IA_PENTIUM 0x00000000 /* Pentium instruction */
|
|
|
|
#define IA_P6 0x00000000 /* P6 instruction */
|
|
|
|
#define IA_KATMAI 0x00000000 /* Katmai instruction */
|
|
|
|
#define IA_WILLAMETTE 0x00000000 /* Willamette instruction */
|
|
|
|
#define IA_PRESCOTT 0x00000000 /* Prescott instruction */
|
|
|
|
#define IA_X86_64 0x00000000 /* x86-64 specific instruction */
|
2003-12-24 23:32:59 +03:00
|
|
|
|
|
|
|
#define IF_ARITHMETIC 0x00000000 /* arithmetic instruction */
|
|
|
|
#define IF_LOGIC 0x00000000 /* logic instruction */
|
|
|
|
#define IF_SYSTEM 0x00000000 /* system instruction (require CPL=0) */
|
2004-10-18 02:05:17 +04:00
|
|
|
#define IF_BRANCH 0x00000000 /* branch instruction */
|
2003-12-24 23:32:59 +03:00
|
|
|
#define IF_FPU 0x00000000 /* FPU instruction */
|
|
|
|
#define IF_MMX 0x00000000 /* MMX instruction */
|
|
|
|
#define IF_3DNOW 0x00000000 /* 3DNow! instruction */
|
|
|
|
#define IF_KNI 0x00000000 /* Katmai new instruction */
|
|
|
|
#define IF_PREFETCH 0x00000000 /* Prefetch instruction */
|
|
|
|
#define IF_SSE 0x00000000 /* SSE instruction */
|
|
|
|
#define IF_SSE2 0x00000000 /* SSE2 instruction */
|
|
|
|
#define IF_PNI 0x00000000 /* Prescott new instruction */
|
|
|
|
|
|
|
|
enum {
|
|
|
|
AL_REG,
|
|
|
|
CL_REG,
|
|
|
|
DL_REG,
|
|
|
|
BL_REG,
|
|
|
|
AH_REG,
|
|
|
|
CH_REG,
|
|
|
|
DH_REG,
|
|
|
|
BH_REG
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
AX_REG,
|
|
|
|
CX_REG,
|
|
|
|
DX_REG,
|
|
|
|
BX_REG,
|
|
|
|
SP_REG,
|
|
|
|
BP_REG,
|
|
|
|
SI_REG,
|
|
|
|
DI_REG
|
|
|
|
};
|
|
|
|
|
|
|
|
enum {
|
|
|
|
eAX_REG,
|
|
|
|
eCX_REG,
|
|
|
|
eDX_REG,
|
|
|
|
eBX_REG,
|
|
|
|
eSP_REG,
|
|
|
|
eBP_REG,
|
|
|
|
eSI_REG,
|
|
|
|
eDI_REG
|
|
|
|
};
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
#if BX_SUPPORT_X86_64
|
2004-12-10 17:04:57 +03:00
|
|
|
enum {
|
|
|
|
rAX_REG,
|
|
|
|
rCX_REG,
|
|
|
|
rDX_REG,
|
|
|
|
rBX_REG,
|
|
|
|
rSP_REG,
|
|
|
|
rBP_REG,
|
|
|
|
rSI_REG,
|
|
|
|
rDI_REG
|
|
|
|
};
|
2004-12-13 01:12:43 +03:00
|
|
|
#endif
|
2004-12-10 17:04:57 +03:00
|
|
|
|
2003-12-24 23:32:59 +03:00
|
|
|
enum {
|
|
|
|
ES_REG,
|
|
|
|
CS_REG,
|
|
|
|
SS_REG,
|
|
|
|
DS_REG,
|
|
|
|
FS_REG,
|
|
|
|
GS_REG
|
|
|
|
};
|
|
|
|
|
|
|
|
class disassembler;
|
|
|
|
|
|
|
|
typedef void (disassembler::*BxDisasmPtr_t) (unsigned attr);
|
|
|
|
typedef void (disassembler::*BxDisasmResolveModrmPtr_t) (unsigned attr);
|
|
|
|
|
2004-12-10 17:04:57 +03:00
|
|
|
struct BxDisasmOpcodeInfo_t
|
|
|
|
{
|
|
|
|
const char *Opcode;
|
|
|
|
unsigned Attr;
|
|
|
|
BxDisasmPtr_t Operand1;
|
|
|
|
unsigned Op1Attr;
|
|
|
|
BxDisasmPtr_t Operand2;
|
|
|
|
unsigned Op2Attr;
|
|
|
|
BxDisasmPtr_t Operand3;
|
|
|
|
unsigned Op3Attr;
|
|
|
|
struct BxDisasmOpcodeInfo_t *AnotherArray;
|
|
|
|
};
|
|
|
|
|
|
|
|
// datasize attributes
|
|
|
|
#define X_SIZE 0x0000
|
|
|
|
#define B_SIZE 0x0100
|
|
|
|
#define W_SIZE 0x0200
|
|
|
|
#define D_SIZE 0x0300
|
|
|
|
#define V_SIZE 0x0400
|
|
|
|
#define Q_SIZE 0x0500
|
2004-12-13 01:12:43 +03:00
|
|
|
#define Z_SIZE 0x0600
|
|
|
|
#define O_SIZE 0x0700
|
|
|
|
#define T_SIZE 0x0800
|
|
|
|
#define P_SIZE 0x0900
|
|
|
|
#define S_SIZE 0x0A00
|
2004-12-10 17:04:57 +03:00
|
|
|
|
|
|
|
// branch hint attribute
|
|
|
|
#define BRANCH_HINT 0x1000
|
|
|
|
|
2003-12-24 23:32:59 +03:00
|
|
|
class disassembler {
|
2001-04-10 05:04:59 +04:00
|
|
|
public:
|
2004-12-08 21:54:15 +03:00
|
|
|
disassembler() { set_syntax_intel(); }
|
2004-12-13 01:12:43 +03:00
|
|
|
unsigned disasm(bx_bool is_32, bx_address base, bx_address ip, Bit8u *instr, char *disbuf);
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2004-12-08 21:54:15 +03:00
|
|
|
void set_syntax_intel();
|
2004-12-10 17:04:57 +03:00
|
|
|
void set_syntax_att ();
|
2004-12-08 21:54:15 +03:00
|
|
|
|
|
|
|
private:
|
|
|
|
bx_bool intel_mode;
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
const char **general_16bit_regname;
|
|
|
|
const char **general_8bit_regname;
|
|
|
|
const char **general_32bit_regname;
|
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
const char **general_8bit_regname_rex;
|
|
|
|
const char **general_64bit_regname;
|
|
|
|
#endif
|
2004-12-08 21:54:15 +03:00
|
|
|
|
|
|
|
const char **segment_name;
|
|
|
|
const char **index16;
|
|
|
|
|
|
|
|
const char *sreg_mod01or10_rm32[8];
|
|
|
|
const char *sreg_mod00_base32[8];
|
|
|
|
const char *sreg_mod01or10_base32[8];
|
|
|
|
const char *sreg_mod00_rm16[8];
|
|
|
|
const char *sreg_mod01or10_rm16[8];
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
private:
|
2004-12-08 21:54:15 +03:00
|
|
|
|
2003-12-24 23:32:59 +03:00
|
|
|
bx_bool i32bit_opsize;
|
|
|
|
bx_bool i32bit_addrsize;
|
2004-12-13 01:12:43 +03:00
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
bx_bool i64bit_opsize;
|
|
|
|
bx_bool i64bit_addrsize;
|
|
|
|
#endif
|
2003-12-24 23:32:59 +03:00
|
|
|
|
|
|
|
Bit8u modrm, mod, nnn, rm;
|
2004-12-08 21:54:15 +03:00
|
|
|
Bit8u sib, scale, sib_index, sib_base;
|
2003-12-24 23:32:59 +03:00
|
|
|
|
|
|
|
union {
|
|
|
|
Bit16u displ16;
|
|
|
|
Bit32u displ32;
|
|
|
|
} displacement;
|
|
|
|
|
2004-12-13 01:12:43 +03:00
|
|
|
bx_address db_eip, db_base;
|
2003-12-24 23:32:59 +03:00
|
|
|
|
|
|
|
unsigned n_prefixes;
|
|
|
|
|
2001-04-10 05:04:59 +04:00
|
|
|
Bit8u *instruction; // for fetching of next byte of instruction
|
|
|
|
|
2003-12-24 23:32:59 +03:00
|
|
|
const char *seg_override;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
char *disbufptr;
|
|
|
|
|
2003-12-24 23:32:59 +03:00
|
|
|
BxDisasmResolveModrmPtr_t resolve_modrm;
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-12-24 23:32:59 +03:00
|
|
|
BX_CPP_INLINE Bit8u fetch_byte() {
|
2002-09-28 10:29:55 +04:00
|
|
|
db_eip++;
|
2001-04-10 05:04:59 +04:00
|
|
|
return(*instruction++);
|
2004-12-13 01:12:43 +03:00
|
|
|
};
|
2003-12-24 23:32:59 +03:00
|
|
|
|
|
|
|
BX_CPP_INLINE Bit8u peek_byte() {
|
2001-04-10 05:04:59 +04:00
|
|
|
return(*instruction);
|
2004-12-13 01:12:43 +03:00
|
|
|
};
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-12-24 23:32:59 +03:00
|
|
|
BX_CPP_INLINE Bit16u fetch_word() {
|
|
|
|
Bit8u b0 = * (Bit8u *) instruction++;
|
|
|
|
Bit8u b1 = * (Bit8u *) instruction++;
|
|
|
|
Bit16u ret16 = (b1<<8) | b0;
|
2002-09-28 10:29:55 +04:00
|
|
|
db_eip += 2;
|
2001-04-10 05:04:59 +04:00
|
|
|
return(ret16);
|
2004-12-13 01:12:43 +03:00
|
|
|
};
|
2001-04-10 05:04:59 +04:00
|
|
|
|
2003-12-24 23:32:59 +03:00
|
|
|
BX_CPP_INLINE Bit32u fetch_dword() {
|
|
|
|
Bit8u b0 = * (Bit8u *) instruction++;
|
|
|
|
Bit8u b1 = * (Bit8u *) instruction++;
|
|
|
|
Bit8u b2 = * (Bit8u *) instruction++;
|
|
|
|
Bit8u b3 = * (Bit8u *) instruction++;
|
|
|
|
Bit32u ret32 = (b3<<24) | (b2<<16) | (b1<<8) | b0;
|
2002-09-28 10:29:55 +04:00
|
|
|
db_eip += 4;
|
2001-04-10 05:04:59 +04:00
|
|
|
return(ret32);
|
2004-12-13 01:12:43 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
BX_CPP_INLINE Bit64u fetch_qword() {
|
|
|
|
Bit64u d0 = fetch_dword();
|
|
|
|
Bit64u d1 = fetch_dword();
|
|
|
|
Bit64u ret64 = (d1<<32) | d0;
|
|
|
|
return(ret64);
|
|
|
|
};
|
|
|
|
#endif
|
2001-04-10 05:04:59 +04:00
|
|
|
|
|
|
|
void dis_sprintf(char *fmt, ...);
|
2003-12-24 23:32:59 +03:00
|
|
|
void decode_modrm();
|
|
|
|
|
2004-12-08 21:54:15 +03:00
|
|
|
void resolve16_mod0 (unsigned mode);
|
|
|
|
void resolve16_mod1or2 (unsigned mode);
|
|
|
|
|
|
|
|
void resolve32_mod0 (unsigned mode);
|
|
|
|
void resolve32_mod1or2 (unsigned mode);
|
|
|
|
|
|
|
|
void resolve32_mod0_rm4 (unsigned mode);
|
|
|
|
void resolve32_mod1or2_rm4 (unsigned mode);
|
|
|
|
|
|
|
|
void initialize_modrm_segregs();
|
|
|
|
|
|
|
|
void print_datasize (unsigned mode);
|
|
|
|
|
|
|
|
void print_memory_access16(int datasize,
|
|
|
|
const char *seg, const char *index, Bit16u disp);
|
|
|
|
void print_memory_access32(int datasize,
|
|
|
|
const char *seg, const char *base, const char *index, int scale, Bit32u disp);
|
|
|
|
|
2004-12-10 17:04:57 +03:00
|
|
|
void print_disassembly_intel(const BxDisasmOpcodeInfo_t *entry);
|
|
|
|
void print_disassembly_att (const BxDisasmOpcodeInfo_t *entry);
|
|
|
|
|
2003-12-24 23:32:59 +03:00
|
|
|
public:
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Codes for Addressing Method:
|
|
|
|
* ---------------------------
|
|
|
|
* A - Direct address. The instruction has no ModR/M byte; the address
|
|
|
|
* of the operand is encoded in the instruction; and no base register,
|
|
|
|
* index register, or scaling factor can be applied.
|
|
|
|
* C - The reg field of the ModR/M byte selects a control register.
|
|
|
|
* D - The reg field of the ModR/M byte selects a debug register.
|
|
|
|
* E - A ModR/M byte follows the opcode and specifies the operand. The
|
|
|
|
* operand is either a general-purpose register or a memory address.
|
|
|
|
* If it is a memory address, the address is computed from a segment
|
|
|
|
* register and any of the following values: a base register, an
|
|
|
|
* index register, a scaling factor, a displacement.
|
2004-10-18 02:05:17 +04:00
|
|
|
* F - Flags Register.
|
2003-12-24 23:32:59 +03:00
|
|
|
* G - The reg field of the ModR/M byte selects a general register.
|
|
|
|
* I - Immediate data. The operand value is encoded in subsequent bytes of
|
|
|
|
* the instruction.
|
|
|
|
* J - The instruction contains a relative offset to be added to the
|
|
|
|
* instruction pointer register.
|
|
|
|
* M - The ModR/M byte may refer only to memory.
|
|
|
|
* O - The instruction has no ModR/M byte; the offset of the operand is
|
|
|
|
* coded as a word or double word (depending on address size attribute)
|
|
|
|
* in the instruction. No base register, index register, or scaling
|
|
|
|
* factor can be applied.
|
|
|
|
* P - The reg field of the ModR/M byte selects a packed quadword MMX
|
|
|
|
* technology register.
|
|
|
|
* Q - A ModR/M byte follows the opcode and specifies the operand. The
|
|
|
|
* operand is either an MMX technology register or a memory address.
|
|
|
|
* If it is a memory address, the address is computed from a segment
|
|
|
|
* register and any of the following values: a base register, an
|
|
|
|
* index register, a scaling factor, and a displacement.
|
|
|
|
* R - The mod field of the ModR/M byte may refer only to a general register.
|
|
|
|
* S - The reg field of the ModR/M byte selects a segment register.
|
|
|
|
* T - The reg field of the ModR/M byte selects a test register.
|
|
|
|
* V - The reg field of the ModR/M byte selects a 128-bit XMM register.
|
|
|
|
* W - A ModR/M byte follows the opcode and specifies the operand. The
|
|
|
|
* operand is either a 128-bit XMM register or a memory address. If
|
|
|
|
* it is a memory address, the address is computed from a segment
|
|
|
|
* register and any of the following values: a base register, an
|
|
|
|
* index register, a scaling factor, and a displacement.
|
2004-10-18 02:05:17 +04:00
|
|
|
* X - Memory addressed by the DS:rSI register pair.
|
2004-12-09 23:01:00 +03:00
|
|
|
* Y - Memory addressed by the ES:rDI register pair.
|
2003-12-24 23:32:59 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Codes for Operand Type:
|
|
|
|
* ----------------------
|
|
|
|
* a - Two one-word operands in memory or two double-word operands in
|
|
|
|
* memory, depending on operand-size attribute (used only by the BOUND
|
|
|
|
* instruction).
|
|
|
|
* b - Byte, regardless of operand-size attribute.
|
|
|
|
* d - Doubleword, regardless of operand-size attribute.
|
|
|
|
* dq - Double-quadword, regardless of operand-size attribute.
|
|
|
|
* p - 32-bit or 48-bit pointer, depending on operand-size attribute.
|
2004-10-18 02:05:17 +04:00
|
|
|
* pd - 128-bit packed double-precision floating-point data.
|
2004-12-09 23:01:00 +03:00
|
|
|
* pi - Quadword MMX technology register (packed integer)
|
2003-12-24 23:32:59 +03:00
|
|
|
* ps - 128-bit packed single-precision floating-point data.
|
|
|
|
* q - Quadword, regardless of operand-size attribute.
|
2004-10-18 02:05:17 +04:00
|
|
|
* s - 6-byte or 10-byte pseudo-descriptor.
|
2004-12-09 23:01:00 +03:00
|
|
|
* si - Doubleword integer register (scalar integer)
|
2003-12-24 23:32:59 +03:00
|
|
|
* ss - Scalar element of a 128-bit packed single-precision floating data.
|
2004-10-18 02:05:17 +04:00
|
|
|
* sd - Scalar element of a 128-bit packed double-precision floating data.
|
|
|
|
* v - Word, doubleword or quadword, depending on operand-size attribute.
|
2003-12-24 23:32:59 +03:00
|
|
|
* w - Word, regardless of operand-size attribute.
|
2004-12-09 23:01:00 +03:00
|
|
|
* z - A word if the effective operand size is 16 bits, or a doubleword
|
2004-10-18 02:05:17 +04:00
|
|
|
* if the effective operand size is 32 or 64 bits.
|
2003-12-24 23:32:59 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
// fpu
|
2004-12-10 02:19:48 +03:00
|
|
|
void ST0 (unsigned attribute);
|
|
|
|
void STj (unsigned attribute);
|
2003-12-24 23:32:59 +03:00
|
|
|
|
|
|
|
// general/segment register
|
2004-12-10 02:19:48 +03:00
|
|
|
void Rw (unsigned attribute);
|
|
|
|
void Rd (unsigned attribute);
|
|
|
|
void Sw (unsigned attribute);
|
2003-12-24 23:32:59 +03:00
|
|
|
|
|
|
|
// control/debug register
|
2004-12-10 02:19:48 +03:00
|
|
|
void Cd (unsigned attribute);
|
|
|
|
void Dd (unsigned attribute);
|
|
|
|
void Td (unsigned attribute);
|
2003-12-24 23:32:59 +03:00
|
|
|
|
2004-12-10 02:19:48 +03:00
|
|
|
// segment register
|
|
|
|
void OP_SEG (unsigned attribute);
|
2003-12-24 23:32:59 +03:00
|
|
|
|
|
|
|
// memory only
|
2004-12-10 02:19:48 +03:00
|
|
|
void OP_MEM (unsigned attribute);
|
|
|
|
|
|
|
|
// general purpose register
|
|
|
|
void REG16 (unsigned attribute);
|
|
|
|
void REG8 (unsigned attribute);
|
|
|
|
void REG32 (unsigned attribute);
|
2003-12-24 23:32:59 +03:00
|
|
|
|
2004-10-18 02:05:17 +04:00
|
|
|
// string instructions
|
2004-12-10 02:19:48 +03:00
|
|
|
void OP_X (unsigned attribute);
|
|
|
|
void OP_Y (unsigned attribute);
|
2003-12-24 23:32:59 +03:00
|
|
|
|
|
|
|
// mmx/xmm
|
2004-12-10 02:19:48 +03:00
|
|
|
void OP_P (unsigned attribute);
|
|
|
|
void OP_Q (unsigned attribute);
|
|
|
|
void OP_W (unsigned attribute);
|
|
|
|
void OP_V (unsigned attribute);
|
2003-12-24 23:32:59 +03:00
|
|
|
|
2004-10-18 02:05:17 +04:00
|
|
|
// mov
|
2004-12-10 02:19:48 +03:00
|
|
|
void OP_O (unsigned attribute);
|
2003-12-24 23:32:59 +03:00
|
|
|
|
2004-12-10 02:19:48 +03:00
|
|
|
// immediate
|
2004-12-13 01:12:43 +03:00
|
|
|
void sIb (unsigned attribute);
|
2004-12-10 02:19:48 +03:00
|
|
|
void I1 (unsigned attribute);
|
|
|
|
void Ib (unsigned attribute);
|
|
|
|
void Iw (unsigned attribute);
|
|
|
|
void Id (unsigned attribute);
|
|
|
|
void Iv (unsigned attribute);
|
2004-12-13 01:12:43 +03:00
|
|
|
#if BX_SUPPORT_X86_64
|
|
|
|
void Iz (unsigned attribute);
|
|
|
|
void Iq (unsigned attribute);
|
|
|
|
#endif
|
2004-12-10 02:19:48 +03:00
|
|
|
|
|
|
|
// general purpose register or memory
|
|
|
|
void Eb (unsigned attribute);
|
|
|
|
void Ew (unsigned attribute);
|
|
|
|
void Ed (unsigned attribute);
|
|
|
|
void Ev (unsigned attribute);
|
|
|
|
|
|
|
|
// general purpose register
|
|
|
|
void Gb (unsigned attribute);
|
|
|
|
void Gv (unsigned attribute);
|
|
|
|
void Gd (unsigned attribute);
|
|
|
|
|
|
|
|
// call/jump
|
|
|
|
void Jb (unsigned attribute);
|
|
|
|
void Jv (unsigned attribute);
|
|
|
|
|
|
|
|
// call/jmp far
|
|
|
|
void Ap (unsigned attribute);
|
2003-12-24 23:32:59 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|