diff --git a/.gitmodules b/.gitmodules index ceba7e2ec..99e1dd8f8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,3 @@ [submodule "import/d3d8to9"] path = import/d3d8to9 url = https://github.com/Cxbx-Reloaded/d3d8to9 -[submodule "import/unicorn"] - path = import/unicorn - url = https://github.com/Cxbx-Reloaded/unicorn diff --git a/build/win32/Cxbx.sln b/build/win32/Cxbx.sln index d848c2ca1..97022e81e 100644 --- a/build/win32/Cxbx.sln +++ b/build/win32/Cxbx.sln @@ -24,15 +24,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{17 EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "d3d8to9", "..\..\import\d3d8to9\d3d8to9.vcxproj", "{7EE21ADA-3B02-4CD6-A891-C2257A54B061}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "x86_64-softmmu", "..\..\import\unicorn\msvc\unicorn\x86_64-softmmu\x86_64-softmmu.vcxproj", "{17077E86-AE7C-41AF-86ED-2BAC03B019BC}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "unicorn_static", "..\..\import\unicorn\msvc\unicorn\unicorn_static\unicorn_static.vcxproj", "{B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}" - ProjectSection(ProjectDependencies) = postProject - {17077E86-AE7C-41AF-86ED-2BAC03B019BC} = {17077E86-AE7C-41AF-86ED-2BAC03B019BC} - EndProjectSection -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unicorn", "unicorn", "{C2940E37-10E0-4DDD-BD9B-7851C61C6C09}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_Direct3D9|Any CPU = Debug_Direct3D9|Any CPU @@ -130,44 +121,6 @@ Global {7EE21ADA-3B02-4CD6-A891-C2257A54B061}.Release|Win32.ActiveCfg = Release|Win32 {7EE21ADA-3B02-4CD6-A891-C2257A54B061}.Release|Win32.Build.0 = Release|Win32 {7EE21ADA-3B02-4CD6-A891-C2257A54B061}.Release|x64.ActiveCfg = Release|Win32 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug_Direct3D9|Any CPU.ActiveCfg = Release|x64 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug_Direct3D9|Any CPU.Build.0 = Release|x64 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug_Direct3D9|Any CPU.Deploy.0 = Release|x64 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug_Direct3D9|Win32.ActiveCfg = Debug|Win32 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug_Direct3D9|Win32.Build.0 = Debug|Win32 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug_Direct3D9|Win32.Deploy.0 = Debug|Win32 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug_Direct3D9|x64.ActiveCfg = Debug|x64 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug_Direct3D9|x64.Build.0 = Debug|x64 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug_Direct3D9|x64.Deploy.0 = Debug|x64 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug|Win32.ActiveCfg = Debug|Win32 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug|Win32.Build.0 = Debug|Win32 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug|x64.ActiveCfg = Debug|x64 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Debug|x64.Build.0 = Debug|x64 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Release|Any CPU.ActiveCfg = Release|Win32 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Release|Win32.ActiveCfg = Release|Win32 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Release|Win32.Build.0 = Release|Win32 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Release|x64.ActiveCfg = Release|x64 - {17077E86-AE7C-41AF-86ED-2BAC03B019BC}.Release|x64.Build.0 = Release|x64 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug_Direct3D9|Any CPU.ActiveCfg = Release|x64 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug_Direct3D9|Any CPU.Build.0 = Release|x64 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug_Direct3D9|Any CPU.Deploy.0 = Release|x64 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug_Direct3D9|Win32.ActiveCfg = Debug|Win32 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug_Direct3D9|Win32.Build.0 = Debug|Win32 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug_Direct3D9|Win32.Deploy.0 = Debug|Win32 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug_Direct3D9|x64.ActiveCfg = Debug|x64 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug_Direct3D9|x64.Build.0 = Debug|x64 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug_Direct3D9|x64.Deploy.0 = Debug|x64 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug|Win32.ActiveCfg = Debug|Win32 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug|Win32.Build.0 = Debug|Win32 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug|x64.ActiveCfg = Debug|x64 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Debug|x64.Build.0 = Debug|x64 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Release|Any CPU.ActiveCfg = Release|Win32 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Release|Win32.ActiveCfg = Release|Win32 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Release|Win32.Build.0 = Release|Win32 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Release|x64.ActiveCfg = Release|x64 - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -176,8 +129,6 @@ Global {4A68E962-3805-4376-99D3-0AC59E9BEE69} = {174CB14E-34E3-422F-9A99-DBE88FF0EFBB} {9131B025-5019-4DEE-84A3-86D2703A81C0} = {174CB14E-34E3-422F-9A99-DBE88FF0EFBB} {2171C0E8-4915-49B9-AC23-A484FA08C126} = {174CB14E-34E3-422F-9A99-DBE88FF0EFBB} - {17077E86-AE7C-41AF-86ED-2BAC03B019BC} = {C2940E37-10E0-4DDD-BD9B-7851C61C6C09} - {B6EFD6D7-C2D4-4FBB-B363-2E08CE09CC96} = {C2940E37-10E0-4DDD-BD9B-7851C61C6C09} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {B5EC6A8A-FBC4-456F-B41D-F0D1E9719E25} diff --git a/build/win32/Cxbx.vcxproj b/build/win32/Cxbx.vcxproj index a59ea3452..bcfab1f7c 100644 --- a/build/win32/Cxbx.vcxproj +++ b/build/win32/Cxbx.vcxproj @@ -102,7 +102,7 @@ Disabled - ..\..\src\Common;..\..\src;..\..\src\Common\Win32;%(AdditionalIncludeDirectories);..\..\import\OpenXDK\include;..\..\import\unicorn\include;..\..\import\glew-2.0.0\include;..\..\import\subhook\ + ..\..\src\Common;..\..\src;..\..\src\Common\Win32;%(AdditionalIncludeDirectories);..\..\import\OpenXDK\include;..\..\import\distorm\include;..\..\import\glew-2.0.0\include;..\..\import\subhook\ NOMINMAX;_WIN32_WINNT=0x0601;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebugDLL @@ -225,7 +225,7 @@ Full AnySuitable - ..\..\src;..\..\src\Common;..\..\src\Common\Win32\;%(AdditionalIncludeDirectories);..\..\import\OpenXDK\include;..\..\import\unicorn\include;..\..\import\glew-2.0.0\include;..\..\src\Common\Win32;..\..\import\subhook\ + ..\..\src;..\..\src\Common;..\..\src\Common\Win32\;%(AdditionalIncludeDirectories);..\..\import\OpenXDK\include;..\..\import\distorm\include;..\..\import\glew-2.0.0\include;..\..\src\Common\Win32;..\..\import\subhook\ NOMINMAX;_WIN32_WINNT=0x0601;WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreadedDLL @@ -836,12 +836,6 @@ - - {b6efd6d7-c2d4-4fbb-b363-2e08ce09cc96} - - - {17077e86-ae7c-41af-86ed-2bac03b019bc} - {cd2dde93-b45e-4d11-876d-d0056c3dd407} diff --git a/import/distorm/include/distorm.h b/import/distorm/include/distorm.h new file mode 100644 index 000000000..100716464 --- /dev/null +++ b/import/distorm/include/distorm.h @@ -0,0 +1,482 @@ +/* diStorm 3.3.3 */ + +/* +distorm.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef DISTORM_H +#define DISTORM_H + +/* + * 64 bit offsets support: + * If the diStorm library you use was compiled with 64 bits offsets, + * make sure you compile your own code with the following macro set: + * SUPPORT_64BIT_OFFSET + * Otherwise comment it out, or you will get a linker error of an unresolved symbol... + * Turned on by default! + */ + +#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) + /* Define this macro for outer projects by default. */ + #define SUPPORT_64BIT_OFFSET +#endif + +/* TINYC has a problem with some 64bits library functions, so ignore 64 bit offsets. */ +#ifdef __TINYC__ + #undef SUPPORT_64BIT_OFFSET +#endif + +/* If your compiler doesn't support stdint.h, define your own 64 bits type. */ +#ifdef SUPPORT_64BIT_OFFSET + #ifdef _MSC_VER + #define OFFSET_INTEGER unsigned __int64 + #else + #include + #define OFFSET_INTEGER uint64_t + #endif +#else + /* 32 bit offsets are used. */ + #define OFFSET_INTEGER unsigned long +#endif + +#ifdef _MSC_VER +/* Since MSVC isn't shipped with stdint.h, we will have our own: */ +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef signed __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef signed __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef signed __int8 int8_t; +typedef unsigned __int8 uint8_t; +#endif + +/* Support C++ compilers */ +#ifdef __cplusplus + extern "C" { +#endif + + +/* *** Helper Macros *** */ + +/* Get the ISC of the instruction, used with the definitions below. */ +#define META_GET_ISC(meta) (((meta) >> 3) & 0x1f) +#define META_SET_ISC(di, isc) (((di)->meta) |= ((isc) << 3)) +/* Get the flow control flags of the instruction, see 'features for decompose' below. */ +#define META_GET_FC(meta) ((meta) & 0x7) + +/* Get the target address of a branching instruction. O_PC operand type. */ +#define INSTRUCTION_GET_TARGET(di) ((_OffsetType)(((di)->addr + (di)->imm.addr + (di)->size))) +/* Get the target address of a RIP-relative memory indirection. */ +#define INSTRUCTION_GET_RIP_TARGET(di) ((_OffsetType)(((di)->addr + (di)->disp + (di)->size))) + +/* + * Operand Size or Adderss size are stored inside the flags: + * 00 - 16 bits + * 01 - 32 bits + * 10 - 64 bits + * 11 - reserved + * + * If you call these set-macros more than once, you will have to clean the bits before doing so. + */ +#define FLAG_SET_OPSIZE(di, size) ((di->flags) |= (((size) & 3) << 8)) +#define FLAG_SET_ADDRSIZE(di, size) ((di->flags) |= (((size) & 3) << 10)) +#define FLAG_GET_OPSIZE(flags) (((flags) >> 8) & 3) +#define FLAG_GET_ADDRSIZE(flags) (((flags) >> 10) & 3) +/* To get the LOCK/REPNZ/REP prefixes. */ +#define FLAG_GET_PREFIX(flags) ((flags) & 7) +/* Indicates whether the instruction is privileged. */ +#define FLAG_GET_PRIVILEGED(flags) (((flags) & FLAG_PRIVILEGED_INSTRUCTION) != 0) + +/* + * Macros to extract segment registers from 'segment': + */ +#define SEGMENT_DEFAULT 0x80 +#define SEGMENT_SET(di, seg) ((di->segment) |= seg) +#define SEGMENT_GET(segment) (((segment) == R_NONE) ? R_NONE : ((segment) & 0x7f)) +#define SEGMENT_IS_DEFAULT(segment) (((segment) & SEGMENT_DEFAULT) == SEGMENT_DEFAULT) + + +/* Decodes modes of the disassembler, 16 bits or 32 bits or 64 bits for AMD64, x86-64. */ +typedef enum { Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2 } _DecodeType; + +typedef OFFSET_INTEGER _OffsetType; + +typedef struct { + _OffsetType codeOffset, nextOffset; /* nextOffset is OUT only. */ + const uint8_t* code; + int codeLen; /* Using signed integer makes it easier to detect an underflow. */ + _DecodeType dt; + unsigned int features; +} _CodeInfo; + +typedef enum { O_NONE, O_REG, O_IMM, O_IMM1, O_IMM2, O_DISP, O_SMEM, O_MEM, O_PC, O_PTR } _OperandType; + +typedef union { + /* Used by O_IMM: */ + int8_t sbyte; + uint8_t byte; + int16_t sword; + uint16_t word; + int32_t sdword; + uint32_t dword; + int64_t sqword; /* All immediates are SIGN-EXTENDED to 64 bits! */ + uint64_t qword; + + /* Used by O_PC: (Use GET_TARGET_ADDR).*/ + _OffsetType addr; /* It's a relative offset as for now. */ + + /* Used by O_PTR: */ + struct { + uint16_t seg; + /* Can be 16 or 32 bits, size is in ops[n].size. */ + uint32_t off; + } ptr; + + /* Used by O_IMM1 (i1) and O_IMM2 (i2). ENTER instruction only. */ + struct { + uint32_t i1; + uint32_t i2; + } ex; +} _Value; + +typedef struct { + /* Type of operand: + O_NONE: operand is to be ignored. + O_REG: index holds global register index. + O_IMM: instruction.imm. + O_IMM1: instruction.imm.ex.i1. + O_IMM2: instruction.imm.ex.i2. + O_DISP: memory dereference with displacement only, instruction.disp. + O_SMEM: simple memory dereference with optional displacement (a single register memory dereference). + O_MEM: complex memory dereference (optional fields: s/i/b/disp). + O_PC: the relative address of a branch instruction (instruction.imm.addr). + O_PTR: the absolute target address of a far branch instruction (instruction.imm.ptr.seg/off). + */ + uint8_t type; /* _OperandType */ + + /* Index of: + O_REG: holds global register index + O_SMEM: holds the 'base' register. E.G: [ECX], [EBX+0x1234] are both in operand.index. + O_MEM: holds the 'index' register. E.G: [EAX*4] is in operand.index. + */ + uint8_t index; + + /* Size in bits of: + O_REG: register + O_IMM: instruction.imm + O_IMM1: instruction.imm.ex.i1 + O_IMM2: instruction.imm.ex.i2 + O_DISP: instruction.disp + O_SMEM: size of indirection. + O_MEM: size of indirection. + O_PC: size of the relative offset + O_PTR: size of instruction.imm.ptr.off (16 or 32) + */ + uint16_t size; +} _Operand; + +#define OPCODE_ID_NONE 0 +/* Instruction could not be disassembled. */ +#define FLAG_NOT_DECODABLE ((uint16_t)-1) +/* The instruction locks memory access. */ +#define FLAG_LOCK (1 << 0) +/* The instruction is prefixed with a REPNZ. */ +#define FLAG_REPNZ (1 << 1) +/* The instruction is prefixed with a REP, this can be a REPZ, it depends on the specific instruction. */ +#define FLAG_REP (1 << 2) +/* Indicates there is a hint taken for Jcc instructions only. */ +#define FLAG_HINT_TAKEN (1 << 3) +/* Indicates there is a hint non-taken for Jcc instructions only. */ +#define FLAG_HINT_NOT_TAKEN (1 << 4) +/* The Imm value is signed extended (E.G in 64 bit decoding mode, a 32 bit imm is usually sign extended into 64 bit imm). */ +#define FLAG_IMM_SIGNED (1 << 5) +/* The destination operand is writable. */ +#define FLAG_DST_WR (1 << 6) +/* The instruction uses RIP-relative indirection. */ +#define FLAG_RIP_RELATIVE (1 << 7) + +/* See flag FLAG_GET_XXX macros above. */ + +/* The instruction is privileged and can only be used from Ring0. */ +#define FLAG_PRIVILEGED_INSTRUCTION (1 << 15) + +/* No register was defined. */ +#define R_NONE ((uint8_t)-1) + +#define REGS64_BASE 0 +#define REGS32_BASE 16 +#define REGS16_BASE 32 +#define REGS8_BASE 48 +#define REGS8_REX_BASE 64 +#define SREGS_BASE 68 +#define FPUREGS_BASE 75 +#define MMXREGS_BASE 83 +#define SSEREGS_BASE 91 +#define AVXREGS_BASE 107 +#define CREGS_BASE 123 +#define DREGS_BASE 132 + +#define OPERANDS_NO (4) + +typedef struct { + /* Used by ops[n].type == O_IMM/O_IMM1&O_IMM2/O_PTR/O_PC. Its size is ops[n].size. */ + _Value imm; + /* Used by ops[n].type == O_SMEM/O_MEM/O_DISP. Its size is dispSize. */ + uint64_t disp; + /* Virtual address of first byte of instruction. */ + _OffsetType addr; + /* General flags of instruction, holds prefixes and more, if FLAG_NOT_DECODABLE, instruction is invalid. */ + uint16_t flags; + /* Unused prefixes mask, for each bit that is set that prefix is not used (LSB is byte [addr + 0]). */ + uint16_t unusedPrefixesMask; + /* Mask of registers that were used in the operands, only used for quick look up, in order to know *some* operand uses that register class. */ + uint32_t usedRegistersMask; + /* ID of opcode in the global opcode table. Use for mnemonic look up. */ + uint16_t opcode; + /* Up to four operands per instruction, ignored if ops[n].type == O_NONE. */ + _Operand ops[OPERANDS_NO]; + /* Size of the whole instruction in bytes. */ + uint8_t size; + /* Segment information of memory indirection, default segment, or overriden one, can be -1. Use SEGMENT macros. */ + uint8_t segment; + /* Used by ops[n].type == O_MEM. Base global register index (might be R_NONE), scale size (2/4/8), ignored for 0 or 1. */ + uint8_t base, scale; + uint8_t dispSize; + /* Meta defines the instruction set class, and the flow control flags. Use META macros. */ + uint8_t meta; + /* The CPU flags that the instruction operates upon. */ + uint16_t modifiedFlagsMask, testedFlagsMask, undefinedFlagsMask; +} _DInst; + +#ifndef DISTORM_LIGHT + +/* Static size of strings. Do not change this value. Keep Python wrapper in sync. */ +#define MAX_TEXT_SIZE (48) +typedef struct { + unsigned int length; + unsigned char p[MAX_TEXT_SIZE]; /* p is a null terminated string. */ +} _WString; + +/* + * Old decoded instruction structure in text format. + * Used only for backward compatibility with diStorm64. + * This structure holds all information the disassembler generates per instruction. + */ +typedef struct { + _WString mnemonic; /* Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc. */ + _WString operands; /* Operands of the decoded instruction, up to 3 operands, comma-seperated. */ + _WString instructionHex; /* Hex dump - little endian, including prefixes. */ + unsigned int size; /* Size of decoded instruction in bytes. */ + _OffsetType offset; /* Start offset of the decoded instruction. */ +} _DecodedInst; + +#endif /* DISTORM_LIGHT */ + +/* Register masks for quick look up, each mask indicates one of a register-class that is being used in some operand. */ +#define RM_AX 1 /* AL, AH, AX, EAX, RAX */ +#define RM_CX 2 /* CL, CH, CX, ECX, RCX */ +#define RM_DX 4 /* DL, DH, DX, EDX, RDX */ +#define RM_BX 8 /* BL, BH, BX, EBX, RBX */ +#define RM_SP 0x10 /* SPL, SP, ESP, RSP */ +#define RM_BP 0x20 /* BPL, BP, EBP, RBP */ +#define RM_SI 0x40 /* SIL, SI, ESI, RSI */ +#define RM_DI 0x80 /* DIL, DI, EDI, RDI */ +#define RM_FPU 0x100 /* ST(0) - ST(7) */ +#define RM_MMX 0x200 /* MM0 - MM7 */ +#define RM_SSE 0x400 /* XMM0 - XMM15 */ +#define RM_AVX 0x800 /* YMM0 - YMM15 */ +#define RM_CR 0x1000 /* CR0, CR2, CR3, CR4, CR8 */ +#define RM_DR 0x2000 /* DR0, DR1, DR2, DR3, DR6, DR7 */ +#define RM_R8 0x4000 /* R8B, R8W, R8D, R8 */ +#define RM_R9 0x8000 /* R9B, R9W, R9D, R9 */ +#define RM_R10 0x10000 /* R10B, R10W, R10D, R10 */ +#define RM_R11 0x20000 /* R11B, R11W, R11D, R11 */ +#define RM_R12 0x40000 /* R12B, R12W, R12D, R12 */ +#define RM_R13 0x80000 /* R13B, R13W, R13D, R13 */ +#define RM_R14 0x100000 /* R14B, R14W, R14D, R14 */ +#define RM_R15 0x200000 /* R15B, R15W, R15D, R15 */ + +/* RIP should be checked using the 'flags' field and FLAG_RIP_RELATIVE. + * Segments should be checked using the segment macros. + * For now R8 - R15 are not supported and non general purpose registers map into same RM. + */ + +/* CPU flags that instructions modify, test or undefine (are EFLAGS compatible!). */ +#define D_CF 1 /* Carry */ +#define D_PF 4 /* Parity */ +#define D_AF 0x10 /* Auxiliary */ +#define D_ZF 0x40 /* Zero */ +#define D_SF 0x80 /* Sign */ +#define D_IF 0x200 /* Interrupt */ +#define D_DF 0x400 /* Direction */ +#define D_OF 0x800 /* Overflow */ + +/* + * Instructions Set classes: + * if you want a better understanding of the available classes, look at disOps project, file: x86sets.py. + */ +/* Indicates the instruction belongs to the General Integer set. */ +#define ISC_INTEGER 1 +/* Indicates the instruction belongs to the 387 FPU set. */ +#define ISC_FPU 2 +/* Indicates the instruction belongs to the P6 set. */ +#define ISC_P6 3 +/* Indicates the instruction belongs to the MMX set. */ +#define ISC_MMX 4 +/* Indicates the instruction belongs to the SSE set. */ +#define ISC_SSE 5 +/* Indicates the instruction belongs to the SSE2 set. */ +#define ISC_SSE2 6 +/* Indicates the instruction belongs to the SSE3 set. */ +#define ISC_SSE3 7 +/* Indicates the instruction belongs to the SSSE3 set. */ +#define ISC_SSSE3 8 +/* Indicates the instruction belongs to the SSE4.1 set. */ +#define ISC_SSE4_1 9 +/* Indicates the instruction belongs to the SSE4.2 set. */ +#define ISC_SSE4_2 10 +/* Indicates the instruction belongs to the AMD's SSE4.A set. */ +#define ISC_SSE4_A 11 +/* Indicates the instruction belongs to the 3DNow! set. */ +#define ISC_3DNOW 12 +/* Indicates the instruction belongs to the 3DNow! Extensions set. */ +#define ISC_3DNOWEXT 13 +/* Indicates the instruction belongs to the VMX (Intel) set. */ +#define ISC_VMX 14 +/* Indicates the instruction belongs to the SVM (AMD) set. */ +#define ISC_SVM 15 +/* Indicates the instruction belongs to the AVX (Intel) set. */ +#define ISC_AVX 16 +/* Indicates the instruction belongs to the FMA (Intel) set. */ +#define ISC_FMA 17 +/* Indicates the instruction belongs to the AES/AVX (Intel) set. */ +#define ISC_AES 18 +/* Indicates the instruction belongs to the CLMUL (Intel) set. */ +#define ISC_CLMUL 19 + +/* Features for decompose: */ +#define DF_NONE 0 +/* The decoder will limit addresses to a maximum of 16 bits. */ +#define DF_MAXIMUM_ADDR16 1 +/* The decoder will limit addresses to a maximum of 32 bits. */ +#define DF_MAXIMUM_ADDR32 2 +/* The decoder will return only flow control instructions (and filter the others internally). */ +#define DF_RETURN_FC_ONLY 4 +/* The decoder will stop and return to the caller when the instruction 'CALL' (near and far) was decoded. */ +#define DF_STOP_ON_CALL 8 +/* The decoder will stop and return to the caller when the instruction 'RET' (near and far) was decoded. */ +#define DF_STOP_ON_RET 0x10 +/* The decoder will stop and return to the caller when the instruction system-call/ret was decoded. */ +#define DF_STOP_ON_SYS 0x20 +/* The decoder will stop and return to the caller when any of the branch 'JMP', (near and far) instructions were decoded. */ +#define DF_STOP_ON_UNC_BRANCH 0x40 +/* The decoder will stop and return to the caller when any of the conditional branch instruction were decoded. */ +#define DF_STOP_ON_CND_BRANCH 0x80 +/* The decoder will stop and return to the caller when the instruction 'INT' (INT, INT1, INTO, INT 3) was decoded. */ +#define DF_STOP_ON_INT 0x100 +/* The decoder will stop and return to the caller when any of the 'CMOVxx' instruction was decoded. */ +#define DF_STOP_ON_CMOV 0x200 +/* The decoder will stop and return to the caller when any flow control instruction was decoded. */ +#define DF_STOP_ON_FLOW_CONTROL (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV) + +/* Indicates the instruction is not a flow-control instruction. */ +#define FC_NONE 0 +/* Indicates the instruction is one of: CALL, CALL FAR. */ +#define FC_CALL 1 +/* Indicates the instruction is one of: RET, IRET, RETF. */ +#define FC_RET 2 +/* Indicates the instruction is one of: SYSCALL, SYSRET, SYSENTER, SYSEXIT. */ +#define FC_SYS 3 +/* Indicates the instruction is one of: JMP, JMP FAR. */ +#define FC_UNC_BRANCH 4 +/* + * Indicates the instruction is one of: + * JCXZ, JO, JNO, JB, JAE, JZ, JNZ, JBE, JA, JS, JNS, JP, JNP, JL, JGE, JLE, JG, LOOP, LOOPZ, LOOPNZ. + */ +#define FC_CND_BRANCH 5 +/* Indiciates the instruction is one of: INT, INT1, INT 3, INTO, UD2. */ +#define FC_INT 6 +/* Indicates the instruction is one of: CMOVxx. */ +#define FC_CMOV 7 + +/* Return code of the decoding function. */ +typedef enum { DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR, DECRES_FILTERED } _DecodeResult; + +/* Define the following interface functions only for outer projects. */ +#if !(defined(DISTORM_STATIC) || defined(DISTORM_DYNAMIC)) + +/* distorm_decode + * Input: + * offset - Origin of the given code (virtual address that is), NOT an offset in code. + * code - Pointer to the code buffer to be disassembled. + * length - Amount of bytes that should be decoded from the code buffer. + * dt - Decoding mode, 16 bits (Decode16Bits), 32 bits (Decode32Bits) or AMD64 (Decode64Bits). + * result - Array of type _DecodeInst which will be used by this function in order to return the disassembled instructions. + * maxInstructions - The maximum number of entries in the result array that you pass to this function, so it won't exceed its bound. + * usedInstructionsCount - Number of the instruction that successfully were disassembled and written to the result array. + * Output: usedInstructionsCount will hold the number of entries used in the result array + * and the result array itself will be filled with the disassembled instructions. + * Return: DECRES_SUCCESS on success (no more to disassemble), DECRES_INPUTERR on input error (null code buffer, invalid decoding mode, etc...), + * DECRES_MEMORYERR when there are not enough entries to use in the result array, BUT YOU STILL have to check for usedInstructionsCount! + * Side-Effects: Even if the return code is DECRES_MEMORYERR, there might STILL be data in the + * array you passed, this function will try to use as much entries as possible! + * Notes: 1)The minimal size of maxInstructions is 15. + * 2)You will have to synchronize the offset,code and length by yourself if you pass code fragments and not a complete code block! + */ + +/* distorm_decompose + * See more documentation online at the GitHub project's wiki. + * + */ +#ifdef SUPPORT_64BIT_OFFSET + + _DecodeResult distorm_decompose64(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + #define distorm_decompose distorm_decompose64 + +#ifndef DISTORM_LIGHT + /* If distorm-light is defined, we won't export these text-formatting functionality. */ + _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + void distorm_format64(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result); + #define distorm_decode distorm_decode64 + #define distorm_format distorm_format64 +#endif /*DISTORM_LIGHT*/ + +#else /*SUPPORT_64BIT_OFFSET*/ + + _DecodeResult distorm_decompose32(_CodeInfo* ci, _DInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + #define distorm_decompose distorm_decompose32 + +#ifndef DISTORM_LIGHT + /* If distorm-light is defined, we won't export these text-formatting functionality. */ + _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); + void distorm_format32(const _CodeInfo* ci, const _DInst* di, _DecodedInst* result); + #define distorm_decode distorm_decode32 + #define distorm_format distorm_format32 +#endif /*DISTORM_LIGHT*/ + +#endif + +/* + * distorm_version + * Input: + * none + * + * Output: unsigned int - version of compiled library. + */ +unsigned int distorm_version(); + +#endif /* DISTORM_STATIC */ + +#ifdef __cplusplus +} /* End Of Extern */ +#endif + +#endif /* DISTORM_H */ diff --git a/import/distorm/include/mnemonics.h b/import/distorm/include/mnemonics.h new file mode 100644 index 000000000..ef9889c8e --- /dev/null +++ b/import/distorm/include/mnemonics.h @@ -0,0 +1,301 @@ +/* +mnemonics.h + +diStorm3 - Powerful disassembler for X86/AMD64 +http://ragestorm.net/distorm/ +distorm at gmail dot com +Copyright (C) 2003-2016 Gil Dabah +This library is licensed under the BSD license. See the file COPYING. +*/ + + +#ifndef MNEMONICS_H +#define MNEMONICS_H + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef DISTORM_LIGHT + +typedef struct WMnemonic { + unsigned char length; + unsigned char p[1]; /* p is a null terminated string, which contains 'length' characters. */ +} _WMnemonic; + +typedef struct WRegister { + unsigned int length; + unsigned char p[6]; /* p is a null terminated string. */ +} _WRegister; + +extern const unsigned char _MNEMONICS[]; +extern const _WRegister _REGISTERS[]; + +#endif /* DISTORM_LIGHT */ + +#ifdef __cplusplus +} /* End Of Extern */ +#endif + +#define GET_REGISTER_NAME(r) (unsigned char*)_REGISTERS[(r)].p +#define GET_MNEMONIC_NAME(m) ((_WMnemonic*)&_MNEMONICS[(m)])->p + + typedef enum { + I_UNDEFINED = 0, I_AAA = 66, I_AAD = 389, I_AAM = 384, I_AAS = 76, I_ADC = 31, I_ADD = 11, I_ADDPD = 3132, + I_ADDPS = 3125, I_ADDSD = 3146, I_ADDSS = 3139, I_ADDSUBPD = 6416, I_ADDSUBPS = 6426, + I_AESDEC = 9231, I_AESDECLAST = 9248, I_AESENC = 9189, I_AESENCLAST = 9206, + I_AESIMC = 9172, I_AESKEYGENASSIST = 9817, I_AND = 41, I_ANDNPD = 3043, I_ANDNPS = 3035, + I_ANDPD = 3012, I_ANDPS = 3005, I_ARPL = 111, I_BLENDPD = 9394, I_BLENDPS = 9375, + I_BLENDVPD = 7641, I_BLENDVPS = 7631, I_BOUND = 104, I_BSF = 4368, I_BSR = 4380, + I_BSWAP = 960, I_BT = 872, I_BTC = 934, I_BTR = 912, I_BTS = 887, I_CALL = 456, + I_CALL_FAR = 260, I_CBW = 228, I_CDQ = 250, I_CDQE = 239, I_CLC = 492, I_CLD = 512, + I_CLFLUSH = 4351, I_CLGI = 1855, I_CLI = 502, I_CLTS = 541, I_CMC = 487, I_CMOVA = 694, + I_CMOVAE = 663, I_CMOVB = 656, I_CMOVBE = 686, I_CMOVG = 754, I_CMOVGE = 738, + I_CMOVL = 731, I_CMOVLE = 746, I_CMOVNO = 648, I_CMOVNP = 723, I_CMOVNS = 708, + I_CMOVNZ = 678, I_CMOVO = 641, I_CMOVP = 716, I_CMOVS = 701, I_CMOVZ = 671, + I_CMP = 71, I_CMPEQPD = 4471, I_CMPEQPS = 4392, I_CMPEQSD = 4629, I_CMPEQSS = 4550, + I_CMPLEPD = 4489, I_CMPLEPS = 4410, I_CMPLESD = 4647, I_CMPLESS = 4568, I_CMPLTPD = 4480, + I_CMPLTPS = 4401, I_CMPLTSD = 4638, I_CMPLTSS = 4559, I_CMPNEQPD = 4510, I_CMPNEQPS = 4431, + I_CMPNEQSD = 4668, I_CMPNEQSS = 4589, I_CMPNLEPD = 4530, I_CMPNLEPS = 4451, + I_CMPNLESD = 4688, I_CMPNLESS = 4609, I_CMPNLTPD = 4520, I_CMPNLTPS = 4441, + I_CMPNLTSD = 4678, I_CMPNLTSS = 4599, I_CMPORDPD = 4540, I_CMPORDPS = 4461, + I_CMPORDSD = 4698, I_CMPORDSS = 4619, I_CMPS = 301, I_CMPUNORDPD = 4498, I_CMPUNORDPS = 4419, + I_CMPUNORDSD = 4656, I_CMPUNORDSS = 4577, I_CMPXCHG = 898, I_CMPXCHG16B = 6395, + I_CMPXCHG8B = 6384, I_COMISD = 2801, I_COMISS = 2793, I_CPUID = 865, I_CQO = 255, + I_CRC32 = 9280, I_CVTDQ2PD = 6809, I_CVTDQ2PS = 3329, I_CVTPD2DQ = 6819, I_CVTPD2PI = 2703, + I_CVTPD2PS = 3255, I_CVTPH2PS = 4183, I_CVTPI2PD = 2517, I_CVTPI2PS = 2507, + I_CVTPS2DQ = 3339, I_CVTPS2PD = 3245, I_CVTPS2PH = 4193, I_CVTPS2PI = 2693, + I_CVTSD2SI = 2723, I_CVTSD2SS = 3275, I_CVTSI2SD = 2537, I_CVTSI2SS = 2527, + I_CVTSS2SD = 3265, I_CVTSS2SI = 2713, I_CVTTPD2DQ = 6798, I_CVTTPD2PI = 2636, + I_CVTTPS2DQ = 3349, I_CVTTPS2PI = 2625, I_CVTTSD2SI = 2658, I_CVTTSS2SI = 2647, + I_CWD = 245, I_CWDE = 233, I_DAA = 46, I_DAS = 56, I_DEC = 86, I_DIV = 1646, + I_DIVPD = 3521, I_DIVPS = 3514, I_DIVSD = 3535, I_DIVSS = 3528, I_DPPD = 9637, + I_DPPS = 9624, I_EMMS = 4122, I_ENTER = 340, I_EXTRACTPS = 9502, I_EXTRQ = 4158, + I_F2XM1 = 1192, I_FABS = 1123, I_FADD = 1023, I_FADDP = 1549, I_FBLD = 1601, + I_FBSTP = 1607, I_FCHS = 1117, I_FCLEX = 7311, I_FCMOVB = 1376, I_FCMOVBE = 1392, + I_FCMOVE = 1384, I_FCMOVNB = 1445, I_FCMOVNBE = 1463, I_FCMOVNE = 1454, I_FCMOVNU = 1473, + I_FCMOVU = 1401, I_FCOM = 1035, I_FCOMI = 1512, I_FCOMIP = 1623, I_FCOMP = 1041, + I_FCOMPP = 1563, I_FCOS = 1311, I_FDECSTP = 1238, I_FDIV = 1061, I_FDIVP = 1594, + I_FDIVR = 1067, I_FDIVRP = 1586, I_FEDISI = 1488, I_FEMMS = 574, I_FENI = 1482, + I_FFREE = 1527, I_FIADD = 1317, I_FICOM = 1331, I_FICOMP = 1338, I_FIDIV = 1361, + I_FIDIVR = 1368, I_FILD = 1418, I_FIMUL = 1324, I_FINCSTP = 1247, I_FINIT = 7326, + I_FIST = 1432, I_FISTP = 1438, I_FISTTP = 1424, I_FISUB = 1346, I_FISUBR = 1353, + I_FLD = 1074, I_FLD1 = 1141, I_FLDCW = 1098, I_FLDENV = 1090, I_FLDL2E = 1155, + I_FLDL2T = 1147, I_FLDLG2 = 1170, I_FLDLN2 = 1178, I_FLDPI = 1163, I_FLDZ = 1186, + I_FMUL = 1029, I_FMULP = 1556, I_FNCLEX = 7303, I_FNINIT = 7318, I_FNOP = 1111, + I_FNSAVE = 7333, I_FNSTCW = 7288, I_FNSTENV = 7271, I_FNSTSW = 7348, I_FPATAN = 1213, + I_FPREM = 1256, I_FPREM1 = 1230, I_FPTAN = 1206, I_FRNDINT = 1288, I_FRSTOR = 1519, + I_FSAVE = 7341, I_FSCALE = 1297, I_FSETPM = 1496, I_FSIN = 1305, I_FSINCOS = 1279, + I_FSQRT = 1272, I_FST = 1079, I_FSTCW = 7296, I_FSTENV = 7280, I_FSTP = 1084, + I_FSTSW = 7356, I_FSUB = 1048, I_FSUBP = 1579, I_FSUBR = 1054, I_FSUBRP = 1571, + I_FTST = 1129, I_FUCOM = 1534, I_FUCOMI = 1504, I_FUCOMIP = 1614, I_FUCOMP = 1541, + I_FUCOMPP = 1409, I_FXAM = 1135, I_FXCH = 1105, I_FXRSTOR = 9914, I_FXRSTOR64 = 9923, + I_FXSAVE = 9886, I_FXSAVE64 = 9894, I_FXTRACT = 1221, I_FYL2X = 1199, I_FYL2XP1 = 1263, + I_GETSEC = 633, I_HADDPD = 4203, I_HADDPS = 4211, I_HLT = 482, I_HSUBPD = 4237, + I_HSUBPS = 4245, I_IDIV = 1651, I_IMUL = 117, I_IN = 447, I_INC = 81, I_INS = 123, + I_INSERTPS = 9569, I_INSERTQ = 4165, I_INT = 367, I_INT_3 = 360, I_INT1 = 476, + I_INTO = 372, I_INVD = 555, I_INVEPT = 8306, I_INVLPG = 1727, I_INVLPGA = 1869, + I_INVPCID = 8323, I_INVVPID = 8314, I_IRET = 378, I_JA = 166, I_JAE = 147, + I_JB = 143, I_JBE = 161, I_JCXZ = 427, I_JECXZ = 433, I_JG = 202, I_JGE = 192, + I_JL = 188, I_JLE = 197, I_JMP = 462, I_JMP_FAR = 467, I_JNO = 138, I_JNP = 183, + I_JNS = 174, I_JNZ = 156, I_JO = 134, I_JP = 179, I_JRCXZ = 440, I_JS = 170, + I_JZ = 152, I_LAHF = 289, I_LAR = 522, I_LDDQU = 7016, I_LDMXCSR = 9944, I_LDS = 335, + I_LEA = 223, I_LEAVE = 347, I_LES = 330, I_LFENCE = 4287, I_LFS = 917, I_LGDT = 1703, + I_LGS = 922, I_LIDT = 1709, I_LLDT = 1668, I_LMSW = 1721, I_LODS = 313, I_LOOP = 421, + I_LOOPNZ = 406, I_LOOPZ = 414, I_LSL = 527, I_LSS = 907, I_LTR = 1674, I_LZCNT = 4385, + I_MASKMOVDQU = 7141, I_MASKMOVQ = 7131, I_MAXPD = 3581, I_MAXPS = 3574, I_MAXSD = 3595, + I_MAXSS = 3588, I_MFENCE = 4313, I_MINPD = 3461, I_MINPS = 3454, I_MINSD = 3475, + I_MINSS = 3468, I_MONITOR = 1771, I_MOV = 218, I_MOVAPD = 2481, I_MOVAPS = 2473, + I_MOVBE = 9273, I_MOVD = 3942, I_MOVDDUP = 2208, I_MOVDQ2Q = 6544, I_MOVDQA = 3968, + I_MOVDQU = 3976, I_MOVHLPS = 2173, I_MOVHPD = 2367, I_MOVHPS = 2359, I_MOVLHPS = 2350, + I_MOVLPD = 2190, I_MOVLPS = 2182, I_MOVMSKPD = 2837, I_MOVMSKPS = 2827, I_MOVNTDQ = 6871, + I_MOVNTDQA = 7917, I_MOVNTI = 952, I_MOVNTPD = 2578, I_MOVNTPS = 2569, I_MOVNTQ = 6863, + I_MOVNTSD = 2596, I_MOVNTSS = 2587, I_MOVQ = 3948, I_MOVQ2DQ = 6535, I_MOVS = 295, + I_MOVSD = 2132, I_MOVSHDUP = 2375, I_MOVSLDUP = 2198, I_MOVSS = 2125, I_MOVSX = 939, + I_MOVSXD = 10027, I_MOVUPD = 2117, I_MOVUPS = 2109, I_MOVZX = 927, I_MPSADBW = 9650, + I_MUL = 1641, I_MULPD = 3192, I_MULPS = 3185, I_MULSD = 3206, I_MULSS = 3199, + I_MWAIT = 1780, I_NEG = 1636, I_NOP = 581, I_NOT = 1631, I_OR = 27, I_ORPD = 3075, + I_ORPS = 3069, I_OUT = 451, I_OUTS = 128, I_PABSB = 7710, I_PABSD = 7740, I_PABSW = 7725, + I_PACKSSDW = 3871, I_PACKSSWB = 3703, I_PACKUSDW = 7938, I_PACKUSWB = 3781, + I_PADDB = 7226, I_PADDD = 7256, I_PADDQ = 6503, I_PADDSB = 6952, I_PADDSW = 6969, + I_PADDUSB = 6642, I_PADDUSW = 6661, I_PADDW = 7241, I_PALIGNR = 9432, I_PAND = 6629, + I_PANDN = 6687, I_PAUSE = 10035, I_PAVGB = 6702, I_PAVGUSB = 2100, I_PAVGW = 6747, + I_PBLENDVB = 7621, I_PBLENDW = 9413, I_PCLMULQDQ = 9669, I_PCMPEQB = 4065, + I_PCMPEQD = 4103, I_PCMPEQQ = 7898, I_PCMPEQW = 4084, I_PCMPESTRI = 9748, + I_PCMPESTRM = 9725, I_PCMPGTB = 3724, I_PCMPGTD = 3762, I_PCMPGTQ = 8109, + I_PCMPGTW = 3743, I_PCMPISTRI = 9794, I_PCMPISTRM = 9771, I_PEXTRB = 9451, + I_PEXTRD = 9468, I_PEXTRQ = 9476, I_PEXTRW = 6333, I_PF2ID = 1936, I_PF2IW = 1929, + I_PFACC = 2050, I_PFADD = 1999, I_PFCMPEQ = 2057, I_PFCMPGE = 1960, I_PFCMPGT = 2006, + I_PFMAX = 2015, I_PFMIN = 1969, I_PFMUL = 2066, I_PFNACC = 1943, I_PFPNACC = 1951, + I_PFRCP = 1976, I_PFRCPIT1 = 2022, I_PFRCPIT2 = 2073, I_PFRSQIT1 = 2032, I_PFRSQRT = 1983, + I_PFSUB = 1992, I_PFSUBR = 2042, I_PHADDD = 7397, I_PHADDSW = 7414, I_PHADDW = 7380, + I_PHMINPOSUW = 8281, I_PHSUBD = 7473, I_PHSUBSW = 7490, I_PHSUBW = 7456, I_PI2FD = 1922, + I_PI2FW = 1915, I_PINSRB = 9552, I_PINSRD = 9590, I_PINSRQ = 9598, I_PINSRW = 6316, + I_PMADDUBSW = 7433, I_PMADDWD = 7095, I_PMAXSB = 8196, I_PMAXSD = 8213, I_PMAXSW = 6986, + I_PMAXUB = 6670, I_PMAXUD = 8247, I_PMAXUW = 8230, I_PMINSB = 8128, I_PMINSD = 8145, + I_PMINSW = 6924, I_PMINUB = 6612, I_PMINUD = 8179, I_PMINUW = 8162, I_PMOVMSKB = 6553, + I_PMOVSXBD = 7776, I_PMOVSXBQ = 7797, I_PMOVSXBW = 7755, I_PMOVSXDQ = 7860, + I_PMOVSXWD = 7818, I_PMOVSXWQ = 7839, I_PMOVZXBD = 8004, I_PMOVZXBQ = 8025, + I_PMOVZXBW = 7983, I_PMOVZXDQ = 8088, I_PMOVZXWD = 8046, I_PMOVZXWQ = 8067, + I_PMULDQ = 7881, I_PMULHRSW = 7560, I_PMULHRW = 2083, I_PMULHUW = 6762, I_PMULHW = 6781, + I_PMULLD = 8264, I_PMULLW = 6518, I_PMULUDQ = 7076, I_POP = 22, I_POPA = 98, + I_POPCNT = 4360, I_POPF = 277, I_POR = 6941, I_PREFETCH = 1894, I_PREFETCHNTA = 2424, + I_PREFETCHT0 = 2437, I_PREFETCHT1 = 2449, I_PREFETCHT2 = 2461, I_PREFETCHW = 1904, + I_PSADBW = 7114, I_PSHUFB = 7363, I_PSHUFD = 4010, I_PSHUFHW = 4018, I_PSHUFLW = 4027, + I_PSHUFW = 4002, I_PSIGNB = 7509, I_PSIGND = 7543, I_PSIGNW = 7526, I_PSLLD = 7046, + I_PSLLDQ = 9869, I_PSLLQ = 7061, I_PSLLW = 7031, I_PSRAD = 6732, I_PSRAW = 6717, + I_PSRLD = 6473, I_PSRLDQ = 9852, I_PSRLQ = 6488, I_PSRLW = 6458, I_PSUBB = 7166, + I_PSUBD = 7196, I_PSUBQ = 7211, I_PSUBSB = 6890, I_PSUBSW = 6907, I_PSUBUSB = 6574, + I_PSUBUSW = 6593, I_PSUBW = 7181, I_PSWAPD = 2092, I_PTEST = 7651, I_PUNPCKHBW = 3802, + I_PUNPCKHDQ = 3848, I_PUNPCKHQDQ = 3917, I_PUNPCKHWD = 3825, I_PUNPCKLBW = 3634, + I_PUNPCKLDQ = 3680, I_PUNPCKLQDQ = 3892, I_PUNPCKLWD = 3657, I_PUSH = 16, + I_PUSHA = 91, I_PUSHF = 270, I_PXOR = 7003, I_RCL = 977, I_RCPPS = 2975, I_RCPSS = 2982, + I_RCR = 982, I_RDFSBASE = 9904, I_RDGSBASE = 9934, I_RDMSR = 600, I_RDPMC = 607, + I_RDRAND = 10048, I_RDTSC = 593, I_RDTSCP = 1886, I_RET = 325, I_RETF = 354, + I_ROL = 967, I_ROR = 972, I_ROUNDPD = 9318, I_ROUNDPS = 9299, I_ROUNDSD = 9356, + I_ROUNDSS = 9337, I_RSM = 882, I_RSQRTPS = 2937, I_RSQRTSS = 2946, I_SAHF = 283, + I_SAL = 997, I_SALC = 394, I_SAR = 1002, I_SBB = 36, I_SCAS = 319, I_SETA = 807, + I_SETAE = 780, I_SETB = 774, I_SETBE = 800, I_SETG = 859, I_SETGE = 845, I_SETL = 839, + I_SETLE = 852, I_SETNO = 767, I_SETNP = 832, I_SETNS = 819, I_SETNZ = 793, + I_SETO = 761, I_SETP = 826, I_SETS = 813, I_SETZ = 787, I_SFENCE = 4343, I_SGDT = 1691, + I_SHL = 987, I_SHLD = 876, I_SHR = 992, I_SHRD = 892, I_SHUFPD = 6358, I_SHUFPS = 6350, + I_SIDT = 1697, I_SKINIT = 1861, I_SLDT = 1657, I_SMSW = 1715, I_SQRTPD = 2877, + I_SQRTPS = 2869, I_SQRTSD = 2893, I_SQRTSS = 2885, I_STC = 497, I_STD = 517, + I_STGI = 1849, I_STI = 507, I_STMXCSR = 9973, I_STOS = 307, I_STR = 1663, I_SUB = 51, + I_SUBPD = 3401, I_SUBPS = 3394, I_SUBSD = 3415, I_SUBSS = 3408, I_SWAPGS = 1878, + I_SYSCALL = 532, I_SYSENTER = 614, I_SYSEXIT = 624, I_SYSRET = 547, I_TEST = 206, + I_TZCNT = 4373, I_UCOMISD = 2764, I_UCOMISS = 2755, I_UD2 = 569, I_UNPCKHPD = 2318, + I_UNPCKHPS = 2308, I_UNPCKLPD = 2276, I_UNPCKLPS = 2266, I_VADDPD = 3161, + I_VADDPS = 3153, I_VADDSD = 3177, I_VADDSS = 3169, I_VADDSUBPD = 6436, I_VADDSUBPS = 6447, + I_VAESDEC = 9239, I_VAESDECLAST = 9260, I_VAESENC = 9197, I_VAESENCLAST = 9218, + I_VAESIMC = 9180, I_VAESKEYGENASSIST = 9834, I_VANDNPD = 3060, I_VANDNPS = 3051, + I_VANDPD = 3027, I_VANDPS = 3019, I_VBLENDPD = 9403, I_VBLENDPS = 9384, I_VBLENDVPD = 9703, + I_VBLENDVPS = 9692, I_VBROADCASTF128 = 7694, I_VBROADCASTSD = 7680, I_VBROADCASTSS = 7666, + I_VCMPEQPD = 5110, I_VCMPEQPS = 4708, I_VCMPEQSD = 5914, I_VCMPEQSS = 5512, + I_VCMPEQ_OSPD = 5291, I_VCMPEQ_OSPS = 4889, I_VCMPEQ_OSSD = 6095, I_VCMPEQ_OSSS = 5693, + I_VCMPEQ_UQPD = 5197, I_VCMPEQ_UQPS = 4795, I_VCMPEQ_UQSD = 6001, I_VCMPEQ_UQSS = 5599, + I_VCMPEQ_USPD = 5400, I_VCMPEQ_USPS = 4998, I_VCMPEQ_USSD = 6204, I_VCMPEQ_USSS = 5802, + I_VCMPFALSEPD = 5232, I_VCMPFALSEPS = 4830, I_VCMPFALSESD = 6036, I_VCMPFALSESS = 5634, + I_VCMPFALSE_OSPD = 5441, I_VCMPFALSE_OSPS = 5039, I_VCMPFALSE_OSSD = 6245, + I_VCMPFALSE_OSSS = 5843, I_VCMPGEPD = 5259, I_VCMPGEPS = 4857, I_VCMPGESD = 6063, + I_VCMPGESS = 5661, I_VCMPGE_OQPD = 5471, I_VCMPGE_OQPS = 5069, I_VCMPGE_OQSD = 6275, + I_VCMPGE_OQSS = 5873, I_VCMPGTPD = 5269, I_VCMPGTPS = 4867, I_VCMPGTSD = 6073, + I_VCMPGTSS = 5671, I_VCMPGT_OQPD = 5484, I_VCMPGT_OQPS = 5082, I_VCMPGT_OQSD = 6288, + I_VCMPGT_OQSS = 5886, I_VCMPLEPD = 5130, I_VCMPLEPS = 4728, I_VCMPLESD = 5934, + I_VCMPLESS = 5532, I_VCMPLE_OQPD = 5317, I_VCMPLE_OQPS = 4915, I_VCMPLE_OQSD = 6121, + I_VCMPLE_OQSS = 5719, I_VCMPLTPD = 5120, I_VCMPLTPS = 4718, I_VCMPLTSD = 5924, + I_VCMPLTSS = 5522, I_VCMPLT_OQPD = 5304, I_VCMPLT_OQPS = 4902, I_VCMPLT_OQSD = 6108, + I_VCMPLT_OQSS = 5706, I_VCMPNEQPD = 5153, I_VCMPNEQPS = 4751, I_VCMPNEQSD = 5957, + I_VCMPNEQSS = 5555, I_VCMPNEQ_OQPD = 5245, I_VCMPNEQ_OQPS = 4843, I_VCMPNEQ_OQSD = 6049, + I_VCMPNEQ_OQSS = 5647, I_VCMPNEQ_OSPD = 5457, I_VCMPNEQ_OSPS = 5055, I_VCMPNEQ_OSSD = 6261, + I_VCMPNEQ_OSSS = 5859, I_VCMPNEQ_USPD = 5345, I_VCMPNEQ_USPS = 4943, I_VCMPNEQ_USSD = 6149, + I_VCMPNEQ_USSS = 5747, I_VCMPNGEPD = 5210, I_VCMPNGEPS = 4808, I_VCMPNGESD = 6014, + I_VCMPNGESS = 5612, I_VCMPNGE_UQPD = 5413, I_VCMPNGE_UQPS = 5011, I_VCMPNGE_UQSD = 6217, + I_VCMPNGE_UQSS = 5815, I_VCMPNGTPD = 5221, I_VCMPNGTPS = 4819, I_VCMPNGTSD = 6025, + I_VCMPNGTSS = 5623, I_VCMPNGT_UQPD = 5427, I_VCMPNGT_UQPS = 5025, I_VCMPNGT_UQSD = 6231, + I_VCMPNGT_UQSS = 5829, I_VCMPNLEPD = 5175, I_VCMPNLEPS = 4773, I_VCMPNLESD = 5979, + I_VCMPNLESS = 5577, I_VCMPNLE_UQPD = 5373, I_VCMPNLE_UQPS = 4971, I_VCMPNLE_UQSD = 6177, + I_VCMPNLE_UQSS = 5775, I_VCMPNLTPD = 5164, I_VCMPNLTPS = 4762, I_VCMPNLTSD = 5968, + I_VCMPNLTSS = 5566, I_VCMPNLT_UQPD = 5359, I_VCMPNLT_UQPS = 4957, I_VCMPNLT_UQSD = 6163, + I_VCMPNLT_UQSS = 5761, I_VCMPORDPD = 5186, I_VCMPORDPS = 4784, I_VCMPORDSD = 5990, + I_VCMPORDSS = 5588, I_VCMPORD_SPD = 5387, I_VCMPORD_SPS = 4985, I_VCMPORD_SSD = 6191, + I_VCMPORD_SSS = 5789, I_VCMPTRUEPD = 5279, I_VCMPTRUEPS = 4877, I_VCMPTRUESD = 6083, + I_VCMPTRUESS = 5681, I_VCMPTRUE_USPD = 5497, I_VCMPTRUE_USPS = 5095, I_VCMPTRUE_USSD = 6301, + I_VCMPTRUE_USSS = 5899, I_VCMPUNORDPD = 5140, I_VCMPUNORDPS = 4738, I_VCMPUNORDSD = 5944, + I_VCMPUNORDSS = 5542, I_VCMPUNORD_SPD = 5330, I_VCMPUNORD_SPS = 4928, I_VCMPUNORD_SSD = 6134, + I_VCMPUNORD_SSS = 5732, I_VCOMISD = 2818, I_VCOMISS = 2809, I_VCVTDQ2PD = 6841, + I_VCVTDQ2PS = 3360, I_VCVTPD2DQ = 6852, I_VCVTPD2PS = 3296, I_VCVTPS2DQ = 3371, + I_VCVTPS2PD = 3285, I_VCVTSD2SI = 2744, I_VCVTSD2SS = 3318, I_VCVTSI2SD = 2558, + I_VCVTSI2SS = 2547, I_VCVTSS2SD = 3307, I_VCVTSS2SI = 2733, I_VCVTTPD2DQ = 6829, + I_VCVTTPS2DQ = 3382, I_VCVTTSD2SI = 2681, I_VCVTTSS2SI = 2669, I_VDIVPD = 3550, + I_VDIVPS = 3542, I_VDIVSD = 3566, I_VDIVSS = 3558, I_VDPPD = 9643, I_VDPPS = 9630, + I_VERR = 1679, I_VERW = 1685, I_VEXTRACTF128 = 9538, I_VEXTRACTPS = 9513, + I_VFMADD132PD = 8409, I_VFMADD132PS = 8396, I_VFMADD132SD = 8435, I_VFMADD132SS = 8422, + I_VFMADD213PD = 8689, I_VFMADD213PS = 8676, I_VFMADD213SD = 8715, I_VFMADD213SS = 8702, + I_VFMADD231PD = 8969, I_VFMADD231PS = 8956, I_VFMADD231SD = 8995, I_VFMADD231SS = 8982, + I_VFMADDSUB132PD = 8348, I_VFMADDSUB132PS = 8332, I_VFMADDSUB213PD = 8628, + I_VFMADDSUB213PS = 8612, I_VFMADDSUB231PD = 8908, I_VFMADDSUB231PS = 8892, + I_VFMSUB132PD = 8461, I_VFMSUB132PS = 8448, I_VFMSUB132SD = 8487, I_VFMSUB132SS = 8474, + I_VFMSUB213PD = 8741, I_VFMSUB213PS = 8728, I_VFMSUB213SD = 8767, I_VFMSUB213SS = 8754, + I_VFMSUB231PD = 9021, I_VFMSUB231PS = 9008, I_VFMSUB231SD = 9047, I_VFMSUB231SS = 9034, + I_VFMSUBADD132PD = 8380, I_VFMSUBADD132PS = 8364, I_VFMSUBADD213PD = 8660, + I_VFMSUBADD213PS = 8644, I_VFMSUBADD231PD = 8940, I_VFMSUBADD231PS = 8924, + I_VFNMADD132PD = 8514, I_VFNMADD132PS = 8500, I_VFNMADD132SD = 8542, I_VFNMADD132SS = 8528, + I_VFNMADD213PD = 8794, I_VFNMADD213PS = 8780, I_VFNMADD213SD = 8822, I_VFNMADD213SS = 8808, + I_VFNMADD231PD = 9074, I_VFNMADD231PS = 9060, I_VFNMADD231SD = 9102, I_VFNMADD231SS = 9088, + I_VFNMSUB132PD = 8570, I_VFNMSUB132PS = 8556, I_VFNMSUB132SD = 8598, I_VFNMSUB132SS = 8584, + I_VFNMSUB213PD = 8850, I_VFNMSUB213PS = 8836, I_VFNMSUB213SD = 8878, I_VFNMSUB213SS = 8864, + I_VFNMSUB231PD = 9130, I_VFNMSUB231PS = 9116, I_VFNMSUB231SD = 9158, I_VFNMSUB231SS = 9144, + I_VHADDPD = 4219, I_VHADDPS = 4228, I_VHSUBPD = 4253, I_VHSUBPS = 4262, I_VINSERTF128 = 9525, + I_VINSERTPS = 9579, I_VLDDQU = 7023, I_VLDMXCSR = 9963, I_VMASKMOVDQU = 7153, + I_VMASKMOVPD = 7971, I_VMASKMOVPS = 7959, I_VMAXPD = 3610, I_VMAXPS = 3602, + I_VMAXSD = 3626, I_VMAXSS = 3618, I_VMCALL = 1735, I_VMCLEAR = 10011, I_VMFUNC = 1803, + I_VMINPD = 3490, I_VMINPS = 3482, I_VMINSD = 3506, I_VMINSS = 3498, I_VMLAUNCH = 1743, + I_VMLOAD = 1833, I_VMMCALL = 1824, I_VMOVAPD = 2498, I_VMOVAPS = 2489, I_VMOVD = 3954, + I_VMOVDDUP = 2256, I_VMOVDQA = 3984, I_VMOVDQU = 3993, I_VMOVHLPS = 2217, + I_VMOVHPD = 2404, I_VMOVHPS = 2395, I_VMOVLHPS = 2385, I_VMOVLPD = 2236, I_VMOVLPS = 2227, + I_VMOVMSKPD = 2858, I_VMOVMSKPS = 2847, I_VMOVNTDQ = 6880, I_VMOVNTDQA = 7927, + I_VMOVNTPD = 2615, I_VMOVNTPS = 2605, I_VMOVQ = 3961, I_VMOVSD = 2165, I_VMOVSHDUP = 2413, + I_VMOVSLDUP = 2245, I_VMOVSS = 2157, I_VMOVUPD = 2148, I_VMOVUPS = 2139, I_VMPSADBW = 9659, + I_VMPTRLD = 10002, I_VMPTRST = 6407, I_VMREAD = 4150, I_VMRESUME = 1753, I_VMRUN = 1817, + I_VMSAVE = 1841, I_VMULPD = 3221, I_VMULPS = 3213, I_VMULSD = 3237, I_VMULSS = 3229, + I_VMWRITE = 4174, I_VMXOFF = 1763, I_VMXON = 10020, I_VORPD = 3088, I_VORPS = 3081, + I_VPABSB = 7717, I_VPABSD = 7747, I_VPABSW = 7732, I_VPACKSSDW = 3881, I_VPACKSSWB = 3713, + I_VPACKUSDW = 7948, I_VPACKUSWB = 3791, I_VPADDB = 7233, I_VPADDD = 7263, + I_VPADDQ = 6510, I_VPADDSB = 6960, I_VPADDSW = 6977, I_VPADDUSW = 6651, I_VPADDW = 7248, + I_VPALIGNR = 9441, I_VPAND = 6635, I_VPANDN = 6694, I_VPAVGB = 6709, I_VPAVGW = 6754, + I_VPBLENDVB = 9714, I_VPBLENDW = 9422, I_VPCLMULQDQ = 9680, I_VPCMPEQB = 4074, + I_VPCMPEQD = 4112, I_VPCMPEQQ = 7907, I_VPCMPEQW = 4093, I_VPCMPESTRI = 9759, + I_VPCMPESTRM = 9736, I_VPCMPGTB = 3733, I_VPCMPGTD = 3771, I_VPCMPGTQ = 8118, + I_VPCMPGTW = 3752, I_VPCMPISTRI = 9805, I_VPCMPISTRM = 9782, I_VPERM2F128 = 9287, + I_VPERMILPD = 7592, I_VPERMILPS = 7581, I_VPEXTRB = 9459, I_VPEXTRD = 9484, + I_VPEXTRQ = 9493, I_VPEXTRW = 6341, I_VPHADDD = 7405, I_VPHADDSW = 7423, I_VPHADDW = 7388, + I_VPHMINPOSUW = 8293, I_VPHSUBD = 7481, I_VPHSUBSW = 7499, I_VPHSUBW = 7464, + I_VPINSRB = 9560, I_VPINSRD = 9606, I_VPINSRQ = 9615, I_VPINSRW = 6324, I_VPMADDUBSW = 7444, + I_VPMADDWD = 7104, I_VPMAXSB = 8204, I_VPMAXSD = 8221, I_VPMAXSW = 6994, I_VPMAXUB = 6678, + I_VPMAXUD = 8255, I_VPMAXUW = 8238, I_VPMINSB = 8136, I_VPMINSD = 8153, I_VPMINSW = 6932, + I_VPMINUB = 6620, I_VPMINUD = 8187, I_VPMINUW = 8170, I_VPMOVMSKB = 6563, + I_VPMOVSXBD = 7786, I_VPMOVSXBQ = 7807, I_VPMOVSXBW = 7765, I_VPMOVSXDQ = 7870, + I_VPMOVSXWD = 7828, I_VPMOVSXWQ = 7849, I_VPMOVZXBD = 8014, I_VPMOVZXBQ = 8035, + I_VPMOVZXBW = 7993, I_VPMOVZXDQ = 8098, I_VPMOVZXWD = 8056, I_VPMOVZXWQ = 8077, + I_VPMULDQ = 7889, I_VPMULHRSW = 7570, I_VPMULHUW = 6771, I_VPMULHW = 6789, + I_VPMULLD = 8272, I_VPMULLW = 6526, I_VPMULUDQ = 7085, I_VPOR = 6946, I_VPSADBW = 7122, + I_VPSHUFB = 7371, I_VPSHUFD = 4036, I_VPSHUFHW = 4045, I_VPSHUFLW = 4055, + I_VPSIGNB = 7517, I_VPSIGND = 7551, I_VPSIGNW = 7534, I_VPSLLD = 7053, I_VPSLLDQ = 9877, + I_VPSLLQ = 7068, I_VPSLLW = 7038, I_VPSRAD = 6739, I_VPSRAW = 6724, I_VPSRLD = 6480, + I_VPSRLDQ = 9860, I_VPSRLQ = 6495, I_VPSRLW = 6465, I_VPSUBB = 7173, I_VPSUBD = 7203, + I_VPSUBQ = 7218, I_VPSUBSB = 6898, I_VPSUBSW = 6915, I_VPSUBUSB = 6583, I_VPSUBUSW = 6602, + I_VPSUBW = 7188, I_VPTEST = 7658, I_VPUNPCKHBW = 3813, I_VPUNPCKHDQ = 3859, + I_VPUNPCKHQDQ = 3929, I_VPUNPCKHWD = 3836, I_VPUNPCKLBW = 3645, I_VPUNPCKLDQ = 3691, + I_VPUNPCKLQDQ = 3904, I_VPUNPCKLWD = 3668, I_VPXOR = 7009, I_VRCPPS = 2989, + I_VRCPSS = 2997, I_VROUNDPD = 9327, I_VROUNDPS = 9308, I_VROUNDSD = 9365, + I_VROUNDSS = 9346, I_VRSQRTPS = 2955, I_VRSQRTSS = 2965, I_VSHUFPD = 6375, + I_VSHUFPS = 6366, I_VSQRTPD = 2910, I_VSQRTPS = 2901, I_VSQRTSD = 2928, I_VSQRTSS = 2919, + I_VSTMXCSR = 9992, I_VSUBPD = 3430, I_VSUBPS = 3422, I_VSUBSD = 3446, I_VSUBSS = 3438, + I_VTESTPD = 7612, I_VTESTPS = 7603, I_VUCOMISD = 2783, I_VUCOMISS = 2773, + I_VUNPCKHPD = 2339, I_VUNPCKHPS = 2328, I_VUNPCKLPD = 2297, I_VUNPCKLPS = 2286, + I_VXORPD = 3117, I_VXORPS = 3109, I_VZEROALL = 4140, I_VZEROUPPER = 4128, + I_WAIT = 10042, I_WBINVD = 561, I_WRFSBASE = 9953, I_WRGSBASE = 9982, I_WRMSR = 586, + I_XABORT = 1007, I_XADD = 946, I_XBEGIN = 1015, I_XCHG = 212, I_XEND = 1811, + I_XGETBV = 1787, I_XLAT = 400, I_XOR = 61, I_XORPD = 3102, I_XORPS = 3095, + I_XRSTOR = 4295, I_XRSTOR64 = 4303, I_XSAVE = 4271, I_XSAVE64 = 4278, I_XSAVEOPT = 4321, + I_XSAVEOPT64 = 4331, I_XSETBV = 1795, I__3DNOW = 10056 + } _InstructionType; + +typedef enum { + R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15, + R_EAX, R_ECX, R_EDX, R_EBX, R_ESP, R_EBP, R_ESI, R_EDI, R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D, + R_AX, R_CX, R_DX, R_BX, R_SP, R_BP, R_SI, R_DI, R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W, + R_AL, R_CL, R_DL, R_BL, R_AH, R_CH, R_DH, R_BH, R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B, + R_SPL, R_BPL, R_SIL, R_DIL, + R_ES, R_CS, R_SS, R_DS, R_FS, R_GS, + R_RIP, + R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7, + R_MM0, R_MM1, R_MM2, R_MM3, R_MM4, R_MM5, R_MM6, R_MM7, + R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15, + R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15, + R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8, + R_DR0, R_DR1, R_DR2, R_DR3, R_UNUSED4, R_UNUSED5, R_DR6, R_DR7 +} _RegisterType; + +#endif /* MNEMONICS_H */ diff --git a/import/distorm/lib/Win32/distorm.lib b/import/distorm/lib/Win32/distorm.lib new file mode 100644 index 000000000..fa0d7537b Binary files /dev/null and b/import/distorm/lib/Win32/distorm.lib differ diff --git a/import/unicorn b/import/unicorn deleted file mode 160000 index 5b4a41e6f..000000000 --- a/import/unicorn +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5b4a41e6fba75f41b149608fabbab94038b8536e diff --git a/src/CxbxKrnl/CxbxKrnl.cpp b/src/CxbxKrnl/CxbxKrnl.cpp index 062da29c1..bc14d8ab0 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -1276,6 +1276,7 @@ __declspec(noreturn) void CxbxKrnlInit InitXboxThread(g_CPUXbox); xboxkrnl::ObInitSystem(); + EmuX86_Init(); // Create the interrupt processing thread DWORD dwThreadId; HANDLE hThread = (HANDLE)_beginthreadex(NULL, NULL, CxbxKrnlInterruptThread, NULL, NULL, (uint*)&dwThreadId); diff --git a/src/CxbxKrnl/Emu.cpp b/src/CxbxKrnl/Emu.cpp index 0c0f2a05d..1423133ca 100644 --- a/src/CxbxKrnl/Emu.cpp +++ b/src/CxbxKrnl/Emu.cpp @@ -191,7 +191,7 @@ bool EmuExceptionBreakpointAsk(LPEXCEPTION_POINTERS e) printf("[0x%.4X] MAIN: Ignored Breakpoint Exception\n", GetCurrentThreadId()); fflush(stdout); - e->ContextRecord->Eip += 1; // Breakpoints are always 1 byte + e->ContextRecord->Eip += EmuX86_OpcodeSize((uint8_t*)e->ContextRecord->Eip); // Skip instruction size bytes return true; } diff --git a/src/CxbxKrnl/EmuX86.cpp b/src/CxbxKrnl/EmuX86.cpp index 274e1adc8..6f4605fb4 100644 --- a/src/CxbxKrnl/EmuX86.cpp +++ b/src/CxbxKrnl/EmuX86.cpp @@ -36,7 +36,15 @@ #define _XBOXKRNL_DEFEXTRN_ #define LOG_PREFIX "X86 " // Intentional extra space to align on 4 characters -#include + +// Link the library into our project. +#pragma comment(lib, "distorm.lib") + +// Cxbx uses dynamic linking of distorm, which by default chooses for 64 bits offsets : +#define SUPPORT_64BIT_OFFSET + +#include "distorm.h" +#include "mnemonics.h" #include "CxbxKrnl.h" #include "Emu.h" // For EmuWarning @@ -222,29 +230,817 @@ void EmuX86_Write(xbaddr addr, uint32_t value, int size) EmuX86_Mem_Write(addr, value, size); } -// Unicorn MMIO->EmuX86 Wrappers -static uint64_t read_cb(struct uc_struct* uc, void *opaque, uint64_t addr, unsigned size) +int ContextRecordOffsetByRegisterType[/*_RegisterType*/R_DR7 + 1] = { 0 }; + +// Populate ContextRecordOffsetByRegisterType for each distorm::_RegisterType +// supported by the XBox1's Coppermine Pentium III. +// Based on https://maximumcrack.wordpress.com/2011/08/07/fpu-mmx-xmm-and-bbq/ +void EmuX86_InitContextRecordOffsetByRegisterType() { - return EmuX86_Read(addr + 0xFD000000, size); + // Unsupported by XBox CPU : R_RAX, R_RCX, R_RDX, R_RBX, R_RSP, R_RBP, R_RSI, R_RDI, R_R8, R_R9, R_R10, R_R11, R_R12, R_R13, R_R14, R_R15, + ContextRecordOffsetByRegisterType[R_EAX] = offsetof(CONTEXT, Eax); + ContextRecordOffsetByRegisterType[R_ECX] = offsetof(CONTEXT, Ecx); + ContextRecordOffsetByRegisterType[R_EDX] = offsetof(CONTEXT, Edx); + ContextRecordOffsetByRegisterType[R_EBX] = offsetof(CONTEXT, Ebx); + ContextRecordOffsetByRegisterType[R_ESP] = offsetof(CONTEXT, Esp); + ContextRecordOffsetByRegisterType[R_EBP] = offsetof(CONTEXT, Ebp); + ContextRecordOffsetByRegisterType[R_ESI] = offsetof(CONTEXT, Esi); + ContextRecordOffsetByRegisterType[R_EDI] = offsetof(CONTEXT, Edi); + // Unsupported by XBox CPU : R_R8D, R_R9D, R_R10D, R_R11D, R_R12D, R_R13D, R_R14D, R_R15D, + ContextRecordOffsetByRegisterType[R_AX] = offsetof(CONTEXT, Eax); + ContextRecordOffsetByRegisterType[R_CX] = offsetof(CONTEXT, Ecx); + ContextRecordOffsetByRegisterType[R_DX] = offsetof(CONTEXT, Edx); + ContextRecordOffsetByRegisterType[R_BX] = offsetof(CONTEXT, Ebx); + ContextRecordOffsetByRegisterType[R_SP] = offsetof(CONTEXT, Esp); // ?? + ContextRecordOffsetByRegisterType[R_BP] = offsetof(CONTEXT, Ebp); // ?? + ContextRecordOffsetByRegisterType[R_SI] = offsetof(CONTEXT, Esi); // ?? + ContextRecordOffsetByRegisterType[R_DI] = offsetof(CONTEXT, Edi); // ?? + // Unsupported by XBox CPU : R_R8W, R_R9W, R_R10W, R_R11W, R_R12W, R_R13W, R_R14W, R_R15W, + ContextRecordOffsetByRegisterType[R_AL] = offsetof(CONTEXT, Eax); + ContextRecordOffsetByRegisterType[R_CL] = offsetof(CONTEXT, Ecx); + ContextRecordOffsetByRegisterType[R_DL] = offsetof(CONTEXT, Edx); + ContextRecordOffsetByRegisterType[R_BL] = offsetof(CONTEXT, Ebx); + ContextRecordOffsetByRegisterType[R_AH] = offsetof(CONTEXT, Eax) + 1; + ContextRecordOffsetByRegisterType[R_CH] = offsetof(CONTEXT, Ecx) + 1; + ContextRecordOffsetByRegisterType[R_DH] = offsetof(CONTEXT, Edx) + 1; + ContextRecordOffsetByRegisterType[R_BH] = offsetof(CONTEXT, Ebx) + 1; + // Unsupported by XBox CPU : R_R8B, R_R9B, R_R10B, R_R11B, R_R12B, R_R13B, R_R14B, R_R15B, + ContextRecordOffsetByRegisterType[R_SPL] = offsetof(CONTEXT, Esp); // ?? + ContextRecordOffsetByRegisterType[R_BPL] = offsetof(CONTEXT, Ebp); // ?? + ContextRecordOffsetByRegisterType[R_SIL] = offsetof(CONTEXT, Esi); // ?? + ContextRecordOffsetByRegisterType[R_DIL] = offsetof(CONTEXT, Edi); // ?? + ContextRecordOffsetByRegisterType[R_ES] = offsetof(CONTEXT, SegEs); + ContextRecordOffsetByRegisterType[R_CS] = offsetof(CONTEXT, SegCs); + ContextRecordOffsetByRegisterType[R_SS] = offsetof(CONTEXT, SegSs); + ContextRecordOffsetByRegisterType[R_DS] = offsetof(CONTEXT, SegDs); + ContextRecordOffsetByRegisterType[R_FS] = offsetof(CONTEXT, SegFs); + ContextRecordOffsetByRegisterType[R_GS] = offsetof(CONTEXT, SegGs); + // R_RIP, TODO : Does this also mean EIP and is that enum missing in distorm? https://github.com/gdabah/distorm/issues/110 + // Unsupported by XBox CPU : R_ST0, R_ST1, R_ST2, R_ST3, R_ST4, R_ST5, R_ST6, R_ST7, + ContextRecordOffsetByRegisterType[R_MM0] = offsetof(CONTEXT, ExtendedRegisters[(10 + 0) * 16]); + ContextRecordOffsetByRegisterType[R_MM1] = offsetof(CONTEXT, ExtendedRegisters[(10 + 1) * 16]); + ContextRecordOffsetByRegisterType[R_MM2] = offsetof(CONTEXT, ExtendedRegisters[(10 + 2) * 16]); + ContextRecordOffsetByRegisterType[R_MM3] = offsetof(CONTEXT, ExtendedRegisters[(10 + 3) * 16]); + ContextRecordOffsetByRegisterType[R_MM4] = offsetof(CONTEXT, ExtendedRegisters[(10 + 4) * 16]); + ContextRecordOffsetByRegisterType[R_MM5] = offsetof(CONTEXT, ExtendedRegisters[(10 + 5) * 16]); + ContextRecordOffsetByRegisterType[R_MM6] = offsetof(CONTEXT, ExtendedRegisters[(10 + 6) * 16]); + ContextRecordOffsetByRegisterType[R_MM7] = offsetof(CONTEXT, ExtendedRegisters[(10 + 7) * 16]); + // Unsupported by XBox CPU : R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7, R_XMM8, R_XMM9, R_XMM10, R_XMM11, R_XMM12, R_XMM13, R_XMM14, R_XMM15, + // Unsupported by XBox CPU : R_YMM0, R_YMM1, R_YMM2, R_YMM3, R_YMM4, R_YMM5, R_YMM6, R_YMM7, R_YMM8, R_YMM9, R_YMM10, R_YMM11, R_YMM12, R_YMM13, R_YMM14, R_YMM15, + // Unsupported by XBox CPU : R_CR0, R_UNUSED0, R_CR2, R_CR3, R_CR4, R_UNUSED1, R_UNUSED2, R_UNUSED3, R_CR8, + ContextRecordOffsetByRegisterType[R_DR0] = offsetof(CONTEXT, Dr0); + ContextRecordOffsetByRegisterType[R_DR1] = offsetof(CONTEXT, Dr1); + ContextRecordOffsetByRegisterType[R_DR2] = offsetof(CONTEXT, Dr2); + ContextRecordOffsetByRegisterType[R_DR3] = offsetof(CONTEXT, Dr3); + // Unsupported by XBox CPU : R_UNUSED4, R_UNUSED5, + ContextRecordOffsetByRegisterType[R_DR6] = offsetof(CONTEXT, Dr6); + ContextRecordOffsetByRegisterType[R_DR7] = offsetof(CONTEXT, Dr7); + + /* struct CONTEXT { // ! markers below, are used in the above offsetof calls + DWORD ContextFlags; + !DWORD Dr0; + !DWORD Dr1; + !DWORD Dr2; + !DWORD Dr3; + !DWORD Dr6; + !DWORD Dr7; + struct _FLOATING_SAVE_AREA { + DWORD ControlWord; + DWORD StatusWord; + DWORD TagWord; + DWORD ErrorOffset; + DWORD ErrorSelector; + DWORD DataOffset; + DWORD DataSelector; + BYTE RegisterArea[SIZE_OF_80387_REGISTERS]; + DWORD Spare0; + } FLOATING_SAVE_AREA FloatSave; + !DWORD SegGs; + !DWORD SegFs; + !DWORD SegEs; + !DWORD SegDs; + !DWORD Edi; + !DWORD Esi; + !DWORD Ebx; + !DWORD Edx; + !DWORD Ecx; + !DWORD Eax; + !DWORD Ebp; + DWORD Eip; + !DWORD SegCs; // MUST BE SANITIZED + DWORD EFlags; // MUST BE SANITIZED + !DWORD Esp; + !DWORD SegSs; + !BYTE ExtendedRegisters[MAXIMUM_SUPPORTED_EXTENSION];*/ } -static void write_cb(struct uc_struct* uc, void *opaque, uint64_t addr, uint64_t data, unsigned size) +inline void * EmuX86_GetRegisterPointer(const LPEXCEPTION_POINTERS e, const uint8_t reg) { - EmuX86_Write(addr + 0xFD000000, (uint32_t)data, size); + int offset = ContextRecordOffsetByRegisterType[reg]; + if (offset > 0) + return (void*)((uintptr_t)(e->ContextRecord) + offset); + + assert(false); + return nullptr; } -// Unicorn IO->EmuX86 Wrappers -static uint32_t hook_in_cb(uc_engine *uc, uint32_t port, int size, void *user_data) +inline uint32_t EmuX86_GetRegisterValue32(const LPEXCEPTION_POINTERS e, const uint8_t reg) { - return EmuX86_IORead(port, size); + if (reg != R_NONE) + { + void* regptr = EmuX86_GetRegisterPointer(e, reg); + if (regptr != nullptr) + return *(uint32_t *)regptr; + } + + return 0; } -static void hook_out_cb(uc_engine *uc, uint32_t port, int size, uint32_t value, void *user_data) +xbaddr EmuX86_Distorm_O_SMEM_Addr(const LPEXCEPTION_POINTERS e, const _DInst& info, const int operand) { - EmuX86_IOWrite(port, value, size); + xbaddr base = EmuX86_GetRegisterValue32(e, info.ops[operand].index); + + return base + (uint32_t)info.disp; +} + +xbaddr EmuX86_Distorm_O_MEM_Addr(const LPEXCEPTION_POINTERS e, const _DInst& info, const int operand) +{ + xbaddr base = EmuX86_GetRegisterValue32(e, info.base); + + uint32_t index = EmuX86_GetRegisterValue32(e, info.ops[operand].index); + + if (info.scale >= 2) + return base + (index * info.scale) + (uint32_t)info.disp; + else + return base + index + (uint32_t)info.disp; +} + +typedef struct { + xbaddr addr; + bool is_internal_addr; // If set, addr points to a CPU context (or Distorm immedate value) member (instead of Xbox memory) + int size; // Expressed in bytes, not bits! +} OperandAddress; + +bool EmuX86_Operand_Addr_ForReadOnly(const LPEXCEPTION_POINTERS e, const _DInst& info, const int operand, OperandAddress &opAddr) +{ + opAddr.size = info.ops[operand].size / 8; // Convert size in bits into bytes + switch (info.ops[operand].type) { + case O_NONE: + { + // ignore operand + return false; + } + case O_REG: + opAddr.is_internal_addr = true; + opAddr.addr = (xbaddr)EmuX86_GetRegisterPointer(e, info.ops[operand].index); + return true; + { + } + case O_IMM: + { + opAddr.is_internal_addr = true; + opAddr.addr = (xbaddr)(&info.imm); + return true; + } + case O_IMM1: + { + opAddr.is_internal_addr = true; + opAddr.addr = (xbaddr)(&info.imm.ex.i1); + return true; + } + case O_IMM2: + { + opAddr.is_internal_addr = true; + opAddr.addr = (xbaddr)(&info.imm.ex.i2); + return true; + } + case O_DISP: + { + opAddr.is_internal_addr = false; + // TODO : Does this operand require : opAddr.size = info.dispSize / 8; // ? + opAddr.addr = (xbaddr)info.disp; + return true; + } + case O_SMEM: + { + opAddr.is_internal_addr = false; + // TODO : Does this operand require : opAddr.size = info.dispSize / 8; // ? + opAddr.addr = EmuX86_Distorm_O_SMEM_Addr(e, info, operand); + return true; + } + case O_MEM: + { + opAddr.is_internal_addr = false; + // TODO : Does this operand require : opAddr.size = info.dispSize / 8; // ? + opAddr.addr = EmuX86_Distorm_O_MEM_Addr(e, info, operand); + return true; + } + case O_PC: + { + opAddr.is_internal_addr = false; + opAddr.addr = (xbaddr)INSTRUCTION_GET_TARGET(&info); + return true; + } + case O_PTR: + { + opAddr.is_internal_addr = false; + opAddr.addr = (xbaddr)info.imm.ptr.off; // TODO : What about info.imm.ptr.seg ? + return true; + } + default: + // UNREACHABLE(info.ops[operand].type); + return false; + } + + return false; +} + +bool EmuX86_Operand_Addr_ForReadWrite(const LPEXCEPTION_POINTERS e, const _DInst& info, const int operand, OperandAddress &opAddr) +{ + // Disallow write-access to immediate value adresses + switch (info.ops[operand].type) { + case O_IMM: + case O_IMM1: + case O_IMM2: + EmuWarning("Refused operand write-access to immedate value address!"); + return false; + } + + // Except for the above restriction, writes may access the same operand addresses as reads : + return EmuX86_Operand_Addr_ForReadOnly(e, info, operand, OUT opAddr); +} + +uint32_t EmuX86_Addr_Read(const OperandAddress &opAddr) +{ + assert(opAddr.size == sizeof(uint8_t) || opAddr.size == sizeof(uint16_t) || opAddr.size == sizeof(uint32_t)); + + if (opAddr.is_internal_addr) { + return EmuX86_Mem_Read(opAddr.addr, opAddr.size); + } + else { + return EmuX86_Read(opAddr.addr, opAddr.size); + } +} + +void EmuX86_Addr_Write(const OperandAddress &opAddr, const uint32_t value) +{ + assert(opAddr.size == sizeof(uint8_t) || opAddr.size == sizeof(uint16_t) || opAddr.size == sizeof(uint32_t)); + + if (opAddr.is_internal_addr) { + EmuX86_Mem_Write(opAddr.addr, value, opAddr.size); + } + else { + EmuX86_Write(opAddr.addr, value, opAddr.size); + } +} + +bool EmuX86_Operand_Read(const LPEXCEPTION_POINTERS e, const _DInst& info, const int operand, OUT uint32_t *value) +{ + OperandAddress opAddr; + if (EmuX86_Operand_Addr_ForReadOnly(e, info, operand, OUT opAddr)) { + *value = EmuX86_Addr_Read(opAddr); + return true; + } + + return false; +} + +bool EmuX86_Operand_Write(LPEXCEPTION_POINTERS e, _DInst& info, int operand, uint32_t value) +{ + OperandAddress opAddr; + if (EmuX86_Operand_Addr_ForReadWrite(e, info, operand, OUT opAddr)) { + EmuX86_Addr_Write(opAddr, value); + return true; + } + + return false; +} + +inline void EmuX86_SetFlags(LPEXCEPTION_POINTERS e, DWORD mask, DWORD value) +{ + // By Ron Jeffery, see http://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge + e->ContextRecord->EFlags ^= ((e->ContextRecord->EFlags ^ value) & mask); +} + +#define BIT(flag, bit) ((static_cast((bool)bit)) << (flag)) +#define BITMASK(flag) BIT(flag, 1) + +// TODO : Verify callers compile bool arguments into bit-operations; +// If not, change these arguments back to unsigned int's and use only +// the least significant bit. +inline void EmuX86_SetFlags_OSZAPC +( + LPEXCEPTION_POINTERS e, + const bool OF, + const bool SF, + const bool ZF, + const bool AF, + const bool PF, + const bool CF +) +{ + EmuX86_SetFlags(e, + BITMASK(EMUX86_EFLAG_OF) | BITMASK(EMUX86_EFLAG_SF) | BITMASK(EMUX86_EFLAG_ZF) | BITMASK(EMUX86_EFLAG_AF) | BITMASK(EMUX86_EFLAG_PF) | BITMASK(EMUX86_EFLAG_CF), + BIT(EMUX86_EFLAG_OF, OF) | BIT(EMUX86_EFLAG_SF, SF) | BIT(EMUX86_EFLAG_ZF, ZF) | BIT(EMUX86_EFLAG_AF, AF) | BIT(EMUX86_EFLAG_PF, PF) | BIT(EMUX86_EFLAG_CF, CF) + ); +} + +inline void EmuX86_SetFlags_OSZPC +( + LPEXCEPTION_POINTERS e, + const bool OF, + const bool SF, + const bool ZF, + const bool PF, + const bool CF +) +{ + EmuX86_SetFlags(e, + BITMASK(EMUX86_EFLAG_OF) | BITMASK(EMUX86_EFLAG_SF) | BITMASK(EMUX86_EFLAG_ZF) | BITMASK(EMUX86_EFLAG_PF) | BITMASK(EMUX86_EFLAG_CF), + BIT(EMUX86_EFLAG_OF, OF) | BIT(EMUX86_EFLAG_SF, SF) | BIT(EMUX86_EFLAG_ZF, ZF) | BIT(EMUX86_EFLAG_PF, PF) | BIT(EMUX86_EFLAG_CF, CF) + ); +} + +inline void EmuX86_SetFlags_OSZAP +( + LPEXCEPTION_POINTERS e, + const bool OF, + const bool SF, + const bool ZF, + const bool AF, + const bool PF +) +{ + EmuX86_SetFlags(e, + BITMASK(EMUX86_EFLAG_OF) | BITMASK(EMUX86_EFLAG_SF) | BITMASK(EMUX86_EFLAG_ZF) | BITMASK(EMUX86_EFLAG_AF) | BITMASK(EMUX86_EFLAG_PF), + BIT(EMUX86_EFLAG_OF, OF) | BIT(EMUX86_EFLAG_SF, SF) | BIT(EMUX86_EFLAG_ZF, ZF) | BIT(EMUX86_EFLAG_AF, AF) | BIT(EMUX86_EFLAG_PF, PF) + ); +} + +// EFLAGS Cross-Reference : http://datasheets.chipdb.org/Intel/x86/Intel%20Architecture/EFLAGS.PDF + +// TODO : Review these CPU flag calculations, maybe peek at how MAME or Bochs does this. +// see : https://github.com/mamedev/mame/blob/master/src/devices/cpu/i386/i386priv.h#L301 + +#define BitSize (info.ops[0].size) // Note : Uses 'info' argument of functions using this macro +// TODO : Use templates for these, so 8, 16 and 32 bit versions will compile into efficient bit manipulations +#define OF_Add(r,s,d) (((r ^ s) & (r ^ d)) >> (BitSize-1)) & 1 // Result, Src, Dest +#define OF_Sub(r,s,d) (((d ^ s) & (r ^ d)) >> (BitSize-1)) & 1 // Result, Src, Dest +#define SFCalc(result) (result >> (BitSize-1)) & 1 +#define ZFCalc(result) (result == 0) +#define AFCalc(r,s,d) ((r ^ s ^ d) >> 3) & 1 // Result, Src, Dest +#define PFCalc(result) (0x6996 >> ((result ^ (result >> 4)) & 0xF)) & 1 // See http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel +#define CFCalc(result) (result >> BitSize) & 1 // TODO : Instead of looking at an actual overflow bit, use high bit of (result XOR dest XOR src) +// Flags calculated : Overflow (for addition or subtraction), Sign, Zero, Adjust, Parity and Carry + +// See http://x86.renejeschke.de/ for affected CPU flags per instruction + +// Keep opcode emulations alphabetically ordered : + +bool EmuX86_Opcode_ADD(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // ADD reads value from source : + uint32_t dest = 0; + if (!EmuX86_Operand_Read(e, info, 1, &dest)) + return false; + + // ADD reads and writes the same operand : + OperandAddress opAddr; + if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr)) + return false; + + const uint32_t src = EmuX86_Addr_Read(opAddr); + + const uint64_t result = (uint64_t)dest + (uint64_t)src; + + // Write back the result + EmuX86_Addr_Write(opAddr, static_cast(result)); + + // The OF, SF, ZF, AF, CF, and PF flags are set according to the result. + EmuX86_SetFlags_OSZAPC(e, + /*EMUX86_EFLAG_OF*/OF_Add(result, src, dest), + /*EMUX86_EFLAG_SF*/SFCalc(result), + /*EMUX86_EFLAG_ZF*/ZFCalc(result), + /*EMUX86_EFLAG_AF*/AFCalc(result, src, dest), + /*EMUX86_EFLAG_PF*/PFCalc(result), + /*EMUX86_EFLAG_CF*/CFCalc(result)); + + return true; +} + +bool EmuX86_Opcode_AND(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // Read value from Source and Destination + uint32_t src = 0; + if (!EmuX86_Operand_Read(e, info, 1, &src)) + return false; + + // AND reads and writes the same operand : + OperandAddress opAddr; + if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr)) + return false; + + uint32_t dest = EmuX86_Addr_Read(opAddr); + + // AND Destination with src + uint32_t result = dest & src; + + // Write back the result + EmuX86_Addr_Write(opAddr, result); + + // The OF and CF flags are cleared; the SF, ZF, and PF flags are set according to the result. The state of the AF flag is undefined. + EmuX86_SetFlags_OSZPC(e, + /*EMUX86_EFLAG_OF*/0, + /*EMUX86_EFLAG_SF*/SFCalc(result), + /*EMUX86_EFLAG_ZF*/ZFCalc(result), + /*EMUX86_EFLAG_PF*/PFCalc(result), + /*EMUX86_EFLAG_CF*/0); + + return true; +} + +bool EmuX86_Opcode_CMP(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // Read value from Source and Destination + uint32_t src = 0; + if (!EmuX86_Operand_Read(e, info, 1, &src)) + return false; + + uint32_t dest = 0; + if (!EmuX86_Operand_Read(e, info, 0, &dest)) + return false; + + // CMP Destination with src (cmp internally is a discarded subtract) + uint64_t result = (uint64_t)dest - (uint64_t)src; + + // The CF, OF, SF, ZF, AF, and PF flags are set according to the result. + EmuX86_SetFlags_OSZAPC(e, + /*EMUX86_EFLAG_OF*/OF_Sub(result, src, dest), + /*EMUX86_EFLAG_SF*/SFCalc(result), + /*EMUX86_EFLAG_ZF*/ZFCalc(result), + /*EMUX86_EFLAG_AF*/AFCalc(result, src, dest), + /*EMUX86_EFLAG_PF*/PFCalc(result), + /*EMUX86_EFLAG_CF*/CFCalc(result)); + + return true; +} + +bool EmuX86_Opcode_CMPXCHG(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // Read value from Source and Destination + uint32_t src = 0; + if (!EmuX86_Operand_Read(e, info, 1, &src)) + return false; + + uint32_t dest = 0; + if (!EmuX86_Operand_Read(e, info, 0, &dest)) + return false; + + if (src == dest) { + // Write the source value to the destination operand + if (!EmuX86_Operand_Write(e, info, 0, src)) { + return false; + } + } else { + // Write the dest value to the source operand + if (!EmuX86_Operand_Write(e, info, 1, dest)) { + return false; + } + } + + // Perform arithmatic operation for flag calculation + uint64_t result = (uint64_t)dest - (uint64_t)src; + + // CF, PF, AF, SF, and OF are set according to the result + EmuX86_SetFlags_OSZAPC(e, + /*EMUX86_EFLAG_OF*/OF_Sub(result, src, dest), + /*EMUX86_EFLAG_SF*/SFCalc(result), + /*EMUX86_EFLAG_ZF*/ZFCalc(result), + /*EMUX86_EFLAG_AF*/AFCalc(result, src, dest), + /*EMUX86_EFLAG_PF*/PFCalc(result), + /*EMUX86_EFLAG_CF*/CFCalc(result)); + + return true; +} + +void EmuX86_Opcode_CPUID(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // This CPUID emulation is based on : + // https://github.com/docbrown/vxb/wiki/Xbox-CPUID-Information + // https://github.com/docbrown/vxb/wiki/Xbox-Hardware-Information and + // http://www.sandpile.org/x86/cpuid.htm + switch (e->ContextRecord->Eax) { // simpler than EmuX86_GetRegisterValue32(e, R_EAX) + case 0: { // CPUID Function 0, return the maximum supported standard level and vendor ID string + // Maximum supported standard level + e->ContextRecord->Eax = 2; + // "GenuineIntel" Intel processor + e->ContextRecord->Ebx = (ULONG)'uneG'; + e->ContextRecord->Edx = (ULONG)'Ieni'; + e->ContextRecord->Ecx = (ULONG)'letn'; + return; + } + case 1: { // CPUID Function 1, Return the processor type / family / model / stepping and feature flags + // Family 6, Model 8, Stepping 10 + e->ContextRecord->Eax = 0x68a; + e->ContextRecord->Ebx = 0; + e->ContextRecord->Ecx = 0; + // Feature Flags + e->ContextRecord->Edx = 0x383F9FF; // FPU, VME, DE, PSE, TSC, MSR, PAE, MCE, CX8, SEP, MTRR, PGE, MCA, CMOV, PAT, PSE36, MMX, FXSR, SSE + return; + } + case 2: { // CPUID Function 2, Return the processor configuration descriptors + // AL : 01 = number of times this level must be queried to obtain all configuration descriptors + // EAX nibble 1 = 01h : code TLB, 4K pages, 4 ways, 32 entries + // EAX nibble 2 = 02h : code TLB, 4M pages, fully, 2 entries + // EAX nibble 3 = 03h : data TLB, 4K pages, 4 ways, 64 entries + e->ContextRecord->Eax = 0x3020101; + // EBX and ECX nibbles = 00h : null descriptor (=unused descriptor) + e->ContextRecord->Ebx = 0; + e->ContextRecord->Ecx = 0; + // EDX nibble 0 = 41h : code and data L2 cache, 128 KB, 4 ways, 32 byte lines + // EDX nibble 1 = 08h : code L1 cache, 16 KB, 4 ways, 32 byte lines + // EDX nibble 2 = 04h : data TLB, 4M pages, 4 ways, 8 entries + // EDX nibble 3 = 0Ch : data L1 cache, 16 KB, 4 ways, 32 byte lines + e->ContextRecord->Edx = 0xC040841; + return; + } + } + + // Note : CPUID instructions never update CPU flags +} + +bool EmuX86_Opcode_DEC(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // DEC reads and writes the same operand : + OperandAddress opAddr; + if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr)) + return false; + + uint32_t dest = EmuX86_Addr_Read(opAddr); + + // DEC Destination to src + uint64_t result = (uint64_t)dest - (uint64_t)1; + + // Write result back + EmuX86_Addr_Write(opAddr, static_cast(result)); + + // The CF flag is not affected. The OF, SF, ZF, AF, and PF flags are set according to the result. + EmuX86_SetFlags_OSZAP(e, + /*EMUX86_EFLAG_OF*/OF_Sub(result, 1, dest), + /*EMUX86_EFLAG_SF*/SFCalc(result), + /*EMUX86_EFLAG_ZF*/ZFCalc(result), + /*EMUX86_EFLAG_AF*/AFCalc(result, 1, dest), + /*EMUX86_EFLAG_PF*/PFCalc(result)); + + return true; +} + +bool EmuX86_Opcode_IN(LPEXCEPTION_POINTERS e, _DInst& info) +{ + uint32_t addr; + if (!EmuX86_Operand_Read(e, info, 1, &addr)) + return false; + + // IN does an I/O read on the address, writing the value to the second operand : + uint32_t value = EmuX86_IORead(addr, info.ops[0].size / 8); // Convert size in bits into bytes + + if (!EmuX86_Operand_Write(e, info, 0, value)) { + return false; + } + + // Note : IN instructions never update CPU flags + + return true; +} + +bool EmuX86_Opcode_INC(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // INC reads and writes the same operand : + OperandAddress opAddr; + if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr)) + return false; + + uint32_t dest = EmuX86_Addr_Read(opAddr); + + // INC Destination to src + uint64_t result = (uint64_t)dest + (uint64_t)1; + + // Write result back + EmuX86_Addr_Write(opAddr, static_cast(result)); + + // The CF flag is not affected. The OF, SF, ZF, AF, and PF flags are set according to the re + EmuX86_SetFlags_OSZAP(e, + /*EMUX86_EFLAG_OF*/OF_Add(result, 1, dest), + /*EMUX86_EFLAG_SF*/SFCalc(result), + /*EMUX86_EFLAG_ZF*/ZFCalc(result), + /*EMUX86_EFLAG_AF*/AFCalc(result, 1, dest), + /*EMUX86_EFLAG_PF*/PFCalc(result)); + + return true; +} + +bool EmuX86_Opcode_MOV(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // MOV reads value from source : + uint32_t value = 0; + if (!EmuX86_Operand_Read(e, info, 1, &value)) + return false; + + // MOV writes value to destination : + if (!EmuX86_Operand_Write(e, info, 0, value)) + return false; + + // Note : MOV instructions never update CPU flags + + return true; +} + +bool EmuX86_Opcode_MOVSX(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // MOVSX reads value from source : + uint32_t value = 0; + if (!EmuX86_Operand_Read(e, info, 1, &value)) + return false; + + // Do MOVSX sign-extension + switch (info.ops[1].size) { + case 8: + if (value & 0x80) + value |= 0xFFFFFF00; + break; + case 16: + if (value & 0x8000) + value |= 0xFFFF0000; + break; + } + + // MOVSX writes value to destination : + if (!EmuX86_Operand_Write(e, info, 0, value)) + return false; + + // Note : MOVSX instructions never update CPU flags + + return true; +} + +bool EmuX86_Opcode_MOVZX(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // MOVZX reads value from source : + uint32_t value = 0; + if (!EmuX86_Operand_Read(e, info, 1, &value)) + return false; + + // TODO : Implement MOVZX zero-extension! + + // MOVZX writes value to destination : + if (!EmuX86_Operand_Write(e, info, 0, value)) + return false; + + // Note : MOVZX instructions never update CPU flags + + return true; +} + +bool EmuX86_Opcode_OR(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // Read value from Source and Destination + uint32_t src = 0; + if (!EmuX86_Operand_Read(e, info, 1, &src)) + return false; + + // OR reads and writes the same operand : + OperandAddress opAddr; + if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr)) + return false; + + uint32_t dest = EmuX86_Addr_Read(opAddr); + + // OR Destination with src + uint32_t result = dest | src; + + // Write back the result + EmuX86_Addr_Write(opAddr, result); + + // The OF and CF flags are cleared; the SF, ZF, and PF flags are set according to the result. The state of the AF flag is undefined. + EmuX86_SetFlags_OSZPC(e, + /*EMUX86_EFLAG_OF*/0, + /*EMUX86_EFLAG_SF*/SFCalc(result), + /*EMUX86_EFLAG_ZF*/ZFCalc(result), + /*EMUX86_EFLAG_PF*/PFCalc(result), + /*EMUX86_EFLAG_CF*/0); + + return true; +} + +bool EmuX86_Opcode_OUT(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // OUT will address the first operand : + uint32_t addr; + if (!EmuX86_Operand_Read(e, info, 0, &addr)) + return false; + + uint32_t value; + if (!EmuX86_Operand_Read(e, info, 1, &value)) + return false; + + // OUT does an I/O write on the address, using the value from the second operand : + EmuX86_IOWrite(addr, value, info.ops[1].size / 8); // Convert size in bits into bytes + + // Note : OUT instructions never update CPU flags + +return true; +} + +bool EmuX86_Opcode_SUB(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // Read value from Source and Destination + uint32_t src = 0; + if (!EmuX86_Operand_Read(e, info, 1, &src)) + return false; + + // SUB reads and writes the same operand : + OperandAddress opAddr; + if (!EmuX86_Operand_Addr_ForReadWrite(e, info, 0, OUT opAddr)) + return false; + + uint32_t dest = EmuX86_Addr_Read(opAddr); + + // SUB Destination with src + uint64_t result = (uint64_t)dest - (uint64_t)src; + + // Write result back + EmuX86_Addr_Write(opAddr, static_cast(result)); + + // The OF, SF, ZF, AF, PF, and CF flags are set according to the result. + EmuX86_SetFlags_OSZAPC(e, + /*EMUX86_EFLAG_OF*/OF_Sub(result, src, dest), + /*EMUX86_EFLAG_SF*/SFCalc(result), + /*EMUX86_EFLAG_ZF*/ZFCalc(result), + /*EMUX86_EFLAG_AF*/AFCalc(result, src, dest), + /*EMUX86_EFLAG_PF*/PFCalc(result), + /*EMUX86_EFLAG_CF*/CFCalc(result)); + + return true; +} + +bool EmuX86_Opcode_TEST(LPEXCEPTION_POINTERS e, _DInst& info) +{ + // TEST reads first value : + uint32_t src = 0; + if (!EmuX86_Operand_Read(e, info, 0, &src)) + return false; + + // TEST reads second value : + uint32_t dest = 0; + if (!EmuX86_Operand_Read(e, info, 1, &dest)) + return false; + + // TEST performs bitwise AND between first and second value : + uint32_t result = src & dest; + + // https://en.wikipedia.org/wiki/TEST_(x86_instruction) + // The OF and CF flags are set to 0. The SF, ZF, and PF flags are set according to the result. The state of the AF flag is undefined. + EmuX86_SetFlags_OSZPC(e, + /*EMUX86_EFLAG_OF*/0, + /*EMUX86_EFLAG_SF*/SFCalc(result), + /*EMUX86_EFLAG_ZF*/ZFCalc(result), + /*EMUX86_EFLAG_PF*/PFCalc(result), + /*EMUX86_EFLAG_CF*/0); + + // result is thrown away + + return true; +} + +bool EmuX86_DecodeOpcode(const uint8_t *Eip, _DInst &info) +{ + unsigned int decodedInstructionsCount = 0; + + _CodeInfo ci; + ci.code = (uint8_t*)Eip; + ci.codeLen = 20; + ci.codeOffset = 0; + ci.dt = (_DecodeType)Decode32Bits; + ci.features = DF_NONE; + + // Checking for DECRES_SUCCESS won't work, since we're passing distorm_decompose + // a codeLen big enough to decode any instruction-length, plus distorm doesn't + // halt cleanly after reaching maxInstructions 1. So instead, just call distorm : + distorm_decompose(&ci, &info, /*maxInstructions=*/1, &decodedInstructionsCount); + // and check if it successfully decoded one instruction : + return (decodedInstructionsCount == 1); +} + +int EmuX86_OpcodeSize(uint8_t *Eip) +{ + _DInst info; + if (EmuX86_DecodeOpcode((uint8_t*)Eip, info)) + return info.size; + + EmuWarning("Error decoding opcode size at 0x%.8X", Eip); + return 1; } -uc_engine* EmuX86_Init(); bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) { // Only decode instructions which reside in the loaded Xbe @@ -252,91 +1048,93 @@ bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e) return false; } - uc_engine* uc = EmuX86_Init(); - - // Sync CPU state to Unicorn - uc_reg_write(uc, UC_X86_REG_EDI, &e->ContextRecord->Edi); - uc_reg_write(uc, UC_X86_REG_ESI, &e->ContextRecord->Esi); - uc_reg_write(uc, UC_X86_REG_EBX, &e->ContextRecord->Ebx); - uc_reg_write(uc, UC_X86_REG_EDX, &e->ContextRecord->Edx); - uc_reg_write(uc, UC_X86_REG_ECX, &e->ContextRecord->Ecx); - uc_reg_write(uc, UC_X86_REG_EAX, &e->ContextRecord->Eax); - uc_reg_write(uc, UC_X86_REG_EIP, &e->ContextRecord->Eip); - uc_reg_write(uc, UC_X86_REG_ESP, &e->ContextRecord->Esp); - uc_reg_write(uc, UC_X86_REG_EBP, &e->ContextRecord->Ebp); - uc_reg_write(uc, UC_X86_REG_EFLAGS, &e->ContextRecord->EFlags); - - // Run Unicorn for one instruction - // NOTE: This is currently slightly slower than old EmuX86, but has potential to be massively optimised - // It's a lot of work, but we can get much higher performance through clever use of Unicorn (and avoiding exceptions) - // This does not count as clever use, but is a test to see how well it works for us - uc_err err = uc_emu_start(uc, e->ContextRecord->Eip, 0, 0, 1); - if (err) { - CxbxKrnlCleanup("Failed on uc_emu_start() with error returned: %u\n", err); + // Decoded instruction information. + // Opcode handler note : + // If an opcode or one of it's operand can't be decoded, that's a clear failure. + // However, if for any reason, an opcode operand cannot be read from or written to, + // that case may be logged, but it shouldn't fail the opcode handler. + _DInst info; + if (!EmuX86_DecodeOpcode((uint8_t*)e->ContextRecord->Eip, OUT info)) { + EmuWarning("Error decoding opcode at 0x%08X", e->ContextRecord->Eip); + return false; } - // Write CPU state back to host - uc_reg_read(uc, UC_X86_REG_EDI, &e->ContextRecord->Edi); - uc_reg_read(uc, UC_X86_REG_ESI, &e->ContextRecord->Esi); - uc_reg_read(uc, UC_X86_REG_EBX, &e->ContextRecord->Ebx); - uc_reg_read(uc, UC_X86_REG_EDX, &e->ContextRecord->Edx); - uc_reg_read(uc, UC_X86_REG_ECX, &e->ContextRecord->Ecx); - uc_reg_read(uc, UC_X86_REG_EAX, &e->ContextRecord->Eax); - uc_reg_read(uc, UC_X86_REG_EIP, &e->ContextRecord->Eip); - uc_reg_read(uc, UC_X86_REG_ESP, &e->ContextRecord->Esp); - uc_reg_read(uc, UC_X86_REG_EBP, &e->ContextRecord->Ebp); - uc_reg_read(uc, UC_X86_REG_EFLAGS, &e->ContextRecord->EFlags); - + switch (info.opcode) { // Keep these cases alphabetically ordered and condensed + case I_ADD: + if (EmuX86_Opcode_ADD(e, info)) break; + goto opcode_error; + case I_AND: + if (EmuX86_Opcode_AND(e, info)) break; + goto opcode_error; + case I_CMP: + if (EmuX86_Opcode_CMP(e, info)) break; + goto opcode_error; + case I_CMPXCHG: + if (EmuX86_Opcode_CMPXCHG(e, info)) break; + goto opcode_error; + case I_CPUID: + EmuX86_Opcode_CPUID(e, info); + break; + case I_DEC: + if (EmuX86_Opcode_DEC(e, info)) break; + goto opcode_error; + case I_IN: + if (EmuX86_Opcode_IN(e, info)) break; + goto opcode_error; + case I_INC: + if (EmuX86_Opcode_INC(e, info)) break; + goto opcode_error; + case I_INVD: // Flush internal caches; initiate flushing of external caches. + break; // We can safely ignore this + case I_MOV: + if (EmuX86_Opcode_MOV(e, info)) break; + goto opcode_error; + case I_MOVSX: + if (EmuX86_Opcode_MOVSX(e, info)) break; + goto opcode_error; + case I_MOVZX: + if (EmuX86_Opcode_MOVZX(e, info)) break; + goto opcode_error; + case I_OR: + if (EmuX86_Opcode_OR(e, info)) break; + goto opcode_error; + case I_OUT: + if (EmuX86_Opcode_OUT(e, info)) break; + goto opcode_error; + case I_SUB: + if (EmuX86_Opcode_SUB(e, info)) break; + goto opcode_error; + case I_TEST: + if (EmuX86_Opcode_TEST(e, info)) break; + goto opcode_error; + case I_WBINVD: // Write back and flush internal caches; initiate writing-back and flushing of external caches. + break; // We can safely ignore this + case I_WRMSR: + // We do not emulate processor specific registers just yet + // Some titles attempt to manually set the TSC via this instruction + // This needs fixing eventually, but should be acceptible to ignore for now! + // Chase: Hollywood Stunt Driver hits this + EmuWarning("WRMSR instruction ignored"); + break; + default: + EmuWarning("Unhandled instruction : %u", info.opcode); + e->ContextRecord->Eip += info.size; + return false; + } + + // When falling through here, the instruction was handled correctly, + // skip over the instruction and continue execution : + e->ContextRecord->Eip += info.size; return true; + +opcode_error: + EmuWarning("0x%08X: Error while handling instruction %u", e->ContextRecord->Eip, info.opcode); // TODO : format decodedInstructions[0] + e->ContextRecord->Eip += info.size; + return false; } -#include -std::unordered_map g_UnicornHandles; - -// Unicorn requires a seperate context per-thread, we handle that by using EmuX86_Init as a GetUnicornContext function -uc_engine* EmuX86_Init() +void EmuX86_Init() { - uc_engine* uc; - uc_hook hook_in, hook_out; - - // First, attempt to fetch a uncorn instance for the current thread - auto it = g_UnicornHandles.find(GetCurrentThreadId()); - if (it != g_UnicornHandles.end()) { - return it->second; - } - - // This thread didn't have a unicorn instance, so create one - uc_err err = uc_open(UC_ARCH_X86, UC_MODE_32, &uc); - if (err) { - CxbxKrnlCleanup("Failed on uc_open() with error returned: %u\n", err); - } - - // Set Unicorn to map 1:1 with our emulated Xbox memory (except HW registers) - // We should map this to 0x0 but unicorn doesn't like that (it can't take a nullptr as an argument) - // Mapping to the XBE base address is good enough - err = uc_mem_map_ptr(uc, XBE_IMAGE_BASE, 0xFD000000 - XBE_IMAGE_BASE, UC_PROT_ALL, (void*)XBE_IMAGE_BASE); // XBE Region (0x00000000) - if (err) { - CxbxKrnlCleanup("Failed on uc_mem_map_ptr(uc, 0, XBOX_MEMORY_SIZE, UC_PROT_ALL, 0) with error returned: %u\n", err); - } - - // Register MMIO and IO Hooks - err = uc_mmio_map(uc, 0xFD000000, 0x3000000, read_cb, write_cb, nullptr); - if (err) { - CxbxKrnlCleanup("Failed on uc_mmio_map() with error returned: %u\n", err); - } - - err = uc_hook_add(uc, &hook_in, UC_HOOK_INSN, hook_in_cb, NULL, 1, 0, UC_X86_INS_IN); - if (err) { - CxbxKrnlCleanup("Failed on uc_hook_add() with error returned: %u\n", err); - } - - err = uc_hook_add(uc, &hook_out, UC_HOOK_INSN, hook_out_cb, NULL, 1, 0, UC_X86_INS_OUT); - if (err) { - CxbxKrnlCleanup("Failed on uc_hook_add() with error returned: %u\n", err); - } - - - g_UnicornHandles[GetCurrentThreadId()] = uc; - - return uc; + DbgPrintf("X86 : Initializing distorm version %d\n", distorm_version()); + EmuX86_InitContextRecordOffsetByRegisterType(); } diff --git a/src/CxbxKrnl/EmuX86.h b/src/CxbxKrnl/EmuX86.h index 0c49cd8ab..6b2423c5a 100644 --- a/src/CxbxKrnl/EmuX86.h +++ b/src/CxbxKrnl/EmuX86.h @@ -57,6 +57,7 @@ #define EMUX86_EFLAG_VIP 20 #define EMUX86_EFLAG_ID 21 +void EmuX86_Init(); int EmuX86_OpcodeSize(uint8_t *Eip); bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e); uint32_t EmuX86_IORead(xbaddr addr, int size); diff --git a/src/devices/video/nv2a.cpp b/src/devices/video/nv2a.cpp index 418d63867..d82ae1750 100644 --- a/src/devices/video/nv2a.cpp +++ b/src/devices/video/nv2a.cpp @@ -55,7 +55,7 @@ namespace xboxkrnl #endif #include // For std::string -#include // For uint32_t +#include // For uint32_t #include // For __beginthreadex(), etc. #include "CxbxKrnl\CxbxKrnl.h" // For XBOX_MEMORY_SIZE, DWORD, etc