summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/i386/i386dasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/i386/i386dasm.c')
-rw-r--r--src/emu/cpu/i386/i386dasm.c2125
1 files changed, 2125 insertions, 0 deletions
diff --git a/src/emu/cpu/i386/i386dasm.c b/src/emu/cpu/i386/i386dasm.c
new file mode 100644
index 00000000000..8d88f34bbd2
--- /dev/null
+++ b/src/emu/cpu/i386/i386dasm.c
@@ -0,0 +1,2125 @@
+/*
+ i386 Disassembler
+
+ Written by Ville Linde
+*/
+
+#include "cpuintrf.h"
+
+enum {
+ PARAM_REG = 1, /* 16 or 32-bit register */
+ PARAM_REG8, /* 8-bit register */
+ PARAM_REG16, /* 16-bit register */
+ PARAM_REG32, /* 32-bit register */
+ PARAM_REG3264, /* 32-bit or 64-bit register */
+ PARAM_REG2_32, /* 32-bit register */
+ PARAM_MMX, /* MMX register */
+ PARAM_XMM, /* XMM register */
+ PARAM_RM, /* 16 or 32-bit memory or register */
+ PARAM_RM8, /* 8-bit memory or register */
+ PARAM_RM16, /* 16-bit memory or register */
+ PARAM_RM32, /* 32-bit memory or register */
+ PARAM_RMPTR, /* 16 or 32-bit memory or register */
+ PARAM_RMPTR8, /* 8-bit memory or register */
+ PARAM_RMPTR16, /* 16-bit memory or register */
+ PARAM_RMPTR32, /* 32-bit memory or register */
+ PARAM_RMXMM, /* 32 or 64-bit memory or register */
+ PARAM_REGORXMM, /* 32 or 64-bit register or XMM register */
+ PARAM_M64, /* 64-bit memory */
+ PARAM_M64PTR, /* 64-bit memory */
+ PARAM_MMXM, /* 64-bit memory or MMX register */
+ PARAM_XMMM, /* 128-bit memory or XMM register */
+ PARAM_I4, /* 4-bit signed immediate */
+ PARAM_I8, /* 8-bit signed immediate */
+ PARAM_I16, /* 16-bit signed immediate */
+ PARAM_UI8, /* 8-bit unsigned immediate */
+ PARAM_UI16, /* 16-bit unsigned immediate */
+ PARAM_IMM, /* 16 or 32-bit immediate */
+ PARAM_IMM64, /* 16, 32 or 64-bit immediate */
+ PARAM_ADDR, /* 16:16 or 16:32 address */
+ PARAM_REL, /* 16 or 32-bit PC-relative displacement */
+ PARAM_REL8, /* 8-bit PC-relative displacement */
+ PARAM_MEM_OFFS_B, /* 8-bit mem offset */
+ PARAM_MEM_OFFS_V, /* 16 or 32-bit mem offset */
+ PARAM_SREG, /* segment register */
+ PARAM_CREG, /* control register */
+ PARAM_DREG, /* debug register */
+ PARAM_TREG, /* test register */
+ PARAM_1, /* used by shift/rotate instructions */
+ PARAM_AL,
+ PARAM_CL,
+ PARAM_DL,
+ PARAM_BL,
+ PARAM_AH,
+ PARAM_CH,
+ PARAM_DH,
+ PARAM_BH,
+ PARAM_DX,
+ PARAM_EAX, /* EAX or AX */
+ PARAM_ECX, /* ECX or CX */
+ PARAM_EDX, /* EDX or DX */
+ PARAM_EBX, /* EBX or BX */
+ PARAM_ESP, /* ESP or SP */
+ PARAM_EBP, /* EBP or BP */
+ PARAM_ESI, /* ESI or SI */
+ PARAM_EDI, /* EDI or DI */
+};
+
+enum
+{
+ MODRM = 1,
+ GROUP,
+ FPU,
+ OP_SIZE,
+ ADDR_SIZE,
+ TWO_BYTE,
+ PREFIX,
+ SEG_CS,
+ SEG_DS,
+ SEG_ES,
+ SEG_FS,
+ SEG_GS,
+ SEG_SS,
+ ISREX
+};
+
+#define FLAGS_MASK 0x0ff
+#define VAR_NAME 0x100
+#define VAR_NAME4 0x200
+#define ALWAYS64 0x400
+#define SPECIAL64 0x800
+#define SPECIAL64_ENT(x) (SPECIAL64 | ((x) << 24))
+
+typedef struct {
+ const char *mnemonic;
+ UINT32 flags;
+ UINT32 param1;
+ UINT32 param2;
+ UINT32 param3;
+ offs_t dasm_flags;
+} I386_OPCODE;
+
+typedef struct {
+ char mnemonic[32];
+ const I386_OPCODE *opcode;
+} GROUP_OP;
+
+static const UINT8 *opcode_ptr;
+static const UINT8 *opcode_ptr_base;
+
+static const I386_OPCODE i386_opcode_table1[256] =
+{
+ // 0x00
+ {"add", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"add", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"add", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"add", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"add", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"add", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"push es", 0, 0, 0, 0 },
+ {"pop es", 0, 0, 0, 0 },
+ {"or", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"or", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"or", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"or", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"or", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"or", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"push cs", 0, 0, 0, 0 },
+ {"two_byte", TWO_BYTE, 0, 0, 0 },
+ // 0x10
+ {"adc", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"adc", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"adc", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"adc", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"adc", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"adc", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"push ss", 0, 0, 0, 0 },
+ {"pop ss", 0, 0, 0, 0 },
+ {"sbb", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"sbb", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"sbb", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"sbb", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"sbb", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"sbb", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"push ds", 0, 0, 0, 0 },
+ {"pop ds", 0, 0, 0, 0 },
+ // 0x20
+ {"and", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"and", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"and", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"and", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"and", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"and", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"seg_es", SEG_ES, 0, 0, 0 },
+ {"daa", 0, 0, 0, 0 },
+ {"sub", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"sub", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"sub", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"sub", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"sub", 0, PARAM_AL, PARAM_I8, 0 },
+ {"sub", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"seg_cs", SEG_CS, 0, 0, 0 },
+ {"das", 0, 0, 0, 0 },
+ // 0x30
+ {"xor", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"xor", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"xor", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"xor", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"xor", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"xor", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"seg_ss", SEG_SS, 0, 0, 0 },
+ {"aaa", 0, 0, 0, 0 },
+ {"cmp", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"cmp", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"cmp", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"cmp", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmp", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"cmp", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"seg_ds", SEG_DS, 0, 0, 0 },
+ {"aas", 0, 0, 0, 0 },
+ // 0x40
+ {"inc", ISREX, PARAM_EAX, 0, 0 },
+ {"inc", ISREX, PARAM_ECX, 0, 0 },
+ {"inc", ISREX, PARAM_EDX, 0, 0 },
+ {"inc", ISREX, PARAM_EBX, 0, 0 },
+ {"inc", ISREX, PARAM_ESP, 0, 0 },
+ {"inc", ISREX, PARAM_EBP, 0, 0 },
+ {"inc", ISREX, PARAM_ESI, 0, 0 },
+ {"inc", ISREX, PARAM_EDI, 0, 0 },
+ {"dec", ISREX, PARAM_EAX, 0, 0 },
+ {"dec", ISREX, PARAM_ECX, 0, 0 },
+ {"dec", ISREX, PARAM_EDX, 0, 0 },
+ {"dec", ISREX, PARAM_EBX, 0, 0 },
+ {"dec", ISREX, PARAM_ESP, 0, 0 },
+ {"dec", ISREX, PARAM_EBP, 0, 0 },
+ {"dec", ISREX, PARAM_ESI, 0, 0 },
+ {"dec", ISREX, PARAM_EDI, 0, 0 },
+ // 0x50
+ {"push", ALWAYS64, PARAM_EAX, 0, 0 },
+ {"push", ALWAYS64, PARAM_ECX, 0, 0 },
+ {"push", ALWAYS64, PARAM_EDX, 0, 0 },
+ {"push", ALWAYS64, PARAM_EBX, 0, 0 },
+ {"push", ALWAYS64, PARAM_ESP, 0, 0 },
+ {"push", ALWAYS64, PARAM_EBP, 0, 0 },
+ {"push", ALWAYS64, PARAM_ESI, 0, 0 },
+ {"push", ALWAYS64, PARAM_EDI, 0, 0 },
+ {"pop", ALWAYS64, PARAM_EAX, 0, 0 },
+ {"pop", ALWAYS64, PARAM_ECX, 0, 0 },
+ {"pop", ALWAYS64, PARAM_EDX, 0, 0 },
+ {"pop", ALWAYS64, PARAM_EBX, 0, 0 },
+ {"pop", ALWAYS64, PARAM_ESP, 0, 0 },
+ {"pop", ALWAYS64, PARAM_EBP, 0, 0 },
+ {"pop", ALWAYS64, PARAM_ESI, 0, 0 },
+ {"pop", ALWAYS64, PARAM_EDI, 0, 0 },
+ // 0x60
+ {"pusha\0pushad\0<invalid>",VAR_NAME,0, 0, 0 },
+ {"popa\0popad\0<invalid>", VAR_NAME,0, 0, 0 },
+ {"bound", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"arpl", MODRM | SPECIAL64_ENT(0),PARAM_RM, PARAM_REG16, 0 },
+ {"seg_fs", SEG_FS, 0, 0, 0 },
+ {"seg_gs", SEG_GS, 0, 0, 0 },
+ {"op_size", OP_SIZE, 0, 0, 0 },
+ {"addr_size", ADDR_SIZE, 0, 0, 0 },
+ {"push", 0, PARAM_IMM, 0, 0 },
+ {"imul", MODRM, PARAM_REG, PARAM_RM, PARAM_IMM },
+ {"push", 0, PARAM_I8, 0, 0 },
+ {"imul", MODRM, PARAM_REG, PARAM_RM, PARAM_I8 },
+ {"insb", 0, 0, 0, 0 },
+ {"insw\0insd\0insd",VAR_NAME, 0, 0, 0 },
+ {"outsb", 0, 0, 0, 0 },
+ {"outsw\0outsd\0outsd",VAR_NAME, 0, 0, 0 },
+ // 0x70
+ {"jo", 0, PARAM_REL8, 0, 0 },
+ {"jno", 0, PARAM_REL8, 0, 0 },
+ {"jb", 0, PARAM_REL8, 0, 0 },
+ {"jae", 0, PARAM_REL8, 0, 0 },
+ {"je", 0, PARAM_REL8, 0, 0 },
+ {"jne", 0, PARAM_REL8, 0, 0 },
+ {"jbe", 0, PARAM_REL8, 0, 0 },
+ {"ja", 0, PARAM_REL8, 0, 0 },
+ {"js", 0, PARAM_REL8, 0, 0 },
+ {"jns", 0, PARAM_REL8, 0, 0 },
+ {"jp", 0, PARAM_REL8, 0, 0 },
+ {"jnp", 0, PARAM_REL8, 0, 0 },
+ {"jl", 0, PARAM_REL8, 0, 0 },
+ {"jge", 0, PARAM_REL8, 0, 0 },
+ {"jle", 0, PARAM_REL8, 0, 0 },
+ {"jg", 0, PARAM_REL8, 0, 0 },
+ // 0x80
+ {"group80", GROUP, 0, 0, 0 },
+ {"group81", GROUP, 0, 0, 0 },
+ {"group80", GROUP, 0, 0, 0 },
+ {"group83", GROUP, 0, 0, 0 },
+ {"test", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"test", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"xchg", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"xchg", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"mov", MODRM, PARAM_RM8, PARAM_REG8, 0 },
+ {"mov", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"mov", MODRM, PARAM_REG8, PARAM_RM8, 0 },
+ {"mov", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"mov", MODRM, PARAM_RM, PARAM_SREG, 0 },
+ {"lea", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"mov", MODRM, PARAM_SREG, PARAM_RM, 0 },
+ {"pop", MODRM, PARAM_RM, 0, 0 },
+ // 0x90
+ {"nop", 0, 0, 0, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_ECX, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_EDX, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_EBX, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_ESP, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_EBP, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_ESI, 0 },
+ {"xchg", 0, PARAM_EAX, PARAM_EDI, 0 },
+ {"cbw\0cwde\0cdqe", VAR_NAME, 0, 0, 0 },
+ {"cwd\0cdq\0cqo", VAR_NAME, 0, 0, 0 },
+ {"call", ALWAYS64, PARAM_ADDR, 0, 0, DASMFLAG_STEP_OVER},
+ {"wait", 0, 0, 0, 0 },
+ {"pushf\0pushfd\0pushfq",VAR_NAME, 0, 0, 0 },
+ {"popf\0popfd\0popfq",VAR_NAME, 0, 0, 0 },
+ {"sahf", 0, 0, 0, 0 },
+ {"lahf", 0, 0, 0, 0 },
+ // 0xa0
+ {"mov", 0, PARAM_AL, PARAM_MEM_OFFS_V, 0 },
+ {"mov", 0, PARAM_EAX, PARAM_MEM_OFFS_V, 0 },
+ {"mov", 0, PARAM_MEM_OFFS_V, PARAM_AL, 0 },
+ {"mov", 0, PARAM_MEM_OFFS_V, PARAM_EAX, 0 },
+ {"movsb", 0, 0, 0, 0 },
+ {"movsw\0movsd\0movsq",VAR_NAME, 0, 0, 0 },
+ {"cmpsb", 0, 0, 0, 0 },
+ {"cmpsw\0cmpsd\0cmpsq",VAR_NAME, 0, 0, 0 },
+ {"test", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"test", 0, PARAM_EAX, PARAM_IMM, 0 },
+ {"stosb", 0, 0, 0, 0 },
+ {"stosw\0stosd\0stosq",VAR_NAME, 0, 0, 0 },
+ {"lodsb", 0, 0, 0, 0 },
+ {"lodsw\0lodsd\0lodsq",VAR_NAME, 0, 0, 0 },
+ {"scasb", 0, 0, 0, 0 },
+ {"scasw\0scasd\0scasq",VAR_NAME, 0, 0, 0 },
+ // 0xb0
+ {"mov", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_CL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_DL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_BL, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_AH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_CH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_DH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_BH, PARAM_UI8, 0 },
+ {"mov", 0, PARAM_EAX, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_ECX, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_EDX, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_EBX, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_ESP, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_EBP, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_ESI, PARAM_IMM64, 0 },
+ {"mov", 0, PARAM_EDI, PARAM_IMM64, 0 },
+ // 0xc0
+ {"groupC0", GROUP, 0, 0, 0 },
+ {"groupC1", GROUP, 0, 0, 0 },
+ {"ret", 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
+ {"ret", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ {"les", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"lds", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"mov", MODRM, PARAM_RMPTR8, PARAM_UI8, 0 },
+ {"mov", MODRM, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"enter", 0, PARAM_I16, PARAM_UI8, 0 },
+ {"leave", 0, 0, 0, 0 },
+ {"retf", 0, PARAM_I16, 0, 0, DASMFLAG_STEP_OUT},
+ {"retf", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ {"int 3", 0, 0, 0, 0, DASMFLAG_STEP_OVER},
+ {"int", 0, PARAM_UI8, 0, 0, DASMFLAG_STEP_OVER},
+ {"into", 0, 0, 0, 0 },
+ {"iret", 0, 0, 0, 0, DASMFLAG_STEP_OUT},
+ // 0xd0
+ {"groupD0", GROUP, 0, 0, 0 },
+ {"groupD1", GROUP, 0, 0, 0 },
+ {"groupD2", GROUP, 0, 0, 0 },
+ {"groupD3", GROUP, 0, 0, 0 },
+ {"aam", 0, PARAM_I8, 0, 0 },
+ {"aad", 0, PARAM_I8, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"xlat", 0, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ {"escape", FPU, 0, 0, 0 },
+ // 0xe0
+ {"loopne", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {"loopz", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {"loop", 0, PARAM_REL8, 0, 0, DASMFLAG_STEP_OVER},
+ {"jcxz\0jecxz\0jrcxz",VAR_NAME, PARAM_REL8, 0, 0 },
+ {"in", 0, PARAM_AL, PARAM_UI8, 0 },
+ {"in", 0, PARAM_EAX, PARAM_UI8, 0 },
+ {"out", 0, PARAM_UI8, PARAM_AL, 0 },
+ {"out", 0, PARAM_UI8, PARAM_EAX, 0 },
+ {"call", 0, PARAM_REL, 0, 0, DASMFLAG_STEP_OVER},
+ {"jmp", 0, PARAM_REL, 0, 0 },
+ {"jmp", 0, PARAM_ADDR, 0, 0 },
+ {"jmp", 0, PARAM_REL8, 0, 0 },
+ {"in", 0, PARAM_AL, PARAM_DX, 0 },
+ {"in", 0, PARAM_EAX, PARAM_DX, 0 },
+ {"out", 0, PARAM_DX, PARAM_AL, 0 },
+ {"out", 0, PARAM_DX, PARAM_EAX, 0 },
+ // 0xf0
+ {"lock", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"repne", PREFIX, 0, 0, 0 },
+ {"rep", PREFIX, 0, 0, 0 },
+ {"hlt", 0, 0, 0, 0 },
+ {"cmc", 0, 0, 0, 0 },
+ {"groupF6", GROUP, 0, 0, 0 },
+ {"groupF7", GROUP, 0, 0, 0 },
+ {"clc", 0, 0, 0, 0 },
+ {"stc", 0, 0, 0, 0 },
+ {"cli", 0, 0, 0, 0 },
+ {"sti", 0, 0, 0, 0 },
+ {"cld", 0, 0, 0, 0 },
+ {"std", 0, 0, 0, 0 },
+ {"groupFE", GROUP, 0, 0, 0 },
+ {"groupFF", GROUP, 0, 0, 0 }
+};
+
+static const I386_OPCODE x64_opcode_alt[] =
+{
+ {"movsxd", MODRM | ALWAYS64,PARAM_REG, PARAM_RMPTR32, 0 },
+};
+
+static const I386_OPCODE i386_opcode_table2[256] =
+{
+ // 0x00
+ {"group0F00", GROUP, 0, 0, 0 },
+ {"group0F01", GROUP, 0, 0, 0 },
+ {"lar", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"lsl", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"syscall", 0, 0, 0, 0 },
+ {"clts", 0, 0, 0, 0 },
+ {"sysret", 0, 0, 0, 0 },
+ {"invd", 0, 0, 0, 0 },
+ {"wbinvd", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"ud2", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x10
+ {"movups\0"
+ "movupd\0"
+ "movsd\0"
+ "movss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movups\0"
+ "movupd\0"
+ "movsd\0"
+ "movss", MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 },
+ {"movlps\0"
+ "movlpd\0"
+ "movddup\0"
+ "movsldup", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movlps\0"
+ "movlpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 },
+ {"unpcklps\0"
+ "unpcklpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"unpckhps\0"
+ "unpckhpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movhps\0"
+ "movhpd\0"
+ "???\0"
+ "movshdup", MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 },
+ {"movhps\0"
+ "movhpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"group0F18", GROUP, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x20
+ {"mov", MODRM, PARAM_REG2_32, PARAM_CREG, 0 },
+ {"mov", MODRM, PARAM_REG2_32, PARAM_DREG, 0 },
+ {"mov", MODRM, PARAM_CREG, PARAM_REG2_32, 0 },
+ {"mov", MODRM, PARAM_DREG, PARAM_REG2_32, 0 },
+ {"mov", MODRM, PARAM_REG2_32, PARAM_TREG, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"mov", MODRM, PARAM_TREG, PARAM_REG2_32, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"movaps\0"
+ "movapd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movaps\0"
+ "movapd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 },
+ {"cvtpi2ps\0"
+ "cvtpi2pd\0"
+ "cvtsi2sd\0"
+ "cvtsi2ss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_RMXMM, 0 },
+ {"movntps\0"
+ "movntpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMMM, PARAM_XMM, 0 },
+ {"cvttps2pi\0"
+ "cvttpd2pi\0"
+ "cvttsd2si\0"
+ "cvttss2si", MODRM|VAR_NAME4,PARAM_REGORXMM, PARAM_XMMM, 0 },
+ {"cvtps2pi\0"
+ "cvtpd2pi\0"
+ "cvtsd2si\0"
+ "cvtss2si", MODRM|VAR_NAME4,PARAM_REGORXMM, PARAM_XMMM, 0 },
+ {"ucomiss\0"
+ "ucomisd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"comiss\0"
+ "comisd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ // 0x30
+ {"wrmsr", 0, 0, 0, 0 },
+ {"rdtsc", 0, 0, 0, 0 },
+ {"rdmsr", 0, 0, 0, 0 },
+ {"rdpmc", 0, 0, 0, 0 },
+ {"sysenter", 0, 0, 0, 0 },
+ {"sysexit", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ // 0x40
+ {"cmovo", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovno", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovb", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovae", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmove", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovne", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovbe", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmova", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovs", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovns", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovpe", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovpo", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovl", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovge", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovle", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"cmovg", MODRM, PARAM_REG, PARAM_RM, 0 },
+ // 0x50
+ {"movmskps\0"
+ "movmskpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_REG3264, PARAM_XMMM, 0 },
+ {"sqrtps\0"
+ "sqrtpd\0"
+ "sqrtsd\0"
+ "sqrtss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"rsqrtps\0"
+ "???\0"
+ "???\0"
+ "rsqrtss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"rcpps\0"
+ "???\0"
+ "???\0"
+ "rcpss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"andps\0"
+ "andpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"andnps\0"
+ "andnpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"orps\0"
+ "orpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"xorps\0"
+ "xorpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"addps\0"
+ "addpd\0"
+ "addsd\0"
+ "addss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"mulps\0"
+ "mulpd\0"
+ "mulsd\0"
+ "mulss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"cvtps2pd\0"
+ "cvtpd2ps\0"
+ "cvtsd2ss\0"
+ "cvtss2sd", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"cvtdq2ps\0"
+ "cvtps2dq\0"
+ "???\0"
+ "cvttps2dq", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"subps\0"
+ "subpd\0"
+ "subsd\0"
+ "subss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"minps\0"
+ "minpd\0"
+ "minsd\0"
+ "minss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"divps\0"
+ "divpd\0"
+ "divsd\0"
+ "divss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"maxps\0"
+ "maxpd\0"
+ "maxsd\0"
+ "maxss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ // 0x60
+ {"punpcklbw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpcklwd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpckldq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"packsswb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pcmpgtb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pcmpgtw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pcmpgtd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"packuswb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpckhbw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpckhwd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpckhdq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"packssdw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"punpcklqdq", MODRM, PARAM_XMM, PARAM_XMMM, 0 },
+ {"punpckhqdq", MODRM, PARAM_XMM, PARAM_XMMM, 0 },
+ {"movd", MODRM, PARAM_MMX, PARAM_RM, 0 },
+ {"movq\0"
+ "movdqa\0"
+ "???\0"
+ "movdqu", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 },
+ // 0x70
+ {"pshufw\0"
+ "pshufd\0"
+ "pshuflw\0"
+ "pshufhw", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, PARAM_I8 },
+ {"group0F71", GROUP, 0, 0, 0 },
+ {"group0F72", GROUP, 0, 0, 0 },
+ {"group0F73", GROUP, 0, 0, 0 },
+ {"pcmpeqb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pcmpeqw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pcmpeqd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"emms", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???\0"
+ "haddpd\0"
+ "haddps\0"
+ "???", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 },
+ {"???\0"
+ "hsubpd\0"
+ "hsubps\0"
+ "???", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 },
+ {"movd\0"
+ "movd\0"
+ "???\0"
+ "movq", MODRM|VAR_NAME4,PARAM_RM, PARAM_MMX, 0 },
+ {"movq\0"
+ "movdqa\0"
+ "???\0"
+ "movdqu", MODRM|VAR_NAME4,PARAM_MMXM, PARAM_MMX, 0 },
+ // 0x80
+ {"jo", 0, PARAM_REL, 0, 0 },
+ {"jno", 0, PARAM_REL, 0, 0 },
+ {"jb", 0, PARAM_REL, 0, 0 },
+ {"jae", 0, PARAM_REL, 0, 0 },
+ {"je", 0, PARAM_REL, 0, 0 },
+ {"jne", 0, PARAM_REL, 0, 0 },
+ {"jbe", 0, PARAM_REL, 0, 0 },
+ {"ja", 0, PARAM_REL, 0, 0 },
+ {"js", 0, PARAM_REL, 0, 0 },
+ {"jns", 0, PARAM_REL, 0, 0 },
+ {"jp", 0, PARAM_REL, 0, 0 },
+ {"jnp", 0, PARAM_REL, 0, 0 },
+ {"jl", 0, PARAM_REL, 0, 0 },
+ {"jge", 0, PARAM_REL, 0, 0 },
+ {"jle", 0, PARAM_REL, 0, 0 },
+ {"jg", 0, PARAM_REL, 0, 0 },
+ // 0x90
+ {"seto", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setno", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setb", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setae", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"sete", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setne", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setbe", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"seta", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"sets", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setns", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setp", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setnp", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setl", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setge", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setle", MODRM, PARAM_RMPTR8, 0, 0 },
+ {"setg", MODRM, PARAM_RMPTR8, 0, 0 },
+ // 0xa0
+ {"push fs", 0, 0, 0, 0 },
+ {"pop fs", 0, 0, 0, 0 },
+ {"cpuid", 0, 0, 0, 0 },
+ {"bt", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"shld", MODRM, PARAM_RM, PARAM_REG, PARAM_I8 },
+ {"shld", MODRM, PARAM_RM, PARAM_REG, PARAM_CL },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"push gs", 0, 0, 0, 0 },
+ {"pop gs", 0, 0, 0, 0 },
+ {"rsm", 0, 0, 0, 0 },
+ {"bts", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"shrd", MODRM, PARAM_RM, PARAM_REG, PARAM_I8 },
+ {"shrd", MODRM, PARAM_RM, PARAM_REG, PARAM_CL },
+ {"group0FAE", GROUP, 0, 0, 0 },
+ {"imul", MODRM, PARAM_REG, PARAM_RM, 0 },
+ // 0xb0
+ {"cmpxchg", MODRM, PARAM_RM8, PARAM_REG, 0 },
+ {"cmpxchg", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"lss", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"btr", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"lfs", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"lgs", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"movzx", MODRM, PARAM_REG, PARAM_RMPTR8, 0 },
+ {"movzx", MODRM, PARAM_REG, PARAM_RMPTR16, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"group0FBA", GROUP, 0, 0, 0 },
+ {"btc", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"bsf", MODRM, PARAM_REG, PARAM_RM, 0 },
+ {"bsr", MODRM, PARAM_REG, PARAM_RM, 0, DASMFLAG_STEP_OVER},
+ {"movsx", MODRM, PARAM_REG, PARAM_RMPTR8, 0 },
+ {"movsx", MODRM, PARAM_REG, PARAM_RMPTR16, 0 },
+ // 0xc0
+ {"xadd", MODRM, PARAM_RM8, PARAM_REG, 0 },
+ {"xadd", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"cmpps\0"
+ "cmppd\0"
+ "cmpsd\0"
+ "cmpss", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movnti", MODRM, PARAM_RM, PARAM_REG, 0 },
+ {"pinsrw", MODRM, PARAM_MMX, PARAM_MMXM, PARAM_I8 },
+ {"pextrw", MODRM, PARAM_MMX, PARAM_MMXM, PARAM_I8 },
+ {"shufps\0"
+ "shufpd\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, PARAM_I8 },
+ {"cmpxchg8b", MODRM, PARAM_M64PTR, 0, 0 },
+ {"bswap", 0, PARAM_EAX, 0, 0 },
+ {"bswap", 0, PARAM_ECX, 0, 0 },
+ {"bswap", 0, PARAM_EDX, 0, 0 },
+ {"bswap", 0, PARAM_EBX, 0, 0 },
+ {"bswap", 0, PARAM_ESP, 0, 0 },
+ {"bswap", 0, PARAM_EBP, 0, 0 },
+ {"bswap", 0, PARAM_ESI, 0, 0 },
+ {"bswap", 0, PARAM_EDI, 0, 0 },
+ // 0xd0
+ {"addsubpd\0"
+ "???\0"
+ "addsubps\0"
+ "???\0", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"psrlw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psrld", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psrlq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmullw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"movq\0"
+ "???\0"
+ "movdq2q\0"
+ "movq2dq", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmovmskb", MODRM, PARAM_REG3264, PARAM_MMXM, 0 },
+ {"psubusb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubusw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pminub", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pand", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddub", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"padduw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmaxub", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pandn", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ // 0xe0
+ {"pavgb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psraw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psrad", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pavgw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmulhuw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmulhw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"???\0"
+ "cvttpd2dq\0"
+ "cvtpd2dq\0"
+ "cvtdq2pd", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"movntq", MODRM, PARAM_M64, PARAM_MMX, 0 },
+ {"psubsb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubsw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pminsw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"por", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddsb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddsw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmaxsw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pxor", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ // 0xf0
+ {"???\0"
+ "???\0"
+ "lddqu\0"
+ "???", MODRM|VAR_NAME4,PARAM_XMM, PARAM_XMMM, 0 },
+ {"psllw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pslld", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psllq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmuludq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"pmaddwd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psadbw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"maskmovq\0"
+ "maskmovdqu\0"
+ "???\0"
+ "???", MODRM|VAR_NAME4,PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"psubq", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddb", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddw", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"paddd", MODRM, PARAM_MMX, PARAM_MMXM, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group80_table[8] =
+{
+ {"add", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"or", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"adc", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"sbb", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"and", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"sub", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"xor", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"cmp", 0, PARAM_RMPTR8, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE group81_table[8] =
+{
+ {"add", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"or", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"adc", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"sbb", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"and", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"sub", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"xor", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"cmp", 0, PARAM_RMPTR, PARAM_IMM, 0 }
+};
+
+static const I386_OPCODE group83_table[8] =
+{
+ {"add", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"or", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"adc", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"sbb", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"and", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"sub", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"xor", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"cmp", 0, PARAM_RMPTR, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE groupC0_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"ror", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"rcl", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"rcr", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"shl", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"shr", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"sal", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"sar", 0, PARAM_RMPTR8, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE groupC1_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"ror", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"rcl", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"rcr", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"shl", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"shr", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"sal", 0, PARAM_RMPTR, PARAM_I8, 0 },
+ {"sar", 0, PARAM_RMPTR, PARAM_I8, 0 }
+};
+
+static const I386_OPCODE groupD0_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"ror", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"rcl", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"rcr", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"shl", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"shr", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"sal", 0, PARAM_RMPTR8, PARAM_1, 0 },
+ {"sar", 0, PARAM_RMPTR8, PARAM_1, 0 }
+};
+
+static const I386_OPCODE groupD1_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"ror", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"rcl", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"rcr", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"shl", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"shr", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"sal", 0, PARAM_RMPTR, PARAM_1, 0 },
+ {"sar", 0, PARAM_RMPTR, PARAM_1, 0 }
+};
+
+static const I386_OPCODE groupD2_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"ror", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"rcl", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"rcr", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"shl", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"shr", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"sal", 0, PARAM_RMPTR8, PARAM_CL, 0 },
+ {"sar", 0, PARAM_RMPTR8, PARAM_CL, 0 }
+};
+
+static const I386_OPCODE groupD3_table[8] =
+{
+ {"rol", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"ror", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"rcl", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"rcr", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"shl", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"shr", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"sal", 0, PARAM_RMPTR, PARAM_CL, 0 },
+ {"sar", 0, PARAM_RMPTR, PARAM_CL, 0 }
+};
+
+static const I386_OPCODE groupF6_table[8] =
+{
+ {"test", 0, PARAM_RMPTR8, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"not", 0, PARAM_RMPTR8, 0, 0 },
+ {"neg", 0, PARAM_RMPTR8, 0, 0 },
+ {"mul", 0, PARAM_RMPTR8, 0, 0 },
+ {"imul", 0, PARAM_RMPTR8, 0, 0 },
+ {"div", 0, PARAM_RMPTR8, 0, 0 },
+ {"idiv", 0, PARAM_RMPTR8, 0, 0 }
+};
+
+static const I386_OPCODE groupF7_table[8] =
+{
+ {"test", 0, PARAM_RMPTR, PARAM_IMM, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"not", 0, PARAM_RMPTR, 0, 0 },
+ {"neg", 0, PARAM_RMPTR, 0, 0 },
+ {"mul", 0, PARAM_RMPTR, 0, 0 },
+ {"imul", 0, PARAM_RMPTR, 0, 0 },
+ {"div", 0, PARAM_RMPTR, 0, 0 },
+ {"idiv", 0, PARAM_RMPTR, 0, 0 }
+};
+
+static const I386_OPCODE groupFE_table[8] =
+{
+ {"inc", 0, PARAM_RMPTR8, 0, 0 },
+ {"dec", 0, PARAM_RMPTR8, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE groupFF_table[8] =
+{
+ {"inc", 0, PARAM_RMPTR, 0, 0 },
+ {"dec", 0, PARAM_RMPTR, 0, 0 },
+ {"call", ALWAYS64, PARAM_RMPTR, 0, 0, DASMFLAG_STEP_OVER},
+ {"call far ptr ",0, PARAM_RM, 0, 0, DASMFLAG_STEP_OVER},
+ {"jmp", ALWAYS64, PARAM_RMPTR, 0, 0 },
+ {"jmp far ptr ",0, PARAM_RM, 0, 0 },
+ {"push", 0, PARAM_RMPTR, 0, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group0F00_table[8] =
+{
+ {"sldt", 0, PARAM_RM, 0, 0 },
+ {"str", 0, PARAM_RM, 0, 0 },
+ {"lldt", 0, PARAM_RM, 0, 0 },
+ {"ltr", 0, PARAM_RM, 0, 0 },
+ {"verr", 0, PARAM_RM, 0, 0 },
+ {"verw", 0, PARAM_RM, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group0F01_table[8] =
+{
+ {"sgdt", 0, PARAM_RM, 0, 0 },
+ {"sidt", 0, PARAM_RM, 0, 0 },
+ {"lgdt", 0, PARAM_RM, 0, 0 },
+ {"lidt", 0, PARAM_RM, 0, 0 },
+ {"smsw", 0, PARAM_RM, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"lmsw", 0, PARAM_RM, 0, 0 },
+ {"invlpg", 0, PARAM_RM, 0, 0 }
+};
+
+static const I386_OPCODE group0F18_table[8] =
+{
+ {"prefetchnta", 0, PARAM_RM8, 0, 0 },
+ {"prefetch0", 0, PARAM_RM8, 0, 0 },
+ {"prefetch1", 0, PARAM_RM8, 0, 0 },
+ {"prefetch2", 0, PARAM_RM8, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group0F71_table[8] =
+{
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psrlw", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psraw", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psllw", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group0F72_table[8] =
+{
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psrld", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"psrldq", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"pslld", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"pslldq", 0, PARAM_MMX, PARAM_I8, 0 },
+};
+
+static const I386_OPCODE group0F73_table[8] =
+{
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psrlq", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psraq", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"psllq", 0, PARAM_MMX, PARAM_I8, 0 },
+ {"???", 0, 0, 0, 0 }
+};
+
+static const I386_OPCODE group0FAE_table[8] =
+{
+ {"fxsave", 0, PARAM_RM, 0, 0 },
+ {"fxrstor", 0, PARAM_RM, 0, 0 },
+ {"ldmxcsr", 0, PARAM_RM, 0, 0 },
+ {"stmxscr", 0, PARAM_RM, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"lfence", 0, 0, 0, 0 },
+ {"mfence", 0, 0, 0, 0 },
+ {"sfence", 0, 0, 0, 0 }
+};
+
+
+static const I386_OPCODE group0FBA_table[8] =
+{
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"???", 0, 0, 0, 0 },
+ {"bt", 0, PARAM_RM, PARAM_I8, 0 },
+ {"bts", 0, PARAM_RM, PARAM_I8, 0 },
+ {"btr", 0, PARAM_RM, PARAM_I8, 0 },
+ {"btc", 0, PARAM_RM, PARAM_I8, 0 }
+};
+
+static const GROUP_OP group_op_table[] =
+{
+ { "group80", group80_table },
+ { "group81", group81_table },
+ { "group83", group83_table },
+ { "groupC0", groupC0_table },
+ { "groupC1", groupC1_table },
+ { "groupD0", groupD0_table },
+ { "groupD1", groupD1_table },
+ { "groupD2", groupD2_table },
+ { "groupD3", groupD3_table },
+ { "groupF6", groupF6_table },
+ { "groupF7", groupF7_table },
+ { "groupFE", groupFE_table },
+ { "groupFF", groupFF_table },
+ { "group0F00", group0F00_table },
+ { "group0F01", group0F01_table },
+ { "group0F18", group0F18_table },
+ { "group0F71", group0F71_table },
+ { "group0F72", group0F72_table },
+ { "group0F73", group0F73_table },
+ { "group0FAE", group0FAE_table },
+ { "group0FBA", group0FBA_table }
+};
+
+
+
+static const char *i386_reg[3][16] =
+{
+ {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w","r11w","r12w","r13w","r14w","r15w"},
+ {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d","r11d","r12d","r13d","r14d","r15d"},
+ {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}
+};
+
+static const char *i386_reg8[8] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"};
+static const char *i386_reg8rex[16] = {"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l"};
+static const char *i386_sreg[8] = {"es", "cs", "ss", "ds", "fs", "gs", "???", "???"};
+
+static int address_size;
+static int operand_size;
+static UINT32 pc;
+static UINT8 modrm;
+static UINT32 segment;
+static offs_t dasm_flags;
+static char modrm_string[256];
+static UINT8 rex, regex, sibex, rmex;
+static UINT8 pre0f;
+static UINT8 curmode;
+
+#define MODRM_REG1 ((modrm >> 3) & 0x7)
+#define MODRM_REG2 (modrm & 0x7)
+
+INLINE UINT8 FETCH(void)
+{
+ if ((opcode_ptr - opcode_ptr_base) + 1 > 15)
+ return 0xff;
+ pc++;
+ return *opcode_ptr++;
+}
+
+INLINE UINT16 FETCH16(void)
+{
+ UINT16 d;
+ if ((opcode_ptr - opcode_ptr_base) + 2 > 15)
+ return 0xffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8);
+ opcode_ptr += 2;
+ pc += 2;
+ return d;
+}
+
+INLINE UINT32 FETCH32(void)
+{
+ UINT32 d;
+ if ((opcode_ptr - opcode_ptr_base) + 4 > 15)
+ return 0xffffffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8) | (opcode_ptr[2] << 16) | (opcode_ptr[3] << 24);
+ opcode_ptr += 4;
+ pc += 4;
+ return d;
+}
+
+INLINE UINT8 FETCHD(void)
+{
+ if ((opcode_ptr - opcode_ptr_base) + 1 > 15)
+ return 0xff;
+ pc++;
+ return *opcode_ptr++;
+}
+
+INLINE UINT16 FETCHD16(void)
+{
+ UINT16 d;
+ if ((opcode_ptr - opcode_ptr_base) + 2 > 15)
+ return 0xffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8);
+ opcode_ptr += 2;
+ pc += 2;
+ return d;
+}
+
+INLINE UINT32 FETCHD32(void)
+{
+ UINT32 d;
+ if ((opcode_ptr - opcode_ptr_base) + 4 > 15)
+ return 0xffffffff;
+ d = opcode_ptr[0] | (opcode_ptr[1] << 8) | (opcode_ptr[2] << 16) | (opcode_ptr[3] << 24);
+ opcode_ptr += 4;
+ pc += 4;
+ return d;
+}
+
+static char *hexstring(UINT32 value, int digits)
+{
+ static char buffer[20];
+ buffer[0] = '0';
+ if (digits)
+ sprintf(&buffer[1], "%0*Xh", digits, value);
+ else
+ sprintf(&buffer[1], "%Xh", value);
+ return (buffer[1] >= '0' && buffer[1] <= '9') ? &buffer[1] : &buffer[0];
+}
+
+static char *hexstring64(UINT32 lo, UINT32 hi)
+{
+ static char buffer[40];
+ buffer[0] = '0';
+ if (hi != 0)
+ sprintf(&buffer[1], "%X%08Xh", hi, lo);
+ else
+ sprintf(&buffer[1], "%Xh", lo);
+ return (buffer[1] >= '0' && buffer[1] <= '9') ? &buffer[1] : &buffer[0];
+}
+
+static char *shexstring(UINT32 value, int digits, int always)
+{
+ static char buffer[20];
+ if (value >= 0x80000000)
+ sprintf(buffer, "-%s", hexstring(-value, digits));
+ else if (always)
+ sprintf(buffer, "+%s", hexstring(value, digits));
+ else
+ return hexstring(value, digits);
+ return buffer;
+}
+
+static char* handle_sib_byte( char* s, UINT8 mod )
+{
+ UINT32 i32;
+ UINT8 scale, i, base;
+ UINT8 sib = FETCHD();
+
+ scale = (sib >> 6) & 0x3;
+ i = ((sib >> 3) & 0x7) | sibex;
+ base = (sib & 0x7) | rmex;
+
+ if (base == 5 && mod == 0) {
+ i32 = FETCH32();
+ s += sprintf( s, "%s", hexstring(i32, 0) );
+ } else if (base != 5 || mod != 3)
+ s += sprintf( s, "%s", i386_reg[address_size][base] );
+
+ if ( i != 4 ) {
+ s += sprintf( s, "+%s", i386_reg[address_size][i] );
+ if (scale)
+ s += sprintf( s, "*%d", 1 << scale );
+ }
+ return s;
+}
+
+static void handle_modrm(char* s)
+{
+ INT8 disp8;
+ INT16 disp16;
+ INT32 disp32;
+ UINT8 mod, rm;
+
+ modrm = FETCHD();
+ mod = (modrm >> 6) & 0x3;
+ rm = (modrm & 0x7) | rmex;
+
+ if( modrm >= 0xc0 )
+ return;
+
+ switch(segment)
+ {
+ case SEG_CS: s += sprintf( s, "cs:" ); break;
+ case SEG_DS: s += sprintf( s, "ds:" ); break;
+ case SEG_ES: s += sprintf( s, "es:" ); break;
+ case SEG_FS: s += sprintf( s, "fs:" ); break;
+ case SEG_GS: s += sprintf( s, "gs:" ); break;
+ case SEG_SS: s += sprintf( s, "ss:" ); break;
+ }
+
+ s += sprintf( s, "[" );
+ if( address_size == 2 ) {
+ if ((rm & 7) == 4)
+ s = handle_sib_byte( s, mod );
+ else if ((rm & 7) == 5 && mod == 0) {
+ disp32 = FETCHD32();
+ s += sprintf( s, "rip%s", shexstring(disp32, 0, TRUE) );
+ } else
+ s += sprintf( s, "%s", i386_reg[2][rm]);
+ if( mod == 1 ) {
+ disp8 = FETCHD();
+ if (disp8 != 0)
+ s += sprintf( s, "%s", shexstring((INT32)disp8, 0, TRUE) );
+ } else if( mod == 2 ) {
+ disp32 = FETCHD32();
+ if (disp32 != 0)
+ s += sprintf( s, "%s", shexstring(disp32, 0, TRUE) );
+ }
+ } else if (address_size == 1) {
+ if ((rm & 7) == 4)
+ s = handle_sib_byte( s, mod );
+ else if ((rm & 7) == 5 && mod == 0) {
+ disp32 = FETCHD32();
+ if (curmode == 64)
+ s += sprintf( s, "eip%s", shexstring(disp32, 0, TRUE) );
+ else
+ s += sprintf( s, "%s", hexstring(disp32, 0) );
+ } else
+ s += sprintf( s, "%s", i386_reg[1][rm]);
+ if( mod == 1 ) {
+ disp8 = FETCHD();
+ if (disp8 != 0)
+ s += sprintf( s, "%s", shexstring((INT32)disp8, 0, TRUE) );
+ } else if( mod == 2 ) {
+ disp32 = FETCHD32();
+ if (disp32 != 0)
+ s += sprintf( s, "%s", shexstring(disp32, 0, TRUE) );
+ }
+ } else {
+ switch( rm )
+ {
+ case 0: s += sprintf( s, "bx+si" ); break;
+ case 1: s += sprintf( s, "bx+di" ); break;
+ case 2: s += sprintf( s, "bx+si" ); break;
+ case 3: s += sprintf( s, "bx+di" ); break;
+ case 4: s += sprintf( s, "si" ); break;
+ case 5: s += sprintf( s, "di" ); break;
+ case 6:
+ if( mod == 0 ) {
+ disp16 = FETCHD16();
+ s += sprintf( s, "%s", hexstring((unsigned) (UINT16) disp16, 0) );
+ } else {
+ s += sprintf( s, "bp" );
+ }
+ break;
+ case 7: s += sprintf( s, "bx" ); break;
+ }
+ if( mod == 1 ) {
+ disp8 = FETCHD();
+ if (disp8 != 0)
+ s += sprintf( s, "%s", shexstring((INT32)disp8, 0, TRUE) );
+ } else if( mod == 2 ) {
+ disp16 = FETCHD16();
+ if (disp16 != 0)
+ s += sprintf( s, "%s", shexstring((INT32)disp16, 0, TRUE) );
+ }
+ }
+ s += sprintf( s, "]" );
+}
+
+static char* handle_param(char* s, UINT32 param)
+{
+ UINT8 i8;
+ UINT16 i16;
+ UINT32 i32;
+ UINT16 ptr;
+ UINT32 addr;
+ INT8 d8;
+ INT16 d16;
+ INT32 d32;
+
+ switch(param)
+ {
+ case PARAM_REG:
+ s += sprintf( s, "%s", i386_reg[operand_size][MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_REG8:
+ s += sprintf( s, "%s", (rex ? i386_reg8rex : i386_reg8)[MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_REG16:
+ s += sprintf( s, "%s", i386_reg[0][MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_REG32:
+ s += sprintf( s, "%s", i386_reg[1][MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_REG3264:
+ s += sprintf( s, "%s", i386_reg[(operand_size == 2) ? 2 : 1][MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_MMX:
+ if (pre0f == 0x66 || pre0f == 0xf2 || pre0f == 0xf3)
+ s += sprintf( s, "xmm%d", MODRM_REG1 | regex );
+ else
+ s += sprintf( s, "mm%d", MODRM_REG1 | regex );
+ break;
+
+ case PARAM_XMM:
+ s += sprintf( s, "xmm%d", MODRM_REG1 | regex );
+ break;
+
+ case PARAM_REGORXMM:
+ if (pre0f != 0xf2 && pre0f != 0xf3)
+ s += sprintf( s, "xmm%d", MODRM_REG1 | regex );
+ else
+ s += sprintf( s, "%s", i386_reg[(operand_size == 2) ? 2 : 1][MODRM_REG1 | regex] );
+ break;
+
+ case PARAM_REG2_32:
+ s += sprintf( s, "%s", i386_reg[1][MODRM_REG2 | rmex] );
+ break;
+
+ case PARAM_RM:
+ case PARAM_RMPTR:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "%s", i386_reg[operand_size][MODRM_REG2 | rmex] );
+ } else {
+ if (param == PARAM_RMPTR)
+ {
+ if( operand_size == 2 )
+ s += sprintf( s, "qword ptr " );
+ else if (operand_size == 1)
+ s += sprintf( s, "dword ptr " );
+ else
+ s += sprintf( s, "word ptr " );
+ }
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_RM8:
+ case PARAM_RMPTR8:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "%s", (rex ? i386_reg8rex : i386_reg8)[MODRM_REG2 | rmex] );
+ } else {
+ if (param == PARAM_RMPTR8)
+ s += sprintf( s, "byte ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_RM16:
+ case PARAM_RMPTR16:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "%s", i386_reg[0][MODRM_REG2 | rmex] );
+ } else {
+ if (param == PARAM_RMPTR16)
+ s += sprintf( s, "word ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_RM32:
+ case PARAM_RMPTR32:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "%s", i386_reg[1][MODRM_REG2 | rmex] );
+ } else {
+ if (param == PARAM_RMPTR32)
+ s += sprintf( s, "dword ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_RMXMM:
+ if( modrm >= 0xc0 ) {
+ if (pre0f != 0xf2 && pre0f != 0xf3)
+ s += sprintf( s, "xmm%d", MODRM_REG2 | rmex );
+ else
+ s += sprintf( s, "%s", i386_reg[(operand_size == 2) ? 2 : 1][MODRM_REG2 | rmex] );
+ } else {
+ if (param == PARAM_RMPTR32)
+ s += sprintf( s, "dword ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_M64:
+ case PARAM_M64PTR:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "???" );
+ } else {
+ if (param == PARAM_M64PTR)
+ s += sprintf( s, "qword ptr " );
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_MMXM:
+ if( modrm >= 0xc0 ) {
+ if (pre0f == 0x66 || pre0f == 0xf2 || pre0f == 0xf3)
+ s += sprintf( s, "xmm%d", MODRM_REG2 | rmex );
+ else
+ s += sprintf( s, "mm%d", MODRM_REG2 | rmex );
+ } else {
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_XMMM:
+ if( modrm >= 0xc0 ) {
+ s += sprintf( s, "xmm%d", MODRM_REG2 | rmex );
+ } else {
+ s += sprintf( s, "%s", modrm_string );
+ }
+ break;
+
+ case PARAM_I4:
+ i8 = FETCHD();
+ s += sprintf( s, "%d", i8 & 0x0f );
+ break;
+
+ case PARAM_I8:
+ i8 = FETCHD();
+ s += sprintf( s, "%s", shexstring((INT8)i8, 0, FALSE) );
+ break;
+
+ case PARAM_I16:
+ i16 = FETCHD16();
+ s += sprintf( s, "%s", shexstring((INT16)i16, 0, FALSE) );
+ break;
+
+ case PARAM_UI8:
+ i8 = FETCHD();
+ s += sprintf( s, "%s", shexstring((UINT8)i8, 0, FALSE) );
+ break;
+
+ case PARAM_UI16:
+ i16 = FETCHD16();
+ s += sprintf( s, "%s", shexstring((UINT16)i16, 0, FALSE) );
+ break;
+
+ case PARAM_IMM64:
+ if (operand_size == 2) {
+ UINT32 lo32 = FETCHD32();
+ i32 = FETCHD32();
+ s += sprintf( s, "%s", hexstring64(lo32, i32) );
+ } else if( operand_size ) {
+ i32 = FETCHD32();
+ s += sprintf( s, "%s", hexstring(i32, 0) );
+ } else {
+ i16 = FETCHD16();
+ s += sprintf( s, "%s", hexstring(i16, 0) );
+ }
+ break;
+
+ case PARAM_IMM:
+ if( operand_size ) {
+ i32 = FETCHD32();
+ s += sprintf( s, "%s", hexstring(i32, 0) );
+ } else {
+ i16 = FETCHD16();
+ s += sprintf( s, "%s", hexstring(i16, 0) );
+ }
+ break;
+
+ case PARAM_ADDR:
+ if( operand_size ) {
+ addr = FETCHD32();
+ ptr = FETCHD16();
+ s += sprintf( s, "%s:", hexstring(ptr, 4) );
+ s += sprintf( s, "%s", hexstring(addr, 0) );
+ } else {
+ addr = FETCHD16();
+ ptr = FETCHD16();
+ s += sprintf( s, "%s:", hexstring(ptr, 4) );
+ s += sprintf( s, "%s", hexstring(addr, 0) );
+ }
+ break;
+
+ case PARAM_REL:
+ if( operand_size ) {
+ d32 = FETCHD32();
+ s += sprintf( s, "%s", hexstring(pc + d32, 0) );
+ } else {
+ /* make sure to keep the relative offset within the segment */
+ d16 = FETCHD16();
+ s += sprintf( s, "%s", hexstring((pc & 0xFFFF0000) | ((pc + d16) & 0x0000FFFF), 0) );
+ }
+ break;
+
+ case PARAM_REL8:
+ d8 = FETCHD();
+ s += sprintf( s, "%s", hexstring(pc + d8, 0) );
+ break;
+
+ case PARAM_MEM_OFFS_B:
+ d8 = FETCHD();
+ s += sprintf( s, "[%s]", hexstring(d8, 0) );
+ break;
+
+ case PARAM_MEM_OFFS_V:
+ if( address_size ) {
+ d32 = FETCHD32();
+ s += sprintf( s, "[%s]", hexstring(d32, 0) );
+ } else {
+ d32 = FETCHD16();
+ s += sprintf( s, "[%s]", hexstring(d32, 0) );
+ }
+ break;
+
+ case PARAM_SREG:
+ s += sprintf( s, "%s", i386_sreg[MODRM_REG1] );
+ break;
+
+ case PARAM_CREG:
+ s += sprintf( s, "cr%d", MODRM_REG1 | regex );
+ break;
+
+ case PARAM_TREG:
+ s += sprintf( s, "tr%d", MODRM_REG1 | regex );
+ break;
+
+ case PARAM_1:
+ s += sprintf( s, "1" );
+ break;
+
+ case PARAM_DX:
+ s += sprintf( s, "dx" );
+ break;
+
+ case PARAM_AL: s += sprintf( s, "al" ); break;
+ case PARAM_CL: s += sprintf( s, "cl" ); break;
+ case PARAM_DL: s += sprintf( s, "dl" ); break;
+ case PARAM_BL: s += sprintf( s, "bl" ); break;
+ case PARAM_AH: s += sprintf( s, "ah" ); break;
+ case PARAM_CH: s += sprintf( s, "ch" ); break;
+ case PARAM_DH: s += sprintf( s, "dh" ); break;
+ case PARAM_BH: s += sprintf( s, "bh" ); break;
+
+ case PARAM_EAX: s += sprintf( s, "%s", i386_reg[operand_size][0 | rmex] ); break;
+ case PARAM_ECX: s += sprintf( s, "%s", i386_reg[operand_size][1 | rmex] ); break;
+ case PARAM_EDX: s += sprintf( s, "%s", i386_reg[operand_size][2 | rmex] ); break;
+ case PARAM_EBX: s += sprintf( s, "%s", i386_reg[operand_size][3 | rmex] ); break;
+ case PARAM_ESP: s += sprintf( s, "%s", i386_reg[operand_size][4 | rmex] ); break;
+ case PARAM_EBP: s += sprintf( s, "%s", i386_reg[operand_size][5 | rmex] ); break;
+ case PARAM_ESI: s += sprintf( s, "%s", i386_reg[operand_size][6 | rmex] ); break;
+ case PARAM_EDI: s += sprintf( s, "%s", i386_reg[operand_size][7 | rmex] ); break;
+ }
+ return s;
+}
+
+static void handle_fpu(char *s, UINT8 op1, UINT8 op2)
+{
+ switch (op1 & 0x7)
+ {
+ case 0: // Group D8
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fadd dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fmul dword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "fcom dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fcomp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fsub dword ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fsubr dword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fdiv dword ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fdivr dword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fadd st(0),st(%d)", op2 & 0x7); break;
+ case 1: sprintf(s, "fcom st(0),st(%d)", op2 & 0x7); break;
+ case 2: sprintf(s, "fsub st(0),st(%d)", op2 & 0x7); break;
+ case 3: sprintf(s, "fdiv st(0),st(%d)", op2 & 0x7); break;
+ case 4: sprintf(s, "fmul st(0),st(%d)", op2 & 0x7); break;
+ case 5: sprintf(s, "fcomp st(0),st(%d)", op2 & 0x7); break;
+ case 6: sprintf(s, "fsubr st(0),st(%d)", op2 & 0x7); break;
+ case 7: sprintf(s, "fdivr st(0),st(%d)", op2 & 0x7); break;
+ }
+ }
+ break;
+ }
+
+ case 1: // Group D9
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fld dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "??? (FPU)"); break;
+ case 2: sprintf(s, "fst dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fstp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fldenv word ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fldcw word ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fstenv word ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fstcw word ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fld st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fxch st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x10: sprintf(s, "fnop"); break;
+ case 0x20: sprintf(s, "fchs"); break;
+ case 0x21: sprintf(s, "fabs"); break;
+ case 0x24: sprintf(s, "ftst"); break;
+ case 0x25: sprintf(s, "fxam"); break;
+ case 0x28: sprintf(s, "fld1"); break;
+ case 0x29: sprintf(s, "fldl2t"); break;
+ case 0x2a: sprintf(s, "fldl2e"); break;
+ case 0x2b: sprintf(s, "fldpi"); break;
+ case 0x2c: sprintf(s, "fldlg2"); break;
+ case 0x2d: sprintf(s, "fldln2"); break;
+ case 0x2e: sprintf(s, "fldz"); break;
+ case 0x30: sprintf(s, "f2xm1"); break;
+ case 0x31: sprintf(s, "fyl2x"); break;
+ case 0x32: sprintf(s, "fptan"); break;
+ case 0x33: sprintf(s, "fpatan"); break;
+ case 0x34: sprintf(s, "fxtract"); break;
+ case 0x35: sprintf(s, "fprem1"); break;
+ case 0x36: sprintf(s, "fdecstp"); break;
+ case 0x37: sprintf(s, "fincstp"); break;
+ case 0x38: sprintf(s, "fprem"); break;
+ case 0x39: sprintf(s, "fyl2xp1"); break;
+ case 0x3a: sprintf(s, "fsqrt"); break;
+ case 0x3b: sprintf(s, "fsincos"); break;
+ case 0x3c: sprintf(s, "frndint"); break;
+ case 0x3d: sprintf(s, "fscale"); break;
+ case 0x3e: sprintf(s, "fsin"); break;
+ case 0x3f: sprintf(s, "fcos"); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 2: // Group DA
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fiadd dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fimul dword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "ficom dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "ficomp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fisub dword ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fisubr dword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fidiv dword ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fidivr dword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fcmovb st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fcmove st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ sprintf(s, "fcmovbe st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(s, "fcmovu st(0),st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+
+ }
+ }
+ break;
+ }
+
+ case 3: // Group DB
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fild dword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "??? (FPU)"); break;
+ case 2: sprintf(s, "fist dword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fistp dword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "??? (FPU)"); break;
+ case 5: sprintf(s, "fld tword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "??? (FPU)"); break;
+ case 7: sprintf(s, "fstp tword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fcmovnb st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fcmovne st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ sprintf(s, "fcmovnbe st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(s, "fcmovnu st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x22: sprintf(s, "fclex"); break;
+ case 0x23: sprintf(s, "finit"); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fucomi st(0),st(%d)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fcomi st(0),st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 4: // Group DC
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fadd qword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fmul qword ptr %s", modrm_string); break;
+ case 2: sprintf(s, "fcom qword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fcomp qword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fsub qword ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fsubr qword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fdiv qword ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fdivr qword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "fadd st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fmul st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ sprintf(s, "fsubr st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fsub st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fdivr st(%d),st(0)", op2 & 0x7); break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(s, "fdiv st(%d),st(0)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 5: // Group DD
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fld qword ptr %s", modrm_string); break;
+ case 1: sprintf(s, "??? (FPU)"); break;
+ case 2: sprintf(s, "fst qword ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fstp qword ptr %s", modrm_string); break;
+ case 4: sprintf(s, "frstor %s", modrm_string); break;
+ case 5: sprintf(s, "??? (FPU)"); break;
+ case 6: sprintf(s, "fsave %s", modrm_string); break;
+ case 7: sprintf(s, "fstsw word ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "ffree st(%d)", op2 & 0x7); break;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ sprintf(s, "fst st(%d)", op2 & 0x7); break;
+
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ sprintf(s, "fstp st(%d)", op2 & 0x7); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ sprintf(s, "fucom st(%d), st(0)", op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fucomp st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 6: // Group DE
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fiadd word ptr %s", modrm_string); break;
+ case 1: sprintf(s, "fimul word ptr %s", modrm_string); break;
+ case 2: sprintf(s, "ficom word ptr %s", modrm_string); break;
+ case 3: sprintf(s, "ficomp word ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fisub word ptr %s", modrm_string); break;
+ case 5: sprintf(s, "fisubr word ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fidiv word ptr %s", modrm_string); break;
+ case 7: sprintf(s, "fidivr word ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
+ sprintf(s, "faddp st(%d)", op2 & 0x7); break;
+
+ case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ sprintf(s, "fmulp st(%d)", op2 & 0x7); break;
+
+ case 0x19: sprintf(s, "fcompp"); break;
+
+ case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
+ sprintf(s, "fsubrp st(%d)", op2 & 0x7); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fsubp st(%d)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fdivrp st(%d), st(0)", op2 & 0x7); break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ sprintf(s, "fdivp st(%d)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+
+ case 7: // Group DF
+ {
+ if (op2 < 0xc0)
+ {
+ pc--; // adjust fetch pointer, so modrm byte read again
+ opcode_ptr--;
+ handle_modrm( modrm_string );
+ switch ((op2 >> 3) & 0x7)
+ {
+ case 0: sprintf(s, "fild word ptr %s", modrm_string); break;
+ case 1: sprintf(s, "??? (FPU)"); break;
+ case 2: sprintf(s, "fist word ptr %s", modrm_string); break;
+ case 3: sprintf(s, "fistp word ptr %s", modrm_string); break;
+ case 4: sprintf(s, "fbld %s", modrm_string); break;
+ case 5: sprintf(s, "fild qword ptr %s", modrm_string); break;
+ case 6: sprintf(s, "fbstp %s", modrm_string); break;
+ case 7: sprintf(s, "fistp qword ptr %s", modrm_string); break;
+ }
+ }
+ else
+ {
+ switch (op2 & 0x3f)
+ {
+ case 0x20: sprintf(s, "fstsw ax"); break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ sprintf(s, "fucomip st(%d)", op2 & 0x7); break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
+ sprintf(s, "fcomip st(%d),st(0)", op2 & 0x7); break;
+
+ default: sprintf(s, "??? (FPU)"); break;
+ }
+ }
+ break;
+ }
+ }
+}
+
+static void decode_opcode(char *s, const I386_OPCODE *op, UINT8 op1)
+{
+ int i;
+ UINT8 op2;
+
+ if (op->flags & SPECIAL64)
+ op = &x64_opcode_alt[op->flags >> 24];
+
+ switch( op->flags & FLAGS_MASK )
+ {
+ case ISREX:
+ if (curmode == 64)
+ {
+ rex = op1;
+ operand_size = (op1 & 8) ? 2 : 1;
+ regex = (op1 << 1) & 8;
+ sibex = (op1 << 2) & 8;
+ rmex = (op1 << 3) & 8;
+ op2 = FETCH();
+ decode_opcode( s, &i386_opcode_table1[op2], op1 );
+ return;
+ }
+ break;
+
+ case OP_SIZE:
+ rex = regex = sibex = rmex = 0;
+ if (operand_size < 2)
+ operand_size ^= 1;
+ op2 = FETCH();
+ decode_opcode( s, &i386_opcode_table1[op2], op2 );
+ return;
+
+ case ADDR_SIZE:
+ rex = regex = sibex = rmex = 0;
+ if (curmode != 64)
+ address_size ^= 1;
+ else
+ address_size ^= 3;
+ op2 = FETCH();
+ decode_opcode( s, &i386_opcode_table1[op2], op2 );
+ return;
+
+ case TWO_BYTE:
+ if (&opcode_ptr[-2] >= opcode_ptr_base)
+ pre0f = opcode_ptr[-2];
+ op2 = FETCHD();
+ decode_opcode( s, &i386_opcode_table2[op2], op1 );
+ return;
+
+ case SEG_CS:
+ case SEG_DS:
+ case SEG_ES:
+ case SEG_FS:
+ case SEG_GS:
+ case SEG_SS:
+ rex = regex = sibex = rmex = 0;
+ segment = op->flags;
+ op2 = FETCH();
+ decode_opcode( s, &i386_opcode_table1[op2], op2 );
+ return;
+
+ case PREFIX:
+ op2 = FETCH();
+ if (op2 != 0x0f)
+ s += sprintf( s, "%-7s ", op->mnemonic );
+ decode_opcode( s, &i386_opcode_table1[op2], op2 );
+ return;
+
+ case GROUP:
+ handle_modrm( modrm_string );
+ for( i=0; i < ARRAY_LENGTH(group_op_table); i++ ) {
+ if( mame_stricmp(op->mnemonic, group_op_table[i].mnemonic) == 0 ) {
+ decode_opcode( s, &group_op_table[i].opcode[MODRM_REG1], op1 );
+ return;
+ }
+ }
+ goto handle_unknown;
+
+ case FPU:
+ op2 = FETCHD();
+ handle_fpu( s, op1, op2);
+ return;
+
+ case MODRM:
+ handle_modrm( modrm_string );
+ break;
+ }
+
+ if ((op->flags & ALWAYS64) && curmode == 64)
+ operand_size = 2;
+
+ if ((op->flags & VAR_NAME) && operand_size > 0)
+ {
+ const char *mnemonic = op->mnemonic + strlen(op->mnemonic) + 1;
+ if (operand_size == 2)
+ mnemonic += strlen(mnemonic) + 1;
+ s += sprintf( s, "%-7s ", mnemonic );
+ }
+ else if (op->flags & VAR_NAME4)
+ {
+ const char *mnemonic = op->mnemonic;
+ int which = (pre0f == 0xf3) ? 3 : (pre0f == 0xf2) ? 2 : (pre0f == 0x66) ? 1 : 0;
+ while (which--)
+ mnemonic += strlen(mnemonic) + 1;
+ s += sprintf( s, "%-7s ", mnemonic );
+ }
+ else
+ s += sprintf( s, "%-7s ", op->mnemonic );
+ dasm_flags = op->dasm_flags;
+
+ if( op->param1 != 0 ) {
+ s = handle_param( s, op->param1 );
+ }
+
+ if( op->param2 != 0 ) {
+ s += sprintf( s, "," );
+ s = handle_param( s, op->param2 );
+ }
+
+ if( op->param3 != 0 ) {
+ s += sprintf( s, "," );
+ s = handle_param( s, op->param3 );
+ }
+ return;
+
+handle_unknown:
+ sprintf(s, "???");
+}
+
+int i386_dasm_one(char *buffer, UINT32 eip, const UINT8 *oprom, int mode)
+{
+ UINT8 op;
+
+ opcode_ptr = opcode_ptr_base = oprom;
+ address_size = (mode == 16) ? 0 : (mode == 32) ? 1 : 2;
+ operand_size = (mode == 16) ? 0 : 1;
+ pc = eip;
+ dasm_flags = 0;
+ segment = 0;
+ curmode = mode;
+ pre0f = 0;
+ rex = regex = sibex = rmex = 0;
+
+ op = FETCH();
+
+ decode_opcode( buffer, &i386_opcode_table1[op], op );
+ return (pc-eip) | dasm_flags | DASMFLAG_SUPPORTED;
+}