summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose Fonseca <jfonseca@vmware.com>2016-09-03 10:06:54 +0100
committerJose Fonseca <jfonseca@vmware.com>2016-09-05 15:57:40 +0100
commit6e1b4f89736c93e0069e60afd68852997c5bbd5a (patch)
tree0b376387fb1d78f59aa9f96b3b4576a2c0389412
parente7daf65a61943ab97881f35e5f2c5786ce829396 (diff)
mhook: Initial import.
-rw-r--r--CMakeLists.txt1
-rw-r--r--thirdparty/mhook/CMakeLists.txt38
-rw-r--r--thirdparty/mhook/COPYING20
-rw-r--r--thirdparty/mhook/disasm-lib/cpu.c93
-rw-r--r--thirdparty/mhook/disasm-lib/cpu.h277
-rw-r--r--thirdparty/mhook/disasm-lib/disasm.c122
-rw-r--r--thirdparty/mhook/disasm-lib/disasm.h578
-rw-r--r--thirdparty/mhook/disasm-lib/disasm_x86.c4662
-rw-r--r--thirdparty/mhook/disasm-lib/disasm_x86.h837
-rw-r--r--thirdparty/mhook/disasm-lib/disasm_x86_tables.h3654
-rw-r--r--thirdparty/mhook/disasm-lib/misc.c185
-rw-r--r--thirdparty/mhook/disasm-lib/misc.h52
-rw-r--r--thirdparty/mhook/mhook-lib/mhook.cpp918
-rw-r--r--thirdparty/mhook/mhook-lib/mhook.h28
-rw-r--r--thirdparty/mhook/mhook-test.cpp218
-rw-r--r--thirdparty/mhook/stdafx.cpp8
-rw-r--r--thirdparty/mhook/stdafx.h20
17 files changed, 11711 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 500eedde..24db020e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -482,6 +482,7 @@ if (WIN32)
add_subdirectory (thirdparty/dxerr)
add_subdirectory (thirdparty/directxtex)
add_subdirectory (thirdparty/devcon)
+ add_subdirectory (thirdparty/mhook)
endif ()
add_subdirectory (thirdparty/crc32c)
diff --git a/thirdparty/mhook/CMakeLists.txt b/thirdparty/mhook/CMakeLists.txt
new file mode 100644
index 00000000..62429ae8
--- /dev/null
+++ b/thirdparty/mhook/CMakeLists.txt
@@ -0,0 +1,38 @@
+remove_definitions (-DNOMINMAX)
+
+add_definitions (-DUNICODE -D_UNICODE)
+
+if (NOT MSVC)
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-comment")
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-enum-compare")
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-pointer-to-int-cast")
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-switch")
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-value")
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-variable")
+endif ()
+
+
+add_convenience_library (mhook
+ disasm-lib/cpu.c
+ disasm-lib/disasm.c
+ disasm-lib/disasm_x86.c
+ disasm-lib/misc.c
+ mhook-lib/mhook.cpp
+)
+
+
+add_executable (mhook-test
+ mhook-test.cpp
+)
+target_link_libraries (mhook-test
+ mhook
+ ws2_32
+)
+add_test (NAME mhook-test COMMAND $<TARGET_FILE:mhook-test>)
+
+
+install (
+ FILES "COPYING"
+ DESTINATION ${DOC_INSTALL_DIR}
+ RENAME LICENSE-mhook.txt
+)
diff --git a/thirdparty/mhook/COPYING b/thirdparty/mhook/COPYING
new file mode 100644
index 00000000..a7fd4533
--- /dev/null
+++ b/thirdparty/mhook/COPYING
@@ -0,0 +1,20 @@
+Copyright (c) 2007-2014, Marton Anka
+Portions Copyright (c) 2007, Matt Conover
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/thirdparty/mhook/disasm-lib/cpu.c b/thirdparty/mhook/disasm-lib/cpu.c
new file mode 100644
index 00000000..2a12692a
--- /dev/null
+++ b/thirdparty/mhook/disasm-lib/cpu.c
@@ -0,0 +1,93 @@
+// Copyright (C) 2003, Matt Conover (mconover@gmail.com)
+#include "cpu.h"
+#include <assert.h>
+
+// NOTE: this assumes default scenarios (i.e., we assume CS/DS/ES/SS and flat
+// and all have a base of 0 and limit of 0xffffffff, we don't try to verify
+// that in the GDT)
+//
+// TODO: use inline assembly to get selector for segment
+// Segment = x86 segment register (SEG_ES = 0, SEG_CS = 1, ...)
+BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset)
+{
+ switch (Segment)
+ {
+ // Windows uses a flat address space (except FS for x86 and GS for x64)
+ case 0: // SEG_ES
+ case 1: // SEG_CS
+ case 2: // SEG_SS
+ case 3: // SEG_DS
+ return (BYTE *)(DWORD_PTR)Offset;
+ case 4: // SEG_FS
+ case 5: // SEG_GS
+ return (BYTE *)(DWORD_PTR)Offset;
+ // Note: we're really supposed to do this, but get_teb is not implemented
+ // in this bastardized version of the disassembler.
+ // return (BYTE *)get_teb() + Offset;
+ default:
+ assert(0);
+ return (BYTE *)(DWORD_PTR)Offset;
+ }
+}
+
+// This is an GDT/LDT selector (pGDT+Selector)
+BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset)
+{
+ DESCRIPTOR_ENTRY Entry;
+ GATE_ENTRY *Gate;
+ ULONG_PTR Base;
+
+ assert(Selector < 0x10000);
+ if (!GetThreadSelectorEntry(GetCurrentThread(), Selector, (LDT_ENTRY *)&Entry)) return NULL;
+ if (!Entry.Present) return NULL;
+ if (Entry.System)
+ {
+ Base = 0;
+#ifdef _WIN64
+ Base |= (ULONG_PTR)Entry.HighOffset64 << 32;
+#endif
+ Base |= Entry.BaseHi << 24;
+ Base |= Entry.BaseMid << 16;
+ Base |= Entry.BaseLow;
+ }
+ else
+ {
+ switch (Entry.Type)
+ {
+ case 1: // 16-bit TSS (available)
+ case 2: // LDT
+ case 3: // 16-bit TSS (busy)
+ case 9: // 32-bit TSS (available)
+ case 11: // 32-bit TSS (busy)
+ Base = 0;
+#ifdef _WIN64
+ Base |= (ULONG_PTR)Entry.HighOffset64 << 32;
+#endif
+ Base |= Entry.BaseHi << 24;
+ Base |= Entry.BaseMid << 16;
+ Base |= Entry.BaseLow;
+ break;
+
+ case 4: // 16-bit call gate
+ case 5: // task gate
+ case 6: // 16-bit interrupt gate
+ case 7: // 16-bit task gate
+ case 12: // 32-bit call gate
+ case 14: // 32-bit interrupt gate
+ case 15: // 32-bit trap gate
+ Gate = (GATE_ENTRY *)&Entry;
+#ifdef _WIN64
+ Base = ((ULONG_PTR)Gate->HighOffset64 << 32) | (Gate->HighOffset << 16) | Gate->LowOffset;
+#else
+ Base = (Gate->HighOffset << 16) | Gate->LowOffset;
+#endif
+ assert(!Offset); Offset = 0;
+ break;
+ default:
+ assert(0);
+ return NULL;
+ }
+ }
+ return (BYTE *)Base + Offset;
+}
+
diff --git a/thirdparty/mhook/disasm-lib/cpu.h b/thirdparty/mhook/disasm-lib/cpu.h
new file mode 100644
index 00000000..cec695f4
--- /dev/null
+++ b/thirdparty/mhook/disasm-lib/cpu.h
@@ -0,0 +1,277 @@
+// Copyright (C) 2003, Matt Conover (mconover@gmail.com)
+#ifndef CPU_H
+#define CPU_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#pragma pack(push,1)
+
+#include <windows.h>
+#include "misc.h"
+
+////////////////////////////////////////////////////////
+// System descriptors
+////////////////////////////////////////////////////////
+
+#define GDT_NULL 0
+#define GDT_R0_CODE 0x08
+#define GDT_R0_DATA 0x10
+#define GDT_R3_CODE 0x18
+#define GDT_R3_DATA 0x20
+#define GDT_TSS 0x28
+#define GDT_PCR 0x30
+#define GDT_R3_TEB 0x38
+#define GDT_VDM 0x40
+#define GDT_LDT 0x48
+#define GDT_DOUBLEFAULT_TSS 0x50
+#define GDT_NMI_TSS 0x58
+
+// 16-bit GDT entries:
+// TODO: #define GDT_ABIOS_UNKNOWN 0x60 (22F30-32F2F)
+#define GDT_ABIOS_VIDEO 0x68
+#define GDT_ABIOS_GDT 0x70 // descriptor describing ABIOS GDT itself
+#define GDT_ABIOS_NTOS 0x78 // first 64K of NTOSKRNL
+#define GDT_ABIOS_CDA 0xE8 // common data area
+#define GDT_ABIOS_CODE 0xF0 // KiI386AbiosCall
+#define GDT_ABIOS_STACK 0xF8
+
+#define SELECTOR_RPL_MASK 0x03 // bits 0-1
+#define SELECTOR_LDT 0x04 // bit 2
+
+// for data selectors
+#define DATA_ACCESS_MASK (1<<0)
+#define DATA_WRITE_ENABLE_MASK (1<<1)
+#define DATA_EXPAND_DOWN_MASK (1<<2)
+
+// for code selectors
+#define CODE_ACCESS_MASK (1<<0)
+#define CODE_READ_MASK (1<<1)
+#define CODE_CONFORMING_MASK (1<<2)
+#define CODE_FLAG (1<<3)
+
+#define TASK_GATE 5
+#define INTERRUPT_GATE 6
+#define TRAP_GATE 7
+
+typedef struct _IDT_ENTRY
+{
+ USHORT LowOffset;
+ USHORT Selector;
+ UCHAR Ignored : 5;
+ UCHAR Zero : 3;
+ UCHAR Type : 3;
+ UCHAR Is32Bit : 1;
+ UCHAR Ignored2 : 1;
+ UCHAR DPL : 2;
+ UCHAR Present : 1;
+ USHORT HighOffset;
+#ifdef _WIN64
+ ULONG HighOffset64;
+ ULONG Reserved;
+#endif
+} IDT_ENTRY, TRAP_GATE_ENTRY;
+
+typedef struct _CALL_GATE_ENTRY
+{
+ USHORT LowOffset;
+ USHORT Selector;
+ UCHAR ParameterCount: 4;
+ UCHAR Ignored : 3;
+ UCHAR Type : 5;
+ UCHAR DPL : 2;
+ UCHAR Present : 1;
+ USHORT HighOffset;
+#ifdef _WIN64
+ ULONG HighOffset64;
+ ULONG Reserved;
+#endif
+} CALL_GATE_ENTRY;
+
+typedef struct _TASK_GATE_ENTRY
+{
+ USHORT Ignored;
+ USHORT Selector;
+ UCHAR Ignored2 : 5;
+ UCHAR Zero : 3;
+ UCHAR Type : 5;
+ UCHAR DPL : 2;
+ UCHAR Present : 1;
+ USHORT Ignored3;
+} TASK_GATE_ENTRY;
+
+typedef struct _DESCRIPTOR_ENTRY
+{
+ USHORT LimitLow;
+ USHORT BaseLow;
+ UCHAR BaseMid;
+ UCHAR Type : 4; // 10EWA (code), E=ExpandDown, W=Writable, A=Accessed
+ // 11CRA (data), C=Conforming, R=Readable, A=Accessed
+ UCHAR System : 1; // if 1 then it is a gate or LDT
+ UCHAR DPL : 2; // descriptor privilege level;
+ // for data selectors, MAX(CPL, RPL) must be <= DPL to access (or else GP# fault)
+ // for non-conforming code selectors (without callgate), MAX(CPL, RPL) must be <= DPL to access (or else GP# fault)
+ // for conforming code selectors, MAX(CPL, RPL) must be >= DPL (i.e., CPL 0-2 cannot access if DPL is 3)
+ // for non-conforming code selectors (with call gate), DPL indicates lowest privilege allowed to access gate
+ UCHAR Present : 1;
+ UCHAR LimitHigh : 4;
+ UCHAR Available: 1; // aka AVL
+ UCHAR Reserved : 1;
+ UCHAR Is32Bit : 1; // aka B flag
+ UCHAR Granularity : 1; // aka G flag
+ UCHAR BaseHi : 8;
+#ifdef _WIN64
+ ULONG HighOffset64;
+ ULONG Reserved2;
+#endif
+} DESCRIPTOR_ENTRY;
+
+typedef struct _GATE_ENTRY
+{
+ USHORT LowOffset;
+ UCHAR Skip;
+ UCHAR Type : 5;
+ UCHAR DPL : 2;
+ UCHAR Present : 1;
+ USHORT HighOffset;
+#ifdef _WIN64
+ ULONG HighOffset64;
+ ULONG Reserved;
+#endif
+} GATE_ENTRY;
+
+// TODO: update for X64
+typedef struct _PTE_ENTRY
+{
+ ULONG Present : 1;
+ ULONG Write : 1;
+ ULONG Owner : 1; // E.g., user mode or supervisor mode
+ ULONG WriteThrough : 1;
+ ULONG CacheDisable : 1;
+ ULONG Accessed : 1;
+ ULONG Dirty : 1;
+ ULONG PAT : 1;
+ ULONG Global : 1;
+ ULONG CopyOnWrite : 1;
+ ULONG Prototype : 1;
+ ULONG Transition : 1;
+ ULONG Address : 20;
+} PTE_ENTRY;
+
+// TODO: update for X64
+typedef struct _PDE_ENTRY
+{
+ ULONG Present : 1;
+ ULONG Write : 1;
+ ULONG Owner : 1;
+ ULONG WriteThrough : 1;
+ ULONG CacheDisable : 1;
+ ULONG Accessed : 1;
+ ULONG Reserved1 : 1;
+ ULONG PageSize : 1;
+ ULONG Global : 1;
+ ULONG Reserved : 3;
+ ULONG Address : 20;
+} PDE_ENTRY;
+
+// TODO: update for X64
+typedef struct _IO_ACCESS_MAP
+{
+ UCHAR DirectionMap[32];
+ UCHAR IoMap[8196];
+} IO_ACCESS_MAP;
+
+#define MIN_TSS_SIZE FIELD_OFFSET(TSS_ENTRY, IoMaps)
+// TODO: update for X64
+typedef struct _TSS_ENTRY
+{
+ USHORT Backlink;
+ USHORT Reserved0;
+ ULONG Esp0;
+ USHORT Ss0;
+ USHORT Reserved1;
+ ULONG NotUsed1[4];
+ ULONG CR3;
+ ULONG Eip;
+ ULONG NotUsed2[9];
+ USHORT Es;
+ USHORT Reserved2;
+ USHORT Cs;
+ USHORT Reserved3;
+ USHORT Ss;
+ USHORT Reserved4;
+ USHORT Ds;
+ USHORT Reserved5;
+ USHORT Fs;
+ USHORT Reserved6;
+ USHORT Gs;
+ USHORT Reserved7;
+ USHORT LDT;
+ USHORT Reserved8;
+ USHORT Flags;
+ USHORT IoMapBase;
+ IO_ACCESS_MAP IoMaps[1];
+ UCHAR IntDirectionMap[32];
+} TSS_ENTRY;
+
+// TODO: update for X64
+typedef struct _TSS16_ENTRY
+{
+ USHORT Backlink;
+ USHORT Sp0;
+ USHORT Ss0;
+ USHORT Sp1;
+ USHORT Ss1;
+ USHORT Sp2;
+ USHORT Ss3;
+ USHORT Ip;
+ USHORT Flags;
+ USHORT Ax;
+ USHORT Cx;
+ USHORT Dx;
+ USHORT Bx;
+ USHORT Sp;
+ USHORT Bp;
+ USHORT Si;
+ USHORT Di;
+ USHORT Es;
+ USHORT Cs;
+ USHORT Ss;
+ USHORT Ds;
+ USHORT LDT;
+} TSS16_ENTRY;
+
+// TODO: update for X64
+typedef struct _GDT_ENTRY
+{
+ USHORT LimitLow;
+ USHORT BaseLow;
+ union {
+ struct {
+ UCHAR BaseMid;
+ UCHAR Flags1;
+ UCHAR Flags2;
+ UCHAR BaseHi;
+ } Bytes;
+ struct {
+ ULONG BaseMid : 8;
+ ULONG Type : 5;
+ ULONG Dpl : 2;
+ ULONG Pres : 1;
+ ULONG LimitHi : 4;
+ ULONG Sys : 1;
+ ULONG Reserved_0 : 1;
+ ULONG Default_Big : 1;
+ ULONG Granularity : 1;
+ ULONG BaseHi : 8;
+ } Bits;
+ } HighWord;
+} GDT_ENTRY;
+
+BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset);
+BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset);
+
+#pragma pack(pop)
+#ifdef __cplusplus
+}
+#endif
+#endif // CPU_H \ No newline at end of file
diff --git a/thirdparty/mhook/disasm-lib/disasm.c b/thirdparty/mhook/disasm-lib/disasm.c
new file mode 100644
index 00000000..7e72baaa
--- /dev/null
+++ b/thirdparty/mhook/disasm-lib/disasm.c
@@ -0,0 +1,122 @@
+// Copyright (C) 2004, Matt Conover (mconover@gmail.com)
+#undef NDEBUG
+#include <assert.h>
+#include <windows.h>
+#include "disasm.h"
+
+#ifdef NO_SANITY_CHECKS
+#define NDEBUG
+#undef assert
+#define assert(x)
+#endif
+
+//////////////////////////////////////////////////////////////////////
+// Global variables
+//////////////////////////////////////////////////////////////////////
+
+ARCHITECTURE_FORMAT SupportedArchitectures[] =
+{
+ { ARCH_X86, &X86 },
+ { ARCH_X86_16, &X86 },
+ { ARCH_X64, &X86 },
+ { ARCH_UNKNOWN, NULL }
+};
+
+typedef struct _DISASM_ARG_INFO
+{
+ INSTRUCTION *MatchedInstruction;
+ BOOL MatchPrefix;
+ U8 *Opcode;
+ U32 OpcodeLength;
+ INSTRUCTION_TYPE InstructionType;
+ U32 Count;
+} DISASM_ARG_INFO;
+
+//////////////////////////////////////////////////////////////////////
+// Function prototypes
+//////////////////////////////////////////////////////////////////////
+
+BOOL InitInstruction(INSTRUCTION *Instruction, DISASSEMBLER *Disassembler);
+struct _ARCHITECTURE_FORMAT *GetArchitectureFormat(ARCHITECTURE_TYPE Type);
+
+//////////////////////////////////////////////////////////////////////
+// Disassembler setup
+//////////////////////////////////////////////////////////////////////
+
+BOOL InitDisassembler(DISASSEMBLER *Disassembler, ARCHITECTURE_TYPE Architecture)
+{
+ ARCHITECTURE_FORMAT *ArchFormat;
+
+ memset(Disassembler, 0, sizeof(DISASSEMBLER));
+ Disassembler->Initialized = DISASSEMBLER_INITIALIZED;
+
+ ArchFormat = GetArchitectureFormat(Architecture);
+ if (!ArchFormat) { assert(0); return FALSE; }
+ Disassembler->ArchType = ArchFormat->Type;
+ Disassembler->Functions = ArchFormat->Functions;
+ return TRUE;
+}
+
+void CloseDisassembler(DISASSEMBLER *Disassembler)
+{
+ memset(Disassembler, 0, sizeof(DISASSEMBLER));
+}
+
+//////////////////////////////////////////////////////////////////////
+// Instruction setup
+//////////////////////////////////////////////////////////////////////
+
+BOOL InitInstruction(INSTRUCTION *Instruction, DISASSEMBLER *Disassembler)
+{
+ memset(Instruction, 0, sizeof(INSTRUCTION));
+ Instruction->Initialized = INSTRUCTION_INITIALIZED;
+ Instruction->Disassembler = Disassembler;
+ memset(Instruction->String, ' ', MAX_OPCODE_DESCRIPTION-1);
+ Instruction->String[MAX_OPCODE_DESCRIPTION-1] = '\0';
+ return TRUE;
+}
+
+// If Decode = FALSE, only the following fields are valid:
+// Instruction->Length, Instruction->Address, Instruction->Prefixes, Instruction->PrefixCount,
+// Instruction->OpcodeBytes, Instruction->Instruction->OpcodeLength, Instruction->Groups,
+// Instruction->Type, Instruction->OperandCount
+//
+// If Disassemble = TRUE, then Instruction->String is valid (also requires Decode = TRUE)
+//
+// WARNING: This will overwrite the previously obtained instruction
+INSTRUCTION *GetInstruction(DISASSEMBLER *Disassembler, U64 VirtualAddress, U8 *Address, U32 Flags)
+{
+ if (Disassembler->Initialized != DISASSEMBLER_INITIALIZED) { assert(0); return NULL; }
+ assert(Address);
+ InitInstruction(&Disassembler->Instruction, Disassembler);
+ Disassembler->Instruction.Address = Address;
+ Disassembler->Instruction.VirtualAddressDelta = VirtualAddress - (U64)Address;
+ if (!Disassembler->Functions->GetInstruction(&Disassembler->Instruction, Address, Flags))
+ {
+ assert(Disassembler->Instruction.Address == Address);
+ assert(Disassembler->Instruction.Length < MAX_INSTRUCTION_LENGTH);
+
+ // Save the address that failed, in case the lower-level disassembler didn't
+ Disassembler->Instruction.Address = Address;
+ Disassembler->Instruction.ErrorOccurred = TRUE;
+ return NULL;
+ }
+ return &Disassembler->Instruction;
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Miscellaneous
+///////////////////////////////////////////////////////////////////////////
+
+static ARCHITECTURE_FORMAT *GetArchitectureFormat(ARCHITECTURE_TYPE Type)
+{
+ ARCHITECTURE_FORMAT *Format;
+ for (Format = SupportedArchitectures; Format->Type != ARCH_UNKNOWN; Format++)
+ {
+ if (Format->Type == Type) return Format;
+ }
+
+ assert(0);
+ return NULL;
+}
+
diff --git a/thirdparty/mhook/disasm-lib/disasm.h b/thirdparty/mhook/disasm-lib/disasm.h
new file mode 100644
index 00000000..6e35ab72
--- /dev/null
+++ b/thirdparty/mhook/disasm-lib/disasm.h
@@ -0,0 +1,578 @@
+// Copyright (C) 2004, Matt Conover (mconover@gmail.com)
+//
+// WARNING:
+// I wouldn't recommend changing any flags like OP_*, ITYPE_*, or *_MASK
+// aside from those marked as UNUSED. This is because the flags parts of
+// the flags are architecture independent and other are left to specific
+// architectures to define, so unless you understand the relationships
+// between them, I would leave them as is.
+
+#ifndef DISASM_H
+#define DISASM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <windows.h>
+#include <stdio.h>
+#include "misc.h"
+
+typedef signed char S8;
+typedef unsigned char U8;
+typedef signed short S16;
+typedef unsigned short U16;
+typedef signed long S32;
+typedef unsigned long U32;
+typedef LONG64 S64;
+typedef ULONG64 U64;
+
+#ifdef SPEEDY
+// On Visual Studio 6, making the internal functions inline makes compiling take forever
+#define INTERNAL static _inline
+#define INLINE _inline
+#else
+#define INTERNAL static
+#define INLINE
+#endif
+
+#define VALID_INSTRUCTION(i) ((i) && !((i)->ErrorOccurred))
+#define NEXT_INSTRUCTION(i) ((i)->Address + (i)->Length)
+#define DISASM_ARCH_TYPE(dis) ((dis)->ArchType)
+#define INS_ARCH_TYPE(ins) DISASM_ARCH_TYPE((ins)->Disassembler)
+
+// NOTE: these should be as big set to the maximum of the supported architectures
+#define MAX_PREFIX_LENGTH 15
+#define MAX_OPERAND_COUNT 3
+#define MAX_INSTRUCTION_LENGTH 25
+#define MAX_OPCODE_LENGTH 3
+#define MAX_OPCODE_DESCRIPTION 256
+
+/////////////////////////////////////////////////////////////////////
+// Code branch
+/////////////////////////////////////////////////////////////////////
+
+#define MAX_CODE_REFERENCE_COUNT 3
+
+typedef struct _CODE_BRANCH
+{
+ U64 Addresses[MAX_CODE_REFERENCE_COUNT]; // NULL if multiple to addresses
+ U32 Count;
+ U8 IsLoop : 1;
+ U8 IsCall : 1; // branch if false
+ U8 IsIndirect : 1; // call/jmp [Address]
+ U8 AddressOffset: 5;
+ struct _INSTRUCTION_OPERAND *Operand; // the operand containg the address
+} CODE_BRANCH;
+
+/////////////////////////////////////////////////////////////////////
+// Data references
+/////////////////////////////////////////////////////////////////////
+
+#define MAX_DATA_REFERENCE_COUNT 3
+
+typedef struct _DATA_REFERENCE
+{
+ U64 Addresses[MAX_DATA_REFERENCE_COUNT]; // NULL if multiple to addresses
+ U32 Count;
+ ULONG_PTR DataSize;
+ struct _INSTRUCTION_OPERAND *Operand; // the operand containg the address
+} DATA_REFERENCE;
+
+////////////////////////////////////////////////////////////////////
+// Instruction
+/////////////////////////////////////////////////////////////////////
+
+//
+// Instruction types (bits 0-7)
+// Instruction groups (bits 8-26)
+//
+#define ITYPE_EXEC_OFFSET (1<<8)
+#define ITYPE_ARITH_OFFSET (1<<9)
+#define ITYPE_LOGIC_OFFSET (1<<10)
+#define ITYPE_STACK_OFFSET (1<<11)
+#define ITYPE_TESTCOND_OFFSET (1<<12)
+#define ITYPE_LOAD_OFFSET (1<<13)
+#define ITYPE_ARRAY_OFFSET (1<<14)
+#define ITYPE_BIT_OFFSET (1<<15)
+#define ITYPE_FLAG_OFFSET (1<<16)
+#define ITYPE_FPU_OFFSET (1<<17)
+#define ITYPE_TRAPS_OFFSET (1<<18)
+#define ITYPE_SYSTEM_OFFSET (1<<19)
+#define ITYPE_OTHER_OFFSET (1<<20)
+#define ITYPE_UNUSED1_OFFSET (1<<21)
+#define ITYPE_UNUSED2_OFFSET (1<<22)
+#define ITYPE_UNUSED3_OFFSET (1<<23)
+#define ITYPE_UNUSED4_OFFSET (1<<24)
+#define ITYPE_UNUSED5_OFFSET (1<<25)
+#define ITYPE_UNUSED6_OFFSET (1<<26)
+#define ITYPE_EXT_UNUSED1 (1<<27)
+#define ITYPE_EXT_UNUSED2 (1<<28)
+#define ITYPE_EXT_UNUSED3 (1<<29)
+#define ITYPE_EXT_UNUSED4 (1<<30)
+#define ITYPE_EXT_UNUSED5 (1<<31)
+
+//
+// X86-specific flags (bits 27-31)
+//
+
+#define ITYPE_EXT_64 ITYPE_EXT_UNUSED1 // Use index 1 if in 64-bit mode and 0 otherwise
+#define ITYPE_EXT_MODRM ITYPE_EXT_UNUSED2 // ModRM byte may extend the opcode
+#define ITYPE_EXT_SUFFIX ITYPE_EXT_UNUSED3 // byte after ModRM/SIB/displacement is the third opcode
+#define ITYPE_EXT_PREFIX ITYPE_EXT_UNUSED4 // prefix
+#define ITYPE_EXT_FPU ITYPE_EXT_UNUSED5 // FPU instructions require special handling
+
+#define ITYPE_3DNOW_OFFSET ITYPE_UNUSED1_OFFSET
+#define ITYPE_MMX_OFFSET ITYPE_UNUSED2_OFFSET
+#define ITYPE_SSE_OFFSET ITYPE_UNUSED3_OFFSET
+#define ITYPE_SSE2_OFFSET ITYPE_UNUSED4_OFFSET
+#define ITYPE_SSE3_OFFSET ITYPE_UNUSED5_OFFSET
+
+//
+// Instruction types
+//
+
+#define ITYPE_TYPE_MASK 0x7FFFFFFF
+#define ITYPE_GROUP_MASK 0x7FFFFF00
+
+typedef enum _INSTRUCTION_TYPE
+{
+ // ITYPE_EXEC group
+ ITYPE_EXEC = ITYPE_EXEC_OFFSET,
+ ITYPE_BRANCH,
+ ITYPE_BRANCHCC, // conditional (not necessarily just flags)
+ ITYPE_CALL,
+ ITYPE_CALLCC, // conditional (not necessarily just flags)
+ ITYPE_RET,
+ ITYPE_LOOPCC,
+
+ // ITYPE_ARITH group
+ ITYPE_ARITH = ITYPE_ARITH_OFFSET,
+ ITYPE_XCHGADD,
+ ITYPE_ADD,
+ ITYPE_SUB,
+ ITYPE_MUL,
+ ITYPE_DIV,
+ ITYPE_INC,
+ ITYPE_DEC,
+ ITYPE_SHL,
+ ITYPE_SHR,
+ ITYPE_ROL,
+ ITYPE_ROR,
+
+ // ITYPE_LOGIC group
+ ITYPE_LOGIC=ITYPE_LOGIC_OFFSET,
+ ITYPE_AND,
+ ITYPE_OR,
+ ITYPE_XOR,
+ ITYPE_NOT,
+ ITYPE_NEG,
+
+ // ITYPE_STACK group
+ ITYPE_STACK=ITYPE_STACK_OFFSET,
+ ITYPE_PUSH,
+ ITYPE_POP,
+ ITYPE_PUSHA,
+ ITYPE_POPA,
+ ITYPE_PUSHF,
+ ITYPE_POPF,
+ ITYPE_ENTER,
+ ITYPE_LEAVE,
+
+ // ITYPE_TESTCOND group
+ ITYPE_TESTCOND=ITYPE_TESTCOND_OFFSET,
+ ITYPE_TEST,
+ ITYPE_CMP,
+
+ // ITYPE_LOAD group
+ ITYPE_LOAD=ITYPE_LOAD_OFFSET,
+ ITYPE_MOV,
+ ITYPE_MOVCC, // conditional
+ ITYPE_LEA,
+ ITYPE_XCHG,
+ ITYPE_XCHGCC, // conditional
+
+ // ITYPE_ARRAY group
+ ITYPE_ARRAY=ITYPE_ARRAY_OFFSET,
+ ITYPE_STRCMP,
+ ITYPE_STRLOAD,
+ ITYPE_STRMOV,
+ ITYPE_STRSTOR,
+ ITYPE_XLAT,
+
+ // ITYPE_BIT group
+ ITYPE_BIT=ITYPE_BIT_OFFSET,
+ ITYPE_BITTEST,
+ ITYPE_BITSET,
+ ITYPE_BITCLR,
+
+ // ITYPE_FLAG group
+ // PF = parify flag
+ // ZF = zero flag
+ // OF = overflow flag
+ // DF = direction flag
+ // SF = sign flag
+ ITYPE_FLAG=ITYPE_FLAG_OFFSET,
+ // clear
+ ITYPE_CLEARCF,
+ ITYPE_CLEARZF,
+ ITYPE_CLEAROF,
+ ITYPE_CLEARDF,
+ ITYPE_CLEARSF,
+ ITYPE_CLEARPF,
+ // set
+ ITYPE_SETCF,
+ ITYPE_SETZF,
+ ITYPE_SETOF,
+ ITYPE_SETDF,
+ ITYPE_SETSF,
+ ITYPE_SETPF,
+ // toggle
+ ITYPE_TOGCF,
+ ITYPE_TOGZF,
+ ITYPE_TOGOF,
+ ITYPE_TOGDF,
+ ITYPE_TOGSF,
+ ITYPE_TOGPF,
+
+ // ITYPE_FPU group
+ ITYPE_FPU=ITYPE_FPU_OFFSET,
+ ITYPE_FADD,
+ ITYPE_FSUB,
+ ITYPE_FMUL,
+ ITYPE_FDIV,
+ ITYPE_FCOMP,
+ ITYPE_FEXCH,
+ ITYPE_FLOAD,
+ ITYPE_FLOADENV,
+ ITYPE_FSTORE,
+ ITYPE_FSTOREENV,
+ ITYPE_FSAVE,
+ ITYPE_FRESTORE,
+ ITYPE_FMOVCC,
+
+ ITYPE_UNUSED1=ITYPE_UNUSED1_OFFSET,
+ ITYPE_UNUSED2=ITYPE_UNUSED2_OFFSET,
+ ITYPE_UNUSED3=ITYPE_UNUSED3_OFFSET,
+
+ // ITYPE_MMX group
+ ITYPE_MMX=ITYPE_MMX_OFFSET,
+ ITYPE_MMX_MOV,
+ ITYPE_MMX_ADD,
+ ITYPE_MMX_SUB,
+ ITYPE_MMX_MUL,
+ ITYPE_MMX_DIV,
+ ITYPE_MMX_AND,
+ ITYPE_MMX_OR,
+ ITYPE_MMX_XOR,
+ ITYPE_MMX_CMP,
+
+ // ITYPE_SSE group
+ ITYPE_SSE=ITYPE_SSE_OFFSET,
+ ITYPE_SSE_MOV,
+ ITYPE_SSE_ADD,
+ ITYPE_SSE_SUB,
+ ITYPE_SSE_MUL,
+ ITYPE_SSE_DIV,
+ ITYPE_SSE_AND,
+ ITYPE_SSE_OR,
+ ITYPE_SSE_XOR,
+ ITYPE_SSE_CMP,
+
+ // ITYPE_SSE2 group
+ ITYPE_SSE2=ITYPE_SSE2_OFFSET,
+ ITYPE_SSE2_MOV,
+ ITYPE_SSE2_ADD,
+ ITYPE_SSE2_SUB,
+ ITYPE_SSE2_MUL,
+ ITYPE_SSE2_DIV,
+ ITYPE_SSE2_AND,
+ ITYPE_SSE2_OR,
+ ITYPE_SSE2_XOR,
+ ITYPE_SSE2_CMP,
+
+ // ITYPE_SSE3 group
+ ITYPE_SSE3=ITYPE_SSE3_OFFSET,
+ ITYPE_SSE3_MOV,
+ ITYPE_SSE3_ADD,
+ ITYPE_SSE3_SUB,
+ ITYPE_SSE3_MUL,
+ ITYPE_SSE3_DIV,
+ ITYPE_SSE3_AND,
+ ITYPE_SSE3_OR,
+ ITYPE_SSE3_XOR,
+ ITYPE_SSE3_CMP,
+
+ // ITYPE_3DNOW group
+ ITYPE_3DNOW=ITYPE_3DNOW_OFFSET,
+ ITYPE_3DNOW_ADD,
+ ITYPE_3DNOW_SUB,
+ ITYPE_3DNOW_MUL,
+ ITYPE_3DNOW_DIV,
+ ITYPE_3DNOW_CMP,
+ ITYPE_3DNOW_XCHG,
+
+ // ITYPE_TRAP
+ ITYPE_TRAPS=ITYPE_TRAPS_OFFSET,
+ ITYPE_TRAP, // generate trap
+ ITYPE_TRAPCC, // conditional trap gen
+ ITYPE_TRAPRET, // return from trap
+ ITYPE_BOUNDS, // gen bounds trap
+ ITYPE_DEBUG, // gen breakpoint trap
+ ITYPE_TRACE, // gen single step trap
+ ITYPE_INVALID, // gen invalid instruction
+ ITYPE_OFLOW, // gen overflow trap
+
+ // ITYPE_SYSTEM group
+ ITYPE_SYSTEM=ITYPE_SYSTEM_OFFSET,
+ ITYPE_HALT, // halt machine
+ ITYPE_IN, // input form port
+ ITYPE_OUT, // output to port
+ ITYPE_CPUID, // identify cpu
+ ITYPE_SETIF, // allow interrupts
+ ITYPE_CLEARIF, // block interrupts
+ ITYPE_SYSCALL,
+ ITYPE_SYSCALLRET,
+
+ // ITYPE_OTHER group
+ ITYPE_OTHER = ITYPE_OTHER_OFFSET,
+ ITYPE_NOP,
+ ITYPE_BCDCONV, // convert to/from BCD
+ ITYPE_SZCONV // convert size of operand
+} INSTRUCTION_TYPE;
+
+//
+// Operand flags
+//
+
+// Type = bits 0-6 (these are mutually exclusive -- bits 0-6 will always be a power of 2))
+#define OPTYPE_NONE 0x00
+#define OPTYPE_IMM 0x01 // immediate value
+#define OPTYPE_OFFSET 0x02 // relative offset
+#define OPTYPE_FLOAT 0x03 // floating point
+#define OPTYPE_BCD 0x04
+#define OPTYPE_STRING 0x05
+#define OPTYPE_SPECIAL 0x06
+#define OPTYPE_MASK 0x7F
+
+// Flags = bits 7-23 (these can be combinations)
+// These are used in the X86 opcode table
+#define OP_REG (1<<7) // 0x80
+#define OP_SIGNED (1<<8)
+#define OP_SYS (1<<9) // parameter is an index into some system structure
+#define OP_CONDR (1<<10)
+#define OP_CONDW (1<<11)
+#define OP_UNUSED (1<<12)
+#define OP_SRC (1<<13) // operand is source operand
+#define OP_DST (1<<14) // operand is destination operand
+#define OP_EXEC (1<<15) // operand is executed
+
+#define OP_CONDE OP_CONDR
+#define OP_COND_EXEC (OP_CONDE|OP_EXEC) // executed only if the pre-conditions are met
+#define OP_COND_SRC (OP_CONDR|OP_SRC) // set only if pre-conditions are met
+#define OP_COND_DST (OP_CONDW|OP_DST) // set only if pre-conditions are met
+#define OP_COND (OP_CONDR|OP_CONDW)
+
+// Bits 16-31 are available for use outside of the opcode table, but they can only
+// be used in INSTRUCTION_OPERAND.Flags, they may conflit with the architecture specific
+// operands. For example, bits 16-31 are used in X86 for AMODE_* and OPTYPE_*
+#define OP_ADDRESS (1<<16)
+#define OP_LOCAL (1<<17)
+#define OP_PARAM (1<<18)
+#define OP_GLOBAL (1<<19)
+#define OP_FAR (1<<20)
+#define OP_IPREL (1<<21)
+
+//
+// X86-specific flags (bits 27-31)
+//
+#define OP_MSR (OP_SYS|OP_UNUSED)
+
+//
+// Other architecture flags
+//
+#define OP_DELAY OP_UNUSED // delayed instruction (e.g., delayed branch that executes after the next instruction)
+
+/////////////////////////////////////////////////////////////////////
+// Architectures
+/////////////////////////////////////////////////////////////////////
+
+typedef enum _ARCHITECTURE_TYPE
+{
+ ARCH_UNKNOWN=0,
+
+ // x86-based
+ ARCH_X86, // 32-bit x86
+ ARCH_X86_16, // 16-bit x86
+ ARCH_X64, // AMD64 and Intel EMD64
+
+ // everything else
+ ARCH_ALPHA,
+ ARCH_ARM,
+ ARCH_DOTNET,
+ ARCH_EFI,
+ ARCH_IA64,
+ ARCH_M68K,
+ ARCH_MIPS,
+ ARCH_PPC,
+ ARCH_SH3,
+ ARCH_SH4,
+ ARCH_SPARC,
+ ARCH_THUMB
+
+} ARCHITECTURE_TYPE;
+
+typedef BOOL (*INIT_INSTRUCTION)(struct _INSTRUCTION *Instruction);
+typedef void (*DUMP_INSTRUCTION)(struct _INSTRUCTION *Instruction, BOOL ShowBytes, BOOL Verbose);
+typedef BOOL (*GET_INSTRUCTION)(struct _INSTRUCTION *Instruction, U8 *Address, U32 Flags);
+typedef U8 *(*FIND_FUNCTION_BY_PROLOGUE)(struct _INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, U32 Flags);
+
+typedef struct _ARCHITECTURE_FORMAT_FUNCTIONS
+{
+ INIT_INSTRUCTION InitInstruction;
+ DUMP_INSTRUCTION DumpInstruction;
+ GET_INSTRUCTION GetInstruction;
+ FIND_FUNCTION_BY_PROLOGUE FindFunctionByPrologue;
+} ARCHITECTURE_FORMAT_FUNCTIONS;
+
+typedef struct _ARCHITECTURE_FORMAT
+{
+ ARCHITECTURE_TYPE Type;
+ ARCHITECTURE_FORMAT_FUNCTIONS *Functions;
+} ARCHITECTURE_FORMAT;
+
+#define DISASSEMBLER_INITIALIZED 0x1234566F
+#define INSTRUCTION_INITIALIZED 0x1234567F
+
+#include "disasm_x86.h"
+
+typedef struct DECLSPEC_ALIGN(16) _S128
+{
+ U64 Low;
+ S64 High;
+} S128;
+typedef struct DECLSPEC_ALIGN(16) _U128
+{
+ U64 Low;
+ U64 High;
+} U128;
+
+typedef struct _INSTRUCTION_OPERAND
+{
+ U32 Flags;
+ U8 Type : 6;
+ U8 Unused : 2;
+ U16 Length;
+
+
+ // If non-NULL, this indicates the target address of the instruction (e.g., a branch or
+ // a displacement with no base register). However, this address is only reliable if the
+ // image is mapped correctly (e.g., the executable is mapped as an image and fixups have
+ // been applied if it is not at its preferred image base).
+ //
+ // If disassembling a 16-bit DOS application, TargetAddress is in the context of
+ // X86Instruction->Segment. For example, if TargetAddress is the address of a code branch,
+ // it is in the CS segment (unless X86Instruction->HasSegmentOverridePrefix is set). If
+ // TargetAddress is a data pointer, it is in the DS segment (unless
+ // X86Instruction->HasSegmentOverridePrefix is set)
+ U64 TargetAddress;
+ U32 Register;
+
+ union
+ {
+ // All 8/16/32-bit operands are extended to 64-bits automatically
+ // If you want to downcast, check whether Flags & OP_SIGNED is set
+ // Like this:
+ // U32 GetOperand32(OPERAND *Operand)
+ // {
+ // if (Operand->Flags & OP_SIGNED) return (S32)Operand->Value_S64;
+ // else return (U32)Operand->Value_U64;
+ //}
+ U64 Value_U64;
+ S64 Value_S64;
+ U128 Value_U128;
+ U128 Float128;
+ U8 Float80[80];
+ U8 BCD[10];
+ };
+} INSTRUCTION_OPERAND;
+
+typedef struct _INSTRUCTION
+{
+ U32 Initialized;
+ struct _DISASSEMBLER *Disassembler;
+
+ char String[MAX_OPCODE_DESCRIPTION];
+ U8 StringIndex;
+ U64 VirtualAddressDelta;
+
+ U32 Groups; // ITYPE_EXEC, ITYPE_ARITH, etc. -- NOTE groups can be OR'd together
+ INSTRUCTION_TYPE Type; // ITYPE_ADD, ITYPE_RET, etc. -- NOTE there is only one possible type
+
+ U8 *Address;
+ U8 *OpcodeAddress;
+ U32 Length;
+
+ U8 Prefixes[MAX_PREFIX_LENGTH];
+ U32 PrefixCount;
+
+ U8 LastOpcode; // last byte of opcode
+ U8 OpcodeBytes[MAX_OPCODE_LENGTH];
+ U32 OpcodeLength; // excludes any operands and prefixes
+
+ INSTRUCTION_OPERAND Operands[MAX_OPERAND_COUNT];
+ U32 OperandCount;
+
+ X86_INSTRUCTION X86;
+
+ DATA_REFERENCE DataSrc;
+ DATA_REFERENCE DataDst;
+ CODE_BRANCH CodeBranch;
+
+ // Direction depends on which direction the stack grows
+ // For example, on x86 a push results in StackChange < 0 since the stack grows down
+ // This is only relevant if (Group & ITYPE_STACK) is true
+ //
+ // If Groups & ITYPE_STACK is set but StackChange = 0, it means that the change
+ // couldn't be determined (non-constant)
+ LONG StackChange;
+
+ // Used to assist in debugging
+ // If set, the current instruction is doing something that requires special handling
+ // For example, popf can cause tracing to be disabled
+
+ U8 StringAligned : 1; // internal only
+ U8 NeedsEmulation : 1; // instruction does something that re
+ U8 Repeat : 1; // instruction repeats until some condition is met (e.g., REP prefix on X86)
+ U8 ErrorOccurred : 1; // set if instruction is invalid
+ U8 AnomalyOccurred : 1; // set if instruction is anomalous
+ U8 LastInstruction : 1; // tells the iterator callback it is the last instruction
+ U8 CodeBlockFirst: 1;
+ U8 CodeBlockLast : 1;
+} INSTRUCTION;
+
+typedef struct _DISASSEMBLER
+{
+ U32 Initialized;
+ ARCHITECTURE_TYPE ArchType;
+ ARCHITECTURE_FORMAT_FUNCTIONS *Functions;
+ INSTRUCTION Instruction;
+ U32 Stage1Count; // GetInstruction called
+ U32 Stage2Count; // Opcode fully decoded
+ U32 Stage3CountNoDecode; // made it through all checks when DISASM_DECODE is not set
+ U32 Stage3CountWithDecode; // made it through all checks when DISASM_DECODE is set
+} DISASSEMBLER;
+
+#define DISASM_DISASSEMBLE (1<<1)
+#define DISASM_DECODE (1<<2)
+#define DISASM_SUPPRESSERRORS (1<<3)
+#define DISASM_SHOWFLAGS (1<<4)
+#define DISASM_ALIGNOUTPUT (1<<5)
+#define DISASM_DISASSEMBLE_MASK (DISASM_ALIGNOUTPUT|DISASM_SHOWBYTES|DISASM_DISASSEMBLE)
+
+BOOL InitDisassembler(DISASSEMBLER *Disassembler, ARCHITECTURE_TYPE Architecture);
+void CloseDisassembler(DISASSEMBLER *Disassembler);
+INSTRUCTION *GetInstruction(DISASSEMBLER *Disassembler, U64 VirtualAddress, U8 *Address, U32 Flags);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // DISASM_H
diff --git a/thirdparty/mhook/disasm-lib/disasm_x86.c b/thirdparty/mhook/disasm-lib/disasm_x86.c
new file mode 100644
index 00000000..26a5d764
--- /dev/null
+++ b/thirdparty/mhook/disasm-lib/disasm_x86.c
@@ -0,0 +1,4662 @@
+// Copyright (C) 2004, Matt Conover (mconover@gmail.com)
+#undef NDEBUG
+#include <assert.h>
+#include "disasm.h"
+#include "cpu.h"
+
+// Since addresses are internally represented as 64-bit, we need to specially handle
+// cases where IP + Displacement wraps around for 16-bit/32-bit operand size
+// Otherwise, ignorethe possibility of wraparounds
+#define SUPPORT_WRAPAROUND
+
+#ifdef NO_SANITY_CHECKS
+#undef NDEBUG
+#undef DEBUG_DISASM
+#undef assert
+#define assert(x)
+#endif
+
+#ifdef DEBUG_DISASM
+#define DISASM_OUTPUT(x) printf x
+#else
+#define DISASM_OUTPUT(x)
+#endif
+
+#include "disasm_x86_tables.h"
+
+#ifdef _WIN64
+#pragma warning(disable:4311 4312)
+#endif
+
+////////////////////////////////////////////////////////////////////////
+// Internal macros
+////////////////////////////////////////////////////////////////////////
+
+#define VIRTUAL_ADDRESS ((U64)Instruction->Address + Instruction->VirtualAddressDelta)
+
+#define AMD64_DIFF (AMD64_8BIT_OFFSET-X86_8BIT_OFFSET)
+#define IS_AMD64() (INS_ARCH_TYPE(Instruction) == ARCH_X64)
+#define IS_X86_32() (INS_ARCH_TYPE(Instruction) == ARCH_X86)
+#define IS_X86_16() (INS_ARCH_TYPE(Instruction) == ARCH_X86_16)
+
+#define X86_BOUND 0x62
+#define X86_PUSH_REG 0x50
+#define X86_PUSH_CS 0x0e
+#define X86_PUSH_DS 0x1e
+#define X86_PUSH_SS 0x16
+#define X86_PUSH_ES 0x06
+#define X86_PUSH_FS 0xa0
+#define X86_PUSH_GS 0xa8
+#define X86_PUSH_U8 0x6a
+#define X86_PUSH_U32 0x68
+#define X86_POP_DS 0x1f
+#define X86_POP_ES 0x07
+#define X86_POP_SS 0x17
+#define X86_POP_FS 0xa1
+#define X86_POP_GS 0xa9
+#define X86_POP_REG 0x58
+
+#define OPCSTR Instruction->String+Instruction->StringIndex
+#define APPEND Instruction->StringIndex += (U8)_snprintf
+#define APPENDPAD(x) \
+{ \
+ if (Instruction->StringAligned) \
+ { \
+ if (Instruction->StringIndex > x) assert(0); \
+ while (x != Instruction->StringIndex) APPENDB(' '); \
+ } \
+ else if (Instruction->StringIndex) \
+ { \
+ APPENDB(' '); \
+ } \
+}
+
+#define APPENDB(a) Instruction->String[Instruction->StringIndex++] = a
+#define APPENDS(a) APPEND(OPCSTR, SIZE_LEFT, a);
+
+#define SIZE_LEFT (MAX_OPCODE_DESCRIPTION-1 > Instruction->StringIndex ? MAX_OPCODE_DESCRIPTION-Instruction->StringIndex : 0)
+
+// If an address size prefix is used for an instruction that doesn't make sense, restore it
+// to the default
+
+#define SANITY_CHECK_OPERAND_SIZE() \
+{ \
+ if (!Instruction->AnomalyOccurred && X86Instruction->HasOperandSizePrefix) \
+ { \
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected operand size prefix\n", VIRTUAL_ADDRESS); \
+ Instruction->AnomalyOccurred = TRUE; \
+ X86Instruction->HasOperandSizePrefix = FALSE; \
+ switch (X86Instruction->OperandSize) \
+ { \
+ case 4: X86Instruction->OperandSize = 2; break; \
+ case 2: X86Instruction->OperandSize = 4; break; \
+ default: assert(0); \
+ } \
+ } \
+}
+
+#define SANITY_CHECK_ADDRESS_SIZE() \
+{ \
+ if (!Instruction->AnomalyOccurred && X86Instruction->HasAddressSizePrefix) \
+ { \
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected address size prefix\n", VIRTUAL_ADDRESS); \
+ Instruction->AnomalyOccurred = TRUE; \
+ } \
+ X86Instruction->HasAddressSizePrefix = FALSE; \
+ switch (INS_ARCH_TYPE(Instruction)) \
+ { \
+ case ARCH_X64: X86Instruction->AddressSize = 8; break; \
+ case ARCH_X86: X86Instruction->AddressSize = 4; break; \
+ case ARCH_X86_16: X86Instruction->AddressSize = 2; break; \
+ } \
+}
+
+#define SANITY_CHECK_SEGMENT_OVERRIDE() \
+ if (!Instruction->AnomalyOccurred && X86Instruction->HasSegmentOverridePrefix) \
+ { \
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected segment override\n", VIRTUAL_ADDRESS); \
+ Instruction->AnomalyOccurred = TRUE; \
+ }
+
+#define INSTR_INC(size) \
+{ \
+ Instruction->Length += size; \
+ Address += size; \
+}
+
+#define X86_SET_TARGET() \
+{ \
+ if (X86Instruction->HasSelector) \
+ { \
+ if (!Instruction->AnomalyOccurred) \
+ { \
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: unexpected segment 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->Selector); \
+ Instruction->AnomalyOccurred = TRUE; \
+ } \
+ } \
+ else \
+ { \
+ switch (X86Instruction->Segment) \
+ { \
+ case SEG_CS: \
+ case SEG_DS: \
+ case SEG_SS: \
+ case SEG_ES: \
+ assert(!X86Instruction->HasSelector); \
+ Operand->TargetAddress = (U64)X86Instruction->Displacement; \
+ /* assert(!GetAbsoluteAddressFromSegment((BYTE)X86Instruction->Segment, (DWORD)X86Instruction->Displacement) || GetAbsoluteAddressFromSegment(X86Instruction->Segment, (DWORD)X86Instruction->Displacement) == Operand->TargetAddress); */ \
+ break; \
+ case SEG_FS: \
+ case SEG_GS: \
+ assert(!X86Instruction->HasSelector); \
+ Operand->TargetAddress = (U64)GetAbsoluteAddressFromSegment((BYTE)X86Instruction->Segment, (DWORD)X86Instruction->Displacement); \
+ break; \
+ default: \
+ assert(0); /* shouldn't be possible */ \
+ break; \
+ } \
+ } \
+}
+
+#define X86_SET_SEG(reg) \
+{ \
+ if (!X86Instruction->HasSegmentOverridePrefix && (reg == REG_EBP || reg == REG_ESP)) \
+ { \
+ assert(!X86Instruction->HasSelector); \
+ X86Instruction->Segment = SEG_SS; \
+ } \
+}
+
+#define X86_SET_ADDR() \
+{ \
+ if (Operand->Flags & OP_DST) \
+ { \
+ assert(!X86Instruction->HasDstAddressing); \
+ X86Instruction->HasDstAddressing = TRUE; \
+ X86Instruction->DstOpIndex[X86Instruction->DstOpCount] = (U8)OperandIndex; \
+ X86Instruction->DstOpCount++; \
+ X86Instruction->DstAddressIndex = (U8)OperandIndex; \
+ } \
+ if (Operand->Flags & OP_SRC) \
+ { \
+ if (Instruction->Type != ITYPE_STRCMP) assert(!X86Instruction->HasSrcAddressing); \
+ X86Instruction->HasSrcAddressing = TRUE; \
+ X86Instruction->SrcOpIndex[X86Instruction->SrcOpCount] = (U8)OperandIndex; \
+ X86Instruction->SrcOpCount++; \
+ X86Instruction->SrcAddressIndex = (U8)OperandIndex; \
+ } \
+}
+
+#define X86_SET_REG(reg) \
+{ \
+ if (Operand->Flags & OP_DST) \
+ { \
+ X86Instruction->DstOpIndex[X86Instruction->DstOpCount] = (U8)OperandIndex; \
+ X86Instruction->DstOpCount++; \
+ assert(OperandIndex < 2); \
+ if (Operand->Length > 1 && reg == REG_ESP) Instruction->Groups |= ITYPE_STACK; \
+ } \
+ if (Operand->Flags & OP_SRC) \
+ { \
+ X86Instruction->SrcOpIndex[X86Instruction->SrcOpCount] = (U8)OperandIndex; \
+ X86Instruction->SrcOpCount++; \
+ } \
+}
+
+#define CHECK_AMD64_REG() { if (IS_AMD64()) Operand->Register += AMD64_DIFF; }
+
+////////////////////////////////////////////////////////////////////////
+// Internal structures/variables
+////////////////////////////////////////////////////////////////////////
+
+ARCHITECTURE_FORMAT_FUNCTIONS X86 =
+{
+ X86_InitInstruction,
+ NULL,
+ X86_GetInstruction,
+ X86_FindFunctionByPrologue
+};
+
+char *X86_Registers[0xE0] =
+{
+ // Segments
+ "es", // 0x00
+ "cs", // 0x01
+ "ss", // 0x02
+ "ds", // 0x03
+ "fs", // 0x04
+ "gs", // 0x05
+ "flags", // 0x06
+ "eflags", // 0x07
+ "rflags", // 0x08
+ "ip+ilen", // 0x09
+ "eip+ilen", // 0x0A
+ "rip+ilen", // 0x0B
+ NULL, // 0x0C
+ NULL, // 0x0D
+ NULL, // 0x0E
+ NULL, // 0x0F
+
+ // Test
+ "tr0", // 0x10
+ "tr1", // 0x11
+ "tr2", // 0x12
+ "tr3", // 0x13
+ "tr4", // 0x14
+ "tr5", // 0x15
+ "tr6", // 0x16
+ "tr7", // 0x17
+ "tr8", // 0x18
+ "tr9", // 0x19
+ "tr10", // 0x1A
+ "tr11", // 0x1B
+ "tr12", // 0x1C
+ "tr13", // 0x1D
+ "tr14", // 0x1E
+ "tr15", // 0x1F
+
+ // Control
+ "cr0", // 0x20
+ "cr1", // 0x21
+ "cr2", // 0x22
+ "cr3", // 0x23
+ "cr4", // 0x24
+ "cr5", // 0x25
+ "cr6", // 0x26
+ "cr7", // 0x27
+ "cr8", // 0x18
+ "cr9", // 0x19
+ "cr10", // 0x1A
+ "cr11", // 0x1B
+ "cr12", // 0x1C
+ "cr13", // 0x1D
+ "cr14", // 0x1E
+ "cr15", // 0x1F
+
+ // Debug
+ "dr0", // 0x30
+ "dr1", // 0x31
+ "dr2", // 0x32
+ "dr3", // 0x33
+ "dr4", // 0x34
+ "dr5", // 0x35
+ "dr6", // 0x36
+ "dr7", // 0x37
+ "dr8", // 0x38
+ "dr9", // 0x39
+ "dr10", // 0x3A
+ "dr11", // 0x3B
+ "dr12", // 0x3C
+ "dr13", // 0x3D
+ "dr14", // 0x3E
+ "dr15", // 0x3F
+
+ // FPU
+ "st(0)", // 0x40
+ "st(1)", // 0x41
+ "st(2)", // 0x42
+ "st(3)", // 0x43
+ "st(4)", // 0x44
+ "st(5)", // 0x45
+ "st(6)", // 0x46
+ "st(7)", // 0x47
+ NULL, // 0x48
+ NULL, // 0x49
+ NULL, // 0x4A
+ NULL, // 0x4B
+ NULL, // 0x4C
+ NULL, // 0x4D
+ NULL, // 0x4E
+ NULL, // 0x4F
+
+ // MMX
+ "mm0", // 0x50
+ "mm1", //
+ "mm2",
+ "mm3",
+ "mm4",
+ "mm5",
+ "mm6",
+ "mm7",
+ NULL, // 0x58
+ NULL, // 0x59
+ NULL, // 0x5A
+ NULL, // 0x5B
+ NULL, // 0x5C
+ NULL, // 0x5D
+ NULL, // 0x5E
+ NULL, // 0x5F
+
+ // XMM
+ "xmm0", // 0x60
+ "xmm1", // 0x61
+ "xmm2", // 0x62
+ "xmm3", // 0x63
+ "xmm4", // 0x64
+ "xmm5", // 0x65
+ "xmm6", // 0x66
+ "xmm7", // 0x67
+ "xmm8", // 0x68
+ "xmm9", // 0x69
+ "xmm10", // 0x6a
+ "xmm11", // 0x6b
+ "xmm12", // 0x6c
+ "xmm13", // 0x6d
+ "xmm14", // 0x6e
+ "xmm15", // 0x6f
+
+ // 8-bit
+ "al", // 0x70
+ "cl", // 0x71
+ "dl", // 0x72
+ "bl", // 0x73
+ "ah", // 0x74
+ "ch", // 0x75
+ "dh", // 0x76
+ "bh", // 0x77
+ NULL, // 0x78
+ NULL, // 0x79
+ NULL, // 0x7A
+ NULL, // 0x7B
+ NULL, // 0x7C
+ NULL, // 0x7D
+ NULL, // 0x7E
+ NULL, // 0x7F
+
+ // 16-bit
+ "ax", // 0x80
+ "cx", // 0x81
+ "dx", // 0x82
+ "bx", // 0x83
+ "sp", // 0x84
+ "bp", // 0x85
+ "si", // 0x86
+ "di", // 0x87
+ NULL, // 0x88
+ NULL, // 0x89
+ NULL, // 0x8A
+ NULL, // 0x8B
+ NULL, // 0x8C
+ NULL, // 0x8D
+ NULL, // 0x8E
+ NULL, // 0x8F
+
+ // 32-bit
+ "eax", // 0x90
+ "ecx", // 0x91
+ "edx", // 0x92
+ "ebx", // 0x93
+ "esp", // 0x94
+ "ebp", // 0x95
+ "esi", // 0x96
+ "edi", // 0x97
+ NULL, // 0x98
+ NULL, // 0x99
+ NULL, // 0x9A
+ NULL, // 0x9B
+ NULL, // 0x9C
+ NULL, // 0x9D
+ NULL, // 0x9E
+ NULL, // 0x9F
+
+ // X86-64 8-bit register
+ "al", // 0xA0
+ "cl", // 0xA1
+ "dl", // 0xA2
+ "bl", // 0xA3
+ "spl", // 0xA4
+ "bpl", // 0xA5
+ "sil", // 0xA6
+ "dil", // 0xA7
+ "r8b", // 0xA8
+ "r9b", // 0xA9
+ "r10b", // 0xAA
+ "r11b", // 0xAB
+ "r12b", // 0xAC
+ "r13b", // 0xAD
+ "r14b", // 0xAE
+ "r15b", // 0xAF
+
+ // X86-64 16-bit register
+ "ax", // 0xB0
+ "cx", // 0xB1
+ "dx", // 0xB2
+ "bx", // 0xB3
+ "sp", // 0xB4
+ "bp", // 0xB5
+ "si", // 0xB6
+ "di", // 0xB7
+ "r8w", // 0xB8
+ "r9w", // 0xB9
+ "r10w", // 0xBA
+ "r11w", // 0xBB
+ "r12w", // 0xBC
+ "r13w", // 0xBD
+ "r14w", // 0xBE
+ "r15w", // 0xBF
+
+ // X86-64 32-bit register
+ "eax", // 0xC0
+ "ecx", // 0xC1
+ "edx", // 0xC2
+ "ebx", // 0xC3
+ "esp", // 0xC4
+ "ebp", // 0xC5
+ "esi", // 0xC6
+ "edi", // 0xC7
+ "r8d", // 0xC8
+ "r9d", // 0xC9
+ "r10d", // 0xCA
+ "r11d", // 0xCB
+ "r12d", // 0xCC
+ "r13d", // 0xCD
+ "r14d", // 0xCE
+ "r15d", // 0xCF
+
+ // X86-64 64-bit register
+ "rax", // 0xD0
+ "rcx", // 0xD1
+ "rdx", // 0xD2
+ "rbx", // 0xD3
+ "rsp", // 0xD4
+ "rbp", // 0xD5
+ "rsi", // 0xD6
+ "rdi", // 0xD7
+ "r8", // 0xD8
+ "r9", // 0xD9
+ "r10", // 0xDA
+ "r11", // 0xDB
+ "r12", // 0xDC
+ "r13", // 0xDD
+ "r14", // 0xDE
+ "r15" // 0xDF
+};
+
+void OutputBounds(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+void OutputGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+void OutputDescriptor(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+void OutputSegOffset(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+void OutputPackedReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+void OutputPackedBCD(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+void OutputScalarReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+void OutputScalarGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+void OutputFPUEnvironment(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+void OutputFPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+void OutputCPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+
+typedef void (*OUTPUT_OPTYPE)(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
+#define OPTYPE_SHIFT 24
+#define MAX_OPTYPE_INDEX 26
+OUTPUT_OPTYPE OptypeHandlers[] =
+{
+ NULL,
+ OutputBounds, // 01 OPTYPE_a
+ OutputGeneral, // 02 OPTYPE_b
+ OutputGeneral, // 03 OPTYPE_d
+ OutputSegOffset, // 04 OPTYPE_p
+ OutputGeneral, // 05 OPTYPE_q
+ OutputDescriptor, // 06 OPTYPE_dt
+ OutputGeneral, // 07 OPTYPE_v
+ OutputGeneral, // 08 OPTYPE_w
+ OutputPackedReal, // 09 OPTYPE_ps
+ OutputPackedReal, // 0A OPTYPE_pd
+ OutputPackedBCD, // 0B OPTYPE_pb
+ OutputScalarReal, // 0C OPTYPE_ss
+ OutputScalarReal, // 0D OPTYPE_sd
+ OutputScalarReal, // 0E OPTYPE_se
+ OutputFPUEnvironment, // 0F OPTYPE_fev
+ OutputFPUState, // 10 OPTYPE_fst1
+ OutputFPUState, // 11 OPTYPE_fst2
+ OutputGeneral, // 12 OPTYPE_z
+ OutputGeneral, // 13 OPTYPE_o
+ OutputGeneral, // 14 OPTYPE_dq
+ OutputGeneral, // 15 OPTYPE_mw
+ OutputScalarGeneral, // 16 OPTYPE_sso
+ OutputScalarGeneral, // 17 OPTYPE_sdo
+ OutputCPUState, // 18 OPTYPE_cpu
+ OutputGeneral, // 19 OPTYPE_lea
+};
+
+#define OPTYPE_a 0x01000000
+#define OPTYPE_b 0x02000000
+#define OPTYPE_d 0x03000000
+#define OPTYPE_p 0x04000000
+#define OPTYPE_q 0x05000000
+#define OPTYPE_dt 0x06000000
+#define OPTYPE_v 0x07000000
+#define OPTYPE_w 0x08000000
+#define OPTYPE_ps 0x09000000 // packed 128-bit single real
+#define OPTYPE_pd 0x0A000000 // packed 128-bit double real
+#define OPTYPE_pb 0x0B000000 // packed BCD (10 bytes, 18-bit precision)
+#define OPTYPE_ss 0x0C000000 // scalar single real
+#define OPTYPE_sd 0x0D000000 // scalar double real
+#define OPTYPE_se 0x0E000000 // scalar extended real
+#define OPTYPE_fev 0x0F000000 // FPU environment (28 bytes if 32-bit modes, 14 bytes in 16-bit mode)
+#define OPTYPE_fst1 0x10000000 // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode)
+#define OPTYPE_fst2 0x11000000 // FPU/MMX/XMM/MXCSR state (512 bytes)
+#define OPTYPE_z 0x12000000
+#define OPTYPE_o 0x13000000
+#define OPTYPE_dq 0x14000000 // OPTYPE_d or OPTYPE_o
+#define OPTYPE_mw 0x15000000 // word if memory, register size otherwise
+#define OPTYPE_sso 0x16000000 // OPTYPE_ss or OPTYPE_o
+#define OPTYPE_sdo 0x17000000 // OPTYPE_ss or OPTYPE_o
+#define OPTYPE_cpu 0x18000000 // pointer to CPU state structure
+#define OPTYPE_lea 0x19000000 // size set by other operand
+
+////////////////////////////////////////////////////////////////////////
+// Internal functions
+////////////////////////////////////////////////////////////////////////
+
+#ifdef TEST_DISASM // TODO: remove
+U32 X86_GetLength(INSTRUCTION *Instruction, U8 *Address);
+#endif
+
+INTERNAL BOOL IsValidLockPrefix(X86_INSTRUCTION *Instruction, U8 Opcode, U32 OpcodeLength, U8 Group, U8 OpcodeExtension);
+INTERNAL U8 *SetOperands(INSTRUCTION *Instruction, U8 *Address, U32 Flags);
+INTERNAL U8 *SetModRM32(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors);
+INTERNAL U8 *SetModRM16(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors);
+INTERNAL U8 *SetSIB(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors);
+INTERNAL U64 ApplyDisplacement(U64 Address, INSTRUCTION *Instruction);
+
+//////////////////////////////////////////////////////////
+// Instruction setup
+//////////////////////////////////////////////////////////
+
+#define APPLY_OFFSET(addr) \
+{ \
+ switch (X86Instruction->OperandSize) \
+ { \
+ case 8: addr = ((U64)(addr + Instruction->VirtualAddressDelta)); break; \
+ case 4: addr = (U64)((U32)(addr + Instruction->VirtualAddressDelta)); break; \
+ case 2: addr = (U64)((U8)(addr + Instruction->VirtualAddressDelta)); break; \
+ default: assert(0); break; \
+ } \
+}
+
+BOOL X86_InitInstruction(INSTRUCTION *Instruction)
+{
+ X86_INSTRUCTION *X86Instruction;
+#ifdef NO_SANITY_CHECKS
+ assert(0); // be sure assertions are disabled
+#endif
+ X86Instruction = &Instruction->X86;
+ memset(X86Instruction, 0, sizeof(X86_INSTRUCTION));
+
+ switch (INS_ARCH_TYPE(Instruction))
+ {
+ case ARCH_X64:
+ X86Instruction->AddressSize = 8;
+ X86Instruction->OperandSize = 4;
+ break;
+ case ARCH_X86:
+ X86Instruction->AddressSize = 4;
+ X86Instruction->OperandSize = 4;
+ break;
+ case ARCH_X86_16:
+ X86Instruction->AddressSize = 2;
+ X86Instruction->OperandSize = 2;
+ break;
+ default:
+ assert(0);
+ return FALSE;
+ }
+ X86Instruction->Instruction = Instruction;
+ X86Instruction->Segment = SEG_DS;
+ return TRUE;
+}
+
+////////////////////////////////////////////////////////////
+// Formatting
+// You can change these to whatever you prefer
+////////////////////////////////////////////////////////////
+
+#define X86_WRITE_OPFLAGS() \
+ if (Flags & DISASM_SHOWFLAGS) \
+ { \
+ APPENDB('{'); \
+ assert(Operand->Flags & (OP_EXEC|OP_SRC|OP_DST)); \
+ if (Operand->Flags & OP_IPREL) APPENDB('r'); \
+ if (Operand->Flags & OP_FAR) APPENDB('f'); \
+ if (Operand->Flags & OP_CONDR) APPENDB('c'); \
+ if (Operand->Flags & OP_EXEC) APPENDB('X'); \
+ else if (Operand->Flags & OP_SRC) APPENDB('R'); \
+ if (Operand->Flags & OP_CONDW) APPENDB('c'); \
+ if (Operand->Flags & OP_DST) APPENDB('W'); \
+ if (Operand->Flags & OP_SYS) APPENDB('S'); \
+ if (Operand->Flags & OP_ADDRESS) APPENDB('A'); \
+ if (Operand->Flags & OP_PARAM) APPENDB('P'); \
+ if (Operand->Flags & OP_LOCAL) APPENDB('L'); \
+ if (Operand->Flags & OP_GLOBAL) APPENDB('G'); \
+ APPENDB('}'); \
+ }
+
+#define X86_WRITE_IMMEDIATE() \
+{ \
+ switch (Operand->Length) \
+ { \
+ case 8: \
+ APPEND(OPCSTR, SIZE_LEFT, "0x%02I64X=", Operand->Value_U64); \
+ if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%I64u", Operand->Value_U64); \
+ /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02I64X=%I64d", -Operand->Value_S64, Operand->Value_S64);*/ \
+ else APPEND(OPCSTR, SIZE_LEFT, "%I64d", Operand->Value_S64); \
+ break; \
+ case 4: \
+ APPEND(OPCSTR, SIZE_LEFT, "0x%02lX=", (U32)Operand->Value_U64); \
+ if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%lu", (U32)Operand->Value_U64); \
+ /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02lX=%ld", (U32)-Operand->Value_S64, (S32)Operand->Value_S64);*/ \
+ else APPEND(OPCSTR, SIZE_LEFT, "%ld", (S32)Operand->Value_S64); \
+ break; \
+ case 2: \
+ APPEND(OPCSTR, SIZE_LEFT, "0x%02X=", (U16)Operand->Value_U64); \
+ if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%u", (U16)Operand->Value_U64); \
+ /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X=%d", (U16)-Operand->Value_S64, (S16)Operand->Value_S64);*/ \
+ else APPEND(OPCSTR, SIZE_LEFT, "%d", (S16)Operand->Value_S64); \
+ break; \
+ case 1: \
+ APPEND(OPCSTR, SIZE_LEFT, "0x%02X=", (U8)Operand->Value_U64); \
+ if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%u", (U8)Operand->Value_U64); \
+ /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X=%d", (U8)-Operand->Value_S64, (S8)Operand->Value_S64);*/ \
+ else APPEND(OPCSTR, SIZE_LEFT, "%d", (S8)Operand->Value_S64); \
+ break; \
+ default: assert(0); break; \
+ } \
+}
+
+#define X86_WRITE_ABSOLUTE_DISPLACEMENT() \
+{ \
+ switch (X86Instruction->AddressSize) \
+ { \
+ case 8: \
+ APPEND(OPCSTR, SIZE_LEFT, "0x%04I64X", X86Instruction->Displacement); \
+ break; \
+ case 4: \
+ APPEND(OPCSTR, SIZE_LEFT, "0x%04lX", (U32)X86Instruction->Displacement); \
+ break; \
+ case 2: \
+ APPEND(OPCSTR, SIZE_LEFT, "0x%04X", (U16)X86Instruction->Displacement); \
+ break; \
+ default: assert(0); break; \
+ } \
+}
+
+#define X86_WRITE_RELATIVE_DISPLACEMENT64() \
+ if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02I64X", X86Instruction->Displacement); \
+ else APPEND(OPCSTR, SIZE_LEFT, "-0x%02I64X", -X86Instruction->Displacement);
+
+#define X86_WRITE_RELATIVE_DISPLACEMENT32() \
+ if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02lX", (U32)X86Instruction->Displacement); \
+ else APPEND(OPCSTR, SIZE_LEFT, "-0x%02lX", (U32)-X86Instruction->Displacement);
+
+#define X86_WRITE_RELATIVE_DISPLACEMENT16() \
+ if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02X", (U16)X86Instruction->Displacement); \
+ else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X", (U16)-X86Instruction->Displacement);
+
+#define X86_WRITE_RELATIVE_DISPLACEMENT() \
+{ \
+ switch (X86Instruction->AddressSize) \
+ { \
+ case 8: \
+ X86_WRITE_RELATIVE_DISPLACEMENT64() \
+ break; \
+ case 4: \
+ X86_WRITE_RELATIVE_DISPLACEMENT32() \
+ break; \
+ case 2: \
+ X86_WRITE_RELATIVE_DISPLACEMENT16() \
+ break; \
+ default: assert(0); break; \
+ } \
+}
+
+#define X86_WRITE_IP_OFFSET(op) \
+{ \
+ switch (X86Instruction->OperandSize) \
+ { \
+ case 8: \
+ APPENDS("[rip+ilen"); \
+ assert((op)->TargetAddress); \
+ X86_WRITE_RELATIVE_DISPLACEMENT64() \
+ APPEND(OPCSTR, SIZE_LEFT, "]=0x%04I64X", (op)->TargetAddress+Instruction->VirtualAddressDelta); \
+ break; \
+ case 4: \
+ APPENDS("[eip+ilen"); \
+ assert((op)->TargetAddress); \
+ X86_WRITE_RELATIVE_DISPLACEMENT32() \
+ APPEND(OPCSTR, SIZE_LEFT, "]=0x%04lX", (U32)((op)->TargetAddress+Instruction->VirtualAddressDelta)); \
+ break; \
+ case 2: \
+ APPENDS("[ip+ilen"); \
+ X86_WRITE_RELATIVE_DISPLACEMENT16() \
+ APPEND(OPCSTR, SIZE_LEFT, "]=0x%04X", (U16)((op)->TargetAddress+Instruction->VirtualAddressDelta)); \
+ break; \
+ default: assert(0); break; \
+ } \
+}
+
+#define X86_WRITE_OFFSET(op) \
+{ \
+ assert((op)->Length <= 8); \
+ if (X86Instruction->HasSelector) \
+ { \
+ assert((op)->Flags & OP_FAR); \
+ APPEND(OPCSTR, SIZE_LEFT, "%s 0x%02X:[", DataSizes[((op)->Length >> 1)], X86Instruction->Selector); \
+ } \
+ else \
+ { \
+ assert(!((op)->Flags & OP_FAR)); \
+ assert(X86Instruction->Segment < SEG_MAX) ; \
+ APPEND(OPCSTR, SIZE_LEFT, "%s %s:[", DataSizes[((op)->Length >> 1)], Segments[X86Instruction->Segment]); \
+ } \
+ X86_WRITE_ABSOLUTE_DISPLACEMENT() \
+ APPENDB(']'); \
+}
+
+void OutputAddress(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ BOOL ShowDisplacement = FALSE;
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+
+ assert(!X86Instruction->HasSelector);
+ assert(X86Instruction->SrcAddressIndex == OperandIndex || X86Instruction->DstAddressIndex == OperandIndex);
+ if (Operand->Length > 16 || (Operand->Length > 1 && (Operand->Length & 1))) APPEND(OPCSTR, SIZE_LEFT, "%d_byte ptr ", Operand->Length);
+ else APPEND(OPCSTR, SIZE_LEFT, "%s ", DataSizes[Operand->Length >> 1]);
+
+ //
+ // This attempts to display the address intelligently
+ // If it has a positive 32-bit displacement, it is shown as seg:Displacement[base+index*scale]
+ // If it is a negative displacement or 8-bit, it is shown as seg:[base+index*scale+displacement]
+ //
+ APPEND(OPCSTR, SIZE_LEFT, "%s:", Segments[X86Instruction->Segment]);
+ if (X86Instruction->HasBaseRegister)
+ {
+ if (X86Instruction->Displacement)
+ {
+ if (X86Instruction->HasFullDisplacement) X86_WRITE_ABSOLUTE_DISPLACEMENT()
+ else ShowDisplacement = TRUE;
+ }
+ APPEND(OPCSTR, SIZE_LEFT, "[%s", X86_Registers[X86Instruction->BaseRegister]);
+ if (X86Instruction->HasIndexRegister)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "+%s", X86_Registers[X86Instruction->IndexRegister]);
+ if (X86Instruction->Scale > 1) APPEND(OPCSTR, SIZE_LEFT, "*%d", X86Instruction->Scale);
+ }
+ if (ShowDisplacement) X86_WRITE_RELATIVE_DISPLACEMENT()
+ APPENDB(']');
+ if (X86Instruction->Relative)
+ {
+ U64 Address = Operand->TargetAddress;
+ assert(Address);
+ APPLY_OFFSET(Address)
+ APPEND(OPCSTR, SIZE_LEFT, "=[0x%04I64X]", Address);
+ }
+ }
+ else if (X86Instruction->HasIndexRegister)
+ {
+ if (X86Instruction->Displacement)
+ {
+ if (X86Instruction->HasFullDisplacement) X86_WRITE_ABSOLUTE_DISPLACEMENT()
+ else ShowDisplacement = TRUE;
+ }
+ APPEND(OPCSTR, SIZE_LEFT, "[%s", X86_Registers[X86Instruction->IndexRegister]);
+ if (X86Instruction->Scale > 1) APPEND(OPCSTR, SIZE_LEFT, "*%d", X86Instruction->Scale);
+ if (ShowDisplacement) X86_WRITE_RELATIVE_DISPLACEMENT()
+ APPENDB(']');
+ }
+ else // just a displacement
+ {
+ APPENDB('[');
+ X86_WRITE_ABSOLUTE_DISPLACEMENT()
+ APPENDB(']');
+ }
+}
+
+void OutputBounds(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ assert(X86Instruction->HasSrcAddressing);
+ assert(!(Operand->Length & 1));
+ Operand->Length >>= 1;
+ APPENDB('(');
+ OutputAddress(Instruction, Operand, OperandIndex);
+ APPENDS(", ");
+ X86Instruction->Displacement += Operand->Length;
+ OutputAddress(Instruction, Operand, OperandIndex);
+ X86Instruction->Displacement -= Operand->Length;
+ APPENDB(')');
+ Operand->Length <<= 1;
+}
+
+void OutputGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) ||
+ (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex))
+ {
+ OutputAddress(Instruction, Operand, OperandIndex);
+ }
+ else
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ }
+}
+
+void OutputDescriptor(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing);
+ OutputAddress(Instruction, Operand, OperandIndex);
+}
+
+void OutputPackedReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) ||
+ (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex))
+ {
+ OutputAddress(Instruction, Operand, OperandIndex);
+ }
+ else
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ }
+}
+
+void OutputPackedBCD(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) ||
+ (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex))
+ {
+ OutputAddress(Instruction, Operand, OperandIndex);
+ }
+ else
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ }
+}
+
+void OutputScalarReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) ||
+ (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex))
+ {
+ OutputAddress(Instruction, Operand, OperandIndex);
+ }
+ else
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ }
+}
+
+void OutputScalarGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ if (Operand->Type == OPTYPE_FLOAT)
+ {
+ OutputScalarReal(Instruction, Operand, OperandIndex);
+ }
+ else
+ {
+ OutputGeneral(Instruction, Operand, OperandIndex);
+ }
+}
+
+void OutputFPUEnvironment(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing);
+ OutputAddress(Instruction, Operand, OperandIndex);
+}
+
+void OutputFPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing);
+ OutputAddress(Instruction, Operand, OperandIndex);
+}
+
+void OutputCPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ assert(X86Instruction->HasSrcAddressing);
+ OutputAddress(Instruction, Operand, OperandIndex);
+}
+
+void OutputSegOffset(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ assert(X86Instruction->HasSrcAddressing);
+ OutputAddress(Instruction, Operand, OperandIndex);
+}
+
+////////////////////////////////////////////////////////////
+// Prologue support
+////////////////////////////////////////////////////////////
+
+typedef struct _PROLOGUE
+{
+ char *Data;
+ U32 Length;
+} PROLOGUE;
+
+PROLOGUE StandardPrologues[] =
+{
+ { "\x55\x8b\xec", 3 },
+ { "\x55\x89\xe5", 3 },
+ { "\x83\xec", 2 },
+ { "\x81\xec", 2 },
+ // TODO: add AMD64 prologues
+ // TODO: add VS2003/VS2003 prologues
+ // TODO: add any unique prologues from other compilers
+ { NULL, 0 }
+};
+
+// Find the first function between StartAddress and EndAddress
+//
+// This will match a standard prologue and then analyze the following instructions to verify
+// it is a valid function
+U8 *X86_FindFunctionByPrologue(INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, U32 Flags)
+{
+ assert(0); // TODO
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////
+// Instruction decoder
+//////////////////////////////////////////////////////////
+
+BOOL X86_GetInstruction(INSTRUCTION *Instruction, U8 *Address, U32 Flags)
+{
+ BOOL SpecialExtension = FALSE;
+ U8 Opcode = 0, OpcodeExtension = 0, Group = 0, SSE_Prefix = 0, Suffix;
+ U32 i = 0, Result = 0, tmpScale;
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ X86_OPCODE *X86Opcode;
+#ifdef TEST_DISASM
+ U32 InstructionLength = 0;
+#endif
+ INSTRUCTION_OPERAND *Operand, *Operand1 = NULL;
+ DISASSEMBLER *Disassembler = Instruction->Disassembler;
+ BOOL Decode = Flags & DISASM_DECODE;
+ BOOL Disassemble = Flags & DISASM_DISASSEMBLE;
+ BOOL SuppressErrors = Flags & DISASM_SUPPRESSERRORS;
+
+ if (Disassemble && !Decode)
+ {
+ assert(0);
+ Decode = TRUE;
+ }
+
+ if (!Address || !X86_InitInstruction(Instruction))
+ {
+ assert(0);
+ goto abort;
+ }
+
+ assert(Instruction->Address == Address);
+ assert(!Instruction->StringIndex && !Instruction->Length);
+
+ Disassembler->Stage1Count++;
+ if (Flags & DISASM_ALIGNOUTPUT) Instruction->StringAligned = TRUE;
+
+ //
+ // Get prefixes or three byte opcode
+ //
+ while (TRUE)
+ {
+ Opcode = *Address;
+ INSTR_INC(1); // increment Instruction->Length and address
+ X86Opcode = &X86_Opcodes_1[Opcode];
+
+ // Handle a misplaced REX prefix -- AMD64 manual says it is just ignored
+ if (IS_AMD64() && (Opcode >= REX_PREFIX_START && Opcode <= REX_PREFIX_END) && X86_PREFIX((&X86_Opcodes_1[*Address])))
+ {
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: REX prefix before legacy prefix 0x%02X\n", VIRTUAL_ADDRESS, Opcode);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ continue;
+ }
+
+ if (X86_PREFIX(X86Opcode))
+ {
+ if (!Instruction->AnomalyOccurred)
+ {
+ for (i = 0; i < Instruction->PrefixCount; i++)
+ {
+ if (Instruction->Prefixes[i] == Opcode)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Duplicate prefix 0x%02X\n", VIRTUAL_ADDRESS, Opcode);
+ Instruction->AnomalyOccurred = TRUE;
+ break;
+ }
+ }
+ }
+
+ switch (Opcode)
+ {
+ case PREFIX_REPNE: // may be three byte opcode
+ SSE_Prefix = Opcode;
+ if (!Instruction->AnomalyOccurred && X86Instruction->HasRepeatWhileEqualPrefix)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ Instruction->Repeat = TRUE;
+ X86Instruction->HasRepeatWhileEqualPrefix = FALSE;
+ X86Instruction->HasRepeatWhileNotEqualPrefix = TRUE;
+ break;
+ case PREFIX_REP: // may be three byte opcode
+ SSE_Prefix = Opcode;
+ if (!Instruction->AnomalyOccurred && X86Instruction->HasRepeatWhileNotEqualPrefix)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+
+ Instruction->Repeat = TRUE;
+ X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE;
+ X86Instruction->HasRepeatWhileEqualPrefix = TRUE;
+ break;
+
+ case PREFIX_OPERAND_SIZE: // may be three byte opcode
+ SSE_Prefix = Opcode;
+ if (!Instruction->AnomalyOccurred && X86Instruction->HasOperandSizePrefix)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+
+ if (X86Instruction->HasOperandSizePrefix) break;
+ else X86Instruction->HasOperandSizePrefix = TRUE;
+ switch (X86Instruction->OperandSize)
+ {
+ case 4: X86Instruction->OperandSize = 2; break;
+ case 2: X86Instruction->OperandSize = 4; break;
+ default: assert(0); goto abort;
+ }
+ break;
+
+ case PREFIX_ADDRESS_SIZE:
+ if (!Instruction->AnomalyOccurred && X86Instruction->HasAddressSizePrefix)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+
+ if (X86Instruction->HasAddressSizePrefix) break;
+ else X86Instruction->HasAddressSizePrefix = TRUE;
+ switch (X86Instruction->AddressSize)
+ {
+ case 8:
+ X86Instruction->AddressSize = 4;
+ break;
+ case 4:
+ assert(!IS_AMD64()); // this should not be possible
+ X86Instruction->AddressSize = 2;
+ break;
+ case 2:
+ X86Instruction->AddressSize = 4;
+ break;
+ default:
+ assert(0); goto abort;
+ }
+ break;
+
+ case PREFIX_SEGMENT_OVERRIDE_ES:
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ if (!IS_AMD64())
+ {
+ X86Instruction->HasSegmentOverridePrefix = TRUE;
+ X86Instruction->Segment = SEG_ES;
+ }
+ else if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ break;
+ case PREFIX_SEGMENT_OVERRIDE_CS:
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ if (!IS_AMD64())
+ {
+ X86Instruction->HasSegmentOverridePrefix = TRUE;
+ X86Instruction->Segment = SEG_CS;
+ }
+ else if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ break;
+ case PREFIX_SEGMENT_OVERRIDE_SS:
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ if (!IS_AMD64())
+ {
+ X86Instruction->HasSegmentOverridePrefix = TRUE;
+ X86Instruction->Segment = SEG_SS;
+ }
+ else if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ break;
+ case PREFIX_SEGMENT_OVERRIDE_DS:
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ if (!IS_AMD64())
+ {
+ X86Instruction->HasSegmentOverridePrefix = TRUE;
+ X86Instruction->Segment = SEG_DS;
+ }
+ else if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ break;
+ case PREFIX_SEGMENT_OVERRIDE_FS:
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ X86Instruction->HasSegmentOverridePrefix = TRUE;
+ X86Instruction->Segment = SEG_FS;
+ break;
+ case PREFIX_SEGMENT_OVERRIDE_GS:
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ X86Instruction->HasSegmentOverridePrefix = TRUE;
+ X86Instruction->Segment = SEG_GS;
+ break;
+
+ case PREFIX_LOCK:
+ if (!Instruction->AnomalyOccurred && X86Instruction->HasLockPrefix)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ X86Instruction->HasLockPrefix = TRUE;
+ break;
+
+ default:
+ assert(0);
+ goto abort;
+ }
+
+ if (Instruction->PrefixCount >= X86_MAX_INSTRUCTION_LEN)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH);
+ goto abort;
+ }
+ else if (Instruction->PrefixCount == X86_MAX_PREFIX_LENGTH)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+
+ assert(Instruction->AnomalyOccurred || Instruction->PrefixCount < X86_MAX_PREFIX_LENGTH);
+ Instruction->Prefixes[Instruction->PrefixCount] = Opcode;
+ Instruction->PrefixCount++;
+ //DISASM_OUTPUT(("[0x%08I64X] Prefix 0x%02X (prefix count %d)\n", VIRTUAL_ADDRESS, Opcode, Instruction->PrefixCount));
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // Check for REX opcode
+ // This is checked here instead of the prefix loop above because it must be the
+ // last prefix
+ if (IS_AMD64() && (Opcode >= REX_PREFIX_START && Opcode <= REX_PREFIX_END))
+ {
+ if (Instruction->PrefixCount >= X86_MAX_INSTRUCTION_LEN)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH);
+ goto abort;
+ }
+ else if (!Instruction->AnomalyOccurred && Instruction->PrefixCount == AMD64_MAX_PREFIX_LENGTH)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+
+ assert(Instruction->AnomalyOccurred || Instruction->PrefixCount < AMD64_MAX_PREFIX_LENGTH);
+
+ Instruction->Prefixes[Instruction->PrefixCount] = Opcode;
+ Instruction->PrefixCount++;
+ X86Instruction->rex_b = Opcode;
+ SET_REX(X86Instruction->rex, X86Instruction->rex_b);
+ DISASM_OUTPUT(("[0x%08I64X] REX prefix 0x%02X (prefix count %d, w=%d, r=%d, x=%d, b=%d)\n", VIRTUAL_ADDRESS, Opcode, Instruction->PrefixCount, X86Instruction->rex.w, X86Instruction->rex.r, X86Instruction->rex.x, X86Instruction->rex.b));
+
+ assert(X86Instruction->AddressSize >= 4);
+ if (X86Instruction->rex.w)
+ {
+ X86Instruction->OperandSize = 8;
+ X86Instruction->HasOperandSizePrefix = FALSE;
+ }
+ else if (X86Instruction->HasOperandSizePrefix)
+ {
+ assert(X86Instruction->OperandSize == 2);
+ }
+ else if (X86Instruction->rex_b == REX_PREFIX_START)
+ {
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: meaningless REX prefix used\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ X86Instruction->rex_b = 0;
+ }
+
+ Opcode = *Address;
+ INSTR_INC(1); // increment Instruction->Length and address
+
+ X86Opcode = &X86_Opcodes_1[Opcode];
+ assert(!X86_PREFIX(X86Opcode));
+ }
+ //DISASM_OUTPUT(("[0x%08I64X] OperandSize = %d, AddressSize = %d\n", VIRTUAL_ADDRESS, X86Instruction->OperandSize, X86Instruction->AddressSize));
+ Instruction->LastOpcode = Opcode;
+ Instruction->OpcodeAddress = Address-1;
+
+ if (X86_INVALID(X86Opcode))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid opcode 0x%02X\n", VIRTUAL_ADDRESS, Opcode);
+ goto abort;
+ }
+
+ if (Opcode == X86_TWO_BYTE_OPCODE)
+ {
+ //
+ // Handle case that it is a group (with opcode extension), floating point, or two byte opcode
+ //
+ assert(!Instruction->OpcodeLength);
+ Instruction->LastOpcode = Opcode = *Address;
+ INSTR_INC(1); // increment Instruction->Length and address
+ assert(X86Opcode->Table == X86_Opcodes_2);
+ X86Opcode = &X86_Opcodes_2[Opcode];
+
+ //
+ // Check for errors
+ //
+ if (X86_INVALID(X86Opcode))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid two byte opcode 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode);
+ goto abort;
+ }
+
+ if (X86Instruction->AddressSize == 8)
+ {
+ if (X86_Invalid_Addr64_2[Opcode])
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X 0x%02X (\"%s\") illegal in 64-bit mode\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic);
+ goto abort;
+ }
+#if 0
+ if (X86Instruction->rex_b &&
+ (GET_REX_B(X86Instruction->rex_b) && !GET_REX_B(X86_REX_2[Opcode]) ||
+ GET_REX_X(X86Instruction->rex_b) && !GET_REX_X(X86_REX_2[Opcode]) ||
+ GET_REX_R(X86Instruction->rex_b) && !GET_REX_R(X86_REX_2[Opcode]) ||
+ GET_REX_W(X86Instruction->rex_b) && !GET_REX_W(X86_REX_2[Opcode])))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal REX prefix 0x%02X for opcode 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->rex_b, X86_TWO_BYTE_OPCODE, Opcode);
+ assert(0);
+ goto abort;
+ }
+#endif
+ }
+
+ if (X86Instruction->OperandSize == 2 && X86_Invalid_Op16_2[Opcode])
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X 0x%02X (\"%s\") illegal with 16-bit operand size\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic);
+ goto abort;
+ }
+
+ X86Instruction->HasModRM = X86_ModRM_2[Opcode];
+ if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address;
+ Instruction->OpcodeBytes[0] = X86_TWO_BYTE_OPCODE;
+ Instruction->OpcodeBytes[1] = Opcode;
+ Instruction->OpcodeLength = 2;
+
+ if (X86_SPECIAL_EXTENSION(X86Opcode))
+ {
+ DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode));
+ SpecialExtension = TRUE;
+ goto HasSpecialExtension;
+ }
+ else if (SSE_Prefix && !X86_INVALID(&X86_SSE[Opcode])) // SSEx instruction
+ {
+ Instruction->OpcodeLength = 3;
+ Instruction->OpcodeBytes[2] = SSE_Prefix;
+ assert(Instruction->OpcodeBytes[1] == Opcode);
+
+ // Since the prefix was really an opcode extension, remove it from
+ // the prefix list
+ for (i = 0; i < Instruction->PrefixCount; i++)
+ {
+ if (Instruction->Prefixes[i]) break;
+ }
+ assert(i != Instruction->PrefixCount);
+ Instruction->PrefixCount--;
+ Instruction->Prefixes[i] = 0;
+
+ // Slide any prefixes following the removed prefix down by 1
+ memmove(&Instruction->Prefixes[i], &Instruction->Prefixes[i+1], Instruction->PrefixCount-i);
+ Instruction->Prefixes[Instruction->PrefixCount] = 0;
+ Instruction->Repeat = FALSE;
+ X86Instruction->HasRepeatWhileEqualPrefix = FALSE;
+ X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE;
+ X86Instruction->HasOperandSizePrefix = FALSE;
+ if (SSE_Prefix == PREFIX_OPERAND_SIZE)
+ {
+ if (IS_AMD64() && X86Instruction->rex.w) X86Instruction->OperandSize = 8;
+ else X86Instruction->OperandSize = 4;
+ }
+
+ if (IS_X86_16())
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: SSE invalid in 16-bit mode\n", VIRTUAL_ADDRESS);
+ goto abort;
+ }
+
+ assert(X86Instruction->HasModRM);
+ switch (SSE_Prefix)
+ {
+ case PREFIX_OPERAND_SIZE: X86Opcode = &X86_SSE[0x000+Opcode]; break;
+ case PREFIX_REPNE: X86Opcode = &X86_SSE[0x100+Opcode]; break;
+ case PREFIX_REP: X86Opcode = &X86_SSE[0x200+Opcode]; break;
+ }
+
+ if (X86_INVALID(X86Opcode))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal SSE instruction opcode 0x%02X 0x%02X + prefix 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Instruction->OpcodeBytes[2]);
+ goto abort;
+ }
+ else if (X86_EXTENDED_OPCODE(X86Opcode))
+ {
+ // SSE in group (13, 14, or 15)
+ OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b);
+ Group = X86_Groups_2[Opcode];
+ X86Instruction->Group = (U8)Group;
+ assert(Group >= 13 && Group <= 15 && X86Opcode->Table);
+ switch (SSE_Prefix)
+ {
+ case PREFIX_OPERAND_SIZE: X86Opcode = &X86Opcode->Table[0x00+OpcodeExtension]; break;
+ case PREFIX_REPNE: X86Opcode = &X86Opcode->Table[0x08+OpcodeExtension]; break;
+ case PREFIX_REP: X86Opcode = &X86Opcode->Table[0x10+OpcodeExtension]; break;
+ }
+
+ if (X86_INVALID(X86Opcode))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal SSE instruction opcode 0x%02X 0x%02X + prefix 0x%02X + extension %d\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Instruction->OpcodeBytes[2], OpcodeExtension);
+ goto abort;
+ }
+ }
+
+ Instruction->Repeat = FALSE;
+ X86Instruction->HasRepeatWhileEqualPrefix = FALSE;
+ X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE;
+ X86Instruction->HasOperandSizePrefix = FALSE;
+ switch (X86_GET_CATEGORY(X86Opcode))
+ {
+ case ITYPE_SSE: case ITYPE_SSE2: case ITYPE_SSE3: break;
+ default: assert(0); goto abort;
+ }
+ }
+ else if (X86_EXTENDED_OPCODE(X86Opcode)) // 2 byte group
+ {
+ assert(!X86Opcode->MnemonicFlags);
+ OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b);
+
+ assert(X86Opcode->Table);
+ X86Opcode = &X86Opcode->Table[OpcodeExtension];
+ if (X86_INVALID(X86Opcode))
+ {
+ Instruction->Length++;
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension);
+ goto abort;
+ }
+
+ assert(!X86_SPECIAL_EXTENSION(X86Opcode));
+ Group = X86_Groups_2[Opcode];
+ X86Instruction->Group = (U8)Group;
+ assert(Group > 0 && Group <= 19);
+ assert(X86Opcode->Mnemonic);
+ DISASM_OUTPUT(("[0x%08I64X] Group %d (bytes 0x%02X 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension, X86Opcode->Mnemonic));
+ }
+ else
+ {
+ assert(X86Opcode->Mnemonic);
+ DISASM_OUTPUT(("[0x%08I64X] Two byte opcode 0x%02X 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic));
+ X86Instruction->HasModRM = X86_ModRM_2[Opcode];
+ if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address;
+ }
+ }
+ else // 1-byte opcode
+ {
+ if (X86Instruction->AddressSize == 8)
+ {
+ if (X86_Invalid_Addr64_1[Opcode])
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X (\"%s\") illegal in 64-bit mode\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic);
+ goto abort;
+ }
+
+#if 0
+ if (X86Instruction->rex_b &&
+ (GET_REX_B(X86Instruction->rex_b) && !GET_REX_B(X86_REX_1[Opcode]) ||
+ GET_REX_X(X86Instruction->rex_b) && !GET_REX_X(X86_REX_1[Opcode]) ||
+ GET_REX_R(X86Instruction->rex_b) && !GET_REX_R(X86_REX_1[Opcode]) ||
+ GET_REX_W(X86Instruction->rex_b) && !GET_REX_W(X86_REX_1[Opcode])))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal REX prefix 0x%02X for opcode 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->rex_b, Opcode);
+ assert(0);
+ goto abort;
+ }
+#endif
+ }
+
+ if (X86Instruction->OperandSize == 2 && X86_Invalid_Op16_1[Opcode])
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X (\"%s\") illegal with 16-bit operand size\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic);
+ goto abort;
+ }
+
+ Instruction->OpcodeBytes[0] = Opcode;
+ Instruction->OpcodeLength = 1;
+ X86Instruction->HasModRM = X86_ModRM_1[Opcode];
+ if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address;
+
+ if (X86_EXTENDED_OPCODE(X86Opcode)) // a group
+ {
+ assert(X86Instruction->HasModRM);
+ OpcodeExtension = GET_MODRM_EXT(*Address); // leave Address pointing at ModRM byte
+
+ if (X86_SPECIAL_EXTENSION(X86Opcode))
+ {
+ DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode));
+ SpecialExtension = TRUE;
+ goto HasSpecialExtension;
+ }
+
+ assert(X86Opcode->Table);
+ X86Opcode = &X86Opcode->Table[OpcodeExtension];
+ if (X86_INVALID(X86Opcode))
+ {
+ Instruction->Length++;
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, Opcode, OpcodeExtension);
+ goto abort;
+ }
+
+ Group = X86_Groups_1[Opcode];
+ X86Instruction->Group = (U8)Group;
+ DISASM_OUTPUT(("[0x%08I64X] Group %d (byte 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, Opcode, OpcodeExtension, X86Opcode->Mnemonic));
+ assert(Group > 0 && Group <= 17);
+ assert(X86Opcode->Mnemonic);
+ }
+ else
+ {
+ if (X86_SPECIAL_EXTENSION(X86Opcode))
+ {
+ DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X\n", VIRTUAL_ADDRESS, Opcode));
+ SpecialExtension = TRUE;
+ goto HasSpecialExtension;
+ }
+
+ DISASM_OUTPUT(("[0x%08I64X] One byte opcode 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic));
+ }
+ }
+
+HasSpecialExtension:
+ if (SpecialExtension)
+ {
+ if (X86Opcode->MnemonicFlags & ITYPE_EXT_MODRM)
+ {
+ assert(X86Opcode->Table);
+ assert(Instruction->OpcodeLength == 2);
+ assert(X86Instruction->HasModRM);
+ X86Opcode = &X86Opcode->Table[*Address];
+ if (X86_INVALID(X86Opcode))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal opcode 0x%02X 0x%02X + modrm 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], *Address);
+ goto abort;
+ }
+ else if (X86_EXTENDED_OPCODE(X86Opcode))
+ {
+ assert(!X86Opcode->MnemonicFlags);
+ OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b);
+
+ assert(X86Opcode->Table);
+ X86Opcode = &X86Opcode->Table[OpcodeExtension];
+ if (X86_INVALID(X86Opcode))
+ {
+ Instruction->Length++;
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension);
+ goto abort;
+ }
+
+ assert(!X86_SPECIAL_EXTENSION(X86Opcode));
+ Group = X86_Groups_2[Opcode];
+ X86Instruction->Group = (U8)Group;
+ assert(Group > 0 && Group <= 19);
+ assert(X86Opcode->Mnemonic);
+ DISASM_OUTPUT(("[0x%08I64X] Group %d (bytes 0x%02X 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension, X86Opcode->Mnemonic));
+ }
+ else if (!X86_OPERAND_COUNT(X86Opcode))
+ {
+ INSTR_INC(1); // increment Instruction->Length and address
+ }
+ }
+ else if (X86Opcode->MnemonicFlags & ITYPE_EXT_FPU)
+ {
+ assert(X86Opcode->Table);
+ if (X86Instruction->modrm_b < 0xC0)
+ {
+ // It is an opcode extension, use the X86Opcode->Table
+ OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b);
+ X86Opcode = &X86Opcode->Table[OpcodeExtension];
+ }
+ else
+ {
+ // The whole ModRM byte is used, these start at index 0x08 in X86Opcode->Table
+ OpcodeExtension = (X86Instruction->modrm_b & 0x3F);
+ X86Opcode = &X86Opcode->Table[0x08 + OpcodeExtension];
+ }
+
+ if (X86_INVALID(X86Opcode))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid FPU opcode 0x%02X + modrm extension 0x%02X (index 0x%02X)\n", VIRTUAL_ADDRESS, Opcode, X86Instruction->modrm_b, 0x08 + OpcodeExtension);
+ goto abort;
+ }
+
+ DISASM_OUTPUT(("[0x%08I64X] FPU instruction is (\"%s\"): 0x%02X + modrm 0x%02X (index 0x%02X)\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Opcode, X86Instruction->modrm_b, 0x08 + OpcodeExtension));
+ if (!X86_OPERAND_COUNT(X86Opcode)) INSTR_INC(1); // increment Instruction->Length and address
+ }
+ else if (X86Opcode->MnemonicFlags & ITYPE_EXT_SUFFIX)
+ {
+ if (X86Instruction->HasOperandSizePrefix)
+ {
+ if (!Instruction->AnomalyOccurred && X86Opcode->Table == X86_3DNOW_0F)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: operand size prefix used with 3DNOW instruction\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ X86Instruction->HasOperandSizePrefix = FALSE;
+ X86Instruction->OperandSize = 4;
+ }
+ Instruction->OperandCount = X86_OPERAND_COUNT(X86Opcode);
+ assert(Instruction->OpcodeLength == 2 && X86Instruction->HasModRM && Instruction->OperandCount == 2);
+ memcpy(&X86Instruction->Opcode, X86Opcode, sizeof(X86_OPCODE));
+ Instruction->Operands[0].Flags = X86Opcode->OperandFlags[0] & X86_OPFLAGS_MASK;
+ Instruction->Operands[1].Flags = X86Opcode->OperandFlags[1] & X86_OPFLAGS_MASK;
+ Instruction->Operands[2].Flags = X86Opcode->OperandFlags[2] & X86_OPFLAGS_MASK;
+ assert(Address == Instruction->Address + Instruction->Length);
+ if (!SetOperands(Instruction, Address, Flags & DISASM_SUPPRESSERRORS)) goto abort;
+ Suffix = Instruction->Address[Instruction->Length++];
+ Instruction->OpcodeBytes[2] = Suffix;
+ Instruction->OpcodeLength = 3;
+ X86Opcode = &X86Opcode->Table[Suffix];
+
+ if (X86_INVALID(X86Opcode))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal opcode 0x%02X 0x%02X + suffix 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Suffix);
+ goto abort;
+ }
+ assert(Instruction->Length >= 4 + Instruction->PrefixCount);
+ }
+ else if (X86Opcode->MnemonicFlags & ITYPE_EXT_64)
+ {
+ assert(X86Opcode->Table);
+ if (IS_AMD64()) X86Opcode = &X86Opcode->Table[1];
+ else X86Opcode = &X86Opcode->Table[0];
+ assert(!X86_INVALID(X86Opcode));
+ }
+ }
+
+ // Detect incompatibilities
+ if (IS_X86_16() && X86Opcode->CPU > CPU_I386)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Instruction \"%s\" (opcode 0x%02X) can't be used in 16-bit X86\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->LastOpcode);
+ goto abort;
+ }
+ if (!IS_AMD64() && X86Opcode->CPU >= CPU_AMD64)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Instruction \"%s\" (opcode 0x%02X) can only be used in X86-64\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->LastOpcode);
+ goto abort;
+ }
+
+ // Copy the opcode into the local structure and set the fields
+ assert(Instruction->OpcodeLength && !X86_INVALID(X86Opcode));
+ memcpy(&X86Instruction->Opcode, X86Opcode, sizeof(X86_OPCODE));
+ Instruction->Groups |= X86_GET_CATEGORY(X86Opcode);
+ assert(Instruction->Groups);
+ Instruction->Type |= X86_GET_TYPE(X86Opcode);
+ assert((U32)Instruction->Type >= Instruction->Groups);
+ Instruction->OperandCount = X86_OPERAND_COUNT(X86Opcode);
+
+ //
+ // Sanity check prefixes now that opcode is known and prefixes are resolved
+ //
+
+ // Instructions that implicitly reference the CS/DS can't have segment override prefixes
+ switch (Instruction->Type)
+ {
+ case ITYPE_PUSHF: case ITYPE_POPF:
+ case ITYPE_ENTER: case ITYPE_LEAVE:
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ X86Instruction->HasSegmentOverridePrefix = FALSE;
+ X86Instruction->Segment = SEG_SS;
+ break;
+ case ITYPE_RET: case ITYPE_DEBUG:
+ case ITYPE_OFLOW: case ITYPE_TRAP:
+ case ITYPE_TRAPRET:
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ X86Instruction->HasSegmentOverridePrefix = FALSE;
+ X86Instruction->Segment = SEG_CS;
+ break;
+ }
+
+ // Check illegal prefixes used with FPU/MMX/SSEx
+ if (Instruction->Groups & (ITYPE_FPU|ITYPE_MMX|ITYPE_SSE|ITYPE_SSE2|ITYPE_SSE3))
+ {
+ // Check for prefixes that produce unpredictable results
+ for (i = 0; i < Instruction->PrefixCount; i++)
+ {
+ switch (Instruction->Prefixes[i])
+ {
+ case PREFIX_OPERAND_SIZE:
+ switch (Instruction->Type)
+ {
+ case ITYPE_FSTOREENV: case ITYPE_FLOADENV: case ITYPE_FSAVE: case ITYPE_FRESTORE: continue;
+ default: break;
+ }
+
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: operand size prefix used with FPU/MMX/SSEx\n", VIRTUAL_ADDRESS);
+ goto abort;
+ }
+ X86Instruction->HasOperandSizePrefix = FALSE;
+ if (X86Instruction->OperandSize == 2) X86Instruction->OperandSize = 2;
+ break;
+
+ case PREFIX_REPNE:
+ case PREFIX_REP:
+ if (Instruction->Groups & ITYPE_FPU) { assert(Instruction->Repeat); continue; }
+ // The Intel manual says this results in unpredictable behavior -- it's not even
+ // clear which SSE prefix is used as the third opcode byte in this case
+ // (e.g., is it the first or last SSE prefix?)
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: rep/repne used with MMX/SSEx\n", VIRTUAL_ADDRESS);
+ goto abort;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // Check for conflicts involving operand size
+ if (IS_AMD64())
+ {
+ // Check for use of rex.w=1 with an operand size prefix
+ if (X86Instruction->rex.w)
+ {
+ assert(X86Instruction->OperandSize == 8);
+ for (i = 0; i < Instruction->PrefixCount; i++)
+ {
+ if (Instruction->Prefixes[i] == PREFIX_OPERAND_SIZE)
+ {
+ X86Instruction->HasOperandSizePrefix = FALSE;
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of operand size prefix meaningless when REX.w=1\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ }
+ }
+ }
+
+ // Set default operand size to 64 instead of 32 for some instructions
+ switch (Instruction->Type)
+ {
+ case ITYPE_PUSH: case ITYPE_POP:
+ case ITYPE_PUSHF: case ITYPE_POPF:
+ case ITYPE_ENTER: case ITYPE_LEAVE:
+ case ITYPE_CALL: case ITYPE_BRANCH:
+ case ITYPE_LOOPCC: case ITYPE_RET:
+ X86Instruction->HasDefault64Operand = TRUE;
+ break;
+
+ case ITYPE_SYSTEM:
+ if (Instruction->OpcodeLength != 2) break;
+
+ // lgdt/lidt/lldt/ltr
+ if ((Instruction->LastOpcode == 0x00 || Instruction->LastOpcode == 0x01) &&
+ (OpcodeExtension == 0x02 || OpcodeExtension == 0x03))
+ {
+ X86Instruction->HasDefault64Operand = TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (X86Instruction->HasDefault64Operand)
+ {
+ if (X86Instruction->rex.w)
+ {
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of REX.w is meaningless (default operand size is 64)\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ X86Instruction->rex_b &= ~8;
+ X86Instruction->rex.w = 0;
+ }
+
+ if (X86Instruction->HasOperandSizePrefix)
+ {
+ assert(X86Instruction->OperandSize == 2);
+ X86Instruction->HasDefault64Operand = FALSE;
+ }
+ else
+ {
+ assert(X86Instruction->OperandSize >= 4);
+ X86Instruction->OperandSize = 8;
+ }
+ }
+ }
+
+ // Make sure rep/repe/repne is set correctly based on instruction
+ if (Instruction->Repeat)
+ {
+ switch (Instruction->Type)
+ {
+ case ITYPE_IN:
+ case ITYPE_OUT:
+ case ITYPE_STRMOV:
+ case ITYPE_STRSTOR:
+ case ITYPE_STRLOAD:
+ if (X86Instruction->HasRepeatWhileNotEqualPrefix)
+ {
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: REPNE should only be used with cmps/scas\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ // Treat it as just a "rep"
+ X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE;
+ X86Instruction->HasRepeatWhileEqualPrefix = TRUE;
+ }
+ break;
+ case ITYPE_STRCMP:
+ break;
+ default:
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Repeat prefix used with non-string instruction\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ Instruction->Repeat = FALSE;
+ X86Instruction->HasRepeatWhileEqualPrefix = FALSE;
+ X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE;
+ break;
+ }
+ }
+
+ if (Disassemble)
+ {
+ assert(!Instruction->StringIndex);
+ if (X86Instruction->HasRepeatWhileEqualPrefix)
+ {
+ if (Instruction->Type == ITYPE_STRCMP) { APPENDS("repe "); }
+ else { APPENDS("rep "); }
+ }
+ if (X86Instruction->HasRepeatWhileNotEqualPrefix) APPENDS("repne ");
+ if (X86Instruction->HasLockPrefix) APPENDS("lock ");
+ if (X86Instruction->HasBranchTakenPrefix) APPENDS("hinttake ");
+ if (X86Instruction->HasBranchNotTakenPrefix) APPENDS("hintskip ");
+ APPENDPAD(12);
+ APPEND(OPCSTR, SIZE_LEFT, "%s", X86Opcode->Mnemonic);
+ APPENDPAD(24);
+ }
+
+ if (Instruction->OperandCount)
+ {
+ Instruction->Operands[0].Flags = X86Opcode->OperandFlags[0] & X86_OPFLAGS_MASK;
+ Instruction->Operands[1].Flags = X86Opcode->OperandFlags[1] & X86_OPFLAGS_MASK;
+ Instruction->Operands[2].Flags = X86Opcode->OperandFlags[2] & X86_OPFLAGS_MASK;
+ Address = SetOperands(Instruction, Address, Flags);
+ if (!Address) goto abort;
+ assert(!(Instruction->Operands[0].Flags & 0x7F));
+ assert(!(Instruction->Operands[1].Flags & 0x7F));
+ assert(!(Instruction->Operands[2].Flags & 0x7F));
+ }
+
+ Disassembler->Stage2Count++;
+
+#ifdef TEST_DISASM
+ //////////////////////////////////////////////////////////////////////
+ // Test against other disassemblers
+ //////////////////////////////////////////////////////////////////////
+
+ if (IS_X86_32())
+ {
+ InstructionLength = X86_GetLength(Instruction, Instruction->Address);
+ if (InstructionLength && Instruction->Length != InstructionLength)
+ {
+ printf("[0x%08I64X] WARNING: instruction lengths differ (%d vs %d)\n", VIRTUAL_ADDRESS, Instruction->Length, InstructionLength);
+ DumpInstruction(Instruction, TRUE, TRUE);
+ assert(0);
+ }
+ }
+ else if (IS_AMD64())
+ {
+ // TODO: need other amd64 (x86-64) disassembler to test against
+ }
+ else if (IS_X86_16())
+ {
+ // TODO: need other x86 16-bit disassembler to test against
+ }
+#endif
+
+ //////////////////////////////////////////////////////////////////////
+ // Post-operand sanity checks
+ //////////////////////////////////////////////////////////////////////
+
+ if (!X86Instruction->HasDstAddressing && !X86Instruction->HasSrcAddressing)
+ {
+ if (X86Instruction->HasAddressSizePrefix)
+ {
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: address size prefix used with no addressing\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ X86Instruction->HasAddressSizePrefix = FALSE;
+ }
+
+ if (X86Instruction->HasSegmentOverridePrefix)
+ {
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: segment override used with no addressing\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ X86Instruction->HasSegmentOverridePrefix = FALSE;
+ }
+ }
+
+ // Detect use of unusual segments
+ if (!Instruction->AnomalyOccurred && !IS_X86_16())
+ {
+ switch (X86Instruction->Segment)
+ {
+ case SEG_CS: case SEG_DS: case SEG_SS:
+ break;
+ case SEG_ES:
+ switch (Instruction->Type)
+ {
+ case ITYPE_IN: case ITYPE_STRMOV: case ITYPE_STRCMP: case ITYPE_STRSTOR:
+ break;
+ default:
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment ES\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ break;
+ }
+ break;
+ case SEG_FS:
+ if (IS_X86_32() && !(Instruction->Groups & ITYPE_EXEC)) break;
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment FS\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ break;
+ case SEG_GS:
+ if (IS_AMD64() && !(Instruction->Groups & ITYPE_EXEC)) break;
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment GS\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ break;
+ default:
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: unexpected segment 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->Selector);
+ Instruction->AnomalyOccurred = TRUE;
+ break;
+ }
+ }
+
+ if ((X86Opcode->OperandFlags[0] & OP_COND_EXEC) == OP_COND_EXEC)
+ {
+ assert(Instruction->Type == ITYPE_BRANCHCC || Instruction->Type == ITYPE_LOOPCC);
+ for (i = 0; i < Instruction->PrefixCount; i++)
+ {
+ switch (Instruction->Prefixes[i])
+ {
+ case PREFIX_BRANCH_NOT_TAKEN:
+ if (!Instruction->AnomalyOccurred && X86Instruction->Segment != SEG_CS)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used with conditional branch\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ X86Instruction->HasSegmentOverridePrefix = FALSE;
+ X86Instruction->Segment = SEG_CS;
+ X86Instruction->HasBranchNotTakenPrefix = TRUE;
+ break;
+ case PREFIX_BRANCH_TAKEN:
+ if (!Instruction->AnomalyOccurred && X86Instruction->Segment != SEG_DS)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used with conditional branch\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ X86Instruction->HasSegmentOverridePrefix = FALSE;
+ X86Instruction->Segment = SEG_CS;
+ X86Instruction->HasBranchTakenPrefix = TRUE;
+ break;
+ }
+ }
+ }
+
+ //
+ // If lock prefix is enabled, verify it is valid
+ //
+ if (X86Instruction->HasLockPrefix &&
+ !IsValidLockPrefix(X86Instruction, Opcode, Instruction->OpcodeLength, Group, OpcodeExtension))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal use of lock prefix for instruction \"%s\"\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic);
+ goto abort;
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Generate disassembly output
+ //////////////////////////////////////////////////////////////////////
+
+ if (Disassemble)
+ {
+ if ((Flags & DISASM_SHOWFLAGS) &&
+ (X86Instruction->Opcode.Preconditions || X86Instruction->Opcode.FlagsChanged || X86Instruction->Opcode.ResultsIfTrue))
+ {
+ APPENDPAD(124);
+ if (X86Instruction->Opcode.Preconditions)
+ {
+ Result = X86Instruction->Opcode.Preconditions;
+ APPENDS("COND:{ ");
+ if (Result & COND_L) APPENDS("L ");
+ if (Result & COND_NL) APPENDS("NL ");
+ if (Result & COND_LE) APPENDS("LE ");
+ if (Result & COND_NLE) APPENDS("NLE ");
+ if (Result & COND_G) APPENDS("G ");
+ if (Result & COND_NG) APPENDS("NG ");
+ if (Result & COND_GE) APPENDS("GE ");
+ if (Result & COND_NGE) APPENDS("NGE ");
+ if (Result & COND_A) APPENDS("A ");
+ if (Result & COND_NA) APPENDS("NA ");
+ if (Result & COND_AE) APPENDS("AE ");
+ if (Result & COND_NAE) APPENDS("NAE ");
+ if (Result & COND_B) APPENDS("B ");
+ if (Result & COND_NB) APPENDS("NB ");
+ if (Result & COND_BE) APPENDS("BE ");
+ if (Result & COND_NBE) APPENDS("NBE ");
+ if (Result & COND_E) APPENDS("E ");
+ if (Result & COND_NE) APPENDS("NE ");
+ if (Result & COND_C) APPENDS("C ");
+ if (Result & COND_NC) APPENDS("NC ");
+ if (Result & COND_Z) APPENDS("Z ");
+ if (Result & COND_NZ) APPENDS("NZ ");
+ if (Result & COND_P) APPENDS("P ");
+ if (Result & COND_NP) APPENDS("NP ");
+ if (Result & COND_PE) APPENDS("PE ");
+ if (Result & COND_PO) APPENDS("PO ");
+ if (Result & COND_O) APPENDS("O ");
+ if (Result & COND_NO) APPENDS("NO ");
+ if (Result & COND_U) APPENDS("U ");
+ if (Result & COND_NU) APPENDS("NU ");
+ if (Result & COND_S) APPENDS("S ");
+ if (Result & COND_NS) APPENDS("NS ");
+ if (Result & COND_D) APPENDS("D ");
+ APPENDB('}');
+ }
+
+ if (X86Instruction->Opcode.FlagsChanged)
+ {
+ Result = X86Instruction->Opcode.FlagsChanged;
+
+ if (Result & FLAG_SET_MASK)
+ {
+ APPENDS("SET:{ ");
+ if (Result & FLAG_CF_SET) APPENDS("C ");
+ if (Result & FLAG_DF_SET) APPENDS("D ");
+ if (Result & FLAG_IF_SET) APPENDS("I ");
+ APPENDB('}');
+ }
+
+ if (Result & FLAG_CLR_MASK)
+ {
+ APPENDS("CLR:{ ");
+ if (Result & FLAG_SF_CLR) APPENDS("S ");
+ if (Result & FLAG_ZF_CLR) APPENDS("Z ");
+ if (Result & FLAG_AF_CLR) APPENDS("A ");
+ if (Result & FLAG_CF_CLR) APPENDS("C ");
+ if (Result & FLAG_DF_CLR) APPENDS("D ");
+ if (Result & FLAG_IF_CLR) APPENDS("I ");
+ if (Result & FLAG_OF_CLR) APPENDS("O ");
+ if ((Result & FPU_ALL_CLR) == FPU_ALL_CLR)
+ {
+ APPENDS("FPU_ALL ");
+ }
+ else
+ {
+ if (Result & FPU_C0_CLR) APPENDS("FPU_C0 ");
+ if (Result & FPU_C1_CLR) APPENDS("FPU_C1 ");
+ if (Result & FPU_C2_CLR) APPENDS("FPU_C2 ");
+ if (Result & FPU_C3_CLR) APPENDS("FPU_C3 ");
+ }
+ APPENDB('}');
+ }
+
+ if ((Result & FLAG_MOD_MASK) == FLAG_MOD_MASK)
+ {
+ APPENDS("MOD:{ ");
+ if ((Result & FLAG_ALL_MOD) == FLAG_ALL_MOD)
+ {
+ APPENDS("FLAGS_ALL ");
+ }
+ else if ((Result & FLAG_COMMON_MOD) == FLAG_COMMON_MOD)
+ {
+ APPENDS("FLAGS_COMMON ");
+ }
+ else
+ {
+ if (Result & FLAG_OF_MOD) APPENDS("O ");
+ if (Result & FLAG_SF_MOD) APPENDS("S ");
+ if (Result & FLAG_ZF_MOD) APPENDS("Z ");
+ if (Result & FLAG_AF_MOD) APPENDS("A ");
+ if (Result & FLAG_PF_MOD) APPENDS("P ");
+ if (Result & FLAG_CF_MOD) APPENDS("C ");
+ if (Result & FLAG_DF_MOD) APPENDS("D ");
+ if (Result & FLAG_IF_MOD) APPENDS("I ");
+ }
+ if ((Result & FPU_ALL_MOD) == FPU_ALL_MOD)
+ {
+ APPENDS("FPU_ALL ");
+ }
+ else
+ {
+ if (Result & FPU_C0_MOD) APPENDS("FPU_C0 ");
+ if (Result & FPU_C1_MOD) APPENDS("FPU_C1 ");
+ if (Result & FPU_C2_MOD) APPENDS("FPU_C2 ");
+ if (Result & FPU_C3_MOD) APPENDS("FPU_C3 ");
+ }
+ APPENDB('}');
+ }
+
+ if (Result & FLAG_TOG_MASK)
+ {
+ APPENDS("TOG:{ ");
+ if (Result & FLAG_CF_TOG) APPENDS("C ");
+ APPENDB('}');
+ }
+ }
+ }
+
+ APPENDS("\n");
+ }
+ else
+ {
+ Instruction->String[0] = '\0';
+ }
+
+ if (!Instruction->Length || Instruction->Length > X86_MAX_INSTRUCTION_LEN)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: maximum instruction length reached (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+
+ if (!Decode)
+ {
+ Disassembler->Stage3CountNoDecode++;
+ return TRUE; // all work is done
+ }
+
+ //////////////////////////////////////////////////////////////////////
+ // Detect particularly interesting intructions
+ //////////////////////////////////////////////////////////////////////
+
+ Operand1 = &Instruction->Operands[0];
+ if (Instruction->Groups & ITYPE_EXEC)
+ {
+ // If it is a negative offset with a 1-byte or 2-byte offset, assume it is a loop
+ if (Operand1->Type == OPTYPE_OFFSET &&
+ Operand1->Length <= 2 && X86Instruction->Displacement < 0)
+ {
+ Instruction->CodeBranch.IsLoop = TRUE;
+ Instruction->CodeBranch.Operand = Operand1;
+ }
+
+ if (!Instruction->AnomalyOccurred &&
+ Operand1->TargetAddress >= (U64)Instruction->Address &&
+ Operand1->TargetAddress < (U64)Instruction->Address + Instruction->Length)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: branch into the middle of an instruction\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+
+ switch (Instruction->Type)
+ {
+ case ITYPE_BRANCH:
+ Operand1->Flags |= OP_ADDRESS;
+ assert(Instruction->OperandCount == 1);
+ if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR)))
+ {
+ assert(!X86Instruction->HasSelector);
+ X86Instruction->Segment = SEG_CS;
+ }
+
+ if (Operand1->TargetAddress)
+ {
+ assert(!Instruction->CodeBranch.AddressOffset);
+ Instruction->CodeBranch.Count = 1;
+ Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress;
+ Instruction->CodeBranch.Operand = Operand1;
+ }
+ // If there is both a base and index register, the Result will probably be too wrong
+ // to even guess
+ else if (X86Instruction->HasFullDisplacement &&
+ ((X86Instruction->HasBaseRegister && !X86Instruction->HasIndexRegister) ||
+ (!X86Instruction->HasBaseRegister && X86Instruction->HasIndexRegister)))
+ {
+ assert(Operand1->Length <= 0xFF);
+ if (!X86Instruction->Scale)
+ {
+ if (Operand1->Length) X86Instruction->Scale = (U8)Operand1->Length;
+ else X86Instruction->Scale = X86Instruction->OperandSize;
+ }
+ assert(Operand1->Length <= 0xFF);
+ tmpScale = MAX(X86Instruction->Scale, Operand1->Length);
+
+ assert(tmpScale <= 16);
+ Instruction->CodeBranch.AddressOffset = (U8)tmpScale;
+ for (i = 0; i < MAX_CODE_REFERENCE_COUNT; i++) Instruction->CodeBranch.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale);
+ Instruction->CodeBranch.Count = i;
+ Instruction->CodeBranch.IsIndirect = TRUE;
+ Instruction->CodeBranch.Operand = Operand1;
+ }
+ break;
+
+ case ITYPE_CALL:
+ Instruction->Groups |= ITYPE_STACK;
+ Instruction->CodeBranch.IsCall = TRUE;
+ Operand1->Flags |= OP_ADDRESS;
+ assert(Instruction->OperandCount == 1);
+ if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR)))
+ {
+ assert(!X86Instruction->HasSelector);
+ X86Instruction->Segment = SEG_CS;
+ }
+
+ if (Operand1->TargetAddress)
+ {
+ assert(!Instruction->CodeBranch.AddressOffset);
+ Instruction->CodeBranch.Count = 1;
+ Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress;
+ Instruction->CodeBranch.Operand = Operand1;
+ }
+ // If there is both a base and index register, the Result will probably be too wrong
+ // to even guess
+ else if (X86Instruction->HasFullDisplacement &&
+ ((X86Instruction->HasBaseRegister && !X86Instruction->HasIndexRegister) ||
+ (!X86Instruction->HasBaseRegister && X86Instruction->HasIndexRegister)))
+ {
+ //DISASM_OUTPUT(("[0x%08I64X] Scale %d, displacement 0x%08I64x\n", VIRTUAL_ADDRESS, X86Instruction->Scale, X86Instruction->Displacement));
+ if (!X86Instruction->Scale)
+ {
+ assert(Operand1->Length <= 0xFF);
+ if (Operand1->Length) X86Instruction->Scale = (U8)Operand1->Length;
+ else X86Instruction->Scale = X86Instruction->OperandSize;
+ }
+ tmpScale = MAX(X86Instruction->Scale, Operand1->Length);
+
+ assert(tmpScale <= 16);
+ Instruction->CodeBranch.AddressOffset = (U8)tmpScale;
+ assert(X86Instruction->Scale > 1);
+ for (i = 0; i < MAX_CODE_REFERENCE_COUNT; i++) Instruction->CodeBranch.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale);
+ Instruction->CodeBranch.Count = i;
+ Instruction->CodeBranch.IsIndirect = TRUE;
+ Instruction->CodeBranch.Operand = Operand1;
+ }
+ break;
+
+ case ITYPE_BRANCHCC:
+ assert(Instruction->OperandCount == 1);
+ assert(Operand1->Flags & OP_ADDRESS);
+ assert(Operand1->Type == OPTYPE_OFFSET);
+ if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR)))
+ {
+ assert(!X86Instruction->HasSelector);
+ X86Instruction->Segment = SEG_CS;
+ }
+
+ if (Operand1->TargetAddress)
+ {
+ assert(!Instruction->CodeBranch.AddressOffset);
+ Instruction->CodeBranch.Count = 2;
+ Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress;
+ Instruction->CodeBranch.Addresses[1] = (U64)Instruction->Address + Instruction->Length;
+ Instruction->CodeBranch.Operand = Operand1;
+ }
+ break;
+
+ case ITYPE_LOOPCC:
+ Instruction->CodeBranch.IsLoop = TRUE;
+ assert(Instruction->OperandCount == 1);
+ assert(Operand1->Flags & OP_ADDRESS);
+ assert(Operand1->Type == OPTYPE_OFFSET);
+ assert(!(Operand1->Flags & (OP_GLOBAL|OP_FAR)));
+ if (Operand1->TargetAddress)
+ {
+ assert(!Instruction->CodeBranch.AddressOffset);
+ Instruction->CodeBranch.Count = 2;
+ Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress;
+ Instruction->CodeBranch.Addresses[1] = (U64)Instruction->Address + Instruction->Length;
+ Instruction->CodeBranch.Operand = Operand1;
+ }
+ break;
+
+ case ITYPE_RET:
+ Instruction->Groups |= ITYPE_STACK;
+ break;
+
+ default:
+ break; // do nothing
+ }
+ }
+ else // possible data instruction
+ {
+ for (i = 0, Operand = Instruction->Operands; i < Instruction->OperandCount; i++, Operand++)
+ {
+ if (Operand->TargetAddress)
+ {
+ if (Operand->Flags & OP_DST)
+ {
+ assert(!Instruction->DataDst.Count);
+ Instruction->DataDst.Count = 1;
+ Instruction->DataDst.Addresses[0] = Operand->TargetAddress;
+ Instruction->DataDst.DataSize = Operand->Length;
+ Instruction->DataDst.Operand = Operand;
+ DISASM_OUTPUT(("[0x%08I64X] Write of size %d to 0x%04I64X\n", VIRTUAL_ADDRESS, Operand->Length, Operand->TargetAddress));
+ }
+ if (Operand->Flags & OP_SRC)
+ {
+ assert(!Instruction->DataSrc.Count);
+ Instruction->DataSrc.Count = 1;
+ Instruction->DataSrc.Addresses[0] = Operand->TargetAddress;
+ Instruction->DataSrc.DataSize = Operand->Length;
+ Instruction->DataSrc.Operand = Operand;
+ DISASM_OUTPUT(("[0x%08I64X] Read of size %d to 0x%04I64X\n", VIRTUAL_ADDRESS, Operand->Length, Operand->TargetAddress));
+ }
+ }
+
+ // If there is both a base and index register, the Result will probably be too wrong
+ // to even guess
+ else if (Operand->Flags & OP_GLOBAL &&
+ ((X86Instruction->HasBaseRegister && !X86Instruction->HasIndexRegister) ||
+ (!X86Instruction->HasBaseRegister && X86Instruction->HasIndexRegister)))
+ {
+ DISASM_OUTPUT(("[0x%08I64X] Data reference (scale %d, size %d, displacement 0x%08I64x)\n", VIRTUAL_ADDRESS, X86Instruction->Scale, Operand->Length, X86Instruction->Displacement));
+ if (!X86Instruction->Scale)
+ {
+ assert(Operand->Length <= 0xFF);
+ if (Operand->Length) X86Instruction->Scale = (U8)Operand->Length;
+ else X86Instruction->Scale = X86Instruction->OperandSize;
+ }
+ tmpScale = MAX(X86Instruction->Scale, Operand->Length);
+
+ assert(X86Instruction->HasFullDisplacement);
+ if (Operand->Flags & OP_DST)
+ {
+ assert(!Instruction->DataDst.Count);
+ assert(tmpScale <= 16);
+ Instruction->CodeBranch.AddressOffset = (U8)tmpScale;
+ for (i = 0; i < MAX_DATA_REFERENCE_COUNT; i++) Instruction->DataDst.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale);
+ Instruction->DataDst.Count = i;
+ Instruction->DataDst.DataSize = Operand->Length;
+ Instruction->DataDst.Operand = Operand;
+ }
+ if (Operand->Flags & OP_SRC)
+ {
+ assert(!Instruction->DataSrc.Count);
+ assert(tmpScale <= 16);
+ Instruction->CodeBranch.AddressOffset = (U8)tmpScale;
+ for (i = 0; i < MAX_DATA_REFERENCE_COUNT; i++) Instruction->DataSrc.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale);
+ Instruction->DataSrc.Count = i;
+ Instruction->DataSrc.DataSize = Operand->Length;
+ Instruction->DataSrc.Operand = Operand;
+ }
+ }
+ }
+ }
+
+ if (Instruction->Groups & ITYPE_STACK)
+ {
+ switch (Instruction->Type)
+ {
+ case ITYPE_PUSH:
+ assert(Instruction->OperandCount == 1 && Operand1->Length);
+ Instruction->StackChange = -Operand1->Length;
+ SANITY_CHECK_ADDRESS_SIZE();
+ break;
+
+ case ITYPE_POP:
+ assert(Instruction->OperandCount == 1 && Operand1->Length);
+ Instruction->StackChange = Operand1->Length;
+ SANITY_CHECK_ADDRESS_SIZE();
+ break;
+
+ case ITYPE_PUSHA:
+ Instruction->StackChange = -(X86Instruction->OperandSize * 8); // xAX, xCX, xDX, xBX, xBP, xSP, xSI, xDI
+ SANITY_CHECK_ADDRESS_SIZE();
+ break;
+
+ case ITYPE_POPA:
+ Instruction->StackChange = X86Instruction->OperandSize * 8; // xDI, xSI, xSP, xBP, xBX, xDX, xCX, xAX
+ SANITY_CHECK_ADDRESS_SIZE();
+ break;
+
+ case ITYPE_PUSHF:
+ Instruction->StackChange = -Operand1->Length;
+ Instruction->NeedsEmulation = TRUE;
+ SANITY_CHECK_ADDRESS_SIZE();
+ break;
+
+ case ITYPE_POPF:
+ Instruction->StackChange = Operand1->Length;
+ Instruction->NeedsEmulation = TRUE;
+ SANITY_CHECK_ADDRESS_SIZE();
+ break;
+
+ case ITYPE_ENTER:
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (Instruction->Operands[1].Value_U64 & 3)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ENTER has invalid operand 2\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ if (Instruction->Operands[2].Value_U64 & ~0x1F)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ENTER has invalid operand 3\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ }
+ SANITY_CHECK_ADDRESS_SIZE();
+ Instruction->Operands[2].Value_U64 &= 0x1F;
+
+ // frame pointer + stack space
+ i = Operand1->Length + (U32)Instruction->Operands[1].Value_U64;
+ Instruction->StackChange = -((LONG)i);
+ i = (U32)Instruction->Operands[2].Value_U64 * Operand1->Length;
+ Instruction->StackChange -= i;
+ break;
+
+ case ITYPE_LEAVE:
+ // This will do "mov esp, ebp; pop ebp" so the StackChange size is dynamic
+ SANITY_CHECK_ADDRESS_SIZE();
+ break;
+
+ case ITYPE_CALL:
+ Instruction->StackChange = -X86Instruction->OperandSize;
+ SANITY_CHECK_ADDRESS_SIZE();
+ break;
+
+ case ITYPE_RET:
+ Instruction->StackChange = X86Instruction->OperandSize;
+
+ switch (Opcode)
+ {
+ case 0xC3: // ret with no args
+ break;
+
+ case 0xC2: // ret with 1 arg
+ if (!Instruction->AnomalyOccurred && (Operand1->Value_U64 & 3))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ret has invalid operand 1\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ Instruction->StackChange += (LONG)Operand1->Value_U64;
+ break;
+
+ case 0xCB: // far ret with no args
+ Instruction->StackChange *= 2; // account for segment
+ Instruction->StackChange += (LONG)Operand1->Value_U64;
+ break;
+
+ case 0xCA: // far ret with 1 arg
+ if (!Instruction->AnomalyOccurred && (Operand1->Value_U64 & 3))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: retf has invalid operand 1\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ Instruction->StackChange *= 2; // account for segment
+ Instruction->StackChange += (LONG)Operand1->Value_U64;
+ break;
+ }
+ SANITY_CHECK_ADDRESS_SIZE();
+ break;
+
+ case ITYPE_ADD:
+ case ITYPE_XCHGADD:
+ if (Instruction->Operands[1].Value_S64) Instruction->StackChange = (LONG)(Instruction->Operands[1].Value_S64);
+ break;
+ case ITYPE_SUB:
+ if (Instruction->Operands[1].Value_S64) Instruction->StackChange = (LONG)(-Instruction->Operands[1].Value_S64);
+ break;
+ case ITYPE_MOV:
+ case ITYPE_AND:
+ break;
+
+ default:
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Instruction \"%s\" is modifying the stack\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ break;
+ }
+
+ if (!Instruction->AnomalyOccurred &&
+ ((X86Instruction->OperandSize != 2 && (Instruction->StackChange & 3)) || (Instruction->StackChange & 1)))
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: \"%s\" has invalid stack change 0x%02X\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->StackChange);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ }
+
+ if (Instruction->Groups & ITYPE_TRAPS)
+ {
+ switch (Instruction->Type)
+ {
+ case ITYPE_TRAP:
+ case ITYPE_TRAPCC:
+ case ITYPE_TRAPRET:
+ case ITYPE_BOUNDS:
+ case ITYPE_DEBUG:
+ case ITYPE_TRACE:
+ case ITYPE_INVALID:
+ case ITYPE_OFLOW:
+ Instruction->NeedsEmulation = TRUE;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+
+ if (Instruction->Groups & ITYPE_SYSTEM)
+ {
+ switch (Instruction->Type)
+ {
+ case ITYPE_CPUID:
+ case ITYPE_SYSCALL:
+ case ITYPE_SYSCALLRET:
+ // This doesn't require privileges
+ break;
+
+ case ITYPE_HALT:
+ case ITYPE_IN:
+ case ITYPE_OUT:
+ default:
+ Instruction->NeedsEmulation = TRUE;
+ break;
+ }
+ }
+
+ Disassembler->Stage3CountWithDecode++;
+ return TRUE;
+
+abort:
+ if (!SuppressErrors)
+ {
+#ifdef TEST_DISASM
+ printf("Dump of 0x%04I64X:\n", VIRTUAL_ADDRESS);
+ __try { DumpAsBytes(stdout, Instruction->Address, (ULONG_PTR)VIRTUAL_ADDRESS, 16, TRUE); }
+ __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {}
+#endif
+ fflush(stdout);
+ }
+ return FALSE;
+}
+
+// Address = address to first byte after the opcode (e.g., first byte of ModR/M byte or
+// immediate value
+//
+// Returns the address immediately following the operand (e.g., the next operand or the
+// start of the next instruction
+INTERNAL U8 *SetOperands(INSTRUCTION *Instruction, U8 *Address, U32 Flags)
+{
+ INSTRUCTION_OPERAND *Operand;
+ U32 Index, OperandIndex;
+ S64 Displacement = 0;
+ U8 Register;
+ U32 OperandFlags, OperandType, AddressMode, Segment;
+ U8 Opcode;
+ MODRM modrm;
+ REX rex;
+ REX_MODRM rex_modrm;
+ X86_OPCODE *X86Opcode;
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+ BOOL Decode = Flags & DISASM_DECODE;
+ BOOL Disassemble = Flags & DISASM_DISASSEMBLE;
+ BOOL SuppressErrors = Flags & DISASM_SUPPRESSERRORS;
+
+ Opcode = Instruction->LastOpcode;
+ X86Opcode = &X86Instruction->Opcode;
+
+ // Setup Mod R/M byte
+ if (X86Instruction->HasModRM)
+ {
+ SET_MODRM(X86Instruction->modrm, X86Instruction->modrm_b);
+ modrm = X86Instruction->modrm;
+ rex = X86Instruction->rex;
+ SET_REX_MODRM(X86Instruction->rex_modrm, rex, modrm);
+ rex_modrm = X86Instruction->rex_modrm;
+ //DISASM_OUTPUT(("[0x%08I64X] ModRM = 0x%02X (mod=%d, reg=%d, rm=%d)\n", VIRTUAL_ADDRESS, X86Instruction->modrm_b, modrm.mod, rex_modrm.reg, rex_modrm.rm));
+ INSTR_INC(1); // increment Instruction->Length and address
+ }
+ else
+ {
+ // initialize them to 0
+ modrm = X86Instruction->modrm;
+ rex = X86Instruction->rex;
+ rex_modrm = X86Instruction->rex_modrm;
+ }
+
+ for (OperandIndex = 0; OperandIndex < Instruction->OperandCount; OperandIndex++)
+ {
+ Operand = &Instruction->Operands[OperandIndex];
+ assert(!(Operand->Flags & 0x7F));
+
+ OperandFlags = X86Opcode->OperandFlags[OperandIndex] & X86_OPFLAGS_MASK;
+ OperandType = X86Opcode->OperandFlags[OperandIndex] & X86_OPTYPE_MASK;
+ AddressMode = X86Opcode->OperandFlags[OperandIndex] & X86_AMODE_MASK;
+ if (Decode && OperandIndex != 0) APPENDS(", ");
+
+ switch (OperandType)
+ {
+ ////////////////////////////////////////////////////////////
+ // Special operand types with no associated addressing mode
+ ////////////////////////////////////////////////////////////
+
+ case OPTYPE_0:
+ if (!Decode) continue;
+ Operand->Value_U64 = 0;
+ Operand->Type = OPTYPE_IMM;
+ //DISASM_OUTPUT(("[SetOperand] const 0\n"));
+ if (Disassemble)
+ {
+ APPENDS("<0>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_1:
+ if (!Decode) continue;
+ Operand->Value_U64 = 1;
+ Operand->Type = OPTYPE_IMM;
+ //DISASM_OUTPUT(("[SetOperand] const 1\n"));
+ if (Disassemble)
+ {
+ APPENDS("<1>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FF:
+ if (!Decode) continue;
+ Operand->Value_U64 = 0xFF;
+ Operand->Type = OPTYPE_IMM;
+ //DISASM_OUTPUT(("[SetOperand] const 0xff\n"));
+ if (Disassemble)
+ {
+ APPENDS("<0xFF>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_TSC:
+ if (!Decode) continue;
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_SPECIAL;
+ //DISASM_OUTPUT(("[SetOperand] TSC\n"));
+ if (Disassemble)
+ {
+ APPENDS("<TSC_MSR>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_CS_MSR:
+ if (!Decode) continue;
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_SPECIAL;
+ //DISASM_OUTPUT(("[SetOperand] CS MSR\n"));
+ if (Disassemble)
+ {
+ APPENDS("<CS_MSR>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_EIP_MSR:
+ if (!Decode) continue;
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_SPECIAL;
+ //DISASM_OUTPUT(("[SetOperand] EIP MSR\n"));
+ if (Disassemble)
+ {
+ APPENDS("<EIP_MSR>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_ESP_MSR:
+ if (!Decode) continue;
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_SPECIAL;
+ //DISASM_OUTPUT(("[SetOperand] ESP MSR\n"));
+ if (Disassemble)
+ {
+ APPENDS("<ESP_MSR>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_KERNELBASE_MSR:
+ if (!Decode) continue;
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_SPECIAL;
+ //DISASM_OUTPUT(("[SetOperand] KernelBase MSR\n"));
+ if (Disassemble)
+ {
+ APPENDS("<KRNLBASE_MSR>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_STAR_MSR:
+ if (!Decode) continue;
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_SPECIAL;
+ //DISASM_OUTPUT(("[SetOperand] KernelBase MSR\n"));
+ if (Disassemble)
+ {
+ APPENDS("<STAR_MSR>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_CSTAR_MSR:
+ assert(!IS_AMD64());
+ if (!Decode) continue;
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_SPECIAL;
+ //DISASM_OUTPUT(("[SetOperand] CSTAR MSR\n"));
+ if (Disassemble)
+ {
+ APPENDS("<CSTAR_MSR>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_LSTAR_MSR:
+ assert(IS_AMD64());
+ if (!Decode) continue;
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_SPECIAL;
+ //DISASM_OUTPUT(("[SetOperand] LSTAR MSR\n"));
+ if (Disassemble)
+ {
+ APPENDS("<LSTAR_MSR>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FMASK_MSR:
+ if (!Decode) continue;
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_SPECIAL;
+ //DISASM_OUTPUT(("[SetOperand] FMASK MSR\n"));
+ if (Disassemble)
+ {
+ APPENDS("<FMASK_MSR>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OP_REG:
+ if (!Decode) continue;
+ // The reg field is included in the opcode
+ Operand->Length = X86Instruction->OperandSize;
+ Register = X86_GET_REG64(Opcode);
+ switch (X86Instruction->OperandSize)
+ {
+ case 8:
+ Operand->Register = AMD64_64BIT_OFFSET + Register;
+ break;
+ case 4:
+ Operand->Register = X86_32BIT_OFFSET + Register;
+ CHECK_AMD64_REG();
+ break;
+ case 2:
+ Operand->Register = X86_16BIT_OFFSET + Register;
+ CHECK_AMD64_REG();
+ break;
+ case 1:
+ Operand->Register = X86_8BIT_OFFSET + Register;
+ if (X86Instruction->rex_b) CHECK_AMD64_REG();
+ break;
+ default:
+ assert(0);
+ return NULL;
+ }
+ X86_SET_REG(Register);
+
+ //DISASM_OUTPUT(("[SetOperand] OP_REG %s\n", X86_Registers[Operand->Register]));
+ if (Disassemble)
+ {
+ APPENDB('<'); APPENDS(X86_Registers[Operand->Register]); APPENDB('>');
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_REG8:
+ if (!Decode) continue;
+ // The reg field is included in the opcode
+ Operand->Length = 1;
+ Register = X86_GET_REG64(Opcode);
+ Operand->Register = X86_8BIT_OFFSET + Register;
+ CHECK_AMD64_REG();
+ X86_SET_REG(Register);
+
+ //DISASM_OUTPUT(("[SetOperand] OP_REG %s\n", X86_Registers[Operand->Register]));
+ if (Disassemble)
+ {
+ APPENDB('<'); APPENDS(X86_Registers[Operand->Register]); APPENDB('>');
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_REG_AL:
+ if (!Decode) continue;
+ Operand->Length = 1;
+ Operand->Register = X86_REG_AL;
+ X86_SET_REG(0);
+ //DISASM_OUTPUT(("[SetOperand] reg AL\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_REG_CL:
+ if (!Decode) continue;
+ Operand->Length = 1;
+ Operand->Register = X86_REG_CL;
+ X86_SET_REG(0);
+ //DISASM_OUTPUT(("[SetOperand] reg CL\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_REG_AH:
+ if (!Decode) continue;
+ Operand->Length = 1;
+ Operand->Register = X86_REG_AH;
+ X86_SET_REG(0);
+ //DISASM_OUTPUT(("[SetOperand] reg AH\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_REG_AX:
+ if (!Decode) continue;
+ Operand->Length = 2;
+ Operand->Register = X86_REG_AX;
+ X86_SET_REG(0);
+ //DISASM_OUTPUT(("[SetOperand] reg AX\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_REG_DX:
+ if (!Decode) continue;
+ Operand->Length = 2;
+ Operand->Register = X86_REG_DX;
+ X86_SET_REG(0);
+ //DISASM_OUTPUT(("[SetOperand] reg DX\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_REG_ECX:
+ if (!Decode) continue;
+ Operand->Length = 4;
+ Operand->Register = X86_REG_ECX;
+ X86_SET_REG(0);
+ //DISASM_OUTPUT(("[SetOperand] reg ECX\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_REG_xBP:
+ if (!Decode) continue;
+ Operand->Length = X86Instruction->OperandSize;
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: Operand->Register = AMD64_REG_RBP; break;
+ case 4: Operand->Register = X86_REG_EBP; break;
+ case 2: Operand->Register = X86_REG_BP; break;
+ default: assert(0); return NULL;
+ }
+ X86_SET_REG(0);
+ //DISASM_OUTPUT(("[SetOperand] xAX_BIG (size = %d)\n", Operand->Length));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_REG_xAX_BIG:
+ if (!Decode) continue;
+ Operand->Length = X86Instruction->OperandSize;
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: Operand->Register = AMD64_REG_RAX; break;
+ case 4: Operand->Register = X86_REG_EAX; break;
+ case 2: Operand->Register = X86_REG_AX; break;
+ default: assert(0); return NULL;
+ }
+ X86_SET_REG(0);
+ //DISASM_OUTPUT(("[SetOperand] xAX_BIG (size = %d)\n", Operand->Length));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_REG_xAX_SMALL:
+ if (!Decode) continue;
+ Operand->Length = X86Instruction->OperandSize >> 1;
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: Operand->Register = X86_REG_EAX; break;
+ case 4: Operand->Register = X86_REG_AX; break;
+ case 2: Operand->Register = X86_REG_AL; break;
+ default: assert(0); return NULL;
+ }
+ X86_SET_REG(0);
+ //DISASM_OUTPUT(("[SetOperand] xAX_SMALL (size = %d)\n", Operand->Length));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_xCX_HI_xBX_LO:
+ if (!Decode) continue;
+ Operand->Length = X86Instruction->OperandSize << 1;
+ if (Disassemble)
+ {
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: APPENDS("<RCX:RBX>"); break;
+ case 4: APPENDS("<ECX:EBX>"); break;
+ case 2: APPENDS("<CX:BX>"); break;
+ default: assert(0); return NULL;
+ }
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] xCX_BIG:xBX_BIG (size = %d)\n", Operand->Length));
+ continue;
+ case OPTYPE_xDX_HI_xAX_LO:
+ if (!Decode) continue;
+ Operand->Length = X86Instruction->OperandSize << 1;
+ if (Disassemble)
+ {
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: APPENDS("<RDX:RAX>"); break;
+ case 4: APPENDS("<EDX:EAX>"); break;
+ case 2: APPENDS("<DX:AX>"); break;
+ default: assert(0); return NULL;
+ }
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] xDX_BIG:xAX_BIG (size = %d)\n", Operand->Length));
+ continue;
+
+ case OPTYPE_EDX_HI_EAX_LO:
+ if (!Decode) continue;
+ Operand->Length = 8;
+ //DISASM_OUTPUT(("[SetOperand] EDX:EAX\n"));
+ if (Disassemble)
+ {
+ APPENDS("<EDX:EAX>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_EDX_ECX_EBX_EAX:
+ Operand->Length = 32;
+ //DISASM_OUTPUT(("[SetOperand] EDX:ECX:EBX:EAX\n"));
+ if (Disassemble)
+ {
+ APPENDS("<EDX:ECX:EBX:EAX>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_FLAGS:
+ if (!Decode) continue;
+ Operand->Length = 2;
+ Operand->Flags |= OP_REG;
+ Operand->Register = X86_REG_FLAGS;
+ //DISASM_OUTPUT(("[SetOperand] reg FLAGS\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_xFLAGS:
+ if (!Decode) continue;
+ Operand->Length = X86Instruction->OperandSize;
+ Operand->Flags |= OP_REG;
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: Operand->Register = AMD64_REG_RFLAGS; break;
+ case 4: Operand->Register = X86_REG_EFLAGS; break;
+ case 2: Operand->Register = X86_REG_FLAGS; break;
+ default: assert(0); return NULL;
+ }
+ //DISASM_OUTPUT(("[SetOperand] reg xFLAGS (size = %d)\n", Operand->Length));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_CS:
+ if (!Decode) continue;
+ if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
+ else Operand->Length = X86Instruction->OperandSize;
+ Operand->Register = X86_SEG_CS;
+ Operand->Flags |= OP_REG;
+ //DISASM_OUTPUT(("[SetOperand] seg CS\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_DS:
+ if (!Decode) continue;
+ if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
+ else Operand->Length = X86Instruction->OperandSize;
+ Operand->Register = X86_SEG_DS;
+ Operand->Flags |= OP_REG;
+ //DISASM_OUTPUT(("[SetOperand] seg DS\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_ES:
+ if (!Decode) continue;
+ if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
+ else Operand->Length = X86Instruction->OperandSize;
+ Operand->Register = X86_SEG_ES;
+ Operand->Flags |= OP_REG;
+ //DISASM_OUTPUT(("[SetOperand] seg ES\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FS:
+ if (!Decode) continue;
+ if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
+ else Operand->Length = X86Instruction->OperandSize;
+ Operand->Register = X86_SEG_FS;
+ Operand->Flags |= OP_REG;
+ //DISASM_OUTPUT(("[SetOperand] seg FS\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_GS:
+ if (!Decode) continue;
+ if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
+ else Operand->Length = X86Instruction->OperandSize;
+ Operand->Register = X86_SEG_GS;
+ Operand->Flags |= OP_REG;
+ //DISASM_OUTPUT(("[SetOperand] seg GS\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_SS:
+ if (!Decode) continue;
+ if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
+ else Operand->Length = X86Instruction->OperandSize;
+ Operand->Register = X86_SEG_SS;
+ Operand->Flags |= OP_REG;
+ //DISASM_OUTPUT(("[SetOperand] seg SS\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_CR0:
+ if (!Decode) continue;
+ Operand->Length = X86Instruction->OperandSize;
+ Operand->Register = X86_REG_CR0;
+ Operand->Flags |= OP_REG;
+ //DISASM_OUTPUT(("[SetOperand] reg CR0\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_STx:
+ if (!Decode) continue;
+ Operand->Length = 10;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Flags |= OP_REG;
+ Register = X86_GET_REG(X86Instruction->modrm_b);
+ Operand->Register = X86_FPU_OFFSET + Register;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_STx: reg st(%d)\n", Register));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_ST0:
+ if (!Decode) continue;
+ Operand->Length = 10;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Flags |= OP_REG;
+ Operand->Register = X86_REG_ST0;
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_ST1:
+ if (!Decode) continue;
+ Operand->Length = 10;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Flags |= OP_REG;
+ Operand->Register = X86_REG_ST1;
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_FPU_STATUS:
+ if (!Decode) continue;
+ Operand->Length = 2;
+ if (Disassemble)
+ {
+ APPENDS("<FPUSTAT>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_FPU_CONTROL:
+ if (!Decode) continue;
+ Operand->Length = 2;
+ if (Disassemble)
+ {
+ APPENDS("<FPUCTRL>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_FPU_TAG:
+ if (!Decode) continue;
+ Operand->Length = 2;
+ if (Disassemble)
+ {
+ APPENDS("<FPUTAG>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_FLDZ:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("<0.0>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FLD1:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("<1.0>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FLDPI:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("<pi>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FLDL2T:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("<log_2 10>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FLDL2E:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("<log_2 e>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FLDLG2:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("<log_10 2>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FLDLN2:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("<ln 2>");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ ////////////////////////////////////////////////////////////
+ // Fixed sizes regardless of operand size
+ ////////////////////////////////////////////////////////////
+
+ case OPTYPE_b: // byte regardless of operand size
+ Operand->Length = 1;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_b (size 1, signed %d)\n", ((OperandFlags & OP_SIGNED) != 0)));
+ break;
+
+ case OPTYPE_w: // word regardless of operand size
+ Operand->Length = 2;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_w (size 2)\n"));
+ break;
+
+ case OPTYPE_d: // dword regardless of operand size
+ Operand->Length = 4;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_d (size 4)\n"));
+ break;
+
+ case OPTYPE_q: // qword regardless of operand size
+ Operand->Length = 8;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_q (size 8)\n"));
+ break;
+
+ case OPTYPE_o: // oword regardless of operand size
+ Operand->Length = 16;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_o (size 16)\n"));
+ break;
+
+ case OPTYPE_dt: // 6-byte or 10-byte pseudo descriptor (sgdt, lgdt, sidt, lidt)
+ if (IS_AMD64()) Operand->Length = 10;
+ else Operand->Length = 6;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_dt (%d bytes)\n", Operand->Length));
+ break;
+
+ case OPTYPE_cpu:
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Undocumented loadall instruction?\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ Operand->Length = 204;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_cpu (size 204)\n"));
+ break;
+
+ ////////////////////////////////////////////////////////////
+ // Sizes depending on the operand size
+ ////////////////////////////////////////////////////////////
+
+ case OPTYPE_z: // word if operand size is 16 bits and dword otherwise
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: case 4: Operand->Length = 4; break;
+ case 2: Operand->Length = 2; break;
+ default: assert(0); return NULL;
+ }
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_z (length %d)\n", Operand->Length));
+ break;
+
+ case OPTYPE_v: // word, dword, or qword
+ Operand->Length = X86Instruction->OperandSize;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_v (size %d, signed = %d)\n", Operand->Length, ((OperandFlags & OP_SIGNED) != 0)));
+ break;
+
+ case OPTYPE_a: // two word or dword operands in memory (used only by bound)
+ assert(Instruction->OpcodeBytes[0] == X86_BOUND);
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: case 4: Operand->Length = 8; break;
+ case 2: Operand->Length = 4; break;
+ default: assert(0); return NULL;
+ }
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_a (size %d)\n", Operand->Length));
+ break;
+
+ case OPTYPE_p: // 32-bit or 48-bit pointer depending on operand size
+ if (!Instruction->AnomalyOccurred && X86Instruction->HasSegmentOverridePrefix)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used when segment is explicit\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: case 4: Operand->Length = 6; break;
+ case 2: Operand->Length = 4; break;
+ default: assert(0); return NULL;
+ }
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_p (length %d)\n", Operand->Length));
+ break;
+
+ case OPTYPE_dq: // dword or qword
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_dq (size 4 or 8)\n"));
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: Operand->Length = 8; break;
+ case 4: case 2: Operand->Length = 4; break;
+ default: assert(0); return NULL;
+ }
+ break;
+
+ case OPTYPE_mw: // a word if the destination operand is memory
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_mw (size 0)\n"));
+ assert(X86Instruction->HasModRM);
+ if (modrm.mod == 3) Operand->Length = X86Instruction->OperandSize; // using register
+ else Operand->Length = 2; // using memory
+ break;
+
+ case OPTYPE_lea:
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_lea (size 0)\n"));
+ assert(OperandIndex == 1);
+ Operand->Length = Instruction->Operands[0].Length;
+ break;
+
+ ////////////////////////////////////////////////////////////
+ // FPU types
+ ////////////////////////////////////////////////////////////
+
+ case OPTYPE_ps: // packed single real
+ Operand->Length = 4;
+ Operand->Type = OPTYPE_FLOAT;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_ps (packed single real)\n"));
+ break;
+ case OPTYPE_pd: // packed double real
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_FLOAT;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_pd (packed double real)\n"));
+ break;
+ case OPTYPE_pb: // packed BCD
+ Operand->Length = 10;
+ Operand->Type = OPTYPE_BCD;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_pb (packed BCD)\n"));
+ break;
+ case OPTYPE_ss: // scalar single real
+ Operand->Length = 4;
+ Operand->Type = OPTYPE_FLOAT;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_ss (single real)\n"));
+ break;
+ case OPTYPE_sd: // scalar double real
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_FLOAT;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_sd (double real)\n"));
+ break;
+ case OPTYPE_se: // extended real
+ Operand->Length = 10;
+ Operand->Type = OPTYPE_FLOAT;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_se (extended real)\n"));
+ break;
+
+ case OPTYPE_fev: // FPU environment (28 bytes in 32-bit modes, 14 bytes in 16-bit real mode)
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: case 4: Operand->Length = 28; break;
+ case 2: Operand->Length = 14; break;
+ default: assert(0); return NULL;
+ }
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_fev (FPU environment, length %d)\n", Operand->Length));
+ break;
+
+ case OPTYPE_fst1: // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode)
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: case 4: Operand->Length = 108; break;
+ case 2: Operand->Length = 94; break;
+ default: assert(0); return NULL;
+ }
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_fst1 (FPU state, length %d)\n", Operand->Length));
+ break;
+
+ case OPTYPE_fst2: // 512 bytes for FPU state (FPU + MMX + XXM + MXCSR)
+ Operand->Length = 512;
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_fst2 (FPU + MMX + XXM + MXCSR state, length 512)\n"));
+ break;
+
+ case OPTYPE_sso:
+ if (modrm.mod == 3) // from register
+ {
+ Operand->Length = 16;
+ }
+ else // from memory
+ {
+ Operand->Length = 4;
+ Operand->Type = OPTYPE_FLOAT;
+ }
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_sso (single real or oword)\n"));
+ break;
+
+ case OPTYPE_sdo:
+ if (modrm.mod == 3) // from register
+ {
+ Operand->Length = 16;
+ }
+ else // from memory
+ {
+ Operand->Length = 8;
+ Operand->Type = OPTYPE_FLOAT;
+ }
+ //DISASM_OUTPUT(("[SetOperand] OPTYPE_sso (double real or oword)\n"));
+ break;
+
+ default:
+ assert(0);
+ return NULL;
+ }
+
+ switch (AddressMode)
+ {
+ ////////////////////////////////////////////////////////////
+ // Special types
+ ////////////////////////////////////////////////////////////
+
+ case AMODE_xlat: // DS:[EBX+AL]
+ if (!Decode) continue;
+ assert(Operand->Length == 1);
+ Operand->Flags |= OP_ADDRESS | OP_REG;
+ Operand->Type = OPTYPE_STRING;
+
+ switch (X86Instruction->AddressSize)
+ {
+ case 8: Operand->Register = AMD64_REG_RBX; break;
+ case 4: Operand->Register = X86_REG_EBX; break;
+ case 2: Operand->Register = X86_REG_BX; break;
+ default: assert(0); return NULL;
+ }
+ X86_SET_ADDR();
+ X86Instruction->Scale = 1;
+ X86Instruction->BaseRegister = Operand->Register;
+ X86Instruction->HasBaseRegister = TRUE;
+ X86Instruction->IndexRegister = X86_REG_AL;
+ X86Instruction->HasIndexRegister = TRUE;
+
+ //DISASM_OUTPUT(("[SetOperand] AMODE_xlat (DS:[EBX+AL])\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]",
+ Segments[X86Instruction->Segment], X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ ////////////////////////////////////////////////////////////
+ // Without mod R/M byte
+ ////////////////////////////////////////////////////////////
+
+ case AMODE_I: // immediate value
+ if (Decode)
+ {
+ Operand->Type = OPTYPE_IMM;
+ switch (Operand->Length)
+ {
+ case 8:
+ if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S64 *)Address);
+ else Operand->Value_U64 = (U64)*((U64 *)Address);
+ break;
+ case 4:
+ if (!(OperandFlags & OP_SIGNED) && OperandIndex == 1 &&
+ (Instruction->Operands[0].Flags & (OP_REG|OP_ADDRESS)) &&
+ Instruction->Operands[0].Length == 8)
+ {
+ // For some opcodes the second operand is a sign-extended imm32 value
+ assert(X86Instruction->OperandSize == 8);
+ switch (Instruction->Type)
+ {
+ case ITYPE_AND:
+ case ITYPE_ADD:
+ case ITYPE_XCHGADD:
+ case ITYPE_CMP:
+ case ITYPE_MOV:
+ case ITYPE_SUB:
+ case ITYPE_TEST:
+ case ITYPE_OR:
+ case ITYPE_XOR:
+ assert(OperandIndex == 1);
+ Operand->Value_S64 = (S64)*((S32 *)Address);
+ break;
+ default:
+ assert(0);
+ if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S32 *)Address);
+ else Operand->Value_U64 = (U64)*((U32 *)Address);
+ break;
+ }
+ }
+ else
+ {
+ if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S32 *)Address);
+ else Operand->Value_U64 = (U64)*((U32 *)Address);
+ }
+ break;
+ case 2:
+ if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S16 *)Address);
+ else Operand->Value_U64 = (U64)*((U16 *)Address);
+ break;
+ case 1:
+ if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S8 *)Address);
+ else Operand->Value_U64 = (U64)*((U8 *)Address);
+ break;
+ default:
+ assert(0);
+ return NULL;
+ }
+ }
+ INSTR_INC(Operand->Length); // increment Instruction->Length and address
+ assert(X86Instruction->OperandSize >= Operand->Length);
+ if (Instruction->Type == ITYPE_PUSH) Operand->Length = X86Instruction->OperandSize;
+
+ //DISASM_OUTPUT(("[SetOperand] AMODE_I (immediate data)\n"));
+ if (Disassemble)
+ {
+ X86_WRITE_IMMEDIATE();
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case AMODE_J: // IP-relative jump offset
+ SANITY_CHECK_ADDRESS_SIZE();
+ if (Decode)
+ {
+ Operand->Flags |= OP_IPREL | OP_SIGNED | OP_REG | OP_ADDRESS;
+ Operand->Type = OPTYPE_OFFSET;
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: Operand->Register = AMD64_REG_RIP; break;
+ case 4: Operand->Register = X86_REG_EIP; break;
+ case 2: Operand->Register = X86_REG_IP; break;
+ default: assert(0); return NULL;
+ }
+ switch (Operand->Length)
+ {
+ case 8: X86Instruction->Displacement = *((S64 *)Address); break;
+ case 4: X86Instruction->Displacement = (S64)*((S32 *)Address); break;
+ case 2: X86Instruction->Displacement = (S64)*((S16 *)Address); break;
+ case 1: X86Instruction->Displacement = (S64)*((S8 *)Address); break;
+ default: assert(0); return NULL;
+ }
+
+ Operand->Value_S64 = X86Instruction->Displacement;
+ X86Instruction->Relative = TRUE;
+
+ if ((Operand->Flags & OP_COND) && !X86Instruction->Displacement)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Both conditions of branch go to same address\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ }
+
+ INSTR_INC(Operand->Length); // increment Instruction->Length and address
+ if (!Decode) continue;
+
+ assert((Operand->Flags & OP_EXEC) && (Instruction->Groups & ITYPE_EXEC));
+ Operand->TargetAddress = ApplyDisplacement((U64)Address, Instruction);
+ X86Instruction->Relative = TRUE;
+ X86_SET_ADDR();
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ X86Instruction->HasSegmentOverridePrefix = FALSE;
+ X86Instruction->Segment = SEG_CS;
+ X86Instruction->BaseRegister = Operand->Register;
+ X86Instruction->HasBaseRegister = TRUE;
+ assert(Instruction->OperandCount == 1);
+ //DISASM_OUTPUT(("[SetOperand] AMODE_J (branch with relative offset)\n"));
+ if (Disassemble)
+ {
+ X86_WRITE_IP_OFFSET(Operand);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case AMODE_O: // word/dword offset
+ Operand->Type = OPTYPE_OFFSET;
+ Operand->Flags |= OP_ADDRESS;
+ SANITY_CHECK_OPERAND_SIZE();
+ switch (X86Instruction->AddressSize)
+ {
+ case 8:
+ if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = *((S64 *)Address);
+ else X86Instruction->Displacement = (S64)*((U64 *)Address);
+ break;
+ case 4:
+ if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = (S64)*((S32 *)Address);
+ else X86Instruction->Displacement = (S64)*((U32 *)Address);
+ break;
+ case 2:
+ if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = (S64)*((S16 *)Address);
+ else X86Instruction->Displacement = (S64)*((U16 *)Address);
+ break;
+ default:
+ assert(0);
+ return FALSE;
+ }
+
+ INSTR_INC(X86Instruction->AddressSize); // increment Instruction->Length and address
+ if (!Decode) continue;
+
+ X86Instruction->HasFullDisplacement = TRUE;
+ X86_SET_ADDR();
+ X86_SET_TARGET();
+ assert(X86Instruction->Segment == SEG_DS || X86Instruction->HasSegmentOverridePrefix);
+ //DISASM_OUTPUT(("[SetOperand] AMODE_O (offset)\n"));
+ if (Disassemble)
+ {
+ X86_WRITE_OFFSET(Operand);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case AMODE_A: // absolute address
+ Operand->Flags |= OP_ADDRESS | OP_FAR;
+ SANITY_CHECK_ADDRESS_SIZE();
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ X86Instruction->HasSelector = TRUE;
+ X86Instruction->HasSegmentOverridePrefix = FALSE;
+ switch (Operand->Length)
+ {
+ case 6:
+ X86Instruction->Segment = *((U16 *)Address); INSTR_INC(2);
+ X86Instruction->Displacement = (S64)*((S32 *)Address); INSTR_INC(4);
+ break;
+ case 4:
+ X86Instruction->Segment = *((U16 *)Address); INSTR_INC(2);
+ X86Instruction->Displacement = (S64)*((S16 *)Address); INSTR_INC(2);
+ break;
+ default:
+ assert(0);
+ return FALSE;
+ }
+ if (!Decode) continue;
+ X86Instruction->HasFullDisplacement = TRUE;
+ X86_SET_ADDR();
+ X86_SET_TARGET();
+ //DISASM_OUTPUT(("[SetOperand] AMODE_A (absolute address)\n"));
+ if (Disassemble)
+ {
+ X86_WRITE_OFFSET(Operand);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case AMODE_X: // DS:[ESI]
+ if (!Decode) continue;
+ Operand->Flags |= OP_ADDRESS | OP_REG;
+ Operand->Type = OPTYPE_STRING;
+ switch (X86Instruction->AddressSize)
+ {
+ case 8: Operand->Register = AMD64_REG_RSI; break;
+ case 4: Operand->Register = X86_REG_ESI; break;
+ case 2: Operand->Register = X86_REG_SI; break;
+ default: assert(0); return NULL;
+ }
+
+ X86Instruction->BaseRegister = Operand->Register;
+ X86Instruction->HasBaseRegister = TRUE;
+ X86_SET_ADDR();
+ if (!X86Instruction->HasSegmentOverridePrefix) X86Instruction->Segment = SEG_DS;
+
+ //DISASM_OUTPUT(("[SetOperand] AMODE_X (addressing via DS:[ESI])\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]",
+ Segments[X86Instruction->Segment], X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case AMODE_Y: // ES:[EDI]
+ if (!Decode) continue;
+ Operand->Flags |= OP_ADDRESS | OP_REG;
+ Operand->Type = OPTYPE_STRING;
+ switch (X86Instruction->AddressSize)
+ {
+ case 8: Operand->Register = AMD64_REG_RDI; break;
+ case 4: Operand->Register = X86_REG_EDI; break;
+ case 2: Operand->Register = X86_REG_DI; break;
+ default: assert(0); return NULL;
+ }
+
+ X86Instruction->BaseRegister = Operand->Register;
+ X86Instruction->HasBaseRegister = TRUE;
+ X86_SET_ADDR();
+ if (X86Instruction->HasSegmentOverridePrefix)
+ {
+ if (!Instruction->AnomalyOccurred)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: segment override used with AMODE_Y\n", VIRTUAL_ADDRESS);
+ Instruction->AnomalyOccurred = TRUE;
+ }
+ Segment = X86Instruction->DstSegment = SEG_ES;
+ X86Instruction->HasDstSegment = TRUE;
+ }
+ else
+ {
+ Segment = X86Instruction->Segment = SEG_ES;
+ }
+
+ //DISASM_OUTPUT(("[SetOperand] AMODE_Y (addressing via ES:[EDI])\n"));
+ if (Disassemble)
+ {
+ APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]",
+ Segments[Segment], X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ ////////////////////////////////////////////////////////////
+ // Mod R/M byte with only registers
+ // Handle that case here since it is straightforward
+ ////////////////////////////////////////////////////////////
+
+ case AMODE_PR: // modrm.rm = mmx register and modrm.mod = 11
+ assert(X86Instruction->HasModRM);
+ if (modrm.mod != 3)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_PR (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ else if (rex_modrm.rm > 7)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_PR (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ else if (X86Instruction->OperandSize == 2)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_PR illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ if (!Decode) continue;
+
+ Operand->Flags |= OP_REG;
+ Operand->Register = X86_MMX_OFFSET + rex_modrm.rm;
+ X86_SET_REG(0);
+
+ if (Disassemble)
+ {
+ assert(X86_Registers[Operand->Register]);
+ APPENDS(X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] AMODE_PR (MMX register)\n"));
+ continue;
+
+ case AMODE_VR: // modrm.rm = xmm register and modrm.mod = 11
+ assert(X86Instruction->HasModRM);
+ if (modrm.mod != 3)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_VR (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ else if (X86Instruction->OperandSize == 2)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_VR illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ if (!Decode) continue;
+
+ Operand->Flags |= OP_REG;
+ Operand->Register = X86_XMM_OFFSET + rex_modrm.rm;
+ X86_SET_REG(0);
+
+ if (Disassemble)
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] AMODE_VR (XMM register)\n"));
+ continue;
+
+ case AMODE_P: // modrm.reg = mmx register
+ assert(X86Instruction->HasModRM);
+ if (rex_modrm.reg > 7)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_P (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.reg, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ else if (X86Instruction->OperandSize == 2)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_P illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ if (!Decode) continue;
+
+ Operand->Flags |= OP_REG;
+ Operand->Register = X86_MMX_OFFSET + rex_modrm.reg;
+ X86_SET_REG(0);
+
+ if (Disassemble)
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] AMODE_P (MMX register)\n"));
+ continue;
+
+ case AMODE_V: // modrm.reg = xmm register
+ assert(X86Instruction->HasModRM);
+ if (X86Instruction->OperandSize == 2)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_P illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ if (!Decode) continue;
+
+ Operand->Flags |= OP_REG;
+ Operand->Register = X86_XMM_OFFSET + rex_modrm.reg; break;
+ X86_SET_REG(0);
+
+ if (Disassemble)
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] AMODE_V (XMM register)\n"));
+ continue;
+
+ case AMODE_R: // modrm.rm is general register and modrm.mod = 11
+ assert(X86Instruction->HasModRM);
+ if (modrm.mod != 3)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_R (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ if (!Decode) continue;
+ Operand->Flags |= OP_REG;
+ switch (Operand->Length)
+ {
+ case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break;
+ case 4: Operand->Register = X86_32BIT_OFFSET, rex_modrm.rm; CHECK_AMD64_REG(); break;
+ case 2: Operand->Register = X86_16BIT_OFFSET, rex_modrm.rm; CHECK_AMD64_REG(); break;
+ case 1: Operand->Register = X86_8BIT_OFFSET, rex_modrm.rm; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break;
+ default: assert(0); return NULL;
+ }
+ X86_SET_REG(rex_modrm.rm);
+ if (Disassemble)
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] AMODE_R (general register)\n"));
+ continue;
+
+ case AMODE_G: // modrm.reg = general register
+ assert(X86Instruction->HasModRM);
+ if (!Decode) continue;
+ Operand->Flags |= OP_REG;
+ switch (Operand->Length)
+ {
+ case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.reg; break;
+ case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.reg; CHECK_AMD64_REG(); break;
+ case 2: Operand->Register = X86_16BIT_OFFSET + rex_modrm.reg; CHECK_AMD64_REG(); break;
+ case 1: Operand->Register = X86_8BIT_OFFSET + rex_modrm.reg; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break;
+ default: assert(0); return NULL;
+ }
+ X86_SET_REG(rex_modrm.reg);
+ if (Disassemble)
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] AMODE_G (general register)\n"));
+ continue;
+
+ case AMODE_S: // modrm.reg = segment register
+ assert(X86Instruction->HasModRM);
+ if (!Decode) continue;
+ Operand->Flags |= OP_REG;
+ switch (X86Instruction->OperandSize)
+ {
+ case 8:
+ case 4:
+ case 2:
+ if (rex_modrm.reg <= 5) Operand->Register = X86_SEGMENT_OFFSET + rex_modrm.reg;
+ break;
+ default:
+ assert(0);
+ return NULL;
+ }
+
+ X86_SET_REG(0);
+ if (Disassemble)
+ {
+ if (rex_modrm.reg > 5) APPEND(OPCSTR, SIZE_LEFT, "seg_%02X", rex_modrm.reg);
+ else APPENDS(X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] AMODE_S (segment register)\n"));
+ continue;
+
+ case AMODE_T: // modrm.reg = test register
+ assert(X86Instruction->HasModRM);
+ if (!Decode) continue;
+ Instruction->Groups |= ITYPE_SYSTEM;
+ Instruction->NeedsEmulation = TRUE;
+ Operand->Flags |= OP_REG;
+ switch (X86Instruction->OperandSize)
+ {
+ case 8:
+ case 4:
+ case 2:
+ Operand->Register = X86_TEST_OFFSET + rex_modrm.reg;
+ break;
+ default:
+ assert(0);
+ return NULL;
+ }
+
+ X86_SET_REG(0);
+ if (Disassemble)
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] AMODE_T (test register)\n"));
+ continue;
+
+ case AMODE_C: // modrm.reg = control register
+ assert(X86Instruction->HasModRM);
+ assert(Instruction->Type == ITYPE_MOV);
+ if (!Decode) continue;
+ Instruction->Groups |= ITYPE_SYSTEM;
+ Instruction->NeedsEmulation = TRUE;
+ Operand->Flags |= OP_REG;
+ if (IS_AMD64()) X86Instruction->OperandSize = 8;
+ switch (X86Instruction->OperandSize)
+ {
+ case 8:
+ case 4:
+ case 2:
+ Operand->Register = X86_CONTROL_OFFSET + rex_modrm.reg;
+ break;
+ default:
+ assert(0);
+ return NULL;
+ }
+
+ X86_SET_REG(0);
+ if (Disassemble)
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] AMODE_C (control register)\n"));
+ continue;
+
+ case AMODE_D: // modrm.reg = debug register
+ assert(X86Instruction->HasModRM);
+ assert(Instruction->Type == ITYPE_MOV);
+ if (!Decode) continue;
+ Instruction->NeedsEmulation = TRUE;
+ Operand->Flags |= OP_REG;
+ Instruction->Groups |= ITYPE_SYSTEM;
+ Instruction->NeedsEmulation = TRUE;
+ if (IS_AMD64()) X86Instruction->OperandSize = 8;
+ switch (X86Instruction->OperandSize)
+ {
+ case 8:
+ case 4:
+ case 2:
+ Operand->Register = X86_DEBUG_OFFSET + rex_modrm.reg;
+ break;
+ default:
+ assert(0);
+ return NULL;
+ }
+
+ X86_SET_REG(0);
+ if (Disassemble)
+ {
+ APPENDS(X86_Registers[Operand->Register]);
+ X86_WRITE_OPFLAGS();
+ }
+ //DISASM_OUTPUT(("[SetOperand] AMODE_D (debug register)\n"));
+ continue;
+
+ ////////////////////////////////////////////////////////////
+ // Mod R/M byte with memory or register
+ ////////////////////////////////////////////////////////////
+
+ case AMODE_M: // memory only
+ assert(X86Instruction->HasModRM);
+ if (modrm.mod == 3)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod = 3 for AMODE_M (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ assert(X86Instruction->Segment == SEG_DS || X86Instruction->HasSegmentOverridePrefix);
+ //DISASM_OUTPUT(("[SetOperand] AMODE_M (memory only)\n"));
+ Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors);
+ if (!Address) return NULL;
+ break;
+
+ case AMODE_E: // general register or memory
+ assert(X86Instruction->HasModRM);
+ if (OperandType == OPTYPE_p && modrm.mod == 3)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod = 3 for AMODE_E with OPTYPE_p (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+
+ //DISASM_OUTPUT(("[SetOperand] AMODE_E (general register or memory)\n"));
+ Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors);
+ if (!Address) return NULL;
+ if (Decode && (Instruction->Type == ITYPE_PUSH || Instruction->Type == ITYPE_POP))
+ {
+ assert(X86Instruction->OperandSize >= Operand->Length);
+ Operand->Length = X86Instruction->OperandSize;
+ }
+ break;
+
+ case AMODE_Q: // mmx register or memory address
+ assert(X86Instruction->HasModRM);
+ //DISASM_OUTPUT(("[SetOperand] AMODE_Q (MMX register or memory address)\n"));
+ if (modrm.mod == 3) // it is a register
+ {
+ if (rex_modrm.rm > 7)
+ {
+ if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_P (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic);
+ goto abort;
+ }
+ Operand->Register = X86_MMX_OFFSET + rex_modrm.rm;
+ Operand->Flags |= OP_REG;
+ X86_SET_REG(0);
+ }
+ else
+ {
+ Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors);
+ if (!Address) return NULL;
+ }
+ break;
+
+ case AMODE_W: // xmm register or memory address
+ assert(X86Instruction->HasModRM);
+ //DISASM_OUTPUT(("[SetOperand] AMODE_W (XMM register or memory address)\n"));
+ if (modrm.mod == 3) // it is a register
+ {
+ Operand->Register = X86_XMM_OFFSET + rex_modrm.rm;
+ Operand->Flags |= OP_REG;
+ X86_SET_REG(0);
+ }
+ else
+ {
+ Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors);
+ if (!Address) return NULL;
+ }
+ break;
+
+ default:
+ assert(0);
+ return NULL;
+ }
+
+ if (!Decode) continue;
+
+ // If this is reached then SetModRM32 was called
+ if ((Operand->Flags & OP_ADDRESS))
+ {
+ assert(Operand->Length);
+ switch (Operand->Register)
+ {
+ case X86_REG_BP:
+ case X86_REG_EBP:
+ case AMD64_REG_RBP:
+ if (X86Instruction->Displacement > 0) Operand->Flags |= OP_PARAM;
+ else Operand->Flags |= OP_LOCAL;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (Disassemble)
+ {
+ Index = OperandType >> OPTYPE_SHIFT;
+ assert(Index > 0 && Index < MAX_OPTYPE_INDEX && OptypeHandlers[Index]);
+ OptypeHandlers[Index](Instruction, Operand, OperandIndex);
+ X86_WRITE_OPFLAGS();
+ }
+ }
+
+ return Address;
+
+abort:
+ if (!SuppressErrors)
+ {
+#ifdef TEST_DISASM
+ printf("Dump of 0x%04I64X:\n", VIRTUAL_ADDRESS);
+ __try { DumpAsBytes(stdout, Instruction->Address, (ULONG_PTR)VIRTUAL_ADDRESS, 16, TRUE); }
+ __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {}
+#endif
+ fflush(stdout);
+ }
+ return NULL;
+}
+
+// NOTE: Address points one byte after ModRM
+INTERNAL U8 *SetModRM16(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors)
+{
+ MODRM modrm;
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+
+ DISASM_OUTPUT(("[SetModRM16] Current instruction length = %d\n", Instruction->Length));
+ modrm = X86Instruction->modrm;
+ assert(!X86Instruction->rex_b);
+
+ //
+ // Both operands are registers
+ // Condition: mod = 3
+ //
+ if (modrm.mod == 3)
+ {
+ //DISASM_OUTPUT(("[SetModRM16] Both regs (rm_reg %d)\n", modrm.rm));
+ switch (Operand->Length)
+ {
+ case 4: Operand->Register = X86_32BIT_OFFSET + modrm.rm; break;
+ case 2: Operand->Register = X86_16BIT_OFFSET + modrm.rm; break;
+ case 1: Operand->Register = X86_8BIT_OFFSET + modrm.rm; break;
+ default: assert(0); return NULL;
+ }
+ Operand->Flags |= OP_REG;
+ }
+
+ //
+ // Address is an absolute address (technically a 16-bit offset from DS:0)
+ // Condition: mod = 0 and rm = 6
+ //
+ else if (modrm.mod == 0 && modrm.rm == 6)
+ {
+ //DISASM_OUTPUT(("[SetModRM16] Absolute addressing (displacement 0x%04X)\n", *(S16 *)Address));
+ X86Instruction->Displacement = (S64)(*((S16 *)Address));
+ if (IS_VALID_ADDRESS(X86Instruction->Displacement))
+ {
+ X86Instruction->HasFullDisplacement = TRUE;
+ X86_SET_TARGET();
+ Operand->Flags |= OP_GLOBAL;
+ }
+ X86_SET_ADDR();
+ Operand->Flags |= OP_ADDRESS;
+ INSTR_INC(2);
+ }
+
+ // Conditions:
+ // (1) mod = 0 and rm != 6
+ // (2) mod = 1-2 and rm = 0-7
+ else
+ {
+ switch (modrm.mod)
+ {
+ case 0: // no displacement
+ //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (no displacement)\n"));
+ break;
+ case 1: // 8-bit signed displacement
+ //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (displacement = 0x%02X, reg_rm = %d)\n", *(S8 *)Address, modrm.rm));
+ X86Instruction->Displacement = (S64)(*((S8 *)Address));
+ INSTR_INC(1); // increment Instruction->Length and address
+ break;
+ case 2: // 16-bit displacement
+ //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (displacement = 0x%04X, reg_rm = %d)\n", *(S16 *)Address, modrm.rm));
+ X86Instruction->Displacement = (S64)(*((S16 *)Address));
+ if (IS_VALID_ADDRESS(X86Instruction->Displacement))
+ {
+ Operand->Flags |= OP_GLOBAL;
+ X86Instruction->HasFullDisplacement = TRUE;
+ }
+ INSTR_INC(2);
+ break;
+ }
+
+ switch (modrm.rm)
+ {
+ case 0:
+ //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX+SI]\n"));
+ X86Instruction->BaseRegister = X86_REG_BX;
+ X86Instruction->IndexRegister = X86_REG_SI;
+ X86Instruction->HasIndexRegister = TRUE;
+ break;
+ case 1:
+ //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX+DI]\n"));
+ X86Instruction->BaseRegister = X86_REG_BX;
+ X86Instruction->IndexRegister = X86_REG_DI;
+ X86Instruction->HasIndexRegister = TRUE;
+ break;
+ case 2:
+ //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP+SI]\n"));
+ X86Instruction->BaseRegister = X86_REG_BP;
+ X86Instruction->IndexRegister = X86_REG_SI;
+ X86Instruction->HasIndexRegister = TRUE;
+ X86_SET_SEG(REG_BP);
+ break;
+ case 3:
+ //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP+DI]\n"));
+ X86Instruction->BaseRegister = X86_REG_BP;
+ X86Instruction->IndexRegister = X86_REG_DI;
+ X86Instruction->HasIndexRegister = TRUE;
+ X86_SET_SEG(REG_BP);
+ break;
+ case 4:
+ //DISASM_OUTPUT(("[SetModRM16] Addressing mode [SI]\n"));
+ X86Instruction->BaseRegister = X86_REG_SI;
+ break;
+ case 5:
+ //DISASM_OUTPUT(("[SetModRM16] Addressing mode [DI]\n"));
+ X86Instruction->BaseRegister = X86_REG_DI;
+ break;
+ case 6:
+ //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP]\n"));
+ X86Instruction->BaseRegister = X86_REG_BP;
+ break;
+ case 7:
+ //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX]\n"));
+ X86Instruction->BaseRegister = X86_REG_BX;
+ break;
+ }
+
+ X86Instruction->HasBaseRegister = TRUE;
+ Operand->Flags |= OP_ADDRESS | OP_REG;
+ X86_SET_ADDR();
+ }
+
+ return Address;
+}
+
+// NOTE: Address points one byte after ModRM
+INTERNAL U8 *SetModRM32(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors)
+{
+ MODRM modrm;
+ REX_MODRM rex_modrm;
+ U32 i, ImmediateSize = 0;
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+
+ if (X86Instruction->AddressSize == 2)
+ {
+ return SetModRM16(Instruction, Address, Operand, OperandIndex, SuppressErrors);
+ }
+
+ //DISASM_OUTPUT(("[SetModRM32] Length %d, modrm = 0x%02X\n", Instruction->Length, X86Instruction->modrm_b));
+ modrm = X86Instruction->modrm;
+ rex_modrm = X86Instruction->rex_modrm;
+
+ //
+ // Both operands are registers
+ // Condition: mod = 3
+ //
+ if (modrm.mod == 3)
+ {
+ switch (Operand->Length)
+ {
+ case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break;
+ case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break;
+ case 2: Operand->Register = X86_16BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break;
+ case 1: Operand->Register = X86_8BIT_OFFSET + rex_modrm.rm; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break;
+ default: assert(0); return NULL;
+ }
+ X86_SET_REG(rex_modrm.rm);
+ Operand->Flags |= OP_REG;
+ }
+
+ //
+ // Address is an absolute address (technically a 32-bit offset from DS:0)
+ // mod = 0 and rm = 5
+ //
+ else if (modrm.mod == 0 && modrm.rm == 5)
+ {
+ //DISASM_OUTPUT(("[SetModRM32] Absolute addressing (displacement 0x%08lX)\n", *(S32 *)Address));
+ Operand->Flags |= OP_ADDRESS;
+ X86Instruction->Displacement = (S64)*((S32 *)Address);
+ INSTR_INC(4); // increment Instruction->Length and address
+
+ if (IS_AMD64())
+ {
+ // RIP-relative addressing always replaced Disp32, even when using a 32-bit address space
+ // (via address size override prefix)
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: Operand->Register = AMD64_REG_RIP; break;
+ case 4: Operand->Register = X86_REG_EIP; break;
+ case 2: Operand->Register = X86_REG_IP; break;
+ default: assert(0); return NULL;
+ }
+ X86Instruction->BaseRegister = Operand->Register;
+ X86Instruction->HasBaseRegister = TRUE;
+ X86Instruction->Relative = TRUE;
+ Operand->Flags |= OP_IPREL | OP_SIGNED | OP_REG;
+ SANITY_CHECK_SEGMENT_OVERRIDE();
+ if (!X86Instruction->HasSegmentOverridePrefix) X86Instruction->Segment = SEG_CS;
+ X86Instruction->HasFullDisplacement = TRUE;
+
+ // Since there may be an immediate value to follow, it is necessary
+ // to determine the length in order get the proper offset
+ //
+ // Maybe there is a better way to do this, since this is wasteful
+ // (the size of the immediate value will have to be decoded again later
+ // in SetOperands)
+
+ for (ImmediateSize = 0, i = OperandIndex+1; i < Instruction->OperandCount; i++)
+ {
+ if ((X86Instruction->Opcode.OperandFlags[i] & X86_AMODE_MASK) != AMODE_I) continue;
+ else assert(!ImmediateSize);
+ switch (X86Instruction->Opcode.OperandFlags[i] & X86_OPTYPE_MASK)
+ {
+ case OPTYPE_v:
+ ImmediateSize = X86Instruction->OperandSize;
+ break;
+ case OPTYPE_z:
+ switch (X86Instruction->OperandSize)
+ {
+ case 8: case 4: ImmediateSize = 4; break;
+ case 2: ImmediateSize = 2; break;
+ default: assert(0); return NULL;
+ }
+ break;
+ case OPTYPE_b:
+ ImmediateSize = 1;
+ break;
+ case OPTYPE_w:
+ ImmediateSize = 2;
+ break;
+ case OPTYPE_1:
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+
+ Operand->TargetAddress = ApplyDisplacement((U64)Address + ImmediateSize, Instruction);
+ }
+ else if (IS_VALID_ADDRESS(X86Instruction->Displacement))
+ {
+ X86_SET_TARGET();
+ Operand->Flags |= OP_GLOBAL;
+ X86Instruction->HasFullDisplacement = TRUE;
+ }
+
+ X86_SET_ADDR();
+ }
+
+ //
+ // Addressing mode indicated by SIB byte
+ // Condition: mod = 0-2 and rm = 4
+ //
+ else if (modrm.rm == 4)
+ {
+ // The X86_SET_*() is called from within SetSIB()
+ Address = SetSIB(Instruction, Address, Operand, OperandIndex, SuppressErrors);
+ if (!Address)
+ {
+ assert(0);
+ return NULL;
+ }
+
+ if (X86Instruction->sib.base != 5) // if base == 5, the displacement is handled in SetSIB
+ {
+ switch (modrm.mod)
+ {
+ case 1: // 8-bit displacement
+ //DISASM_OUTPUT(("[SetModRM32] After SIB: displacement 0x%02X\n", *((S8 *)Address)));
+ X86Instruction->Displacement = (S64)(*((S8 *)Address));
+ INSTR_INC(1); // increment Instruction->Length and address
+ break;
+ case 2: // 32-bit displacement
+ //DISASM_OUTPUT(("[SetModRM32] After SIB: displacement 0x%08lX\n", *((S32 *)Address)));
+ X86Instruction->Displacement = (S64)*((S32 *)Address);
+ if (IS_VALID_ADDRESS(X86Instruction->Displacement))
+ {
+ Operand->Flags |= OP_GLOBAL;
+ X86Instruction->HasFullDisplacement = TRUE;
+ }
+ INSTR_INC(4); // increment Instruction->Length and address
+ break;
+ }
+ }
+ }
+
+ // Indirect addressing
+ // Conditions:
+ // (1) mod = 0 and (rm = 0-3 or 6-7)
+ // (2) mod = 1-2 and rm != 4
+ else
+ {
+ switch (X86Instruction->AddressSize)
+ {
+ case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break;
+ case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break;
+ default: assert(0); return NULL;
+ }
+ X86Instruction->BaseRegister = Operand->Register;
+ X86Instruction->HasBaseRegister = TRUE;
+ Operand->Flags |= OP_ADDRESS | OP_REG;
+ X86_SET_SEG(rex_modrm.rm);
+ X86_SET_ADDR();
+
+ switch (modrm.mod)
+ {
+ case 0: // no displacement
+ //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (no displacement, reg_rm = %d)\n", rex_modrm.rm));
+ break;
+ case 1: // 8-bit signed displacement
+ //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (displacement = 0x%02X, reg_rm = %d)\n", *(S8 *)Address, rex_modrm.rm));
+ X86Instruction->Displacement = (S64)(*((S8 *)Address));
+ INSTR_INC(1); // increment Instruction->Length and address
+ break;
+ case 2: // 32-bit displacement
+ //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (displacement = 0x%08lX, reg_rm = %d)\n", *(S32 *)Address, rex_modrm.rm));
+ X86Instruction->Displacement = (S64)*((S32 *)Address);
+ if (IS_VALID_ADDRESS(X86Instruction->Displacement))
+ {
+ Operand->Flags |= OP_GLOBAL;
+ X86Instruction->HasFullDisplacement = TRUE;
+ }
+ INSTR_INC(4); // increment Instruction->Length and address
+ break;
+ }
+ }
+
+ return Address;
+}
+
+// NOTE: Address points at SIB
+INTERNAL U8 *SetSIB(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors)
+{
+ REX rex;
+ SIB sib;
+ REX_SIB rex_sib;
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+
+ X86Instruction->sib_b = *Address;
+ SET_SIB(X86Instruction->sib, *Address);
+ sib = X86Instruction->sib;
+ rex = X86Instruction->rex;
+ SET_REX_SIB(X86Instruction->rex_sib, rex, sib);
+ rex_sib = X86Instruction->rex_sib;
+
+ //if (!X86Instruction->rex_b) DISASM_OUTPUT(("[0x%08I64X] SIB = 0x%02X (scale=%d, index=%d, base=%d)\n", VIRTUAL_ADDRESS, *Address, sib.scale, sib.index, sib.base)); \
+ //else DISASM_OUTPUT(("[0x%08I64X] SIB = 0x%02X (scale=%d, index=%d, base=%d)\n", VIRTUAL_ADDRESS, *Address, sib.scale, rex_sib.index, rex_sib.base)); \
+ //DISASM_OUTPUT(("[SetSIB] Current instruction length = %d\n", Instruction->Length));
+
+ Operand->Flags |= OP_ADDRESS;
+ X86_SET_ADDR();
+ INSTR_INC(1); // increment Instruction->Length and address
+
+ if (sib.base == 5)
+ {
+ switch (X86Instruction->modrm.mod)
+ {
+ case 0:
+ X86Instruction->Displacement = (S64)*((S32 *)Address);
+ if (IS_VALID_ADDRESS(X86Instruction->Displacement))
+ {
+ X86Instruction->HasFullDisplacement = TRUE;
+ X86_SET_TARGET();
+ Operand->Flags |= OP_GLOBAL;
+ }
+ INSTR_INC(4);
+ break;
+ case 1:
+ X86Instruction->Displacement = (S64)(*((S8 *)Address));
+ if (rex_sib.base == 5)
+ {
+ switch (X86Instruction->AddressSize)
+ {
+ case 8: Operand->Register = AMD64_REG_RBP; break;
+ case 4: Operand->Register = X86_REG_EBP; break;
+ default: assert(0); return NULL;
+ }
+ X86_SET_SEG(REG_EBP);
+ }
+ else
+ {
+ Operand->Register = AMD64_REG_R13;
+ }
+
+ X86Instruction->BaseRegister = Operand->Register;
+ X86Instruction->HasBaseRegister = TRUE;
+ Operand->Flags |= OP_REG;
+ INSTR_INC(1);
+ break;
+ case 2:
+ X86Instruction->Displacement = (S64)*((S32 *)Address);
+ if (rex_sib.base == 5)
+ {
+ switch (X86Instruction->AddressSize)
+ {
+ case 8: Operand->Register = AMD64_REG_RBP; break;
+ case 4: Operand->Register = X86_REG_EBP; break;
+ default: assert(0); return NULL;
+ }
+ X86_SET_SEG(REG_EBP);
+ }
+ else
+ {
+ Operand->Register = AMD64_REG_R13;
+ }
+
+ if (IS_VALID_ADDRESS(X86Instruction->Displacement))
+ {
+ Operand->Flags |= OP_GLOBAL;
+ X86Instruction->HasFullDisplacement = TRUE;
+ }
+ X86Instruction->BaseRegister = Operand->Register;
+ X86Instruction->HasBaseRegister = TRUE;
+ Operand->Flags |= OP_REG;
+ INSTR_INC(4);
+ break;
+ }
+ }
+ else
+ {
+ switch (X86Instruction->AddressSize)
+ {
+ case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_sib.base; break;
+ case 4: Operand->Register = X86_32BIT_OFFSET + rex_sib.base; CHECK_AMD64_REG(); break;
+ default: assert(0); return NULL;
+ }
+ X86Instruction->BaseRegister = Operand->Register;
+ X86Instruction->HasBaseRegister = TRUE;
+ X86_SET_SEG(rex_sib.base);
+ Operand->Flags |= OP_REG;
+ }
+
+ if (rex_sib.index != 4)
+ {
+ switch (X86Instruction->AddressSize)
+ {
+ case 8:
+ X86Instruction->IndexRegister = AMD64_64BIT_OFFSET + rex_sib.index;
+ break;
+ case 4:
+ X86Instruction->IndexRegister = X86_32BIT_OFFSET + rex_sib.index;
+ break;
+ default:
+ fflush(stdout);
+ assert(0);
+ return NULL;
+ }
+
+ Operand->TargetAddress = 0;
+ X86Instruction->HasIndexRegister = TRUE;
+ //DISASM_OUTPUT(("[SetSIB] Index register = %s\n", X86_Registers[X86_32BIT_OFFSET + rex_sib.index]));
+
+ switch (sib.scale)
+ {
+ case 0: X86Instruction->Scale = 1; break;
+ case 1: X86Instruction->Scale = 2; break;
+ case 2: X86Instruction->Scale = 4; break;
+ case 3: X86Instruction->Scale = 8; break;
+ }
+ //DISASM_OUTPUT(("[SetSIB] Scale = %d\n", X86Instruction->Scale));
+ }
+
+ return Address;
+}
+
+INTERNAL U64 ApplyDisplacement(U64 Address, INSTRUCTION *Instruction)
+{
+ X86_INSTRUCTION *X86Instruction = &Instruction->X86;
+
+#ifdef SUPPORT_WRAPAROUND
+ U64 VirtualAddress = Address + Instruction->VirtualAddressDelta;
+ switch (X86Instruction->OperandSize)
+ {
+ case 8:
+ {
+ U64 PreAddr = VirtualAddress;
+ U64 PostAddr = PreAddr + X86Instruction->Displacement;
+ return Address + (PostAddr - PreAddr);
+ }
+ case 4:
+ {
+ // We have to do this carefully...
+ // If EIP = FFFFF000 and Displacement=2000 then the final IP should be 1000
+ // due to wraparound
+ U32 PreAddr = (U32)VirtualAddress;
+ U32 PostAddr = PreAddr + (S32)X86Instruction->Displacement;
+ return Address + (PostAddr - PreAddr);
+ }
+ case 2:
+ {
+ // We have to do this carefully...
+ // If IP = F000 and Displacement=2000 then the final IP should be 1000
+ // due to wraparound
+ U16 PreAddr = (U16)VirtualAddress;
+ U16 PostAddr = PreAddr + (S16)X86Instruction->Displacement;
+ return Address + (PostAddr - PreAddr);
+ }
+ default:
+ assert(0);
+ return 0;
+ }
+#else
+ return (Address + X86Instruction->Displacement);
+#endif
+}
+
+
+
+INTERNAL BOOL IsValidLockPrefix(X86_INSTRUCTION *X86Instruction, U8 Opcode, U32 OpcodeLength, U8 Group, U8 OpcodeExtension)
+{
+ switch (OpcodeLength)
+ {
+ case 1:
+ switch (X86_LockPrefix_1[Opcode])
+ {
+ case 0: // instruction can't be locked
+ return FALSE;
+ case 1: // instruction can be locked
+ break;
+ case GR:
+ assert(Group);
+ if (!X86_LockPrefix_Groups[Group-1][OpcodeExtension]) return FALSE;
+ break;
+ default:
+ assert(0);
+ return FALSE;
+ }
+ break;
+
+ case 2:
+ case 3:
+ switch (X86_LockPrefix_2[Opcode])
+ {
+ case 0: // lock prefix is not acceptable
+ return FALSE;
+ case 1: // lock prefix allowed
+ break;
+ case GR:
+ assert(Group);
+ if (!X86_LockPrefix_Groups[Group-1][OpcodeExtension]) return FALSE;
+ break;
+ default:
+ assert(0);
+ return FALSE;
+ }
+ break;
+
+ default:
+ assert(0);
+ return FALSE;
+ }
+
+ if (!X86Instruction->HasModRM || X86Instruction->modrm.mod == 3 || !X86Instruction->HasDstAddressing)
+ {
+ DISASM_OUTPUT(("[0x%08I64X] ERROR: Instruction \"%s\" with LOCK prefix has invalid ModRM addressing\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic, X86Instruction->Instruction->Address));
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/thirdparty/mhook/disasm-lib/disasm_x86.h b/thirdparty/mhook/disasm-lib/disasm_x86.h
new file mode 100644
index 00000000..e64a11f2
--- /dev/null
+++ b/thirdparty/mhook/disasm-lib/disasm_x86.h
@@ -0,0 +1,837 @@
+// Copyright (C) 2004, Matt Conover (mconover@gmail.com)
+#ifndef X86_DISASM_H
+#define X86_DISASM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// NOTE: the processor may actually accept less than this amount (officially 15)
+// #define AMD64_MAX_INSTRUCTION_LEN 15 // theoretical max 25=5+2+1+1+8+8
+#define AMD64_MAX_PREFIX_LENGTH 5 // 4 legacy + 1 rex
+#define AMD64_MAX_ADDRESS_LENGTH 18 // modrm + sib + 8 byte displacement + 8 byte immediate value
+
+// NOTE: the processor may actually accept less than this amount (officially 15)
+#define X86_MAX_INSTRUCTION_LEN 15 // theoretical 16=4+2+1+1+4+4
+#define X86_MAX_PREFIX_LENGTH 4
+#define X86_MAX_OPCODE_LENGTH 3 // third byte is either a suffix or prefix
+#define X86_MAX_ADDRESS_LENGTH 10 // modrm + sib + 4 byte displacement + 4 byte immediate value
+#define X86_MAX_OPERANDS 3
+
+#define X86_PREFIX(a) ((a)->MnemonicFlags == ITYPE_EXT_PREFIX)
+#define X86_SPECIAL_EXTENSION(a) ((a)->MnemonicFlags & (ITYPE_EXT_MODRM|ITYPE_EXT_FPU|ITYPE_EXT_SUFFIX|ITYPE_EXT_64))
+#define X86_EXTENDED_OPCODE(a) ((a)->Table)
+#define X86_INVALID(a) (!(a)->MnemonicFlags && !(a)->Table)
+#define X86_OPERAND_COUNT(a) ((a)->OperandFlags[0] ? ((a)->OperandFlags[1] ? ((a)->OperandFlags[2] ? 3 : 2) : 1) : 0)
+#define X86_GET_CATEGORY(p) ((p)->MnemonicFlags & ITYPE_GROUP_MASK)
+#define X86_GET_TYPE(p) ((p)->MnemonicFlags & ITYPE_TYPE_MASK)
+
+// Various instructions being specially decoded
+#define X86_TWO_BYTE_OPCODE 0x0f
+#define PREFIX_SEGMENT_OVERRIDE_ES 0x26
+#define PREFIX_SEGMENT_OVERRIDE_CS 0x2e
+#define PREFIX_BRANCH_NOT_TAKEN 0x2e // used only with conditional jumps
+#define PREFIX_SEGMENT_OVERRIDE_SS 0x36
+#define PREFIX_SEGMENT_OVERRIDE_DS 0x3e
+#define PREFIX_BRANCH_TAKEN 0x3e // used only with conditional jumps
+#define PREFIX_SEGMENT_OVERRIDE_FS 0x64
+#define PREFIX_SEGMENT_OVERRIDE_GS 0x65
+#define PREFIX_OPERAND_SIZE 0x66
+#define PREFIX_ADDRESS_SIZE 0x67
+#define PREFIX_LOCK 0xf0
+#define PREFIX_REPNE 0xf2
+#define PREFIX_REP 0xf3
+
+//////////////////////////////////////////////////////////////////
+// Implicit operand handling
+//////////////////////////////////////////////////////////////////
+
+#define X86_AMODE_MASK 0x00FF0000 // bits 16-23 (AMODE_*)
+#define X86_OPFLAGS_MASK 0x0000FF80 // bits 7-15 (OPTYPE_*)
+#define X86_OPTYPE_MASK 0xFF0000FF // bits 0-7 (OPTYPE_* below + OP_REG) and 24-31 (OPTYPE_* above)
+
+#define OPTYPE_0 0x01
+#define OPTYPE_1 0x02
+#define OPTYPE_FF 0x03
+//...
+#define OPTYPE_CS 0x10
+#define OPTYPE_DS 0x11
+#define OPTYPE_ES 0x12
+#define OPTYPE_FS 0x13
+#define OPTYPE_GS 0x14
+#define OPTYPE_SS 0x15
+#define OPTYPE_CR0 0x16
+#define OPTYPE_TSC 0x17 // time stamp counter
+//...
+#define OPTYPE_FLAGS 0x20
+#define OPTYPE_xFLAGS 0x21 // RFLAGS/EFLAGS (depending on operand size)
+#define OPTYPE_xCX_HI_xBX_LO 0x22 // represented by 2 registers CX:BX or ECX:EBX (depending on operand size)
+#define OPTYPE_xDX_HI_xAX_LO 0x23 // DX:AX or EDX:EAX (depending on operand size)
+#define OPTYPE_EDX_HI_EAX_LO 0x24 // DX:AX or EDX:EAX (depending on operand size)
+#define OPTYPE_EDX_ECX_EBX_EAX 0x25 // all registers are set
+//...
+#define OPTYPE_STx 0x30
+#define OPTYPE_ST0 0x31
+#define OPTYPE_ST1 0x32
+#define OPTYPE_FPU_STATUS 0x33
+#define OPTYPE_FPU_CONTROL 0x34
+#define OPTYPE_FPU_TAG 0x35
+#define OPTYPE_FLDZ 0x36 // 0
+#define OPTYPE_FLD1 0x37 // 1
+#define OPTYPE_FLDPI 0x38 // pi
+#define OPTYPE_FLDL2T 0x39 // lg 10
+#define OPTYPE_FLDL2E 0x3A // lg e
+#define OPTYPE_FLDLG2 0x3B // log_10 2
+#define OPTYPE_FLDLN2 0x3C // log_e 2
+//...
+#define OPTYPE_CS_MSR 0x40
+#define OPTYPE_EIP_MSR 0x41
+#define OPTYPE_ESP_MSR 0x42
+#define OPTYPE_KERNELBASE_MSR 0x43
+#define OPTYPE_FMASK_MSR 0x44
+#define OPTYPE_STAR_MSR 0x45
+#define OPTYPE_CSTAR_MSR 0x46 // 32-bit mode
+#define OPTYPE_LSTAR_MSR 0x47 // 64-bit mode
+
+
+// NOTE: OPTYPES >= 0x80 reserved for registers (OP_REG+XX)
+#define OPTYPE_REG_AL OP_REG+0x01
+#define OPTYPE_REG_CL OP_REG+0x02
+#define OPTYPE_REG_AH OP_REG+0x03
+#define OPTYPE_REG_AX OP_REG+0x04
+#define OPTYPE_REG_DX OP_REG+0x05
+#define OPTYPE_REG_ECX OP_REG+0x06
+#define OPTYPE_REG8 OP_REG+0x07
+
+// If address size is 2, use BP
+// If address size is 4, use EBP
+// If address size is 8, use RBP
+#define OPTYPE_REG_xBP OP_REG+0x08
+
+// If address size is 2, use BP
+// If address size is 4, use EBP
+// If address size is 8, use RBP
+#define OPTYPE_REG_xSP OP_REG+0x09
+
+// If operand size is 2, take 8-bit register
+// If operand size is 4, take 16-bit register
+// If operand size is 8, take 32-bit register
+#define OPTYPE_REG_xAX_SMALL OP_REG+0x0a
+
+// If operand size is 2, take 16-bit register
+// If operand size is 4, take 32-bit register
+// If operand size is 8, take 64-bit register
+#define OPTYPE_REG_xAX_BIG OP_REG+0x0b
+
+typedef enum _CPU_TYPE
+{
+ CPU_UNKNOWN=0,
+
+ ///////////////////////////////////////
+ // 1st generation
+ ///////////////////////////////////////
+ // 1978
+ //CPU_8086 = 1MB address limit, 16-bit registers
+ // 1982
+ //CPU_i186
+
+ ///////////////////////////////////////
+ // 2nd generation
+ ///////////////////////////////////////
+ // 1982
+ //CPU_I286 // 16MB limit, 16-bit registers, added protected mode
+ CPU_I287, // CPU_I286 + math coprocessor
+
+ ///////////////////////////////////////
+ // 3rd generation
+ ///////////////////////////////////////
+ // 1985
+ CPU_I386, // 32-bit registers, 4GB memory limit
+ // 1988
+ CPU_I387, // CPU_I386 + math coprocessor
+
+ ///////////////////////////////////////
+ // 4th generation (1989)
+ ///////////////////////////////////////
+ CPU_I486,
+
+ ///////////////////////////////////////
+ // 5th generation
+ ///////////////////////////////////////
+ // 1993
+ CPU_PENTIUM, // superscalar architecture
+ // 1997
+ //CPU_PENTIUM_MMX
+
+ ///////////////////////////////////////
+ // 6th generation (1995)
+ ///////////////////////////////////////
+ CPU_PENTIUM_PRO, // P6 architecture, no MMX, out-of-order execution, speculative execution
+ //CPU_CYRIX_6X86,
+ //CPU_AMD_K5 // RISC processor
+ // 1997
+ CPU_PENTIUM2, // Pentium Pro architecture + MMX
+ //CPU_AMD_K6,
+ //CPU_CYRIX_6X86MX, // Cyrix 6x86 + MMX
+ // 1998
+ CPU_AMD_K6_2, // added 3DNow! (MMX)
+ // 1999
+ // CPU_AMD_K6_3 // added SSE
+
+ ///////////////////////////////////////
+ // 7th generation
+ ///////////////////////////////////////
+ // 1999
+ CPU_PENTIUM3, // introduced SSE
+ // CPU_AMD_K7 // aka Athlon
+ // 2000
+ CPU_PENTIUM4, // introduced SSE2 and hyperthreading
+
+ // 2004? 2005?
+ CPU_PRESCOTT, // introduced SSE3
+
+ ///////////////////////////////////////
+ // 8th generation (X86-64)
+ // IA32 instruction set with 64-bit extensions, >4GB RAM
+ ///////////////////////////////////////
+
+ // 2003
+ CPU_AMD64, // includes Athlon 64 and Opteron aka X86-64
+
+ // 2004?
+ //CPU_EMD64 // Intel's version of AMD64
+ CPU_IA64 // aka Itanium: new instruction set -- adds JMPE to IA32 mode to return to IA64 native code
+
+} CPU_TYPE;
+
+//////////////////////////////////////////////////////////////////
+// Conditions (these can be OR'd)
+//////////////////////////////////////////////////////////////////
+
+// Used for Flags.Preconditions
+#define COND_O (1<<0) // overflow (signed)
+#define COND_C (1<<1) // below (unsigned)
+#define COND_Z (1<<2) // equal (unsigned)
+#define COND_S (1<<3) // sign set (signed)
+#define COND_P (1<<4) // parity even
+#define COND_BE (1<<5) // CF or ZF is set (unsigned)
+#define COND_L (1<<6) // (SF && !OF) || (OF && !SF)
+#define COND_LE (1<<7) // ZF || (SF && !OF) || (OF && !SF) (signed)
+#define COND_NO (1<<8) // !O
+#define COND_NC (1<<9) // !C (not below, above or equal to)
+#define COND_NZ (1<<10) // !Z (not equal)
+#define COND_NS (1<<11) // !S
+#define COND_NP (1<<12) // !P (parity odd)
+#define COND_NL (1<<13) // (!SF && !OF) || (SF && OF)
+#define COND_G (1<<14) // !ZF && ((!SF && !OF) || (SF && OF))
+#define COND_D (1<<15) // DF
+#define COND_REG_xCX_BIG_Z (1<<16) // CX/ECX/RCX (depending on address size) == 0
+#define COND_REG_xCX_BIG_NZ (1<<17) // CX/ECX/RCX (depending on address size) != 0
+#define COND_OP1_EQ_OP2 (1<<18)
+#define COND_OP1_EQ_OP3 (1<<19)
+#define COND_B COND_C
+#define COND_NAE COND_C
+#define COND_E COND_Z
+#define COND_NA COND_BE
+#define COND_PE COND_P
+#define COND_U COND_P
+#define COND_NGE COND_L
+#define COND_NG COND_LE
+#define COND_PO COND_NP
+#define COND_NU COND_NP
+#define COND_NE COND_NZ
+#define COND_NB COND_NC
+#define COND_AE COND_NC
+#define COND_NE COND_NZ
+#define COND_A (COND_NC|COND_NZ)
+#define COND_NBE COND_A
+#define COND_GE COND_NL
+#define COND_NLE COND_G
+
+// Used for Opcode.FlagsChanged
+#define FLAG_CF_SET (1<<0)
+#define FLAG_DF_SET (1<<1)
+#define FLAG_IF_SET (1<<2)
+#define FLAG_SET_MASK (FLAG_CF_SET|FLAG_DF_SET|FLAG_IF_SET)
+
+#define FLAG_SF_CLR (1<<3)
+#define FLAG_ZF_CLR (1<<4)
+#define FLAG_AF_CLR (1<<5)
+#define FLAG_CF_CLR (1<<6)
+#define FLAG_DF_CLR (1<<7)
+#define FLAG_IF_CLR (1<<8)
+#define FLAG_OF_CLR (1<<9)
+#define FPU_C0_CLR (1<<19)
+#define FPU_C1_CLR (1<<20)
+#define FPU_C2_CLR (1<<21)
+#define FPU_C3_CLR (1<<22)
+#define FPU_ALL_CLR (FPU_C0_CLR|FPU_C1_CLR|FPU_C2_CLR|FPU_C3_CLR)
+#define FLAG_CLR_MASK (FLAG_SF_CLR|FLAG_ZF_CLR|FLAG_AF_CLR|FLAG_CF_CLR|FLAG_DF_CLR|FLAG_IF_CLR|FLAG_OF_CLR|FPU_ALL_CLR)
+
+#define FLAG_OF_MOD (1<<10)
+#define FLAG_SF_MOD (1<<11)
+#define FLAG_ZF_MOD (1<<12)
+#define FLAG_AF_MOD (1<<13)
+#define FLAG_PF_MOD (1<<14)
+#define FLAG_CF_MOD (1<<15)
+#define FLAG_DF_MOD (1<<16)
+#define FLAG_IF_MOD (1<<17)
+#define FLAG_ALL_MOD (FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD|FLAG_CF_MOD|FLAG_DF_MOD|FLAG_IF_MOD)
+#define FLAG_COMMON_MOD (FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD|FLAG_CF_MOD)
+#define FPU_C0_MOD (1<<23)
+#define FPU_C1_MOD (1<<24)
+#define FPU_C2_MOD (1<<25)
+#define FPU_C3_MOD (1<<26)
+#define FPU_ALL_MOD (FPU_C0_MOD|FPU_C1_MOD|FPU_C2_MOD|FPU_C3_MOD)
+#define FLAG_MOD_MASK (FLAG_ALL_MOD|FPU_ALL_MOD)
+
+#define FLAG_CF_TOG (1<<18)
+#define FLAG_TOG_MASK FLAG_CF_TOG
+
+// Used for Opcode.ResultsIfTrue and Opcode.ResultsIfFalse
+#define OP1_DST (1<<0)
+#define OP2_DST (1<<1)
+#define OP3_DST (1<<2)
+#define OP1_SRC (1<<3)
+#define OP2_SRC (1<<4)
+#define OP3_SRC (1<<5)
+#define FPU_STACK_INC (1<<6)
+#define FPU_STACK_INC2 (1<<7)
+#define FPU_STACK_DEC (1<<8)
+#define SERIALIZE_WRITE (1<<9)
+#define SERIALIZE_READ (1<<10)
+#define xCX_DEC (1<<11)
+#define xCX_REP_DEC (1<<12)
+#define xDI_DEC (1<<13)
+#define xDI_INC (1<<14)
+#define xSI_DEC (1<<15)
+#define xSI_INC (1<<16)
+#define xDI_DECx (1<<17)
+#define xDI_INCx (1<<18)
+#define xSI_DECx (1<<19)
+#define xSI_INCx (1<<20)
+#define FPU_STACK_PUSH FPU_STACK_DEC
+#define FPU_STACK_POP FPU_STACK_INC
+#define FPU_STACK_POP2 FPU_STACK_INC2
+#define SERIALIZE_ALL (SERIALIZE_WRITE|SERIALIZE_READ)
+
+#define X86_SEGMENT_OFFSET 0x00
+#define X86_TEST_OFFSET 0x10
+#define X86_CONTROL_OFFSET 0x20
+#define X86_DEBUG_OFFSET 0x30
+#define X86_FPU_OFFSET 0x40
+#define X86_MMX_OFFSET 0x50
+#define X86_XMM_OFFSET 0x60
+#define X86_8BIT_OFFSET 0x70
+#define X86_16BIT_OFFSET 0x80
+#define X86_32BIT_OFFSET 0x90
+#define AMD64_8BIT_OFFSET 0xA0
+#define AMD64_16BIT_OFFSET 0xB0
+#define AMD64_32BIT_OFFSET 0xC0
+#define AMD64_64BIT_OFFSET 0xD0
+
+typedef enum _X86_REGISTER
+{
+ // Segments
+ X86_SEG_ES = X86_SEGMENT_OFFSET,
+ X86_SEG_CS,
+ X86_SEG_SS,
+ X86_SEG_DS,
+ X86_SEG_FS,
+ X86_SEG_GS,
+
+ // Miscellaneous
+ X86_REG_FLAGS,
+ X86_REG_EFLAGS,
+ AMD64_REG_RFLAGS,
+ X86_REG_IP,
+ X86_REG_EIP,
+ AMD64_REG_RIP,
+
+ // Test registers
+ X86_REG_TR0 = X86_TEST_OFFSET,
+ X86_REG_TR1,
+ X86_REG_TR2,
+ X86_REG_TR3,
+ X86_REG_TR4,
+ X86_REG_TR5,
+ X86_REG_TR6,
+ X86_REG_TR7,
+ X86_REG_TR8,
+ X86_REG_TR9,
+ X86_REG_TR10,
+ X86_REG_TR11,
+ X86_REG_TR12,
+ X86_REG_TR13,
+ X86_REG_TR14,
+ X86_REG_TR15,
+
+ // Control registers
+ X86_REG_CR0=X86_CONTROL_OFFSET,
+ X86_REG_CR1,
+ X86_REG_CR2,
+ X86_REG_CR3,
+ X86_REG_CR4,
+ X86_REG_CR5,
+ X86_REG_CR6,
+ X86_REG_CR7,
+ X86_REG_CR8,
+ X86_REG_CR9,
+ X86_REG_CR10,
+ X86_REG_CR11,
+ X86_REG_CR12,
+ X86_REG_CR13,
+ X86_REG_CR14,
+ X86_REG_CR15,
+
+ // Debug registers
+ X86_REG_DR0=X86_DEBUG_OFFSET,
+ X86_REG_DR1,
+ X86_REG_DR2,
+ X86_REG_DR3,
+ X86_REG_DR4,
+ X86_REG_DR5,
+ X86_REG_DR6,
+ X86_REG_DR7,
+ X86_REG_DR8,
+ X86_REG_DR9,
+ X86_REG_DR10,
+ X86_REG_DR11,
+ X86_REG_DR12,
+ X86_REG_DR13,
+ X86_REG_DR14,
+ X86_REG_DR15,
+
+ // FPU registers
+ X86_REG_ST0=X86_FPU_OFFSET,
+ X86_REG_ST1,
+ X86_REG_ST2,
+ X86_REG_ST3,
+ X86_REG_ST4,
+ X86_REG_ST5,
+ X86_REG_ST6,
+ X86_REG_ST7,
+
+ // MMX registers
+ X86_REG_MM0=X86_MMX_OFFSET,
+ X86_REG_MM1,
+ X86_REG_MM2,
+ X86_REG_MM3,
+ X86_REG_MM4,
+ X86_REG_MM5,
+ X86_REG_MM6,
+ X86_REG_MM7,
+
+ // XMM registers
+ X86_REG_XMM0=X86_XMM_OFFSET,
+ X86_REG_XMM1,
+ X86_REG_XMM2,
+ X86_REG_XMM3,
+ X86_REG_XMM4,
+ X86_REG_XMM5,
+ X86_REG_XMM6,
+ X86_REG_XMM7,
+
+ // 8-bit registers
+ X86_REG_AL=X86_8BIT_OFFSET,
+ X86_REG_CL,
+ X86_REG_DL,
+ X86_REG_BL,
+ X86_REG_AH,
+ X86_REG_CH,
+ X86_REG_DH,
+ X86_REG_BH,
+
+ // 16-bit registers
+ X86_REG_AX=X86_16BIT_OFFSET,
+ X86_REG_CX,
+ X86_REG_DX,
+ X86_REG_BX,
+ X86_REG_SP,
+ X86_REG_BP,
+ X86_REG_SI,
+ X86_REG_DI,
+
+ // 32-bit registers
+ X86_REG_EAX=X86_32BIT_OFFSET,
+ X86_REG_ECX,
+ X86_REG_EDX,
+ X86_REG_EBX,
+ X86_REG_ESP,
+ X86_REG_EBP,
+ X86_REG_ESI,
+ X86_REG_EDI,
+
+ // AMD64 8-bit registers
+ AMD64_REG_AL=AMD64_8BIT_OFFSET,
+ AMD64_REG_CL,
+ AMD64_REG_DL,
+ AMD64_REG_BL,
+ AMD64_REG_SPL,
+ AMD64_REG_BPL,
+ AMD64_REG_SIL,
+ AMD64_REG_DIL,
+ AMD64_REG_R8B,
+ AMD64_REG_R9B,
+ AMD64_REG_R10B,
+ AMD64_REG_R11B,
+ AMD64_REG_R12B,
+ AMD64_REG_R13B,
+ AMD64_REG_R14B,
+ AMD64_REG_R15B,
+
+ // AMD64 16-bit registers
+ AMD64_REG_AX=AMD64_16BIT_OFFSET,
+ AMD64_REG_CX,
+ AMD64_REG_DX,
+ AMD64_REG_BX,
+ AMD64_REG_SP,
+ AMD64_REG_BP,
+ AMD64_REG_SI,
+ AMD64_REG_DI,
+ AMD64_REG_R8W,
+ AMD64_REG_R9W,
+ AMD64_REG_R10W,
+ AMD64_REG_R11W,
+ AMD64_REG_R12W,
+ AMD64_REG_R13W,
+ AMD64_REG_R14W,
+ AMD64_REG_R15W,
+
+ // AMD64 32-bit registers
+ AMD64_REG_EAX=AMD64_32BIT_OFFSET,
+ AMD64_REG_ECX,
+ AMD64_REG_EDX,
+ AMD64_REG_EBX,
+ AMD64_REG_ESP,
+ AMD64_REG_EBP,
+ AMD64_REG_ESI,
+ AMD64_REG_EDI,
+ AMD64_REG_R8D,
+ AMD64_REG_R9D,
+ AMD64_REG_R10D,
+ AMD64_REG_R11D,
+ AMD64_REG_R12D,
+ AMD64_REG_R13D,
+ AMD64_REG_R14D,
+ AMD64_REG_R15D,
+
+ // AMD64 64-bit registers
+ AMD64_REG_RAX=AMD64_64BIT_OFFSET,
+ AMD64_REG_RCX,
+ AMD64_REG_RDX,
+ AMD64_REG_RBX,
+ AMD64_REG_RSP,
+ AMD64_REG_RBP,
+ AMD64_REG_RSI,
+ AMD64_REG_RDI,
+ AMD64_REG_R8,
+ AMD64_REG_R9,
+ AMD64_REG_R10,
+ AMD64_REG_R11,
+ AMD64_REG_R12,
+ AMD64_REG_R13,
+ AMD64_REG_R14,
+ AMD64_REG_R15
+} X86_REGISTER;
+
+typedef enum _X86_TEST_REGISTER
+{
+ REG_TR0=0,
+ REG_TR1,
+ REG_TR2,
+ REG_TR3,
+ REG_TR4,
+ REG_TR5,
+ REG_TR6,
+ REG_TR7,
+ REG_TR8,
+ REG_TR9,
+ REG_TR10,
+ REG_TR11,
+ REG_TR12,
+ REG_TR13,
+ REG_TR14,
+ REG_TR15
+} X86_TEST_REGISTER;
+
+typedef enum _X86_CONTROL_REGISTER
+{
+ REG_CR0,
+ REG_CR1,
+ REG_CR2,
+ REG_CR3,
+ REG_CR4,
+ REG_CR5,
+ REG_CR6,
+ REG_CR7,
+ REG_CR8,
+ REG_CR9,
+ REG_CR10,
+ REG_CR11,
+ REG_CR12,
+ REG_CR13,
+ REG_CR14,
+ REG_CR15
+} X86_CONTROL_REGISTER;
+
+typedef enum _X86_DEBUG_REGISTER
+{
+ REG_DR0,
+ REG_DR1,
+ REG_DR2,
+ REG_DR3,
+ REG_DR4,
+ REG_DR5,
+ REG_DR6,
+ REG_DR7,
+ REG_DR8,
+ REG_DR9,
+ REG_DR10,
+ REG_DR11,
+ REG_DR12,
+ REG_DR13,
+ REG_DR14,
+ REG_DR15
+} X86_DEBUG_REGISTER;
+
+typedef enum _X86_MMX_REGISTER
+{
+ REG_MM0=0,
+ REG_MM1=1,
+ REG_MM2=2,
+ REG_MM3=3,
+ REG_MM4=4,
+ REG_MM5=5,
+ REG_MM6=6,
+ REG_MM7=7
+} X86_MMX_REGISTER;
+
+typedef enum _X86_SSE_REGISTER
+{
+ REG_XMM0=0,
+ REG_XMM1=1,
+ REG_XMM2=2,
+ REG_XMM3=3,
+ REG_XMM4=4,
+ REG_XMM5=5,
+ REG_XMM6=6,
+ REG_XMM7=7
+} X86_SSE_REGISTER;
+
+typedef enum _X86_FPU_REGISTER
+{
+ REG_ST0=0,
+ REG_ST1=1,
+ REG_ST2=2,
+ REG_ST3=3,
+ REG_ST4=4,
+ REG_ST5=5,
+ REG_ST6=6,
+ REG_ST7=7
+} X86_FPU_REGISTER;
+
+typedef enum _X86_8BIT_REGISTER
+{
+ REG_AL = 0,
+ REG_CL = 1,
+ REG_DL = 2,
+ REG_BL = 3,
+ REG_AH = 4,
+ REG_CH = 5,
+ REG_DH = 6,
+ REG_BH = 7
+} X86_8BIT_REGISTER;
+
+typedef enum _X86_16BIT_REGISTER
+{
+ REG_AX = 0,
+ REG_CX = 1,
+ REG_DX = 2,
+ REG_BX = 3,
+ REG_SP = 4,
+ REG_BP = 5,
+ REG_SI = 6,
+ REG_DI = 7
+} X86_16BIT_REGISTER;
+
+typedef enum _X86_32BIT_REGISTER
+{
+ REG_EAX = 0,
+ REG_ECX = 1,
+ REG_EDX = 2,
+ REG_EBX = 3,
+ REG_ESP = 4,
+ REG_EBP = 5,
+ REG_ESI = 6,
+ REG_EDI = 7
+} X86_32BIT_REGISTER;
+
+typedef enum _X86_SEGMENT
+{
+ SEG_ES = 0,
+ SEG_CS = 1,
+ SEG_SS = 2,
+ SEG_DS = 3,
+ SEG_FS = 4,
+ SEG_GS = 5,
+ SEG_MAX = 6
+} X86_SEGMENT;
+
+extern char *X86_Registers[];
+
+#pragma pack(push,1)
+typedef struct _MODRM
+{
+ U8 mod : 2;
+ U8 reg : 3;
+ U8 rm : 3;
+} MODRM;
+typedef struct _SIB
+{
+ U8 scale : 2;
+ U8 index : 3;
+ U8 base : 3;
+} SIB;
+typedef struct _REX
+{
+ U8 unused : 4; // bits 4,5,6,7
+ U8 w : 1; // bit 3
+ U8 r : 1; // bit 2
+ U8 x : 1; // bit 1
+ U8 b : 1; // bit 0
+} REX;
+typedef struct _REX_MODRM
+{
+ U8 reg : 4;
+ U8 rm : 4;
+} REX_MODRM;
+typedef struct _REX_SIB
+{
+ U8 index : 4;
+ U8 base : 4;
+} REX_SIB;
+#pragma pack(pop)
+
+//
+// Properties:
+// If an operand is OP_COND_EXEC, it means that it is executed only if the pre-conditions are met.
+//
+// If if an instruction has one or more OP_COND_DST operands, then the actions are determined by
+// whether the Opcode.Preconditions are met or not. If all the COND_* flags in Opcode.Preconditions
+// are true, then the results are determined by ResultsIfTrue. If the preconditions are not met, then
+// the results are determined by ResultsIfFalse.
+//
+// If Preconditions == NOCOND, then results in ResultsIfTrue are unconditional and ResultsIfFalse
+// is ignored
+//
+typedef struct _X86_OPCODE
+{
+ struct _X86_OPCODE *Table;
+ CPU_TYPE CPU; // minimum CPU (starting with i386)
+ U32 MnemonicFlags;
+ char Mnemonic[X86_MAX_INSTRUCTION_LEN+1];
+ U32 OperandFlags[X86_MAX_OPERANDS];
+ U32 Preconditions;
+ U32 FlagsChanged; // changes in flags
+ U32 ResultsIfTrue; // results if Preconditions are met
+ U32 ResultsIfFalse; // results if Preconditions are not met
+} X86_OPCODE;
+
+typedef struct _X86_INSTRUCTION
+{
+ struct _INSTRUCTION *Instruction; // the generic instruction format representing this instruction
+
+ X86_OPCODE Opcode;
+
+ U8 sib_b;
+ U8 modrm_b;
+ MODRM modrm;
+ SIB sib;
+ U8 rex_b;
+ REX rex;
+ REX_MODRM rex_modrm;
+ REX_SIB rex_sib;
+
+ X86_SEGMENT DstSegment;
+ union
+ {
+ X86_SEGMENT Segment;
+ DWORD Selector;
+ };
+
+ // NOTE: these are for internal use, use Instruction->Operands[]
+ //
+ // If DstRegAddressing or SrcRegAddressing = TRUE then BaseRegister is the base register
+ // It is the operand represented by SIBOperand
+ //
+ // The operand indices of the destination operands is in DstOpIndex[0 to DstOpCount-1]
+ // The operand indices of the source operands is in SrcOpIndex[0 to SrcOpCount-1]
+ //
+ // These are used both for instructions like xadd/xchg (where both operands are source/destination)
+ // and to represent implicit registers (e.g., cmpxchg)
+
+ U8 SrcOpIndex[3];
+ U8 DstOpIndex[3];
+
+ // Addressing mode:
+ // If DstRegAddressing = TRUE, then these apply to DstReg
+ // If SrcRegAddressing = TRUE, then this applies to SrcReg[AddressIndex]
+ // If both are false, then SrcReg and DstReg are not addresses
+ X86_REGISTER BaseRegister;
+ X86_REGISTER IndexRegister;
+
+ U8 Scale;
+ U8 HasDefault64Operand : 1;
+ U8 HasOperandSizePrefix : 1;
+ U8 HasAddressSizePrefix : 1;
+ U8 HasSegmentOverridePrefix : 1;
+ U8 HasLockPrefix : 1;
+ U8 HasRepeatWhileEqualPrefix : 1;
+ U8 HasRepeatWhileNotEqualPrefix : 1;
+ U8 HasBranchTakenPrefix : 1;
+ U8 HasBranchNotTakenPrefix : 1;
+ U8 HasDstAddressing : 1;
+ U8 HasSrcAddressing : 1;
+ U8 HasModRM : 1;
+ U8 HasBaseRegister : 1;
+ U8 HasIndexRegister : 1;
+ U8 HasFullDisplacement : 1;
+ U8 HasDstSegment : 1; // used for ins/cmps/scas/movs/etc which have 2 segments
+ U8 DstAddressIndex : 2; // DstOpIndex[DstAddressIndex]
+ U8 SrcAddressIndex : 2; // SrcOpIndex[SrcAddressIndex]
+ U8 DstOpCount : 2;
+ U8 SrcOpCount : 2;
+ U8 OperandSize : 4;
+ U8 AddressSize : 4;
+ U8 Relative : 1;
+ U8 HasSelector : 1; // segment is actually a selector
+ U8 Group : 5;
+
+ S64 Displacement;
+
+} X86_INSTRUCTION;
+
+////////////////////////////////////////////////////////////////////////////////////
+// Exported functions
+////////////////////////////////////////////////////////////////////////////////////
+
+extern ARCHITECTURE_FORMAT_FUNCTIONS X86;
+
+// Instruction setup
+BOOL X86_InitInstruction(struct _INSTRUCTION *Instruction);
+void X86_CloseInstruction(struct _INSTRUCTION *Instruction);
+
+// Instruction translator
+BOOL X86_TranslateInstruction(struct _INSTRUCTION *Instruction, BOOL Verbose);
+
+// Instruction decoder
+BOOL X86_GetInstruction(struct _INSTRUCTION *Instruction, U8 *Address, DWORD Flags);
+
+// Function finding
+U8 *X86_FindFunctionByPrologue(struct _INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, DWORD Flags);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // X86_DISASM_H
+
diff --git a/thirdparty/mhook/disasm-lib/disasm_x86_tables.h b/thirdparty/mhook/disasm-lib/disasm_x86_tables.h
new file mode 100644
index 00000000..9ddb3f4f
--- /dev/null
+++ b/thirdparty/mhook/disasm-lib/disasm_x86_tables.h
@@ -0,0 +1,3654 @@
+// Copyright (C) 2004, Matt Conover (mconover@gmail.com)
+//
+// The opcode tables in this file are based off the Intel Instruction Set Reference
+// and an assortment of disassemblers, primarily libdisasm (by mammon)
+
+#ifndef DISASM_X86_TABLES
+#define DISASM_X86_TABLES
+
+#define X86_GET_REG(val) ((val) & 7)
+#define X86_GET_REG64(val) ((GET_REX_B(X86Instruction->rex_b) << 3) | ((val) & 7))
+
+#define GET_MODRM_MOD(a) (((a) >> 6) & 3) // bits 6, 7
+#define GET_MODRM_REG(a) (((a) >> 3) & 7) // bits 3, 4, 5
+#define GET_MODRM_EXT(a) (((a) >> 3) & 7) // bits 3, 4, 5
+#define GET_MODRM_RM(a) ((a) & 7) // bits 0, 1, 2
+
+#define GET_SIB_SCALE(a) (((a) >> 6) & 3) // bits 6, 7
+#define GET_SIB_INDEX(a) (((a) >> 3) & 7) // bits 3, 4, 5
+#define GET_SIB_BASE(a) ((a) & 7) // bits 0, 1, 2
+
+#define REX_PREFIX_START 0x40
+#define REX_PREFIX_END 0x4F
+#define GET_REX_W(r) (((r) & 8) >> 3) // bit 3
+#define GET_REX_R(r) (((r) & 4) >> 2) // bit 2
+#define GET_REX_X(r) (((r) & 2) >> 1) // bit 1
+#define GET_REX_B(r) ((r) & 1) // bit 0
+#define REX_MASK(n) ((n >> 16) & 0x0F) // bits 0-3
+
+// Groupings to make the opcode table more readible
+#define NOARGS { 0, 0, 0 }
+#define NOCOND 0
+#define NOGROUP NULL
+#define NOACTION 0
+#define NOCHANGE 0
+#define IGNORED 0
+#define NOINSTR NOGROUP, CPU_UNKNOWN, 0, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED
+#define GROUP CPU_UNKNOWN, 0, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED
+#define PREFIX NOGROUP, CPU_UNKNOWN, ITYPE_EXT_PREFIX, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED
+#define EXT_FPU CPU_UNKNOWN, ITYPE_EXT_FPU, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED
+#define EXT_64 CPU_UNKNOWN, ITYPE_EXT_64, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED
+#define EXT_SUFFIX(a, b, c) CPU_UNKNOWN, ITYPE_EXT_SUFFIX, "", { a, b, c }, NOCOND, NOCHANGE, NOACTION, IGNORED
+#define EXT_MODRM CPU_UNKNOWN, ITYPE_EXT_MODRM, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED
+
+#define SET_MODRM(modrm, src) \
+{ \
+ (modrm).mod = GET_MODRM_MOD(src); \
+ (modrm).reg = GET_MODRM_REG(src); \
+ (modrm).rm = GET_MODRM_RM(src); \
+}
+
+#define SET_REX_MODRM(rex_modrm, rex, modrm) \
+{ \
+ (rex_modrm).rm = ((rex).b << 3) | (modrm).rm; \
+ (rex_modrm).reg = ((rex).r << 3) | (modrm).reg; \
+}
+
+#define SET_SIB(sib, src) \
+{ \
+ (sib).scale = GET_SIB_SCALE(src); \
+ (sib).index = GET_SIB_INDEX(src); \
+ (sib).base = GET_SIB_BASE(src); \
+}
+
+#define SET_REX_SIB(rex_sib, rex, sib) \
+{ \
+ (rex_sib).index = ((rex).x << 3) | (sib).index; \
+ (rex_sib).base = ((rex).b << 3) | (sib).base; \
+}
+
+#define SET_REX(rex, src) \
+{ \
+ (rex).w = GET_REX_W(src); \
+ (rex).r = GET_REX_R(src); \
+ (rex).x = GET_REX_X(src); \
+ (rex).b = GET_REX_B(src); \
+}
+
+// Addressing modes
+#define AMODE_A 0x00010000
+#define AMODE_C 0x00020000
+#define AMODE_D 0x00030000
+#define AMODE_E 0x00040000
+#define AMODE_G 0x00050000
+#define AMODE_I 0x00060000
+#define AMODE_J 0x00070000
+#define AMODE_M 0x00080000
+#define AMODE_O 0x00090000
+#define AMODE_P 0x000A0000
+#define AMODE_Q 0x000B0000
+#define AMODE_R 0x000C0000
+#define AMODE_S 0x000D0000
+#define AMODE_T 0x000E0000
+#define AMODE_V 0x000F0000
+#define AMODE_W 0x00100000
+#define AMODE_X 0x00110000
+#define AMODE_Y 0x00120000
+#define AMODE_PR 0x00130000
+#define AMODE_VR 0x00140000
+#define AMODE_xlat 0x00150000
+
+// Operand types
+#define OPTYPE_a 0x01000000
+#define OPTYPE_b 0x02000000
+#define OPTYPE_d 0x03000000
+#define OPTYPE_p 0x04000000
+#define OPTYPE_q 0x05000000
+#define OPTYPE_dt 0x06000000
+#define OPTYPE_v 0x07000000
+#define OPTYPE_w 0x08000000
+#define OPTYPE_ps 0x09000000 // packed 128-bit single real
+#define OPTYPE_pd 0x0A000000 // packed 128-bit double real
+#define OPTYPE_pb 0x0B000000 // packed BCD (10 bytes, 18-bit precision)
+#define OPTYPE_ss 0x0C000000 // scalar single real
+#define OPTYPE_sd 0x0D000000 // scalar double real
+#define OPTYPE_se 0x0E000000 // scalar extended real
+#define OPTYPE_fev 0x0F000000 // FPU environment (28 bytes if 32-bit modes, 14 bytes in 16-bit mode)
+#define OPTYPE_fst1 0x10000000 // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode)
+#define OPTYPE_fst2 0x11000000 // FPU/MMX/XMM/MXCSR state (512 bytes)
+#define OPTYPE_z 0x12000000
+#define OPTYPE_o 0x13000000
+#define OPTYPE_dq 0x14000000 // OPTYPE_d or OPTYPE_o
+#define OPTYPE_mw 0x15000000 // word if memory, register size otherwise
+#define OPTYPE_sso 0x16000000 // OPTYPE_ss or OPTYPE_o
+#define OPTYPE_sdo 0x17000000 // OPTYPE_ss or OPTYPE_o
+#define OPTYPE_cpu 0x18000000 // pointer to CPU state structure
+#define OPTYPE_lea 0x19000000 // size set by other operand
+// NOTE: if you change this, you must also update OptypeHandlers[] in disasm_x86.c
+// Be sure to preserve the ordering
+
+//////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// Registers
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+static char *Addressing16[8] = {"bx+si","bx+di","bp+si","bp+di","si","di","bp","bx"};
+static char *MMX_Registers[8] = {"mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"};
+static char *SSE_Registers[8] = {"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"};
+static char *DR_Registers[8] = {"dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7"};
+static char *CR_Registers[8] = {"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7"};
+static char *TR_Registers[8] = {"tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7"};
+static char *FPU_Registers[8] = {"st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"};
+static char *Segments[8] = {"es", "cs", "ss", "ds", "fs", "gs", "ERROR", "ERROR"};
+static char *Registers8[8] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" };
+static char *Registers16[8] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
+static char *Registers32[8] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" };
+static char *REX_Registers8[16] = {"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" };
+static char *REX_Registers16[16] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" };
+static char *REX_Registers32[16] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" };
+static char *REX_Registers64[16] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" };
+static char *DataSizes[8+1] = {"byte ptr", "word ptr", "dword ptr", "6_byte ptr", "qword ptr", "10_byte ptr", "INVALID PTR", "INVALID PTR", "oword ptr"};
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// FPU constants
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+BYTE float_0[10] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+BYTE float_1[10] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x3F };
+BYTE float_l2t[10] = { 0xFE, 0x8A, 0x1B, 0xCD, 0x4B, 0x78, 0x9A, 0xD4, 0x00, 0x40 };
+BYTE float_l2e[10] = { 0xBC, 0xF0, 0x17, 0x5C, 0x29, 0x3B, 0xAA, 0xB8, 0xFF, 0x3F };
+BYTE float_pi[10] = { 0x35, 0xC2, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9, 0x00, 0x40 };
+BYTE float_lg2[10] = { 0x99, 0xF7, 0xCF, 0xFB, 0x84, 0x9A, 0x20, 0x9A, 0xFD, 0x3F };
+BYTE float_ln2[10] = { 0xAC, 0x79, 0xCF, 0xD1, 0xF7, 0x17, 0x72, 0xB1, 0xFE, 0x3F };
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// Tables
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+extern X86_OPCODE X86_Opcodes_2[0x100];
+extern X86_OPCODE X86_Group_1_80[8], X86_Group_1_81[8], X86_Group_1_82[8], X86_Group_1_83[8], X86_Group_2_C0[8], X86_Group_2_C1[8], X86_Group_2_D0[8], X86_Group_2_D1[8], X86_Group_2_D2[8], X86_Group_2_D3[8], X86_Group_3_F6[8], X86_Group_3_F7[8], X86_Group_4[8], X86_Group_5[8], X86_Group_6[8], X86_Group_7[8], X86_Group_8[8], X86_Group_9[8], X86_Group_10[8], X86_Group_11[8], X86_Group_12_C6[8], X86_Group_12_C7[8], X86_Group_13[8], X86_Group_14[8], X86_Group_15[8], X86_Group_16[8], X86_Group_17[8], X86_Group_P[8];
+extern X86_OPCODE X86_SSE[0x300], X86_SSE2_Group_13[24], X86_SSE2_Group_14[24], X86_SSE2_Group_15[24];
+extern X86_OPCODE X86_ESC_0[0x48], X86_ESC_1[0x48], X86_ESC_2[0x48], X86_ESC_3[0x48], X86_ESC_3[0x48], X86_ESC_4[0x48], X86_ESC_5[0x48], X86_ESC_6[0x48], X86_ESC_7[0x48];
+extern X86_OPCODE X86_3DNOW_0F[0x100];
+extern X86_OPCODE X86_0F01_ModRM[0x100];
+extern X86_OPCODE X86_Opcode_63[2], X86_Opcode_0F05[2];
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// Opcode tables
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+X86_OPCODE X86_Opcodes_1[0x100] = // 1 byte opcodes
+{
+ { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "add", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "add", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_ES | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_ES | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */
+ { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x08 */
+ { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x09 */
+ { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0A */
+ { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0B */
+ { NOGROUP, CPU_I386, ITYPE_OR, "or", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0C */
+ { NOGROUP, CPU_I386, ITYPE_OR, "or", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0D */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_CS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x0E */
+ { X86_Opcodes_2, GROUP }, /* 0x0F */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x10 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x11 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x12 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x13 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x14 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x15 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_SS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x16 */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_SS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x17 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x18 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x19 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1A */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1B */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1C */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1D */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_DS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x1E */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_DS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x1F */
+ { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x20 */
+ { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x21 */
+ { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x22 */
+ { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x23 */
+ { NOGROUP, CPU_I386, ITYPE_AND, "and", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x24 */
+ { NOGROUP, CPU_I386, ITYPE_AND, "and", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x25 */
+ { PREFIX }, /* 0x26 */
+ { NOGROUP, CPU_I386, ITYPE_BCDCONV, "daa", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_AF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x27 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x28 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x29 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2A */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2B */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2C */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2D */
+ { PREFIX }, /* 0x2E */
+ { NOGROUP, CPU_I386, ITYPE_BCDCONV, "das", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_AF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x2F */
+ { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x30 */
+ { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x31 */
+ { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x32 */
+ { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x33 */
+ { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x34 */
+ { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x35 */
+ { PREFIX }, /* 0x36 */
+ { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aaa", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_AF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x37 */
+ { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x38 */
+ { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x39 */
+ { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_G | OPTYPE_b | OP_SRC, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3A */
+ { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3B */
+ { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { OPTYPE_REG_AL | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3C */
+ { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { OPTYPE_REG_xAX_BIG | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_z | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3D */
+ { PREFIX }, /* 0x3E */
+ { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aas", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_AF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x3F */
+ { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x40 */
+ { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x41 */
+ { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x42 */
+ { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x43 */
+ { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x44 */
+ { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x45 */
+ { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x46 */
+ { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x47 */
+ { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x48 */
+ { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x49 */
+ { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4A */
+ { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4B */
+ { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4C */
+ { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4D */
+ { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4E */
+ { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4F */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x50 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x51 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x52 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x53 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x54 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x55 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x56 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x57 */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x58 */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x59 */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5A */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5B */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5C */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5D */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5E */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5F */
+ { NOGROUP, CPU_I386, ITYPE_PUSHA, "pushad", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x60 */
+ { NOGROUP, CPU_I386, ITYPE_POPA, "popad", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x61 */
+ { NOGROUP, CPU_I386, ITYPE_BOUNDS, "bound", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_M | OPTYPE_a | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x62 */
+ { X86_Opcode_63, EXT_64 }, /* 0x63 */
+ { PREFIX }, /* 0x64 */
+ { PREFIX }, /* 0x65 */
+ { PREFIX }, /* 0x66 */
+ { PREFIX }, /* 0x67 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { AMODE_I | OPTYPE_z | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x68 */
+ { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_z | OP_SIGNED | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x69 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6A */
+ { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x6B */
+ { NOGROUP, CPU_I386, ITYPE_IN, "insb", { AMODE_Y | OPTYPE_b | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DEC | xCX_REP_DEC, xDI_INC | xCX_REP_DEC }, /* 0x6C */
+ { NOGROUP, CPU_I386, ITYPE_IN, "insd", { AMODE_Y | OPTYPE_z | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DECx | xCX_REP_DEC, xDI_INCx | xCX_REP_DEC }, /* 0x6D */
+ { NOGROUP, CPU_I386, ITYPE_OUT, "outsb", { OPTYPE_REG_DX | OP_SYS | OP_DST, AMODE_X | OPTYPE_b | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DEC | xCX_REP_DEC, xSI_INC | xCX_REP_DEC }, /* 0x6E */
+ { NOGROUP, CPU_I386, ITYPE_OUT, "outsd", { OPTYPE_REG_DX | OP_SYS | OP_DST, AMODE_X | OPTYPE_z | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DECx | xCX_REP_DEC, xSI_INCx | xCX_REP_DEC}, /* 0x6F */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jo", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_O, NOCHANGE, OP1_DST, NOACTION }, /* 0x70 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jno", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NO, NOCHANGE, OP1_DST, NOACTION }, /* 0x71 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jb", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_C, NOCHANGE, OP1_DST, NOACTION }, /* 0x72 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnb", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NC, NOCHANGE, OP1_DST, NOACTION }, /* 0x73 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_Z, NOCHANGE, OP1_DST, NOACTION }, /* 0x74 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NZ, NOCHANGE, OP1_DST, NOACTION }, /* 0x75 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jbe", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_BE, NOCHANGE, OP1_DST, NOACTION }, /* 0x76 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "ja", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_A, NOCHANGE, OP1_DST, NOACTION }, /* 0x77 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "js", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_S, NOCHANGE, OP1_DST, NOACTION }, /* 0x78 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jns", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NS, NOCHANGE, OP1_DST, NOACTION }, /* 0x79 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpe", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PE, NOCHANGE, OP1_DST, NOACTION }, /* 0x7A */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpo", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PO, NOCHANGE, OP1_DST, NOACTION }, /* 0x7B */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jl", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_L, NOCHANGE, OP1_DST, NOACTION }, /* 0x7C */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jge", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_GE, NOCHANGE, OP1_DST, NOACTION }, /* 0x7D */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jle", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_LE, NOCHANGE, OP1_DST, NOACTION }, /* 0x7E */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jg", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_G, NOCHANGE, OP1_DST, NOACTION }, /* 0x7F */
+ { X86_Group_1_80, GROUP }, /* 0x80 Eb Ib */
+ { X86_Group_1_81, GROUP }, /* 0x81 Ev Iz */
+ { X86_Group_1_82, GROUP }, /* 0x82 Eb Ib */
+ { X86_Group_1_83, GROUP }, /* 0x83 Ev Ib */
+ { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x84 */
+ { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x85 */
+ { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, AMODE_G | OPTYPE_b | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x86 */
+ { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_G | OPTYPE_v | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x87 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x88 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x89 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8A */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8B */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_mw | OP_DST, AMODE_S | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8C */
+ { NOGROUP, CPU_I386, ITYPE_LEA, "lea", { AMODE_G | OPTYPE_v | OP_DST, AMODE_M | OPTYPE_lea | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8D */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_S | OPTYPE_w | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8E */
+ { X86_Group_10, GROUP }, /* 0x8F */
+ { NOGROUP, CPU_I386, ITYPE_NOP, "nop", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x90 */
+ { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x91 */
+ { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x92 */
+ { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x93 */
+ { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x94 */
+ { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x95 */
+ { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x96 */
+ { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x97 */
+ { NOGROUP, CPU_I386, ITYPE_SZCONV, "cwde", { OPTYPE_REG_xAX_BIG | OP_SIGNED | OP_DST, OPTYPE_REG_xAX_SMALL | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x98 */
+ { NOGROUP, CPU_I386, ITYPE_SZCONV, "cdq", { OPTYPE_xDX_HI_xAX_LO | OP_SIGNED | OP_DST, OPTYPE_REG_xAX_BIG | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x99 */
+ { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_A | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9A */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "wait", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9B */
+ { NOGROUP, CPU_I386, ITYPE_PUSHF, "pushf", { OPTYPE_xFLAGS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9C */
+ { NOGROUP, CPU_I386, ITYPE_POPF, "popf", { OPTYPE_xFLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_ALL_MOD, NOACTION, IGNORED }, /* 0x9D */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "sahf", { OPTYPE_FLAGS | OP_DST, OPTYPE_REG_AH | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_AF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x9E */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "lahf", { OPTYPE_REG_AH | OP_DST, OPTYPE_FLAGS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9F */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG_AL | OP_DST, AMODE_O | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA0 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_O | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA1 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_O | OPTYPE_b | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA2 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_O | OPTYPE_v | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA3 */
+ { NOGROUP, CPU_I386, ITYPE_STRMOV, "movsb", { AMODE_Y | OPTYPE_b | OP_DST, AMODE_X | OPTYPE_b | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DEC | xSI_DEC | xCX_REP_DEC, xDI_INC | xSI_INC | xCX_REP_DEC}, /* 0xA4 */
+ { NOGROUP, CPU_I386, ITYPE_STRMOV, "movsd", { AMODE_Y | OPTYPE_z | OP_DST, AMODE_X | OPTYPE_z | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DECx | xSI_DECx| xCX_REP_DEC, xDI_INCx | xSI_INCx | xCX_REP_DEC }, /* 0xA5 */
+ { NOGROUP, CPU_I386, ITYPE_STRCMP, "cmpsb", { AMODE_X | OPTYPE_b | OP_SRC, AMODE_Y | OPTYPE_b | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DEC | xSI_DEC | xCX_REP_DEC, xDI_INC | xSI_INC | xCX_REP_DEC }, /* 0xA6 */
+ { NOGROUP, CPU_I386, ITYPE_STRCMP, "cmpsd", { AMODE_X | OPTYPE_z | OP_SRC, AMODE_Y | OPTYPE_z | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DECx | xSI_DECx | xCX_REP_DEC, xDI_INCx | xSI_INCx | xCX_REP_DEC}, /* 0xA7 */
+ { NOGROUP, CPU_I386, ITYPE_TEST, "test", { OPTYPE_REG_AL | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0xA8 */
+ { NOGROUP, CPU_I386, ITYPE_TEST, "test", { OPTYPE_REG_xAX_BIG | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0xA9 */
+ { NOGROUP, CPU_I386, ITYPE_STRSTOR, "stosb", { AMODE_Y | OPTYPE_b | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DEC | xSI_DEC | xCX_REP_DEC, xDI_INC | xSI_INC | xCX_REP_DEC }, /* 0xAA */
+ { NOGROUP, CPU_I386, ITYPE_STRSTOR, "stosd", { AMODE_Y | OPTYPE_z | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DECx | xSI_DECx | xCX_REP_DEC, xDI_INCx | xSI_INCx | xCX_REP_DEC }, /* 0xAB */
+ { NOGROUP, CPU_I386, ITYPE_STRLOAD, "lodsb", { OPTYPE_REG_AL | OP_DST, AMODE_X | OPTYPE_b | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DEC | xCX_REP_DEC, xSI_INC | xCX_REP_DEC }, /* 0xAC */
+ { NOGROUP, CPU_I386, ITYPE_STRLOAD, "lodsd", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_X | OPTYPE_z | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DECx | xCX_REP_DEC, xSI_INCx | xCX_REP_DEC }, /* 0xAD */
+ { NOGROUP, CPU_I386, ITYPE_STRCMP, "scasb", { OPTYPE_REG_AL | OP_SRC, AMODE_Y | OPTYPE_b | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DEC | xCX_REP_DEC, xDI_INC | xCX_REP_DEC }, /* 0xAE */
+ { NOGROUP, CPU_I386, ITYPE_STRCMP, "scasd", { OPTYPE_REG_xAX_BIG | OP_SRC, AMODE_Y | OPTYPE_z | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DECx, xDI_INCx }, /* 0xAF */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB0 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB1 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB2 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB3 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB4 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB5 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB6 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB7 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB8 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB9 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBA */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBB */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBC */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBD */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBE */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBF */
+ { X86_Group_2_C0, GROUP }, /* 0xC0 Eb Ib */
+ { X86_Group_2_C1, GROUP }, /* 0xC1 Ev Ib */
+ { NOGROUP, CPU_I386, ITYPE_RET, "ret", { AMODE_I | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC2 */
+ { NOGROUP, CPU_I386, ITYPE_RET, "ret", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC3 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "les", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC4 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "lds", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC5 */
+ { X86_Group_12_C6, GROUP }, /* 0xC6 Eb Ib */
+ { X86_Group_12_C7, GROUP }, /* 0xC7 Ev Iz */
+ { NOGROUP, CPU_I386, ITYPE_ENTER, "enter", { OPTYPE_REG_xBP | OP_SRC | OP_DST, AMODE_I | OPTYPE_w | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC8 */
+ { NOGROUP, CPU_I386, ITYPE_LEAVE, "leave", { OPTYPE_REG_xBP | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC9 */
+ { NOGROUP, CPU_I386, ITYPE_RET, "retf", { AMODE_I | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCA */
+ { NOGROUP, CPU_I386, ITYPE_RET, "retf", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCB */
+ { NOGROUP, CPU_I386, ITYPE_DEBUG, "int3", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCC */
+ { NOGROUP, CPU_I386, ITYPE_TRAP, "int", { AMODE_I | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCD */
+ { NOGROUP, CPU_I386, ITYPE_OFLOW, "into", NOARGS, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xCE */
+ { NOGROUP, CPU_I386, ITYPE_TRAPRET, "iret", NOARGS, NOCOND, FLAG_ALL_MOD, NOACTION, IGNORED }, /* 0xCF */
+ { X86_Group_2_D0, GROUP }, /* 0xD0 Eb, 1 */
+ { X86_Group_2_D1, GROUP }, /* 0xD1 Ev, 1 */
+ { X86_Group_2_D2, GROUP }, /* 0xD2 Eb, CL */
+ { X86_Group_2_D3, GROUP }, /* 0xD3 Ev, CL */
+ { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aam", { OPTYPE_REG_AX | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD, NOACTION, IGNORED }, /* 0xD4 */
+ { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aad", { OPTYPE_REG_AX | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD, NOACTION, IGNORED }, /* 0xD5 */
+ { NOGROUP, CPU_I386, ITYPE_ARITH, "salc", { OPTYPE_REG_AL | OP_DST, OPTYPE_FF | OP_SRC, OPTYPE_0 | OP_SRC }, COND_C, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0xD6 */
+ { NOGROUP, CPU_I386, ITYPE_XLAT, "xlat", { OPTYPE_REG_AL | OP_DST, AMODE_xlat | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD7 */
+ { X86_ESC_0, EXT_FPU }, /* 0xD8 */
+ { X86_ESC_1, EXT_FPU }, /* 0xD9 */
+ { X86_ESC_2, EXT_FPU }, /* 0xDA */
+ { X86_ESC_3, EXT_FPU }, /* 0xDB */
+ { X86_ESC_4, EXT_FPU }, /* 0xDC */
+ { X86_ESC_5, EXT_FPU }, /* 0xDD */
+ { X86_ESC_6, EXT_FPU }, /* 0xDE */
+ { X86_ESC_7, EXT_FPU }, /* 0xDF */
+ { NOGROUP, CPU_I386, ITYPE_LOOPCC, "loopnz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_NZ | COND_NZ, NOCHANGE, OP1_DST | xCX_DEC, NOACTION }, /* 0xE0 */
+ { NOGROUP, CPU_I386, ITYPE_LOOPCC, "loopz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_NZ | COND_Z, NOCHANGE, OP1_DST | xCX_DEC, NOACTION }, /* 0xE1 */
+ { NOGROUP, CPU_I386, ITYPE_LOOPCC, "loop", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_NZ, NOCHANGE, OP1_DST | xCX_DEC, NOACTION }, /* 0xE2 */
+ { NOGROUP, CPU_I386, ITYPE_LOOPCC, "jecxz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_Z, NOCHANGE, OP1_DST, NOACTION }, /* 0xE3 */
+ { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE4 */
+ { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_b | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE5 */
+ { NOGROUP, CPU_I386, ITYPE_OUT, "out", { AMODE_I | OPTYPE_b | OP_SYS | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE6 */
+ { NOGROUP, CPU_I386, ITYPE_OUT, "out", { AMODE_I | OPTYPE_b | OP_SYS | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE7 */
+ { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_J | OPTYPE_z | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE8 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_J | OPTYPE_z | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE9 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_A | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEA */
+ { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_J | OPTYPE_b | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEB */
+ { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_AL | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEC */
+ { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_xAX_BIG | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xED */
+ { NOGROUP, CPU_I386, ITYPE_OUT, "out", { OPTYPE_REG_DX | OP_SYS | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEE */
+ { NOGROUP, CPU_I386, ITYPE_OUT, "out", { OPTYPE_REG_DX | OP_SYS | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEF */
+ { PREFIX }, /* 0xF0 */
+ { NOGROUP, CPU_I386, ITYPE_DEBUG, "int1", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, // aka icebp /* 0xF1 */
+ { PREFIX }, /* 0xF2 */
+ { PREFIX }, /* 0xF3 */
+ { NOGROUP, CPU_I386, ITYPE_HALT, "hlt", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF4 */
+ { NOGROUP, CPU_I386, ITYPE_TOGCF, "cmc", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_CF_TOG, IGNORED }, /* 0xF5 */
+ { X86_Group_3_F6, GROUP }, /* 0xF6 Eb */
+ { X86_Group_3_F7, GROUP }, /* 0xF7 Ev */
+ { NOGROUP, CPU_I386, ITYPE_CLEARCF, "clc", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_CF_CLR, NOACTION, IGNORED }, /* 0xF8 */
+ { NOGROUP, CPU_I386, ITYPE_SETCF, "stc", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_CF_SET, NOACTION, IGNORED }, /* 0xF9 */
+ { NOGROUP, CPU_I386, ITYPE_CLEARIF, "cli", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_IF_CLR, NOACTION, IGNORED }, /* 0xFA */
+ { NOGROUP, CPU_I386, ITYPE_SETIF, "sti", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_IF_SET, NOACTION, IGNORED }, /* 0xFB */
+ { NOGROUP, CPU_I386, ITYPE_CLEARDF, "cld", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_DF_CLR, NOACTION, IGNORED }, /* 0xFC */
+ { NOGROUP, CPU_I386, ITYPE_SETDF, "std", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_DF_SET, NOACTION, IGNORED }, /* 0xFD */
+ { X86_Group_4, GROUP }, /* 0xFE */
+ { X86_Group_5, GROUP }, /* 0xFF */
+};
+
+X86_OPCODE X86_Opcodes_2[0x100] = // 2 byte opcodes
+{
+ { X86_Group_6, GROUP }, /* 0x00 */
+ { X86_0F01_ModRM, EXT_MODRM }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lar", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lsl", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { X86_Opcode_0F05, EXT_64 }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "clts", { OPTYPE_CR0 | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_SYSCALLRET, "sysret", { OPTYPE_STAR_MSR | OP_MSR | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */
+ // 0F 07 could also be this undocumented instruction on older CPUs:
+ // { NOGROUP, CPU_I386, ITYPE_SYSTEM, "loadall", { AMODE_Y | OPTYPE_cpu | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */
+ { NOGROUP, CPU_I486, ITYPE_SYSTEM, "invd", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x08 */
+ { NOGROUP, CPU_I486, ITYPE_SYSTEM, "wbinvd", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x09 */
+ { NOINSTR }, /* 0x0A */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_INVALID, "undef" /* aka UD2 */, NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x0B */
+ { NOINSTR }, /* 0x0C */
+ { X86_Group_P, GROUP }, /* 0x0D */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "femms", { OPTYPE_FPU_TAG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x0E */
+ { X86_3DNOW_0F, EXT_SUFFIX(AMODE_P | OPTYPE_q, AMODE_Q | OPTYPE_q, 0) }, /* 0x0F */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movups", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x10 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movups", { AMODE_W | OPTYPE_ps | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x11 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movlps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x12 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movlps", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x13 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "unpcklps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x14 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "unpckhps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x15 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movhps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x16 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movhps", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x17 */
+ { X86_Group_17, GROUP }, /* 0x18 */
+ { NOINSTR }, /* 0x19 */
+ { NOINSTR }, /* 0x1A */
+ { NOINSTR }, /* 0x1B */
+ { NOINSTR }, /* 0x1C */
+ { NOINSTR }, /* 0x1D */
+ { NOINSTR }, /* 0x1E */
+ { NOINSTR }, /* 0x1F */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_R | OPTYPE_dq | OP_DST, AMODE_C | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x20 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_R | OPTYPE_dq | OP_DST, AMODE_D | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x21 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_C | OPTYPE_dq | OP_DST, AMODE_R | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x22 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_D | OPTYPE_dq | OP_DST, AMODE_R | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x23 */
+ { NOINSTR }, /* 0x24 */
+ //{ NOGROUP, CPU_I486, ITYPE_MOV, "mov", { AMODE_R | OPTYPE_d | OP_DST, AMODE_T | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x24 */
+ { NOINSTR }, /* 0x25 */
+ { NOINSTR }, /* 0x26 */
+ //{ NOGROUP, CPU_I486, ITYPE_MOV, "mov", { AMODE_T | OPTYPE_d | OP_DST, AMODE_R | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x26 */
+ { NOINSTR }, /* 0x27 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movaps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x28 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movaps", { AMODE_W | OPTYPE_ps | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x29 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtpi2ps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2A */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movntps", { AMODE_M | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2B */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvttps2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2C */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtps2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2D */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "ucomiss", { AMODE_V | OPTYPE_ss | OP_SRC, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, /* 0x2E */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "comiss", { AMODE_V | OPTYPE_ps | OP_SRC, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, /* 0x2F */
+ { NOGROUP, CPU_PENTIUM, ITYPE_SYSTEM, "wrmsr", { OPTYPE_REG_ECX | OP_MSR | OP_DST, OPTYPE_EDX_HI_EAX_LO | OP_SRC, 0 } , NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x30 */
+ { NOGROUP, CPU_PENTIUM, ITYPE_SYSTEM, "rdtsc", { OPTYPE_EDX_HI_EAX_LO | OP_DST, OPTYPE_TSC | OP_MSR | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x31 */
+ { NOGROUP, CPU_PENTIUM, ITYPE_SYSTEM, "rdmsr", { OPTYPE_EDX_HI_EAX_LO | OP_DST, OPTYPE_REG_ECX | OP_MSR | OP_SRC, 0 } , NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x32 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_OTHER, "rdpmc", { OPTYPE_EDX_HI_EAX_LO | OP_DST, OPTYPE_REG_ECX | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x33 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSCALL, "sysenter", { OPTYPE_CS_MSR | OP_MSR | OP_SRC, OPTYPE_EIP_MSR | OP_MSR | OP_SRC, OPTYPE_ESP_MSR | OP_MSR | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x34 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSCALLRET, "sysexit", { OPTYPE_CS_MSR | OP_MSR | OP_SRC, OPTYPE_EIP_MSR | OP_MSR | OP_SRC, OPTYPE_ESP_MSR | OP_MSR | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x35 */
+ { NOINSTR }, /* 0x36 */
+ { NOINSTR }, /* 0x37 */
+ { NOINSTR }, /* 0x38 */
+ { NOINSTR }, /* 0x39 */
+ { NOINSTR }, /* 0x3A */
+ { NOINSTR }, /* 0x3B */
+ { NOINSTR }, /* 0x3C */
+ { NOINSTR }, /* 0x3D */
+ { NOINSTR }, /* 0x3E */
+ { NOINSTR }, /* 0x3F */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovo", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_O, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x40 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovno", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NO, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x41 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovc", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_C, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x42 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovnc", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NC, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x43 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovz", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_Z, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x44 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovnz", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NZ, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x45 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovbe", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_BE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x46 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmova", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_A, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x47 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovs", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_S, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x48 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovns", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NS, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x49 */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovpe", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_PE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4A */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovpo", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_PO, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4B */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovl", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_L, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4C */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovge", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_GE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4D */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovle", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_LE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4E */
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovg", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_G, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4F */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "movmskps", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR | OPTYPE_ps| OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x50 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "sqrtps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x51 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "rsqrtps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x52 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "rcpps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x53 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_AND, "andps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x54 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_AND, "andnps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x55 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_OR, "orps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x56 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_XOR, "xorps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x57 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_ADD, "addps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x58 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MUL, "mulps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x59 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtps2pd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5A */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtdq2ps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5B */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_SUB, "subps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5C */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "minps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5D */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_DIV, "divps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5E */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "maxps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5F */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpcklbw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x60 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpcklwd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x61 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckldq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x62 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "packsswb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x63 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpgtb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x64 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpgtw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x65 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpgtd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x66 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "packuswb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x67 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckhbw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x68 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckhwd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x69 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckhdq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6A */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "packssdw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6B */
+ { NOINSTR }, /* 0x6C */
+ { NOINSTR }, /* 0x6D */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6E */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6F */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pshufw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x70 */
+ { X86_Group_13, GROUP }, /* 0x71 */
+ { X86_Group_14, GROUP }, /* 0x72 */
+ { X86_Group_15, GROUP }, /* 0x73 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpeqb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x74 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpeqw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x75 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpeqd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x76 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "emms", { OPTYPE_FPU_TAG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x77 */
+ { NOINSTR }, /* 0x78 */
+ { NOINSTR }, /* 0x79 */
+ { NOINSTR }, /* 0x7A */
+ { NOINSTR }, /* 0x7B */
+ { NOINSTR }, /* 0x7C */
+ { NOINSTR }, /* 0x7D */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movd", { AMODE_E | OPTYPE_dq | OP_DST, AMODE_P | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x7E */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movq", { AMODE_Q | OPTYPE_q | OP_DST, AMODE_P | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x7F */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jo", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_O, NOCHANGE, OP1_DST, NOACTION }, /* 0x80 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jno", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NO, NOCHANGE, OP1_DST, NOACTION }, /* 0x81 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jb", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_C, NOCHANGE, OP1_DST, NOACTION }, /* 0x82 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnb", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NC, NOCHANGE, OP1_DST, NOACTION }, /* 0x83 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jz", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_Z, NOCHANGE, OP1_DST, NOACTION }, /* 0x84 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnz", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NZ, NOCHANGE, OP1_DST, NOACTION }, /* 0x85 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jbe", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_BE, NOCHANGE, OP1_DST, NOACTION }, /* 0x86 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "ja", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_A, NOCHANGE, OP1_DST, NOACTION }, /* 0x87 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "js", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_S, NOCHANGE, OP1_DST, NOACTION }, /* 0x88 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jns", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NS, NOCHANGE, OP1_DST, NOACTION }, /* 0x89 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpe", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PE, NOCHANGE, OP1_DST, NOACTION }, /* 0x8A */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpo", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PO, NOCHANGE, OP1_DST, NOACTION }, /* 0x8B */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jl", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_L, NOCHANGE, OP1_DST, NOACTION }, /* 0x8C */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jge", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_GE, NOCHANGE, OP1_DST, NOACTION }, /* 0x8D */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jle", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_LE, NOCHANGE, OP1_DST, NOACTION }, /* 0x8E */
+ { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jg", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_G, NOCHANGE, OP1_DST, NOACTION }, /* 0x8F */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "seto", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_O, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x90 */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setno", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NO, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x91 */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setb", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_C, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x92 */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setnb", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NC, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x93 */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "sete", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_Z, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x94 */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setne", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NZ, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x95 */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setbe", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_BE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x96 */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "seta", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_A, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x97 */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "sets", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_S, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x98 */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setns", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NS, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x99 */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setpe", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_PE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9A */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setpo", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_PO, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9B */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setl", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_L, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9C */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setge", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_GE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9D */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setle", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_LE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9E */
+ { NOGROUP, CPU_I386, ITYPE_MOVCC, "setg", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_G, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9F */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_FS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA0 */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_FS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA1 */
+ { NOGROUP, CPU_PENTIUM, ITYPE_CPUID, "cpuid", { OPTYPE_EDX_ECX_EBX_EAX | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA2 */
+ { NOGROUP, CPU_I386, ITYPE_BITTEST, "bt", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xA3 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "shld", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xA4 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "shld", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, OPTYPE_REG_CL | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xA5 */
+ { NOINSTR }, /* 0xA6 */
+ { NOINSTR }, /* 0xA7 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_GS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA8 */
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_GS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA9 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "rsm", NOARGS, NOCOND, FLAG_ALL_MOD, NOACTION, IGNORED }, /* 0xAA */
+ { NOGROUP, CPU_I386, ITYPE_BITTEST, "bts", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAB */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "shrd", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAC */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "shrd", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, OPTYPE_REG_CL | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAD */
+ { X86_Group_16, GROUP }, /* 0xAE */
+ { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAF */
+ { NOGROUP, CPU_I486, ITYPE_XCHGCC, "cmpxchg", { AMODE_E | OPTYPE_b | OP_SRC | OP_COND_DST, OPTYPE_REG_AL | OP_SRC | OP_COND_DST, AMODE_G | OPTYPE_b | OP_COND_SRC }, COND_OP1_EQ_OP2, FLAG_COMMON_MOD, OP1_DST | OP3_SRC, OP2_DST | OP1_SRC }, /* 0xB0 */
+ { NOGROUP, CPU_I486, ITYPE_XCHGCC, "cmpxchg", { AMODE_E | OPTYPE_v | OP_SRC | OP_COND_DST, OPTYPE_REG_xAX_BIG | OP_SRC | OP_COND_DST, AMODE_G | OPTYPE_v | OP_COND_SRC }, COND_OP1_EQ_OP2, FLAG_COMMON_MOD, OP1_DST | OP3_SRC, OP2_DST | OP1_SRC }, /* 0xB1 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "lss", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB2 */
+ { NOGROUP, CPU_I386, ITYPE_BITTEST, "btr", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xB3 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "lfs", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB4 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "lgs", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB5 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "movzx", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB6 */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "movzx", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB7 */
+ { NOINSTR }, /* 0xB8 */
+ { X86_Group_11, GROUP }, /* 0xB9 */
+ { X86_Group_8, GROUP }, /* 0xBA */
+ { NOGROUP, CPU_I386, ITYPE_BITTEST, "btc", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xBB */
+ { NOGROUP, CPU_I386, ITYPE_BITTEST, "bsf", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0xBC */
+ { NOGROUP, CPU_I386, ITYPE_BITTEST, "bsr", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0xBD */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "movsx", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBE */
+ { NOGROUP, CPU_I386, ITYPE_MOV, "movsx", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBF */
+ { NOGROUP, CPU_I486, ITYPE_XCHGADD, "xadd", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, AMODE_G | OPTYPE_b | OP_SRC | OP_DST, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0xC0 */
+ { NOGROUP, CPU_I486, ITYPE_XCHGADD, "xadd", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_G | OPTYPE_v | OP_SRC | OP_DST, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0xC1 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "cmpps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0xC2 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movnti", { AMODE_M | OPTYPE_dq | OP_DST, AMODE_G | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC3 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pinsrw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC4 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pextrw", { AMODE_G | OPTYPE_d | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC5 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "shufps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC6 */
+ { X86_Group_9, GROUP }, /* 0xC7 */
+ { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC8 */
+ { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC9 */
+ { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCA */
+ { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCB */
+ { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCC */
+ { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCD */
+ { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCE */
+ { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCF */
+ { NOINSTR }, /* 0xD0 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD1 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrld", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD2 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD3 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_ADD, "paddq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD4 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MUL, "pmullw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD5 */
+ { NOINSTR }, /* 0xD6 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pmovmskb", { AMODE_G | OPTYPE_d | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD7 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubusb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD8 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubusw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD9 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pminub", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDA */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_AND, "pand", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDB */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddusb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDC */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddusw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDD */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pmaxub", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDE */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_AND, "pandn", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDF */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pavgb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE0 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psraw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE1 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrad", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE2 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pavgw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE3 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MUL, "pmulhuw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE4 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MUL, "pmulhw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE5 */
+ { NOINSTR }, /* 0xE6 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movntq", { AMODE_M | OPTYPE_q | OP_DST, AMODE_P | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE7 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubsb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE8 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE9 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pminsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEA */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_OR, "por", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEB */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddsb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEC */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xED */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pmaxsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEE */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_XOR, "pxor", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEF */
+ { NOINSTR }, /* 0xF0 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF1 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pslld", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF2 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF3 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MUL, "pmuludq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF4 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "pmaddwd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF5 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "psadbw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF6 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "maskmovq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF7 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF8 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF9 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFA */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_SUB, "psubq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFB */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFC */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFD */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFE */
+ { NOINSTR } /* 0xFF */,
+};
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// Groups
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+X86_OPCODE X86_Group_1_80[8] = // 80
+{
+ { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_1_81[8] = // 81
+{
+ { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_1_82[8] = // 82
+{
+ { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_1_83[8] = // 83
+{
+ { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_2_C0[8] = // C0
+{
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_2_C1[8] = // C1
+{
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_2_D0[8] = // D0
+{
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_2_D1[8] = // D1
+{
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_2_D2[8] = // D2
+{
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_2_D3[8] = // D3
+{
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_3_F6[8] = // F6
+{
+ { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_NOT, "not", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_NEG, "neg", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_MUL, "mul", { OPTYPE_REG_AX | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, OPTYPE_REG_AL | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { OPTYPE_REG_AX | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_b | OP_SIGNED | OP_SRC, OPTYPE_REG_AL | OP_SIGNED | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_DIV, "div", { OPTYPE_REG_AX | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, OPTYPE_REG_AX | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_DIV, "idiv", { OPTYPE_REG_AX | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_b | OP_SIGNED | OP_SRC, OPTYPE_REG_AX | OP_SIGNED | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED } /* 0x07 */,
+};
+
+X86_OPCODE X86_Group_3_F7[8] = // F7
+{
+ { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_NOT, "not", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_NEG, "neg", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_MUL, "mul", { OPTYPE_xDX_HI_xAX_LO | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { OPTYPE_xDX_HI_xAX_LO | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_DIV, "div", { OPTYPE_xDX_HI_xAX_LO | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_DIV, "idiv", { OPTYPE_xDX_HI_xAX_LO | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_4[8] = // FE
+{
+ { NOGROUP, CPU_I386, ITYPE_INC, "inc", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x01 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR } /* 0x07 */
+};
+
+X86_OPCODE X86_Group_5[8] = // FF
+{
+ { NOGROUP, CPU_I386, ITYPE_INC, "inc", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_E | OPTYPE_v | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_E | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_E | OPTYPE_v | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_E | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { AMODE_E | OPTYPE_v | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_6[8] = // 0F 00
+{
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "sldt", { AMODE_E | OPTYPE_mw | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "str", { AMODE_E | OPTYPE_mw | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lldt", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "ltr", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "verr", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "verw", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_IA64, ITYPE_BRANCH, "jmpe", { AMODE_E | OPTYPE_v | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOINSTR } /* 0x07 */
+};
+
+X86_OPCODE X86_Group_7[8] = // 0F 01
+{
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "sgdt", { AMODE_M | OPTYPE_dt | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "sidt", { AMODE_M | OPTYPE_dt | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lgdt", { AMODE_M | OPTYPE_dt | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lidt", { AMODE_M | OPTYPE_dt | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "smsw", { AMODE_E | OPTYPE_mw | OP_DST, OPTYPE_CR0 | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lmsw", { OPTYPE_CR0 | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I486, ITYPE_SYSTEM, "invlpg", { AMODE_M | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_8[8] = // 0F BA
+{
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOINSTR }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_BITTEST, "bt", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_BITTEST, "bts", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_BITTEST, "btr", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_BITTEST, "btc", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_9[8] = // 0F C7
+{
+ { NOINSTR }, /* 0x00 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_XCHGCC, "cmpxchg8b", { AMODE_M | OPTYPE_q | OP_SRC | OP_COND_DST, OPTYPE_xDX_HI_xAX_LO | OP_SRC | OP_COND_DST, OPTYPE_xCX_HI_xBX_LO | OP_COND_SRC }, COND_OP1_EQ_OP2, FLAG_ZF_MOD, OP1_DST | OP3_SRC, OP2_DST | OP1_SRC }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_10[8] = // 8F (NOTE: AMD64 labels this Group 1A)
+{
+ { NOGROUP, CPU_I386, ITYPE_POP, "pop", { AMODE_E | OPTYPE_v | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOINSTR }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_11[8] = // 0F B9 (NOTE: AMD64 labels this Group 10)
+{
+ { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED } /* 0x07 */
+};
+
+X86_OPCODE X86_Group_12_C6[8] = // C6 (NOTE: AMD64 labels this Group 11)
+{
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC6 */
+ { NOINSTR }, /* 0x01 */
+ { NOINSTR }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_12_C7[8] = // C7 (NOTE: AMD64 labels this Group 11)
+{
+ { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOINSTR }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+// NOTE: the X86_SSE2_* is only followed if it is a 3-byte opcode (e.g., prefix is 66, F2, or F3)
+X86_OPCODE X86_Group_13[8] = // 0F 71 (NOTE: AMD64 labels this Group 12)
+{
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlw", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psraw", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllw", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_14[8] = // 0F 72 (NOTE: AMD64 labels this Group 13)
+{
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrld", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrad", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pslld", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_15[8] = // 0F 73 (NOTE: AMD64 labels this Group 14)
+{
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrldq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pslldq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED } /* 0x07 */
+};
+
+X86_OPCODE X86_Group_16[8] = // 0F AE (NOTE: AMD64 labels this Group 15)
+{
+ { NOGROUP, CPU_PENTIUM2, ITYPE_FPU, "fxsave", { AMODE_M | OPTYPE_fst2 | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_FPU, "fxrstor", { AMODE_M | OPTYPE_fst2 | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "ldmxcsr", { AMODE_M | OPTYPE_d | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "stmxcsr", { AMODE_M | OPTYPE_d | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "lfence", NOARGS, NOCOND, NOCHANGE, SERIALIZE_READ, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "mfence", NOARGS, NOCOND, NOCHANGE, SERIALIZE_ALL, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "sfence", NOARGS, NOCOND, NOCHANGE, SERIALIZE_WRITE, IGNORED } /* 0x07 */
+};
+
+X86_OPCODE X86_Group_17[8] = // 0F 18 (NOTE: AMD64 labels this Group 16)
+{
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetchnta", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetcht0", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetcht1", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetcht2", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x05 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */
+};
+
+X86_OPCODE X86_Group_P[8] = // 0F 0D
+{
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "prefetch", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "prefetchw", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// FPU (ESC) opcodes
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+
+X86_OPCODE X86_ESC_0[0x48] = // D8
+{
+ //
+ // ModRM < C0
+ // Index 0x00-0x07 = opcode extension
+ //
+
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x00
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x01
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { AMODE_M | OPTYPE_ss | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // 0x02
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { AMODE_M | OPTYPE_ss | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // 0x03
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x04
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x05
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x06
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x07
+
+ //
+ // ModRM >= C0: ST(0) <- ST(0) + ST(i)
+ // Index 0x08-0x47 = ModRM 0xC0-0xFF
+ //
+
+ // C0-C7
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7
+ // C8-CF
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+ // D0-D7
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x7
+ // D8-DF
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xF
+ // E0-E7
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7
+ // E8-EF
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF
+ // F0-F7
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7
+ // F8-FF
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED } // xF
+};
+
+
+X86_OPCODE X86_ESC_1[0x48] = // D9
+{
+ //
+ // ModRM < C0
+ // Index 0x00-0x07 = opcode extension
+ //
+
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { AMODE_M | OPTYPE_ss | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x00
+ { NOINSTR }, // 0x01
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { AMODE_M | OPTYPE_ss | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x02
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { AMODE_M | OPTYPE_ss | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x03
+ { NOGROUP, CPU_I287, ITYPE_FLOADENV, "fldenv", { AMODE_M | OPTYPE_fev | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // 0x04
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldcw", { OPTYPE_FPU_CONTROL | OP_DST, AMODE_M | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // 0x05
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstenv", { AMODE_M | OPTYPE_fev | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // 0x06
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fnstcw", { AMODE_M | OPTYPE_w | OP_DST, OPTYPE_FPU_CONTROL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // 0x07
+
+ //
+ // ModRM >= C0
+ // Index 0x08-0x47 = ModRM 0xC0-0xFF
+ //
+
+ // C0-C7
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x7
+ // C8-CF
+ { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF
+ // D0-D7
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fnop", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // D8-DF
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+ // E0-E7
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fchs", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fabs", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FPU, "ftst", { OPTYPE_ST0 | OP_SRC, OPTYPE_FLDZ | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fxam", { OPTYPE_ST0 | OP_SRC, 0, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // E8-EF
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld1", { OPTYPE_FLD1 | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldl2t", { OPTYPE_FLDL2T | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldl2e", { OPTYPE_FLDL2E | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldpi", { OPTYPE_FLDPI | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldlg2", { OPTYPE_FLDLG2| OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldln2", { OPTYPE_FLDLN2 | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldz", { OPTYPE_FLDZ | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xE
+ { NOINSTR }, // xF
+ // F0-F7
+ { NOGROUP, CPU_I287, ITYPE_FPU, "f2xm1", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fyl2x", { OPTYPE_ST1 | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fptan", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, FPU_STACK_PUSH, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fpatan", { OPTYPE_ST1 | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC , 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fxtract", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_DST, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x4
+ { NOGROUP, CPU_I387, ITYPE_FPU, "fprem1", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fdecstp", NOARGS, NOCOND, FPU_C1_MOD, FPU_STACK_DEC, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fincstp", NOARGS, NOCOND, FPU_C1_MOD, FPU_STACK_INC, IGNORED }, // x7
+ // F8-FF
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fprem", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fyl2xp1", { OPTYPE_ST1 | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fsqrt", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fsincos", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, FPU_STACK_PUSH, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FPU, "frndint", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fscale", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fsin", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fcos", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, NOACTION, IGNORED } // xF
+};
+
+
+X86_OPCODE X86_ESC_2[0x48] = // DA
+{
+ //
+ // ModRM < C0
+ // Index 0x00-0x07 = opcode extension
+ //
+
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fiadd", { OPTYPE_ST0 | OP_SIGNED | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fimul", { OPTYPE_ST0 | OP_SIGNED | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficom", { AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC | OP_DST, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficomp", { AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC | OP_DST, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fisub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fisubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fidiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fidivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7
+
+ //
+ // ModRM >= C0
+ // Index 0x08-0x47 = ModRM 0xC0-0xFF
+ //
+
+ // C0-C7
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7
+ // C8-CF
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF
+ // D0-D7
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7
+ // D8-DF
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF
+ // E0-E7
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // E8-EF
+ { NOINSTR }, // x8
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucompp", { OPTYPE_ST1 | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP2, IGNORED }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+ // F0-F7
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // F8-FF
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR } // xF
+};
+
+
+
+X86_OPCODE X86_ESC_3[0x48] = // DB
+{
+ //
+ // ModRM < C0
+ // Index 0x00-0x07 = opcode extension
+ //
+
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fild", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x00
+ { NOGROUP, CPU_PENTIUM4, ITYPE_FSTORE, "fisttp", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x01
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fist", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x02
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fistp", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x03
+ { NOINSTR }, // 0x04
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { AMODE_M | OPTYPE_se | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x05
+ { NOINSTR }, // 0x06
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { AMODE_M | OPTYPE_se | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x07
+
+ //
+ // ModRM >= C0
+ // Index 0x08-0x47 = ModRM 0xC0-0xFF
+ //
+
+ // C0-C7
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7
+ // C8-CF
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF
+ // D0-D7
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7
+ // D8-DF
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF
+ // E0-E7
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FPU, "fnclex", { OPTYPE_FPU_STATUS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FPU, "finit", { OPTYPE_FPU_STATUS | OP_DST, 0, 0 }, NOCOND, FPU_ALL_CLR, NOACTION, IGNORED }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // E8-EF
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xF
+ // F0-F7
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x7
+ // F8-FF
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR } // xF
+};
+
+X86_OPCODE X86_ESC_4[0x48] = // DC
+{
+ //
+ // ModRM < C0
+ // Index 0x00-0x07 = opcode extension
+ //
+
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x00
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x01
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // 0x02
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // 0x03
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x04
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x05
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x06
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x07
+
+ //
+ // ModRM >= C0
+ // Index 0x08-0x47 = ModRM 0xC0-0xFF
+ //
+
+ // C0-C7
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7
+ // C8-CF
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF
+ // D0-D7
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // D8-DF
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+ // E0-E7
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7
+ // E8-EF
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF
+ // F0-F7
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7
+ // F8-FF
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED } // xF
+};
+
+
+X86_OPCODE X86_ESC_5[0x48] = // DD
+{
+ //
+ // ModRM < C0
+ // Index 0x00-0x07 = opcode extension
+ //
+ //
+
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { AMODE_M | OPTYPE_sd | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_FSTORE, "fisttp", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FRESTORE, "frstor", { AMODE_M | OPTYPE_fst1 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x4
+ { NOINSTR }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FSAVE, "fsave", { AMODE_M | OPTYPE_fst1 | OP_DST, 0 }, NOCOND, FPU_ALL_CLR, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fnstsw", { AMODE_M | OPTYPE_w | OP_DST, OPTYPE_FPU_STATUS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7
+
+ //
+ // ModRM >= C0
+ // Index 0x08-0x47 = ModRM 0xC0-0xFF
+ //
+
+ // C0-C7
+ { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7
+ // C8-CF
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+ // D0-D7
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7
+ // D8-DF
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xF
+ // E0-E7
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x7
+ // E8-EF
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x8
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x9
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xB
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xC
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xD
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xE
+ { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xF
+ // F0-F7
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // F8-FF
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR } // xF
+};
+
+
+X86_OPCODE X86_ESC_6[0x48] = // DE
+{
+ //
+ // ModRM < C0
+ // Index 0x00-0x07 = opcode extension
+ //
+
+ { NOGROUP, CPU_I287, ITYPE_FADD, "fiadd", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x00
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fimul", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x01
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficom", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // 0x02
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficomp", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // 0x03
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fisub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x04
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fisubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x05
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fidiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x06
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fidivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x07
+ //
+ // ModRM >= C0
+ // Index 0x08-0x47 = ModRM 0xC0-0xFF
+ //
+
+ // C0-C7
+ { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x7
+ // C8-CF
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xF
+ // D0-D7
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // D8-DF
+ { NOINSTR }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcompp", { OPTYPE_ST1 | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP2, IGNORED }, // x9
+ { NOINSTR }, // 0xA
+ { NOINSTR }, // 0xB
+ { NOINSTR }, // 0xC
+ { NOINSTR }, // 0xD
+ { NOINSTR }, // 0xE
+ { NOINSTR }, // 0xF
+ // E0-E7
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x7
+ // E8-EF
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xF
+ // F0-F7
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x0
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x2
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x4
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x5
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x6
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x7
+ // F8-FF
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE
+ { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED } // xF
+};
+
+
+X86_OPCODE X86_ESC_7[0x48] = // DF
+{
+ //
+ // ModRM < C0
+ // Index 0x00-0x07 = opcode extension
+ //
+
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fild", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0, 0}, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x00
+ { NOGROUP, CPU_PENTIUM4, ITYPE_FSTORE, "fisttp", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x01
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fist", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x02
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fistp", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x03
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fbld", { AMODE_M | OPTYPE_pb | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x04
+ { NOGROUP, CPU_I287, ITYPE_FLOAD, "fild", { AMODE_M | OPTYPE_q | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x05
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fbstp", { AMODE_M | OPTYPE_pb | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x06
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fistp", { AMODE_M | OPTYPE_q | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0}, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x07
+
+ //
+ // ModRM >= C0
+ // Index 0x08-0x47 = ModRM 0xC0-0xFF
+ //
+ // C0-C7
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // C8-CF
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+ // D0-D7
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // D8-DF
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+ // E0-E7
+ { NOGROUP, CPU_I287, ITYPE_FSTORE, "fnstsw", { OPTYPE_REG_AX | OP_DST, OPTYPE_FPU_STATUS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ // E8-EF
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x8
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x9
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xA
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xB
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xF
+ // F0-F7
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x0
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x1
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x2
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x3
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x4
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x5
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x6
+ { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x7
+ // F8-FF
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR } // xF
+};
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// SSE opcodes
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+X86_OPCODE X86_SSE[0x300] =
+{
+ // prefix 0x66 (operand size)
+ /* 0x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 1x */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movupd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movupd", { AMODE_W | OPTYPE_pd | OP_DST, AMODE_V | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movlpd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_M | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movlpd", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "unpcklpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "unpckhpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movhpd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_M | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "mpvhpd", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 2x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movapd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movapd", { AMODE_W | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpi2pd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movntpd", { AMODE_M | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttpd2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpd2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "ucomisd", { AMODE_V | OPTYPE_sd | OP_SRC, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "comisd", { AMODE_V | OPTYPE_pd | OP_SRC, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, // xF
+
+ /* 3x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 4x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 5x */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "movmskpd", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "sqrtpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "andpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "andnpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_OR, "orpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_XOR, "xorpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "addpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "mulpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpd2ps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtps2dq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "subpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "minpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_DIV, "divpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maxpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+
+ /* 6x */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpcklbw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpcklwd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckldq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "packsswb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pcmpgtb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pcmpgtw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pcmpgtd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "packuswb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhbw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhwd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhdq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "packssdw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpcklqdq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhqdq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqa", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+
+ /* 7x */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pshufd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { X86_SSE2_Group_13, GROUP }, // x1
+ { X86_SSE2_Group_14, GROUP }, // x2
+ { X86_SSE2_Group_15, GROUP }, // x3
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "pcmpeqb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "pcmpeqw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "pcmpeqd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_ADD, "haddpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_SUB, "hsubpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movd", { AMODE_E | OPTYPE_dq | OP_DST, AMODE_V | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqa", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+
+ /* 8x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 9x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Ax */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Bx */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Cx */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "cmppd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, // x2
+ { NOINSTR }, // x3
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pinsrw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pextrw", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR| OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "shufpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Dx */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3, "addsubpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrld", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmullw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movq", { AMODE_W | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pmovmskb", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR| OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubusb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubusw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pminub", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "pand", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddusb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddusw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pmaxub", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "pandn", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+
+ /* Ex */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pavgb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psraw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrad", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pavgw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmulhuw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmulhw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttpd2dq", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movntdq", { AMODE_M | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubsb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubsw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pminsw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_OR, "por", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddsb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddsw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pmaxuw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_XOR, "pxor", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+
+ /* Fx */
+ { NOINSTR }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pslld", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmuludq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "pmaddwd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psadbw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maskmovdqu", { AMODE_V | OPTYPE_o | OP_DST, AMODE_VR| OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE
+ { NOINSTR }, // xF
+
+ // prefix 0xf2 (repne)
+ /* 0x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 1x */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movsd", { AMODE_V | OPTYPE_sdo | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movsd", { AMODE_W | OPTYPE_sd | OP_DST, AMODE_V | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_MOV, "movddup", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 2x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtsi2sd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOINSTR }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttsd2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtsd2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 3x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 4x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 5x */
+ { NOINSTR }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "sqrtsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "addsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "mulsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtsd2ss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOINSTR }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "subsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "minsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_DIV, "divsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maxsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+
+ /* 6x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqa", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+
+ /* 7x */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pshuflw", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_ADD, "haddps", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_SUB, "hsubps", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 8x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 9x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Ax */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Bx */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Cx */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "cmpsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Dx */
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE3, "addsubps", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdq2q", { AMODE_P | OPTYPE_q | OP_DST, AMODE_VR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Ex */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpd2dq", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Fx */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3, "lddqu", { AMODE_V | OPTYPE_o | OP_DST, AMODE_M | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ // prefix 0xf3 (rep)
+ /* 0x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 1x */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movss", { AMODE_V | OPTYPE_sso | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movss", { AMODE_W | OPTYPE_ss | OP_DST, AMODE_V | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_MOV, "movsldup", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_MOV, "movshdup", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 2x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtsi2ss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOINSTR }, // xB
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvttss2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtss2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 3x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 4x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 5x */
+ { NOINSTR }, // x0
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "sqrtss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "rsqrtss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "rcpss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "addss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "mulss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtss2sd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttps2dq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "subss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "minss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_DIV, "divss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maxss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+
+ /* 6x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqu", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+
+ /* 7x */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pshufhw", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movq", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqu", { AMODE_W | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF
+
+ /* 8x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* 9x */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Ax */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Bx */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Cx */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "cmpss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Dx */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movq2dq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Ex */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtdq2pd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR }, // xF
+
+ /* Fx */
+ { NOINSTR }, // x0
+ { NOINSTR }, // x1
+ { NOINSTR }, // x2
+ { NOINSTR }, // x3
+ { NOINSTR }, // x4
+ { NOINSTR }, // x5
+ { NOINSTR }, // x6
+ { NOINSTR }, // x7
+ { NOINSTR }, // x8
+ { NOINSTR }, // x9
+ { NOINSTR }, // xA
+ { NOINSTR }, // xB
+ { NOINSTR }, // xC
+ { NOINSTR }, // xD
+ { NOINSTR }, // xE
+ { NOINSTR } // xF
+};
+
+X86_OPCODE X86_SSE2_Group_13[24] = // 66/F2/F3 0F 71
+{
+ // prefix 0x66 (operand size)
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlw", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psraw", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllw", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+
+ // prefix 0xf2 (repne)
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOINSTR }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+
+ // prefix 0xf3 (rep)
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOINSTR }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+X86_OPCODE X86_SSE2_Group_14[24] = // 66/F2/F3 0F 72
+{
+ // prefix 0x66 (operand size)
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrld", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrad", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pslld", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+
+ // prefix 0xf2 (repne)
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOINSTR }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+
+ // prefix 0xf3 (rep)
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOINSTR }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+X86_OPCODE X86_SSE2_Group_15[24] =
+{
+ // prefix 0x66 (operand size)
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrldq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */
+ { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pslldq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */
+
+ // prefix 0xf2 (repne)
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOINSTR }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+
+ // prefix 0xf3 (rep)
+ { NOINSTR }, /* 0x00 */
+ { NOINSTR }, /* 0x01 */
+ { NOINSTR }, /* 0x02 */
+ { NOINSTR }, /* 0x03 */
+ { NOINSTR }, /* 0x04 */
+ { NOINSTR }, /* 0x05 */
+ { NOINSTR }, /* 0x06 */
+ { NOINSTR }, /* 0x07 */
+};
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// 3DNow opcodes
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+X86_OPCODE X86_3DNOW_0F[0x100] =
+{
+ { NOINSTR }, /* 00 */
+ { NOINSTR }, /* 01 */
+ { NOINSTR }, /* 02 */
+ { NOINSTR }, /* 03 */
+ { NOINSTR }, /* 04 */
+ { NOINSTR }, /* 05 */
+ { NOINSTR }, /* 06 */
+ { NOINSTR }, /* 07 */
+ { NOINSTR }, /* 08 */
+ { NOINSTR }, /* 09 */
+ { NOINSTR }, /* 0A */
+ { NOINSTR }, /* 0B */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pi2fw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0C */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pi2fd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0D */
+ { NOINSTR }, /* 0E */
+ { NOINSTR }, /* 0F */
+ { NOINSTR }, /* 10 */
+ { NOINSTR }, /* 11 */
+ { NOINSTR }, /* 12 */
+ { NOINSTR }, /* 13 */
+ { NOINSTR }, /* 14 */
+ { NOINSTR }, /* 15 */
+ { NOINSTR }, /* 16 */
+ { NOINSTR }, /* 17 */
+ { NOINSTR }, /* 18 */
+ { NOINSTR }, /* 19 */
+ { NOINSTR }, /* 1A */
+ { NOINSTR }, /* 1B */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pf2iw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 1C */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pf2id", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 1D */
+ { NOINSTR }, /* 1E */
+ { NOINSTR }, /* 1F */
+ { NOINSTR }, /* 20 */
+ { NOINSTR }, /* 21 */
+ { NOINSTR }, /* 22 */
+ { NOINSTR }, /* 23 */
+ { NOINSTR }, /* 24 */
+ { NOINSTR }, /* 25 */
+ { NOINSTR }, /* 26 */
+ { NOINSTR }, /* 27 */
+ { NOINSTR }, /* 28 */
+ { NOINSTR }, /* 29 */
+ { NOINSTR }, /* 2A */
+ { NOINSTR }, /* 2B */
+ { NOINSTR }, /* 2C */
+ { NOINSTR }, /* 2D */
+ { NOINSTR }, /* 2E */
+ { NOINSTR }, /* 2F */
+ { NOINSTR }, /* 30 */
+ { NOINSTR }, /* 31 */
+ { NOINSTR }, /* 32 */
+ { NOINSTR }, /* 33 */
+ { NOINSTR }, /* 34 */
+ { NOINSTR }, /* 35 */
+ { NOINSTR }, /* 36 */
+ { NOINSTR }, /* 37 */
+ { NOINSTR }, /* 38 */
+ { NOINSTR }, /* 39 */
+ { NOINSTR }, /* 3A */
+ { NOINSTR }, /* 3B */
+ { NOINSTR }, /* 3C */
+ { NOINSTR }, /* 3D */
+ { NOINSTR }, /* 3E */
+ { NOINSTR }, /* 3F */
+ { NOINSTR }, /* 40 */
+ { NOINSTR }, /* 41 */
+ { NOINSTR }, /* 42 */
+ { NOINSTR }, /* 43 */
+ { NOINSTR }, /* 44 */
+ { NOINSTR }, /* 45 */
+ { NOINSTR }, /* 46 */
+ { NOINSTR }, /* 47 */
+ { NOINSTR }, /* 48 */
+ { NOINSTR }, /* 49 */
+ { NOINSTR }, /* 4A */
+ { NOINSTR }, /* 4B */
+ { NOINSTR }, /* 4C */
+ { NOINSTR }, /* 4D */
+ { NOINSTR }, /* 4E */
+ { NOINSTR }, /* 4F */
+ { NOINSTR }, /* 50 */
+ { NOINSTR }, /* 51 */
+ { NOINSTR }, /* 52 */
+ { NOINSTR }, /* 53 */
+ { NOINSTR }, /* 54 */
+ { NOINSTR }, /* 55 */
+ { NOINSTR }, /* 56 */
+ { NOINSTR }, /* 57 */
+ { NOINSTR }, /* 58 */
+ { NOINSTR }, /* 59 */
+ { NOINSTR }, /* 5A */
+ { NOINSTR }, /* 5B */
+ { NOINSTR }, /* 5C */
+ { NOINSTR }, /* 5D */
+ { NOINSTR }, /* 5E */
+ { NOINSTR }, /* 5F */
+ { NOINSTR }, /* 60 */
+ { NOINSTR }, /* 61 */
+ { NOINSTR }, /* 62 */
+ { NOINSTR }, /* 63 */
+ { NOINSTR }, /* 64 */
+ { NOINSTR }, /* 65 */
+ { NOINSTR }, /* 66 */
+ { NOINSTR }, /* 67 */
+ { NOINSTR }, /* 68 */
+ { NOINSTR }, /* 69 */
+ { NOINSTR }, /* 6A */
+ { NOINSTR }, /* 6B */
+ { NOINSTR }, /* 6C */
+ { NOINSTR }, /* 6D */
+ { NOINSTR }, /* 6E */
+ { NOINSTR }, /* 6F */
+ { NOINSTR }, /* 70 */
+ { NOINSTR }, /* 71 */
+ { NOINSTR }, /* 72 */
+ { NOINSTR }, /* 73 */
+ { NOINSTR }, /* 74 */
+ { NOINSTR }, /* 75 */
+ { NOINSTR }, /* 76 */
+ { NOINSTR }, /* 77 */
+ { NOINSTR }, /* 78 */
+ { NOINSTR }, /* 79 */
+ { NOINSTR }, /* 7A */
+ { NOINSTR }, /* 7B */
+ { NOINSTR }, /* 7C */
+ { NOINSTR }, /* 7D */
+ { NOINSTR }, /* 7E */
+ { NOINSTR }, /* 7F */
+ { NOINSTR }, /* 80 */
+ { NOINSTR }, /* 81 */
+ { NOINSTR }, /* 82 */
+ { NOINSTR }, /* 83 */
+ { NOINSTR }, /* 84 */
+ { NOINSTR }, /* 85 */
+ { NOINSTR }, /* 86 */
+ { NOINSTR }, /* 87 */
+ { NOINSTR }, /* 88 */
+ { NOINSTR }, /* 89 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfnacc", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 8A */
+ { NOINSTR }, /* 8B */
+ { NOINSTR }, /* 8C */
+ { NOINSTR }, /* 8D */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfpnacc", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 8E */
+ { NOINSTR }, /* 8F */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_CMP, "pfcmpge", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 90 */
+ { NOINSTR }, /* 91 */
+ { NOINSTR }, /* 92 */
+ { NOINSTR }, /* 93 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfmin", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 94 */
+ { NOINSTR }, /* 95 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrcp", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 96 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrsqrt", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 97 */
+ { NOINSTR }, /* 98 */
+ { NOINSTR }, /* 99 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_SUB, "pfsub", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 9A */
+ { NOINSTR }, /* 9B */
+ { NOINSTR }, /* 9C */
+ { NOINSTR }, /* 9D */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_ADD, "pfadd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 9E */
+ { NOINSTR }, /* 9F */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_CMP, "pfcmpgt", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A0 */
+ { NOINSTR }, /* A1 */
+ { NOINSTR }, /* A2 */
+ { NOINSTR }, /* A3 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfmax", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A4 */
+ { NOINSTR }, /* A5 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrcpit1", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A6 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrsqit1", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A7 */
+ { NOINSTR }, /* A8 */
+ { NOINSTR }, /* A9 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_SUB, "pfsubr", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* AA */
+ { NOINSTR }, /* AB */
+ { NOINSTR }, /* AC */
+ { NOINSTR }, /* AD */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfacc", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* AE */
+ { NOINSTR }, /* AF */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_CMP, "pfcmpeq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B0 */
+ { NOINSTR }, /* B1 */
+ { NOINSTR }, /* B2 */
+ { NOINSTR }, /* B3 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_MUL, "pfmul", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B4 */
+ { NOINSTR }, /* B5 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrcpit2", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B6 */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_MUL, "pmulhrw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B7 */
+ { NOINSTR }, /* B8 */
+ { NOINSTR }, /* B9 */
+ { NOINSTR }, /* BA */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_XCHG, "pswapd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* BB */
+ { NOINSTR }, /* BC */
+ { NOINSTR }, /* BD */
+ { NOINSTR }, /* BE */
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pavgb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* BF */
+ { NOINSTR }, /* C0 */
+ { NOINSTR }, /* C1 */
+ { NOINSTR }, /* C2 */
+ { NOINSTR }, /* C3 */
+ { NOINSTR }, /* C4 */
+ { NOINSTR }, /* C5 */
+ { NOINSTR }, /* C6 */
+ { NOINSTR }, /* C7 */
+ { NOINSTR }, /* C8 */
+ { NOINSTR }, /* C9 */
+ { NOINSTR }, /* CA */
+ { NOINSTR }, /* CB */
+ { NOINSTR }, /* CC */
+ { NOINSTR }, /* CD */
+ { NOINSTR }, /* CE */
+ { NOINSTR }, /* CF */
+ { NOINSTR }, /* D0 */
+ { NOINSTR }, /* D1 */
+ { NOINSTR }, /* D2 */
+ { NOINSTR }, /* D3 */
+ { NOINSTR }, /* D4 */
+ { NOINSTR }, /* D5 */
+ { NOINSTR }, /* D6 */
+ { NOINSTR }, /* D7 */
+ { NOINSTR }, /* D8 */
+ { NOINSTR }, /* D9 */
+ { NOINSTR }, /* DA */
+ { NOINSTR }, /* DB */
+ { NOINSTR }, /* DC */
+ { NOINSTR }, /* DD */
+ { NOINSTR }, /* DE */
+ { NOINSTR }, /* DF */
+ { NOINSTR }, /* E0 */
+ { NOINSTR }, /* E1 */
+ { NOINSTR }, /* E2 */
+ { NOINSTR }, /* E3 */
+ { NOINSTR }, /* E4 */
+ { NOINSTR }, /* E5 */
+ { NOINSTR }, /* E6 */
+ { NOINSTR }, /* E7 */
+ { NOINSTR }, /* E8 */
+ { NOINSTR }, /* E9 */
+ { NOINSTR }, /* EA */
+ { NOINSTR }, /* EB */
+ { NOINSTR }, /* EC */
+ { NOINSTR }, /* ED */
+ { NOINSTR }, /* EE */
+ { NOINSTR }, /* EF */
+ { NOINSTR }, /* F0 */
+ { NOINSTR }, /* F1 */
+ { NOINSTR }, /* F2 */
+ { NOINSTR }, /* F3 */
+ { NOINSTR }, /* F4 */
+ { NOINSTR }, /* F5 */
+ { NOINSTR }, /* F6 */
+ { NOINSTR }, /* F7 */
+ { NOINSTR }, /* F8 */
+ { NOINSTR }, /* F9 */
+ { NOINSTR }, /* FA */
+ { NOINSTR }, /* FB */
+ { NOINSTR }, /* FC */
+ { NOINSTR }, /* FD */
+ { NOINSTR }, /* FE */
+ { NOINSTR } /* FF */
+};
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// 64-bit replacement opcodes
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+X86_OPCODE X86_Opcode_63[2] =
+{
+ { NOGROUP, CPU_I386, ITYPE_SYSTEM, "arpl", { AMODE_E | OPTYPE_w | OP_SRC, AMODE_G | OPTYPE_w | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, // !ARCH_AMD64
+ { NOGROUP, CPU_AMD64, ITYPE_MOV, "movsxd", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_d | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED } // ARCH_AMD64
+};
+
+X86_OPCODE X86_Opcode_0F05[2] =
+{
+ { NOGROUP, CPU_AMD_K6_2, ITYPE_SYSCALL, "syscall", { OPTYPE_STAR_MSR | OP_MSR | OP_SRC, OPTYPE_CSTAR_MSR | OP_MSR | OP_SRC, OPTYPE_FMASK_MSR | OP_MSR | OP_SRC }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, // !ARCH_AMD64
+ { NOGROUP, CPU_AMD64, ITYPE_SYSCALL, "syscall", { OPTYPE_STAR_MSR | OP_MSR | OP_SRC, OPTYPE_LSTAR_MSR | OP_MSR | OP_SRC, OPTYPE_FMASK_MSR | OP_MSR | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED } // ARCH_AMD64
+};
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// Other 3 byte opcodes
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+// Three byte opcodes where the third opcode byte is ModRM
+X86_OPCODE X86_0F01_ModRM[0x100] =
+{
+ /* 0x */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* 1x */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* 2x */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* 3x */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* 4x */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* 5x */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* 6x */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* 7x */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* 8x */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* 9x */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* Ax */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* Bx */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* Cx */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { NOGROUP, CPU_PRESCOTT, ITYPE_SYSTEM, "monitor", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { NOGROUP, CPU_PRESCOTT, ITYPE_SYSTEM, "mwait", NOARGS, NOCOND, NOCHANGE, SERIALIZE_ALL, IGNORED }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* Dx */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* Ex */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { X86_Group_7, GROUP }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP }, // xF
+
+ /* Fx */
+ { X86_Group_7, GROUP }, // x0
+ { X86_Group_7, GROUP }, // x1
+ { X86_Group_7, GROUP }, // x2
+ { X86_Group_7, GROUP }, // x3
+ { X86_Group_7, GROUP }, // x4
+ { X86_Group_7, GROUP }, // x5
+ { X86_Group_7, GROUP }, // x6
+ { X86_Group_7, GROUP }, // x7
+ { NOGROUP, CPU_AMD64, ITYPE_SYSTEM, "swapgs", { OPTYPE_KERNELBASE_MSR | OP_MSR | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8
+ { X86_Group_7, GROUP }, // x9
+ { X86_Group_7, GROUP }, // xA
+ { X86_Group_7, GROUP }, // xB
+ { X86_Group_7, GROUP }, // xC
+ { X86_Group_7, GROUP }, // xD
+ { X86_Group_7, GROUP }, // xE
+ { X86_Group_7, GROUP } // xF
+};
+
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+// Sanity checking tables
+/////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////
+
+#define S2 1 // SSE2
+#define S3 2 // SSE3
+BYTE X86_ModRM_1[0x100] =
+{
+ // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
+ /* 0x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
+ /* 1x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
+ /* 2x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
+ /* 3x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
+ /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 6x */ 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0,
+ /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 8x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Cx */ 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Dx */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Fx */ 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1
+};
+BYTE X86_ModRM_2[0x100] =
+{
+ // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
+ /* 0x */ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
+ /* 1x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,
+ /* 2x */ 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 4x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 6x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 7x */ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 9x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* Ax */ 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1,
+ /* Bx */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,
+ /* Cx */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Dx */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* Ex */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* Fx */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0
+};
+
+BYTE X86_SSE_2[0x100] =
+{
+ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 1x */ 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0,
+ /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 5x */ 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1,
+ /* 7x */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Cx */ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Dx */ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Ex */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Fx */ 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+// Indicates if a LOCK prefix is allowed
+// The following are allowed:
+// add, adc, and, btc, btr, bts, cmpxchg, cmpxchg8, dec, inc,
+// neg, not, or, sbb, sub, xor, xadd, xchg
+#define GR 2
+BYTE X86_LockPrefix_1[0x100] =
+{
+ // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
+ /* 0x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
+ /* 1x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
+ /* 2x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
+ /* 3x */ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 8x */ GR, GR, GR, GR, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Fx */ 0, 0, 0, 0, 0, 0, GR, GR, 0, 0, 0, 0, 0, 0, GR, GR
+};
+
+BYTE X86_LockPrefix_2[0x100] =
+{
+ // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
+ /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ /* Bx */ 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, GR, 1, 0, 0, 0, 0,
+ /* Cx */ 1, 1, 0, 0, 0, 0, 0, GR, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+BYTE X86_LockPrefix_Groups[17][8] =
+{
+// x0 x1 x2 x3 x4 x5 x6 x7
+ { 1, 1, 1, 1, 1, 1, 1, 0 }, // group 1
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 2
+ { 0, 0, 1, 1, 0, 0, 0, 0 }, // group 3
+ { 1, 1, 0, 0, 0, 0, 0, 0 }, // group 4
+ { 1, 1, 0, 0, 0, 0, 0, 0 }, // group 5
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 6
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 7
+ { 0, 0, 0, 0, 1, 1, 1, 1 }, // group 8
+ { 0, 1, 0, 0, 0, 0, 0, 0 }, // group 9
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 10
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 11
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 12
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 13
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 14
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 15
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 16
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 17
+};
+
+#define X86_MAX_GROUP 19
+BYTE X86_Groups_1[0x100] = // one-byte opcodes
+{
+ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
+ /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
+ /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
+ /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */
+ /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
+ /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */
+ /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
+ /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */
+ /* 8x */ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, /* 8x */
+ /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */
+ /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */
+ /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
+ /* Cx */ 2, 2, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */
+ /* Dx */ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */
+ /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */
+ /* Fx */ 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 4, 5 /* Fx */
+};
+
+// 19 = Group P
+// 20 = 3DNow
+BYTE X86_Groups_2[0x100] = // two-byte opcodes
+{
+ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ /* 0x */ 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 19, /* 0x */
+ /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, /* 1x */
+ /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
+ /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */
+ /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
+ /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */
+ /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
+ /* 7x */ 0, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */
+ /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */
+ /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */
+ /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, /* Ax */
+ /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 8, 0, 0, 0, 0, 0, /* Bx */
+ /* Cx */ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */
+ /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */
+ /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */
+ /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */
+};
+
+// Indicate which 1-byte opcodes are invalid with a 16-bit operand size
+BYTE X86_Invalid_Op16_1[0x100] =
+{
+ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
+ /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
+ /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
+ /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */
+ /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
+ /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */
+ /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
+ /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */
+ /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */
+ /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */
+ /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */
+ /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
+ /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */
+ /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */
+ /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */
+ /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */
+};
+
+// Indicate which 2-byte opcodes are invalid with a 16-bit operand size
+BYTE X86_Invalid_Op16_2[0x100] =
+{
+ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
+ /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
+ /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
+ /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */
+ /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
+ /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */
+ /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
+ /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */
+ /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */
+ /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */
+ /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */
+ /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
+ /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* Cx */
+ /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */
+ /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */
+ /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */
+};
+
+// Indicate which 1-byte opcodes are invalid with a 64-bit address size
+BYTE X86_Invalid_Addr64_1[0x100] =
+{
+ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ /* 0x */ 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, /* 0x */
+ /* 1x */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* 1x */
+ /* 2x */ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, /* 2x */
+ /* 3x */ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, /* 3x */
+ /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
+ /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */
+ /* 6x */ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
+ /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */
+ /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */
+ /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* 9x */
+ /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */
+ /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
+ /* Cx */ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* Cx */
+ /* Dx */ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */
+ /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* Ex */
+ /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */
+};
+
+// Indicate which 2-byte opcodes are invalid with a 64-bit address size
+BYTE X86_Invalid_Addr64_2[0x100] =
+{
+ /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */
+ /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */
+ /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */
+ /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */
+ /* 3x */ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */
+ /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */
+ /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */
+ /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */
+ /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */
+ /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */
+ /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */
+ /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */
+ /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */
+ /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */
+ /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */
+ /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */
+ /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */
+};
+
+#endif // DISASM_X86_TABLES \ No newline at end of file
diff --git a/thirdparty/mhook/disasm-lib/misc.c b/thirdparty/mhook/disasm-lib/misc.c
new file mode 100644
index 00000000..c5b0ac61
--- /dev/null
+++ b/thirdparty/mhook/disasm-lib/misc.c
@@ -0,0 +1,185 @@
+// Copyright (C) 2002, Matt Conover (mconover@gmail.com)
+#include "misc.h"
+
+BOOL IsHexChar(BYTE ch)
+{
+ switch (ch)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ case '8': case '9':
+ case 'A': case 'a': case 'B': case 'b':
+ case 'C': case 'c': case 'D': case 'd':
+ case 'E': case 'e': case 'F': case 'f':
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+// NOTE: caller must free the buffer returned
+BYTE *HexToBinary(char *Input, DWORD InputLength, DWORD *OutputLength)
+{
+ DWORD i, j, ByteCount = 0;
+ char temp_byte[3];
+ BYTE *p, *ByteString = NULL;
+
+ if (!InputLength || !OutputLength) return NULL;
+ else *OutputLength = 0;
+
+ while (*Input && isspace(*Input)) { Input++; InputLength--; }
+ if (!*Input) return NULL;
+ if (Input[0] == '\"') { Input++; InputLength--; }
+ p = (BYTE *)strchr(Input, '\"');
+ if (p) InputLength--;
+
+ if (InputLength > 2 && Input[2] == ' ') // assume spaces
+ {
+ for (i = 0; i < InputLength; i += 3)
+ {
+ while (i < InputLength && isspace(Input[i])) i++; // skip over extra space, \r, and \n
+ if (i >= InputLength) break;
+
+ if (!IsHexChar(Input[i]))
+ {
+ //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i);
+ goto abort;
+ }
+
+ if (i+1 >= InputLength || !Input[i+1])
+ {
+ //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1);
+ goto abort;
+ }
+
+ if (i+2 < InputLength && Input[i+2] && !isspace(Input[i+2]))
+ {
+ //fprintf(stderr, "ERROR: Hex string is malformed at offset %lu (0x%04x)\n", i, i);
+ //fprintf(stderr, "Found '%c' (0x%02x) instead of space\n", Input[i+2], Input[i+2]);
+ goto abort;
+ }
+
+ ByteCount++;
+ }
+
+ if (!ByteCount)
+ {
+ //fprintf(stderr, "Error: no input (byte count = 0)\n");
+ goto abort;
+ }
+
+ ByteString = malloc(ByteCount+1);
+ if (!ByteString)
+ {
+ //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount);
+ goto abort;
+ }
+
+ memset(ByteString, 0, ByteCount+1);
+ for (i = 0, j = 0; j < ByteCount; i += 3, j++)
+ {
+ while (isspace(Input[i])) i++; // skip over extra space, \r, and \n
+ temp_byte[0] = Input[i];
+ temp_byte[1] = Input[i+1];
+ temp_byte[2] = 0;
+ ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16);
+ }
+ }
+ else if (InputLength > 2 && Input[0] == '\\')
+ {
+ for (i = 0; i < InputLength; i += 2)
+ {
+ if (Input[i] != '\\' || (Input[i+1] != 'x' && Input[i+1] != '0'))
+ {
+ //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i);
+ goto abort;
+ }
+ i += 2;
+
+ if (!IsHexChar(Input[i]))
+ {
+ //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i);
+ goto abort;
+ }
+ if (i+1 >= InputLength || !Input[i+1])
+ {
+ //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1);
+ goto abort;
+ }
+
+ ByteCount++;
+ }
+
+ if (!ByteCount)
+ {
+ //fprintf(stderr, "Error: no input (byte count = 0)\n");
+ goto abort;
+ }
+
+ ByteString = malloc(ByteCount+1);
+ if (!ByteString)
+ {
+ //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount);
+ goto abort;
+ }
+
+ memset(ByteString, 0, ByteCount+1);
+ for (i = j = 0; j < ByteCount; i += 2, j++)
+ {
+ i += 2;
+ temp_byte[0] = Input[i];
+ temp_byte[1] = Input[i+1];
+ temp_byte[2] = 0;
+ ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16);
+ }
+ }
+ else // assume it is a hex string with no spaces with 2 bytes per character
+ {
+ for (i = 0; i < InputLength; i += 2)
+ {
+ if (!IsHexChar(Input[i]))
+ {
+ //fprintf(stderr, "ERROR: invalid hex character at offset %lu (0x%04x)\n", i, i);
+ goto abort;
+ }
+ if (i+1 >= InputLength || !Input[i+1])
+ {
+ //fprintf(stderr, "ERROR: hex string terminates unexpectedly at offset %lu (0x%04x)\n", i+1, i+1);
+ goto abort;
+ }
+
+ ByteCount++;
+ }
+
+ if (!ByteCount)
+ {
+ //fprintf(stderr, "Error: no input (byte count = 0)\n");
+ goto abort;
+ }
+
+ ByteString = malloc(ByteCount+1);
+ if (!ByteString)
+ {
+ //fprintf(stderr, "ERROR: failed to allocate %lu bytes\n", ByteCount);
+ goto abort;
+ }
+
+ memset(ByteString, 0, ByteCount+1);
+ for (i = 0, j = 0; j < ByteCount; i += 2, j++)
+ {
+ temp_byte[0] = Input[i];
+ temp_byte[1] = Input[i+1];
+ temp_byte[2] = 0;
+ ByteString[j] = (BYTE)strtoul(temp_byte, NULL, 16);
+ }
+ }
+
+ *OutputLength = ByteCount;
+ return ByteString;
+
+abort:
+ if (OutputLength) *OutputLength = 0;
+ if (ByteString) free(ByteString);
+ return NULL;
+}
+
diff --git a/thirdparty/mhook/disasm-lib/misc.h b/thirdparty/mhook/disasm-lib/misc.h
new file mode 100644
index 00000000..b3f585b7
--- /dev/null
+++ b/thirdparty/mhook/disasm-lib/misc.h
@@ -0,0 +1,52 @@
+// Copyright (C) 2002, Matt Conover (mconover@gmail.com)
+#ifndef MISC_H
+#define MISC_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+// NOTE: start is inclusive, end is exclusive (as in start <= x < end)
+#define IS_IN_RANGE(x, s, e) \
+( \
+ ((ULONG_PTR)(x) == (ULONG_PTR)(s) && (ULONG_PTR)(x) == (ULONG_PTR)(e)) || \
+ ((ULONG_PTR)(x) >= (ULONG_PTR)(s) && (ULONG_PTR)(x) < (ULONG_PTR)(e)) \
+)
+
+#if _MSC_VER >= 1400
+#pragma warning(disable:4996)
+#endif
+
+#if defined(_WIN64)
+ #define VALID_ADDRESS_MAX 0x7FFEFFFFFFFFFFFF // Win64 specific
+ typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
+#else
+ #define VALID_ADDRESS_MAX 0x7FFEFFFF // Win32 specific
+ typedef unsigned long ULONG_PTR, *PULONG_PTR;
+#endif
+
+#ifndef DECLSPEC_ALIGN
+ #if (_MSC_VER >= 1300) && !defined(MIDL_PASS)
+ #define DECLSPEC_ALIGN(x) __declspec(align(x))
+ #else
+ #define DECLSPEC_ALIGN(x)
+ #endif
+#endif
+
+#define VALID_ADDRESS_MIN 0x10000 // Win32 specific
+#define IS_VALID_ADDRESS(a) IS_IN_RANGE(a, VALID_ADDRESS_MIN, VALID_ADDRESS_MAX+1)
+
+BOOL IsHexChar(BYTE ch);
+BYTE *HexToBinary(char *Input, DWORD InputLength, DWORD *OutputLength);
+
+#ifdef __cplusplus
+}
+#endif
+#endif // MISC_H
diff --git a/thirdparty/mhook/mhook-lib/mhook.cpp b/thirdparty/mhook/mhook-lib/mhook.cpp
new file mode 100644
index 00000000..3380dcea
--- /dev/null
+++ b/thirdparty/mhook/mhook-lib/mhook.cpp
@@ -0,0 +1,918 @@
+//Copyright (c) 2007-2008, Marton Anka
+//
+//Permission is hereby granted, free of charge, to any person obtaining a
+//copy of this software and associated documentation files (the "Software"),
+//to deal in the Software without restriction, including without limitation
+//the rights to use, copy, modify, merge, publish, distribute, sublicense,
+//and/or sell copies of the Software, and to permit persons to whom the
+//Software is furnished to do so, subject to the following conditions:
+//
+//The above copyright notice and this permission notice shall be included
+//in all copies or substantial portions of the Software.
+//
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+//OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+//THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+//IN THE SOFTWARE.
+
+#include <windows.h>
+#include <tlhelp32.h>
+#include <stdio.h>
+#include "mhook.h"
+#include "../disasm-lib/disasm.h"
+
+//=========================================================================
+#ifndef cntof
+#define cntof(a) (sizeof(a)/sizeof(a[0]))
+#endif
+
+//=========================================================================
+#ifndef GOOD_HANDLE
+#define GOOD_HANDLE(a) ((a!=INVALID_HANDLE_VALUE)&&(a!=NULL))
+#endif
+
+//=========================================================================
+#ifndef gle
+#define gle GetLastError
+#endif
+
+//=========================================================================
+#ifndef ODPRINTF
+
+#ifdef _DEBUG
+#define ODPRINTF(a) odprintf a
+#else
+#define ODPRINTF(a)
+#endif
+
+inline void __cdecl odprintf(PCSTR format, ...) {
+ va_list args;
+ va_start(args, format);
+ int len = _vscprintf(format, args);
+ if (len > 0) {
+ len += (1 + 2);
+ PSTR buf = (PSTR) malloc(len);
+ if (buf) {
+ len = vsprintf_s(buf, len, format, args);
+ if (len > 0) {
+ while (len && isspace(buf[len-1])) len--;
+ buf[len++] = '\r';
+ buf[len++] = '\n';
+ buf[len] = 0;
+ OutputDebugStringA(buf);
+ }
+ free(buf);
+ }
+ va_end(args);
+ }
+}
+
+inline void __cdecl odprintf(PCWSTR format, ...) {
+ va_list args;
+ va_start(args, format);
+ int len = _vscwprintf(format, args);
+ if (len > 0) {
+ len += (1 + 2);
+ PWSTR buf = (PWSTR) malloc(sizeof(WCHAR)*len);
+ if (buf) {
+ len = vswprintf_s(buf, len, format, args);
+ if (len > 0) {
+ while (len && iswspace(buf[len-1])) len--;
+ buf[len++] = L'\r';
+ buf[len++] = L'\n';
+ buf[len] = 0;
+ OutputDebugStringW(buf);
+ }
+ free(buf);
+ }
+ va_end(args);
+ }
+}
+
+#endif //#ifndef ODPRINTF
+
+//=========================================================================
+#define MHOOKS_MAX_CODE_BYTES 32
+#define MHOOKS_MAX_RIPS 4
+
+//=========================================================================
+// The trampoline structure - stores every bit of info about a hook
+struct MHOOKS_TRAMPOLINE {
+ PBYTE pSystemFunction; // the original system function
+ DWORD cbOverwrittenCode; // number of bytes overwritten by the jump
+ PBYTE pHookFunction; // the hook function that we provide
+ BYTE codeJumpToHookFunction[MHOOKS_MAX_CODE_BYTES]; // placeholder for code that jumps to the hook function
+ BYTE codeTrampoline[MHOOKS_MAX_CODE_BYTES]; // placeholder for code that holds the first few
+ // bytes from the system function and a jump to the remainder
+ // in the original location
+ BYTE codeUntouched[MHOOKS_MAX_CODE_BYTES]; // placeholder for unmodified original code
+ // (we patch IP-relative addressing)
+ MHOOKS_TRAMPOLINE* pPrevTrampoline; // When in the free list, thess are pointers to the prev and next entry.
+ MHOOKS_TRAMPOLINE* pNextTrampoline; // When not in the free list, this is a pointer to the prev and next trampoline in use.
+};
+
+//=========================================================================
+// The patch data structures - store info about rip-relative instructions
+// during hook placement
+struct MHOOKS_RIPINFO
+{
+ DWORD dwOffset;
+ S64 nDisplacement;
+};
+
+struct MHOOKS_PATCHDATA
+{
+ S64 nLimitUp;
+ S64 nLimitDown;
+ DWORD nRipCnt;
+ MHOOKS_RIPINFO rips[MHOOKS_MAX_RIPS];
+};
+
+//=========================================================================
+// Global vars
+static BOOL g_bVarsInitialized = FALSE;
+static CRITICAL_SECTION g_cs;
+static MHOOKS_TRAMPOLINE* g_pHooks = NULL;
+static MHOOKS_TRAMPOLINE* g_pFreeList = NULL;
+static DWORD g_nHooksInUse = 0;
+static HANDLE* g_hThreadHandles = NULL;
+static DWORD g_nThreadHandles = 0;
+#define MHOOK_JMPSIZE 5
+#define MHOOK_MINALLOCSIZE 4096
+
+//=========================================================================
+// Toolhelp defintions so the functions can be dynamically bound to
+typedef HANDLE (WINAPI * _CreateToolhelp32Snapshot)(
+ DWORD dwFlags,
+ DWORD th32ProcessID
+ );
+
+typedef BOOL (WINAPI * _Thread32First)(
+ HANDLE hSnapshot,
+ LPTHREADENTRY32 lpte
+ );
+
+typedef BOOL (WINAPI * _Thread32Next)(
+ HANDLE hSnapshot,
+ LPTHREADENTRY32 lpte
+ );
+
+//=========================================================================
+// Bring in the toolhelp functions from kernel32
+_CreateToolhelp32Snapshot fnCreateToolhelp32Snapshot = (_CreateToolhelp32Snapshot) GetProcAddress(GetModuleHandle(L"kernel32"), "CreateToolhelp32Snapshot");
+_Thread32First fnThread32First = (_Thread32First) GetProcAddress(GetModuleHandle(L"kernel32"), "Thread32First");
+_Thread32Next fnThread32Next = (_Thread32Next) GetProcAddress(GetModuleHandle(L"kernel32"), "Thread32Next");
+
+//=========================================================================
+// Internal function:
+//
+// Remove the trampoline from the specified list, updating the head pointer
+// if necessary.
+//=========================================================================
+static VOID ListRemove(MHOOKS_TRAMPOLINE** pListHead, MHOOKS_TRAMPOLINE* pNode) {
+ if (pNode->pPrevTrampoline) {
+ pNode->pPrevTrampoline->pNextTrampoline = pNode->pNextTrampoline;
+ }
+
+ if (pNode->pNextTrampoline) {
+ pNode->pNextTrampoline->pPrevTrampoline = pNode->pPrevTrampoline;
+ }
+
+ if ((*pListHead) == pNode) {
+ (*pListHead) = pNode->pNextTrampoline;
+ assert((*pListHead)->pPrevTrampoline == NULL);
+ }
+
+ pNode->pPrevTrampoline = NULL;
+ pNode->pNextTrampoline = NULL;
+}
+
+//=========================================================================
+// Internal function:
+//
+// Prepend the trampoline from the specified list and update the head pointer.
+//=========================================================================
+static VOID ListPrepend(MHOOKS_TRAMPOLINE** pListHead, MHOOKS_TRAMPOLINE* pNode) {
+ pNode->pPrevTrampoline = NULL;
+ pNode->pNextTrampoline = (*pListHead);
+ if ((*pListHead)) {
+ (*pListHead)->pPrevTrampoline = pNode;
+ }
+ (*pListHead) = pNode;
+}
+
+//=========================================================================
+static VOID EnterCritSec() {
+ if (!g_bVarsInitialized) {
+ InitializeCriticalSection(&g_cs);
+ g_bVarsInitialized = TRUE;
+ }
+ EnterCriticalSection(&g_cs);
+}
+
+//=========================================================================
+static VOID LeaveCritSec() {
+ LeaveCriticalSection(&g_cs);
+}
+
+//=========================================================================
+// Internal function:
+//
+// Skip over jumps that lead to the real function. Gets around import
+// jump tables, etc.
+//=========================================================================
+static PBYTE SkipJumps(PBYTE pbCode) {
+ PBYTE pbOrgCode = pbCode;
+#ifdef _M_IX86_X64
+#ifdef _M_IX86
+ //mov edi,edi: hot patch point
+ if (pbCode[0] == 0x8b && pbCode[1] == 0xff)
+ pbCode += 2;
+ // push ebp; mov ebp, esp; pop ebp;
+ // "collapsed" stackframe generated by MSVC
+ if (pbCode[0] == 0x55 && pbCode[1] == 0x8b && pbCode[2] == 0xec && pbCode[3] == 0x5d)
+ pbCode += 4;
+#endif
+ if (pbCode[0] == 0xff && pbCode[1] == 0x25) {
+#ifdef _M_IX86
+ // on x86 we have an absolute pointer...
+ PBYTE pbTarget = *(PBYTE *)&pbCode[2];
+ // ... that shows us an absolute pointer.
+ return SkipJumps(*(PBYTE *)pbTarget);
+#elif defined _M_X64
+ // on x64 we have a 32-bit offset...
+ INT32 lOffset = *(INT32 *)&pbCode[2];
+ // ... that shows us an absolute pointer
+ return SkipJumps(*(PBYTE*)(pbCode + 6 + lOffset));
+ } else if (pbCode[0] == 0x48 && pbCode[1] == 0xff && pbCode[2] == 0x25) {
+ // or we can have the same with a REX prefix
+ INT32 lOffset = *(INT32 *)&pbCode[3];
+ // ... that shows us an absolute pointer
+ return SkipJumps(*(PBYTE*)(pbCode + 7 + lOffset));
+#endif
+ } else if (pbCode[0] == 0xe9) {
+ // here the behavior is identical, we have...
+ // ...a 32-bit offset to the destination.
+ return SkipJumps(pbCode + 5 + *(INT32 *)&pbCode[1]);
+ } else if (pbCode[0] == 0xeb) {
+ // and finally an 8-bit offset to the destination
+ return SkipJumps(pbCode + 2 + *(CHAR *)&pbCode[1]);
+ }
+#else
+#error unsupported platform
+#endif
+ return pbOrgCode;
+}
+
+//=========================================================================
+// Internal function:
+//
+// Writes code at pbCode that jumps to pbJumpTo. Will attempt to do this
+// in as few bytes as possible. Important on x64 where the long jump
+// (0xff 0x25 ....) can take up 14 bytes.
+//=========================================================================
+static PBYTE EmitJump(PBYTE pbCode, PBYTE pbJumpTo) {
+#ifdef _M_IX86_X64
+ PBYTE pbJumpFrom = pbCode + 5;
+ SIZE_T cbDiff = pbJumpFrom > pbJumpTo ? pbJumpFrom - pbJumpTo : pbJumpTo - pbJumpFrom;
+ ODPRINTF((L"mhooks: EmitJump: Jumping from %p to %p, diff is %p", pbJumpFrom, pbJumpTo, cbDiff));
+ if (cbDiff <= 0x7fff0000) {
+ pbCode[0] = 0xe9;
+ pbCode += 1;
+ *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbJumpTo - pbJumpFrom);
+ pbCode += sizeof(DWORD);
+ } else {
+ pbCode[0] = 0xff;
+ pbCode[1] = 0x25;
+ pbCode += 2;
+#ifdef _M_IX86
+ // on x86 we write an absolute address (just behind the instruction)
+ *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbCode + sizeof(DWORD));
+#elif defined _M_X64
+ // on x64 we write the relative address of the same location
+ *((PDWORD)pbCode) = (DWORD)0;
+#endif
+ pbCode += sizeof(DWORD);
+ *((PDWORD_PTR)pbCode) = (DWORD_PTR)(pbJumpTo);
+ pbCode += sizeof(DWORD_PTR);
+ }
+#else
+#error unsupported platform
+#endif
+ return pbCode;
+}
+
+
+//=========================================================================
+// Internal function:
+//
+// Round down to the next multiple of rndDown
+//=========================================================================
+static size_t RoundDown(size_t addr, size_t rndDown)
+{
+ return (addr / rndDown) * rndDown;
+}
+
+//=========================================================================
+// Internal function:
+//
+// Will attempt allocate a block of memory within the specified range, as
+// near as possible to the specified function.
+//=========================================================================
+static MHOOKS_TRAMPOLINE* BlockAlloc(PBYTE pSystemFunction, PBYTE pbLower, PBYTE pbUpper) {
+ SYSTEM_INFO sSysInfo = {0};
+ ::GetSystemInfo(&sSysInfo);
+
+ // Always allocate in bulk, in case the system actually has a smaller allocation granularity than MINALLOCSIZE.
+ const ptrdiff_t cAllocSize = max(sSysInfo.dwAllocationGranularity, MHOOK_MINALLOCSIZE);
+
+ MHOOKS_TRAMPOLINE* pRetVal = NULL;
+ PBYTE pModuleGuess = (PBYTE) RoundDown((size_t)pSystemFunction, cAllocSize);
+ int loopCount = 0;
+ for (PBYTE pbAlloc = pModuleGuess; pbLower < pbAlloc && pbAlloc < pbUpper; ++loopCount) {
+ // determine current state
+ MEMORY_BASIC_INFORMATION mbi;
+ ODPRINTF((L"mhooks: BlockAlloc: Looking at address %p", pbAlloc));
+ if (!VirtualQuery(pbAlloc, &mbi, sizeof(mbi)))
+ break;
+ // free & large enough?
+ if (mbi.State == MEM_FREE && mbi.RegionSize >= (unsigned)cAllocSize) {
+ // and then try to allocate it
+ pRetVal = (MHOOKS_TRAMPOLINE*) VirtualAlloc(pbAlloc, cAllocSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+ if (pRetVal) {
+ size_t trampolineCount = cAllocSize / sizeof(MHOOKS_TRAMPOLINE);
+ ODPRINTF((L"mhooks: BlockAlloc: Allocated block at %p as %d trampolines", pRetVal, trampolineCount));
+
+ pRetVal[0].pPrevTrampoline = NULL;
+ pRetVal[0].pNextTrampoline = &pRetVal[1];
+
+ // prepare them by having them point down the line at the next entry.
+ for (size_t s = 1; s < trampolineCount; ++s) {
+ pRetVal[s].pPrevTrampoline = &pRetVal[s - 1];
+ pRetVal[s].pNextTrampoline = &pRetVal[s + 1];
+ }
+
+ // last entry points to the current head of the free list
+ pRetVal[trampolineCount - 1].pNextTrampoline = g_pFreeList;
+ break;
+ }
+ }
+
+ // This is a spiral, should be -1, 1, -2, 2, -3, 3, etc. (* cAllocSize)
+ ptrdiff_t bytesToOffset = (cAllocSize * (loopCount + 1) * ((loopCount % 2 == 0) ? -1 : 1));
+ pbAlloc = pbAlloc + bytesToOffset;
+ }
+
+ return pRetVal;
+}
+
+//=========================================================================
+// Internal function:
+//
+// Will try to allocate a big block of memory inside the required range.
+//=========================================================================
+static MHOOKS_TRAMPOLINE* FindTrampolineInRange(PBYTE pLower, PBYTE pUpper) {
+ if (!g_pFreeList) {
+ return NULL;
+ }
+
+ // This is a standard free list, except we're doubly linked to deal with soem return shenanigans.
+ MHOOKS_TRAMPOLINE* curEntry = g_pFreeList;
+ while (curEntry) {
+ if ((MHOOKS_TRAMPOLINE*) pLower < curEntry && curEntry < (MHOOKS_TRAMPOLINE*) pUpper) {
+ ListRemove(&g_pFreeList, curEntry);
+
+ return curEntry;
+ }
+
+ curEntry = curEntry->pNextTrampoline;
+ }
+
+ return NULL;
+}
+
+//=========================================================================
+// Internal function:
+//
+// Will try to allocate the trampoline structure within 2 gigabytes of
+// the target function.
+//=========================================================================
+static MHOOKS_TRAMPOLINE* TrampolineAlloc(PBYTE pSystemFunction, S64 nLimitUp, S64 nLimitDown) {
+
+ MHOOKS_TRAMPOLINE* pTrampoline = NULL;
+
+ // determine lower and upper bounds for the allocation locations.
+ // in the basic scenario this is +/- 2GB but IP-relative instructions
+ // found in the original code may require a smaller window.
+ PBYTE pLower = pSystemFunction + nLimitUp;
+ pLower = pLower < (PBYTE)(DWORD_PTR)0x0000000080000000 ?
+ (PBYTE)(0x1) : (PBYTE)(pLower - (PBYTE)0x7fff0000);
+ PBYTE pUpper = pSystemFunction + nLimitDown;
+ pUpper = pUpper < (PBYTE)(DWORD_PTR)0xffffffff80000000 ?
+ (PBYTE)(pUpper + (DWORD_PTR)0x7ff80000) : (PBYTE)(DWORD_PTR)0xfffffffffff80000;
+ ODPRINTF((L"mhooks: TrampolineAlloc: Allocating for %p between %p and %p", pSystemFunction, pLower, pUpper));
+
+ // try to find a trampoline in the specified range
+ pTrampoline = FindTrampolineInRange(pLower, pUpper);
+ if (!pTrampoline) {
+ // if it we can't find it, then we need to allocate a new block and
+ // try again. Just fail if that doesn't work
+ g_pFreeList = BlockAlloc(pSystemFunction, pLower, pUpper);
+ pTrampoline = FindTrampolineInRange(pLower, pUpper);
+ }
+
+ // found and allocated a trampoline?
+ if (pTrampoline) {
+ ListPrepend(&g_pHooks, pTrampoline);
+ }
+
+ return pTrampoline;
+}
+
+//=========================================================================
+// Internal function:
+//
+// Return the internal trampoline structure that belongs to a hooked function.
+//=========================================================================
+static MHOOKS_TRAMPOLINE* TrampolineGet(PBYTE pHookedFunction) {
+ MHOOKS_TRAMPOLINE* pCurrent = g_pHooks;
+
+ while (pCurrent) {
+ if (pCurrent->pHookFunction == pHookedFunction) {
+ return pCurrent;
+ }
+
+ pCurrent = pCurrent->pNextTrampoline;
+ }
+
+ return NULL;
+}
+
+//=========================================================================
+// Internal function:
+//
+// Free a trampoline structure.
+//=========================================================================
+static VOID TrampolineFree(MHOOKS_TRAMPOLINE* pTrampoline, BOOL bNeverUsed) {
+ ListRemove(&g_pHooks, pTrampoline);
+
+ // If a thread could feasinbly have some of our trampoline code
+ // on its stack and we yank the region from underneath it then it will
+ // surely crash upon returning. So instead of freeing the
+ // memory we just let it leak. Ugly, but safe.
+ if (bNeverUsed) {
+ ListPrepend(&g_pFreeList, pTrampoline);
+ }
+
+ g_nHooksInUse--;
+}
+
+//=========================================================================
+// Internal function:
+//
+// Suspend a given thread and try to make sure that its instruction
+// pointer is not in the given range.
+//=========================================================================
+static HANDLE SuspendOneThread(DWORD dwThreadId, PBYTE pbCode, DWORD cbBytes) {
+ // open the thread
+ HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId);
+ if (GOOD_HANDLE(hThread)) {
+ // attempt suspension
+ DWORD dwSuspendCount = SuspendThread(hThread);
+ if (dwSuspendCount != -1) {
+ // see where the IP is
+ CONTEXT ctx;
+ ctx.ContextFlags = CONTEXT_CONTROL;
+ int nTries = 0;
+ while (GetThreadContext(hThread, &ctx)) {
+#ifdef _M_IX86
+ PBYTE pIp = (PBYTE)(DWORD_PTR)ctx.Eip;
+#elif defined _M_X64
+ PBYTE pIp = (PBYTE)(DWORD_PTR)ctx.Rip;
+#endif
+ if (pIp >= pbCode && pIp < (pbCode + cbBytes)) {
+ if (nTries < 3) {
+ // oops - we should try to get the instruction pointer out of here.
+ ODPRINTF((L"mhooks: SuspendOneThread: suspended thread %d - IP is at %p - IS COLLIDING WITH CODE", dwThreadId, pIp));
+ ResumeThread(hThread);
+ Sleep(100);
+ SuspendThread(hThread);
+ nTries++;
+ } else {
+ // we gave it all we could. (this will probably never
+ // happen - unless the thread has already been suspended
+ // to begin with)
+ ODPRINTF((L"mhooks: SuspendOneThread: suspended thread %d - IP is at %p - IS COLLIDING WITH CODE - CAN'T FIX", dwThreadId, pIp));
+ ResumeThread(hThread);
+ CloseHandle(hThread);
+ hThread = NULL;
+ break;
+ }
+ } else {
+ // success, the IP is not conflicting
+ ODPRINTF((L"mhooks: SuspendOneThread: Successfully suspended thread %d - IP is at %p", dwThreadId, pIp));
+ break;
+ }
+ }
+ } else {
+ // couldn't suspend
+ CloseHandle(hThread);
+ hThread = NULL;
+ }
+ }
+ return hThread;
+}
+
+//=========================================================================
+// Internal function:
+//
+// Resumes all previously suspended threads in the current process.
+//=========================================================================
+static VOID ResumeOtherThreads() {
+ // make sure things go as fast as possible
+ INT nOriginalPriority = GetThreadPriority(GetCurrentThread());
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ // go through our list
+ for (DWORD i=0; i<g_nThreadHandles; i++) {
+ // and resume & close thread handles
+ ResumeThread(g_hThreadHandles[i]);
+ CloseHandle(g_hThreadHandles[i]);
+ }
+ // clean up
+ free(g_hThreadHandles);
+ g_hThreadHandles = NULL;
+ g_nThreadHandles = 0;
+ SetThreadPriority(GetCurrentThread(), nOriginalPriority);
+}
+
+//=========================================================================
+// Internal function:
+//
+// Suspend all threads in this process while trying to make sure that their
+// instruction pointer is not in the given range.
+//=========================================================================
+static BOOL SuspendOtherThreads(PBYTE pbCode, DWORD cbBytes) {
+ BOOL bRet = FALSE;
+ // make sure we're the most important thread in the process
+ INT nOriginalPriority = GetThreadPriority(GetCurrentThread());
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+ // get a view of the threads in the system
+ HANDLE hSnap = fnCreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, GetCurrentProcessId());
+ if (GOOD_HANDLE(hSnap)) {
+ THREADENTRY32 te;
+ te.dwSize = sizeof(te);
+ // count threads in this process (except for ourselves)
+ DWORD nThreadsInProcess = 0;
+ if (fnThread32First(hSnap, &te)) {
+ do {
+ if (te.th32OwnerProcessID == GetCurrentProcessId()) {
+ if (te.th32ThreadID != GetCurrentThreadId()) {
+ nThreadsInProcess++;
+ }
+ }
+ te.dwSize = sizeof(te);
+ } while(fnThread32Next(hSnap, &te));
+ }
+ ODPRINTF((L"mhooks: SuspendOtherThreads: counted %d other threads", nThreadsInProcess));
+ if (nThreadsInProcess) {
+ // alloc buffer for the handles we really suspended
+ g_hThreadHandles = (HANDLE*)malloc(nThreadsInProcess*sizeof(HANDLE));
+ if (g_hThreadHandles) {
+ ZeroMemory(g_hThreadHandles, nThreadsInProcess*sizeof(HANDLE));
+ DWORD nCurrentThread = 0;
+ BOOL bFailed = FALSE;
+ te.dwSize = sizeof(te);
+ // go through every thread
+ if (fnThread32First(hSnap, &te)) {
+ do {
+ if (te.th32OwnerProcessID == GetCurrentProcessId()) {
+ if (te.th32ThreadID != GetCurrentThreadId()) {
+ // attempt to suspend it
+ g_hThreadHandles[nCurrentThread] = SuspendOneThread(te.th32ThreadID, pbCode, cbBytes);
+ if (GOOD_HANDLE(g_hThreadHandles[nCurrentThread])) {
+ ODPRINTF((L"mhooks: SuspendOtherThreads: successfully suspended %d", te.th32ThreadID));
+ nCurrentThread++;
+ } else {
+ ODPRINTF((L"mhooks: SuspendOtherThreads: error while suspending thread %d: %d", te.th32ThreadID, gle()));
+ // TODO: this might not be the wisest choice
+ // but we can choose to ignore failures on
+ // thread suspension. It's pretty unlikely that
+ // we'll fail - and even if we do, the chances
+ // of a thread's IP being in the wrong place
+ // is pretty small.
+ // bFailed = TRUE;
+ }
+ }
+ }
+ te.dwSize = sizeof(te);
+ } while(fnThread32Next(hSnap, &te) && !bFailed);
+ }
+ g_nThreadHandles = nCurrentThread;
+ bRet = !bFailed;
+ }
+ }
+ CloseHandle(hSnap);
+ //TODO: we might want to have another pass to make sure all threads
+ // in the current process (including those that might have been
+ // created since we took the original snapshot) have been
+ // suspended.
+ } else {
+ ODPRINTF((L"mhooks: SuspendOtherThreads: can't CreateToolhelp32Snapshot: %d", gle()));
+ }
+ SetThreadPriority(GetCurrentThread(), nOriginalPriority);
+ if (!bRet) {
+ ODPRINTF((L"mhooks: SuspendOtherThreads: Had a problem (or not running multithreaded), resuming all threads."));
+ ResumeOtherThreads();
+ }
+ return bRet;
+}
+
+//=========================================================================
+// if IP-relative addressing has been detected, fix up the code so the
+// offset points to the original location
+static void FixupIPRelativeAddressing(PBYTE pbNew, PBYTE pbOriginal, MHOOKS_PATCHDATA* pdata)
+{
+#if defined _M_X64
+ S64 diff = pbNew - pbOriginal;
+ for (DWORD i = 0; i < pdata->nRipCnt; i++) {
+ DWORD dwNewDisplacement = (DWORD)(pdata->rips[i].nDisplacement - diff);
+ ODPRINTF((L"mhooks: fixing up RIP instruction operand for code at 0x%p: "
+ L"old displacement: 0x%8.8x, new displacement: 0x%8.8x",
+ pbNew + pdata->rips[i].dwOffset,
+ (DWORD)pdata->rips[i].nDisplacement,
+ dwNewDisplacement));
+ *(PDWORD)(pbNew + pdata->rips[i].dwOffset) = dwNewDisplacement;
+ }
+#endif
+}
+
+//=========================================================================
+// Examine the machine code at the target function's entry point, and
+// skip bytes in a way that we'll always end on an instruction boundary.
+// We also detect branches and subroutine calls (as well as returns)
+// at which point disassembly must stop.
+// Finally, detect and collect information on IP-relative instructions
+// that we can patch.
+static DWORD DisassembleAndSkip(PVOID pFunction, DWORD dwMinLen, MHOOKS_PATCHDATA* pdata) {
+ DWORD dwRet = 0;
+ pdata->nLimitDown = 0;
+ pdata->nLimitUp = 0;
+ pdata->nRipCnt = 0;
+#ifdef _M_IX86
+ ARCHITECTURE_TYPE arch = ARCH_X86;
+#elif defined _M_X64
+ ARCHITECTURE_TYPE arch = ARCH_X64;
+#else
+ #error unsupported platform
+#endif
+ DISASSEMBLER dis;
+ if (InitDisassembler(&dis, arch)) {
+ INSTRUCTION* pins = NULL;
+ U8* pLoc = (U8*)pFunction;
+ DWORD dwFlags = DISASM_DECODE | DISASM_DISASSEMBLE | DISASM_ALIGNOUTPUT;
+
+ ODPRINTF((L"mhooks: DisassembleAndSkip: Disassembling %p", pLoc));
+ while ( (dwRet < dwMinLen) && (pins = GetInstruction(&dis, (ULONG_PTR)pLoc, pLoc, dwFlags)) ) {
+ ODPRINTF(("mhooks: DisassembleAndSkip: %p:(0x%2.2x) %s", pLoc, pins->Length, pins->String));
+ if (pins->Type == ITYPE_RET ) break;
+ if (pins->Type == ITYPE_BRANCH ) break;
+ if (pins->Type == ITYPE_BRANCHCC) break;
+ if (pins->Type == ITYPE_CALL ) break;
+ if (pins->Type == ITYPE_CALLCC ) break;
+
+ #if defined _M_X64
+ BOOL bProcessRip = FALSE;
+ // mov or lea to register from rip+imm32
+ if ((pins->Type == ITYPE_MOV || pins->Type == ITYPE_LEA) && (pins->X86.Relative) &&
+ (pins->X86.OperandSize == 8) && (pins->OperandCount == 2) &&
+ (pins->Operands[1].Flags & OP_IPREL) && (pins->Operands[1].Register == AMD64_REG_RIP))
+ {
+ // rip-addressing "mov reg, [rip+imm32]"
+ ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 1, pins->X86.Displacement, *(PDWORD)(pLoc+3)));
+ bProcessRip = TRUE;
+ }
+ // mov or lea to rip+imm32 from register
+ else if ((pins->Type == ITYPE_MOV || pins->Type == ITYPE_LEA) && (pins->X86.Relative) &&
+ (pins->X86.OperandSize == 8) && (pins->OperandCount == 2) &&
+ (pins->Operands[0].Flags & OP_IPREL) && (pins->Operands[0].Register == AMD64_REG_RIP))
+ {
+ // rip-addressing "mov [rip+imm32], reg"
+ ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 0, pins->X86.Displacement, *(PDWORD)(pLoc+3)));
+ bProcessRip = TRUE;
+ }
+ else if ( (pins->OperandCount >= 1) && (pins->Operands[0].Flags & OP_IPREL) )
+ {
+ // unsupported rip-addressing
+ ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 0));
+ // dump instruction bytes to the debug output
+ for (DWORD i=0; i<pins->Length; i++) {
+ ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i]));
+ }
+ break;
+ }
+ else if ( (pins->OperandCount >= 2) && (pins->Operands[1].Flags & OP_IPREL) )
+ {
+ // unsupported rip-addressing
+ ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 1));
+ // dump instruction bytes to the debug output
+ for (DWORD i=0; i<pins->Length; i++) {
+ ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i]));
+ }
+ break;
+ }
+ else if ( (pins->OperandCount >= 3) && (pins->Operands[2].Flags & OP_IPREL) )
+ {
+ // unsupported rip-addressing
+ ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 2));
+ // dump instruction bytes to the debug output
+ for (DWORD i=0; i<pins->Length; i++) {
+ ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i]));
+ }
+ break;
+ }
+ // follow through with RIP-processing if needed
+ if (bProcessRip) {
+ // calculate displacement relative to function start
+ S64 nAdjustedDisplacement = pins->X86.Displacement + (pLoc - (U8*)pFunction);
+ // store displacement values furthest from zero (both positive and negative)
+ if (nAdjustedDisplacement < pdata->nLimitDown)
+ pdata->nLimitDown = nAdjustedDisplacement;
+ if (nAdjustedDisplacement > pdata->nLimitUp)
+ pdata->nLimitUp = nAdjustedDisplacement;
+ // store patch info
+ if (pdata->nRipCnt < MHOOKS_MAX_RIPS) {
+ pdata->rips[pdata->nRipCnt].dwOffset = dwRet + 3;
+ pdata->rips[pdata->nRipCnt].nDisplacement = pins->X86.Displacement;
+ pdata->nRipCnt++;
+ } else {
+ // no room for patch info, stop disassembly
+ break;
+ }
+ }
+ #endif
+
+ dwRet += pins->Length;
+ pLoc += pins->Length;
+ }
+
+ CloseDisassembler(&dis);
+ }
+
+ return dwRet;
+}
+
+//=========================================================================
+BOOL Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction) {
+ MHOOKS_TRAMPOLINE* pTrampoline = NULL;
+ PVOID pSystemFunction = *ppSystemFunction;
+ // ensure thread-safety
+ EnterCritSec();
+ ODPRINTF((L"mhooks: Mhook_SetHook: Started on the job: %p / %p", pSystemFunction, pHookFunction));
+ // find the real functions (jump over jump tables, if any)
+ pSystemFunction = SkipJumps((PBYTE)pSystemFunction);
+ pHookFunction = SkipJumps((PBYTE)pHookFunction);
+ ODPRINTF((L"mhooks: Mhook_SetHook: Started on the job: %p / %p", pSystemFunction, pHookFunction));
+ // figure out the length of the overwrite zone
+ MHOOKS_PATCHDATA patchdata = {0};
+ DWORD dwInstructionLength = DisassembleAndSkip(pSystemFunction, MHOOK_JMPSIZE, &patchdata);
+ if (dwInstructionLength >= MHOOK_JMPSIZE) {
+ ODPRINTF((L"mhooks: Mhook_SetHook: disassembly signals %d bytes", dwInstructionLength));
+ // suspend every other thread in this process, and make sure their IP
+ // is not in the code we're about to overwrite.
+ SuspendOtherThreads((PBYTE)pSystemFunction, dwInstructionLength);
+ // allocate a trampoline structure (TODO: it is pretty wasteful to get
+ // VirtualAlloc to grab chunks of memory smaller than 100 bytes)
+ pTrampoline = TrampolineAlloc((PBYTE)pSystemFunction, patchdata.nLimitUp, patchdata.nLimitDown);
+ if (pTrampoline) {
+ ODPRINTF((L"mhooks: Mhook_SetHook: allocated structure at %p", pTrampoline));
+ DWORD dwOldProtectSystemFunction = 0;
+ DWORD dwOldProtectTrampolineFunction = 0;
+ // set the system function to PAGE_EXECUTE_READWRITE
+ if (VirtualProtect(pSystemFunction, dwInstructionLength, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) {
+ ODPRINTF((L"mhooks: Mhook_SetHook: readwrite set on system function"));
+ // mark our trampoline buffer to PAGE_EXECUTE_READWRITE
+ if (VirtualProtect(pTrampoline, sizeof(MHOOKS_TRAMPOLINE), PAGE_EXECUTE_READWRITE, &dwOldProtectTrampolineFunction)) {
+ ODPRINTF((L"mhooks: Mhook_SetHook: readwrite set on trampoline structure"));
+
+ // create our trampoline function
+ PBYTE pbCode = pTrampoline->codeTrampoline;
+ // save original code..
+ for (DWORD i = 0; i<dwInstructionLength; i++) {
+ pTrampoline->codeUntouched[i] = pbCode[i] = ((PBYTE)pSystemFunction)[i];
+ }
+ pbCode += dwInstructionLength;
+ // plus a jump to the continuation in the original location
+ pbCode = EmitJump(pbCode, ((PBYTE)pSystemFunction) + dwInstructionLength);
+ ODPRINTF((L"mhooks: Mhook_SetHook: updated the trampoline"));
+
+ // fix up any IP-relative addressing in the code
+ FixupIPRelativeAddressing(pTrampoline->codeTrampoline, (PBYTE)pSystemFunction, &patchdata);
+
+ DWORD_PTR dwDistance = (PBYTE)pHookFunction < (PBYTE)pSystemFunction ?
+ (PBYTE)pSystemFunction - (PBYTE)pHookFunction : (PBYTE)pHookFunction - (PBYTE)pSystemFunction;
+ if (dwDistance > 0x7fff0000) {
+ // create a stub that jumps to the replacement function.
+ // we need this because jumping from the API to the hook directly
+ // will be a long jump, which is 14 bytes on x64, and we want to
+ // avoid that - the API may or may not have room for such stuff.
+ // (remember, we only have 5 bytes guaranteed in the API.)
+ // on the other hand we do have room, and the trampoline will always be
+ // within +/- 2GB of the API, so we do the long jump in there.
+ // the API will jump to the "reverse trampoline" which
+ // will jump to the user's hook code.
+ pbCode = pTrampoline->codeJumpToHookFunction;
+ pbCode = EmitJump(pbCode, (PBYTE)pHookFunction);
+ ODPRINTF((L"mhooks: Mhook_SetHook: created reverse trampoline"));
+ FlushInstructionCache(GetCurrentProcess(), pTrampoline->codeJumpToHookFunction,
+ pbCode - pTrampoline->codeJumpToHookFunction);
+
+ // update the API itself
+ pbCode = (PBYTE)pSystemFunction;
+ pbCode = EmitJump(pbCode, pTrampoline->codeJumpToHookFunction);
+ } else {
+ // the jump will be at most 5 bytes so we can do it directly
+ // update the API itself
+ pbCode = (PBYTE)pSystemFunction;
+ pbCode = EmitJump(pbCode, (PBYTE)pHookFunction);
+ }
+
+ // update data members
+ pTrampoline->cbOverwrittenCode = dwInstructionLength;
+ pTrampoline->pSystemFunction = (PBYTE)pSystemFunction;
+ pTrampoline->pHookFunction = (PBYTE)pHookFunction;
+
+ // flush instruction cache and restore original protection
+ FlushInstructionCache(GetCurrentProcess(), pTrampoline->codeTrampoline, dwInstructionLength);
+ VirtualProtect(pTrampoline, sizeof(MHOOKS_TRAMPOLINE), dwOldProtectTrampolineFunction, &dwOldProtectTrampolineFunction);
+ } else {
+ ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtect 2: %d", gle()));
+ }
+ // flush instruction cache and restore original protection
+ FlushInstructionCache(GetCurrentProcess(), pSystemFunction, dwInstructionLength);
+ VirtualProtect(pSystemFunction, dwInstructionLength, dwOldProtectSystemFunction, &dwOldProtectSystemFunction);
+ } else {
+ ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtect 1: %d", gle()));
+ }
+ if (pTrampoline->pSystemFunction) {
+ // this is what the application will use as the entry point
+ // to the "original" unhooked function.
+ *ppSystemFunction = pTrampoline->codeTrampoline;
+ ODPRINTF((L"mhooks: Mhook_SetHook: Hooked the function!"));
+ } else {
+ // if we failed discard the trampoline (forcing VirtualFree)
+ TrampolineFree(pTrampoline, TRUE);
+ pTrampoline = NULL;
+ }
+ }
+ // resume everybody else
+ ResumeOtherThreads();
+ } else {
+ ODPRINTF((L"mhooks: disassembly signals %d bytes (unacceptable)", dwInstructionLength));
+ }
+ LeaveCritSec();
+ return (pTrampoline != NULL);
+}
+
+//=========================================================================
+BOOL Mhook_Unhook(PVOID *ppHookedFunction) {
+ ODPRINTF((L"mhooks: Mhook_Unhook: %p", *ppHookedFunction));
+ BOOL bRet = FALSE;
+ EnterCritSec();
+ // get the trampoline structure that corresponds to our function
+ MHOOKS_TRAMPOLINE* pTrampoline = TrampolineGet((PBYTE)*ppHookedFunction);
+ if (pTrampoline) {
+ // make sure nobody's executing code where we're about to overwrite a few bytes
+ SuspendOtherThreads(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode);
+ ODPRINTF((L"mhooks: Mhook_Unhook: found struct at %p", pTrampoline));
+ DWORD dwOldProtectSystemFunction = 0;
+ // make memory writable
+ if (VirtualProtect(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) {
+ ODPRINTF((L"mhooks: Mhook_Unhook: readwrite set on system function"));
+ PBYTE pbCode = (PBYTE)pTrampoline->pSystemFunction;
+ for (DWORD i = 0; i<pTrampoline->cbOverwrittenCode; i++) {
+ pbCode[i] = pTrampoline->codeUntouched[i];
+ }
+ // flush instruction cache and make memory unwritable
+ FlushInstructionCache(GetCurrentProcess(), pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode);
+ VirtualProtect(pTrampoline->pSystemFunction, pTrampoline->cbOverwrittenCode, dwOldProtectSystemFunction, &dwOldProtectSystemFunction);
+ // return the original function pointer
+ *ppHookedFunction = pTrampoline->pSystemFunction;
+ bRet = TRUE;
+ ODPRINTF((L"mhooks: Mhook_Unhook: sysfunc: %p", *ppHookedFunction));
+ // free the trampoline while not really discarding it from memory
+ TrampolineFree(pTrampoline, FALSE);
+ ODPRINTF((L"mhooks: Mhook_Unhook: unhook successful"));
+ } else {
+ ODPRINTF((L"mhooks: Mhook_Unhook: failed VirtualProtect 1: %d", gle()));
+ }
+ // make the other guys runnable
+ ResumeOtherThreads();
+ }
+ LeaveCritSec();
+ return bRet;
+}
+
+//=========================================================================
diff --git a/thirdparty/mhook/mhook-lib/mhook.h b/thirdparty/mhook/mhook-lib/mhook.h
new file mode 100644
index 00000000..1d7cfff5
--- /dev/null
+++ b/thirdparty/mhook/mhook-lib/mhook.h
@@ -0,0 +1,28 @@
+//Copyright (c) 2007-2008, Marton Anka
+//
+//Permission is hereby granted, free of charge, to any person obtaining a
+//copy of this software and associated documentation files (the "Software"),
+//to deal in the Software without restriction, including without limitation
+//the rights to use, copy, modify, merge, publish, distribute, sublicense,
+//and/or sell copies of the Software, and to permit persons to whom the
+//Software is furnished to do so, subject to the following conditions:
+//
+//The above copyright notice and this permission notice shall be included
+//in all copies or substantial portions of the Software.
+//
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+//OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+//THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+//IN THE SOFTWARE.
+
+#ifdef _M_IX86
+#define _M_IX86_X64
+#elif defined _M_X64
+#define _M_IX86_X64
+#endif
+
+BOOL Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction);
+BOOL Mhook_Unhook(PVOID *ppHookedFunction);
diff --git a/thirdparty/mhook/mhook-test.cpp b/thirdparty/mhook/mhook-test.cpp
new file mode 100644
index 00000000..79dc767e
--- /dev/null
+++ b/thirdparty/mhook/mhook-test.cpp
@@ -0,0 +1,218 @@
+//Copyright (c) 2007-2008, Marton Anka
+//
+//Permission is hereby granted, free of charge, to any person obtaining a
+//copy of this software and associated documentation files (the "Software"),
+//to deal in the Software without restriction, including without limitation
+//the rights to use, copy, modify, merge, publish, distribute, sublicense,
+//and/or sell copies of the Software, and to permit persons to whom the
+//Software is furnished to do so, subject to the following conditions:
+//
+//The above copyright notice and this permission notice shall be included
+//in all copies or substantial portions of the Software.
+//
+//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+//OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+//THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+//IN THE SOFTWARE.
+
+#include "stdafx.h"
+#include "mhook-lib/mhook.h"
+
+//=========================================================================
+// Define _NtOpenProcess so we can dynamically bind to the function
+//
+typedef struct _CLIENT_ID {
+ DWORD_PTR UniqueProcess;
+ DWORD_PTR UniqueThread;
+} CLIENT_ID, *PCLIENT_ID;
+
+typedef ULONG (WINAPI* _NtOpenProcess)(OUT PHANDLE ProcessHandle,
+ IN ACCESS_MASK AccessMask, IN PVOID ObjectAttributes,
+ IN PCLIENT_ID ClientId );
+
+//=========================================================================
+// Define _SelectObject so we can dynamically bind to the function
+typedef HGDIOBJ (WINAPI* _SelectObject)(HDC hdc, HGDIOBJ hgdiobj);
+
+//=========================================================================
+// Define _getaddrinfo so we can dynamically bind to the function
+typedef int (WSAAPI* _getaddrinfo)(const char* nodename, const char* servname, const struct addrinfo* hints, struct addrinfo** res);
+
+//=========================================================================
+// Define _HeapAlloc so we can dynamically bind to the function
+typedef LPVOID (WINAPI *_HeapAlloc)(HANDLE, DWORD, SIZE_T);
+
+//=========================================================================
+// Define _NtClose so we can dynamically bind to the function
+typedef ULONG (WINAPI* _NtClose)(IN HANDLE Handle);
+
+//=========================================================================
+// Get the current (original) address to the functions to be hooked
+//
+_NtOpenProcess TrueNtOpenProcess = (_NtOpenProcess)
+ GetProcAddress(GetModuleHandle(L"ntdll"), "NtOpenProcess");
+
+_SelectObject TrueSelectObject = (_SelectObject)
+ GetProcAddress(GetModuleHandle(L"gdi32"), "SelectObject");
+
+_getaddrinfo Truegetaddrinfo = (_getaddrinfo)GetProcAddress(GetModuleHandle(L"ws2_32"), "getaddrinfo");
+
+_HeapAlloc TrueHeapAlloc = (_HeapAlloc)GetProcAddress(GetModuleHandle(L"kernel32"), "HeapAlloc");
+
+_NtClose TrueNtClose = (_NtClose)GetProcAddress(GetModuleHandle(L"ntdll"), "NtClose");
+
+//=========================================================================
+// This is the function that will replace NtOpenProcess once the hook
+// is in place
+//
+ULONG WINAPI HookNtOpenProcess(OUT PHANDLE ProcessHandle,
+ IN ACCESS_MASK AccessMask,
+ IN PVOID ObjectAttributes,
+ IN PCLIENT_ID ClientId)
+{
+ printf("***** Call to open process %d\n", ClientId->UniqueProcess);
+ return TrueNtOpenProcess(ProcessHandle, AccessMask,
+ ObjectAttributes, ClientId);
+}
+
+//=========================================================================
+// This is the function that will replace SelectObject once the hook
+// is in place
+//
+HGDIOBJ WINAPI HookSelectobject(HDC hdc, HGDIOBJ hgdiobj)
+{
+ printf("***** Call to SelectObject(0x%p, 0x%p)\n", hdc, hgdiobj);
+ return TrueSelectObject(hdc, hgdiobj);
+}
+
+//=========================================================================
+// This is the function that will replace SelectObject once the hook
+// is in place
+//
+int WSAAPI Hookgetaddrinfo(const char* nodename, const char* servname, const struct addrinfo* hints, struct addrinfo** res)
+{
+ printf("***** Call to getaddrinfo(0x%p, 0x%p, 0x%p, 0x%p)\n", nodename, servname, hints, res);
+ return Truegetaddrinfo(nodename, servname, hints, res);
+}
+
+//=========================================================================
+// This is the function that will replace HeapAlloc once the hook
+// is in place
+//
+LPVOID WINAPI HookHeapAlloc(HANDLE a_Handle, DWORD a_Bla, SIZE_T a_Bla2) {
+ printf("***** Call to HeapAlloc(0x%p, %u, 0x%p)\n", a_Handle, a_Bla, a_Bla2);
+ return TrueHeapAlloc(a_Handle, a_Bla, a_Bla2);
+}
+
+//=========================================================================
+// This is the function that will replace NtClose once the hook
+// is in place
+//
+ULONG WINAPI HookNtClose(HANDLE hHandle) {
+ printf("***** Call to NtClose(0x%p)\n", hHandle);
+ return TrueNtClose(hHandle);
+}
+
+//=========================================================================
+// This is where the work gets done.
+//
+int wmain(int argc, WCHAR* argv[])
+{
+ HANDLE hProc = NULL;
+
+ // Set the hook
+ if (Mhook_SetHook((PVOID*)&TrueNtOpenProcess, HookNtOpenProcess)) {
+ // Now call OpenProcess and observe NtOpenProcess being redirected
+ // under the hood.
+ hProc = OpenProcess(PROCESS_ALL_ACCESS,
+ FALSE, GetCurrentProcessId());
+ if (hProc) {
+ printf("Successfully opened self: %p\n", hProc);
+ CloseHandle(hProc);
+ } else {
+ printf("Could not open self: %d\n", GetLastError());
+ }
+ // Remove the hook
+ Mhook_Unhook((PVOID*)&TrueNtOpenProcess);
+ }
+
+ // Call OpenProces again - this time there won't be a redirection as
+ // the hook has bee removed.
+ hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
+ if (hProc) {
+ printf("Successfully opened self: %p\n", hProc);
+ CloseHandle(hProc);
+ } else {
+ printf("Could not open self: %d\n", GetLastError());
+ }
+
+ // Test another hook, this time in SelectObject
+ // (SelectObject is interesting in that on XP x64, the second instruction
+ // in the trampoline uses IP-relative addressing and we need to do some
+ // extra work under the hood to make things work properly. This really
+ // is more of a test case rather than a demo.)
+ printf("Testing SelectObject.\n");
+ if (Mhook_SetHook((PVOID*)&TrueSelectObject, HookSelectobject)) {
+ // error checking omitted for brevity. doesn't matter much
+ // in this context anyway.
+ HDC hdc = GetDC(NULL);
+ HDC hdcMem = CreateCompatibleDC(hdc);
+ HBITMAP hbm = CreateCompatibleBitmap(hdc, 32, 32);
+ HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hbm);
+ SelectObject(hdcMem, hbmOld);
+ DeleteObject(hbm);
+ DeleteDC(hdcMem);
+ ReleaseDC(NULL, hdc);
+ // Remove the hook
+ Mhook_Unhook((PVOID*)&TrueSelectObject);
+ }
+
+ printf("Testing getaddrinfo.\n");
+ if (Mhook_SetHook((PVOID*)&Truegetaddrinfo, Hookgetaddrinfo)) {
+ // error checking omitted for brevity. doesn't matter much
+ // in this context anyway.
+ WSADATA wd = {0};
+ WSAStartup(MAKEWORD(2, 2), &wd);
+ char* ip = "localhost";
+ struct addrinfo aiHints;
+ struct addrinfo *res = NULL;
+ memset(&aiHints, 0, sizeof(aiHints));
+ aiHints.ai_family = PF_UNSPEC;
+ aiHints.ai_socktype = SOCK_STREAM;
+ if (getaddrinfo(ip, NULL, &aiHints, &res)) {
+ printf("getaddrinfo failed\n");
+ } else {
+ int n = 0;
+ while(res) {
+ res = res->ai_next;
+ n++;
+ }
+ printf("got %d addresses\n", n);
+ }
+ WSACleanup();
+ // Remove the hook
+ Mhook_Unhook((PVOID*)&Truegetaddrinfo);
+ }
+
+ printf("Testing HeapAlloc.\n");
+ if (Mhook_SetHook((PVOID*)&TrueHeapAlloc, HookHeapAlloc))
+ {
+ free(malloc(10));
+ // Remove the hook
+ Mhook_Unhook((PVOID*)&TrueHeapAlloc);
+ }
+
+ printf("Testing NtClose.\n");
+ if (Mhook_SetHook((PVOID*)&TrueNtClose, HookNtClose))
+ {
+ CloseHandle(NULL);
+ // Remove the hook
+ Mhook_Unhook((PVOID*)&TrueNtClose);
+ }
+
+ return 0;
+}
+
diff --git a/thirdparty/mhook/stdafx.cpp b/thirdparty/mhook/stdafx.cpp
new file mode 100644
index 00000000..fb742136
--- /dev/null
+++ b/thirdparty/mhook/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// mhook-test.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/thirdparty/mhook/stdafx.h b/thirdparty/mhook/stdafx.h
new file mode 100644
index 00000000..76cc8f68
--- /dev/null
+++ b/thirdparty/mhook/stdafx.h
@@ -0,0 +1,20 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+//for the getaddrinfo test
+#include <WS2tcpip.h>
+#pragma comment(lib, "ws2_32")
+
+#include <windows.h>
+#include <stdio.h>
+
+
+