From 317b9dfe00665696b82baa98ecb4f0359405c1b7 Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Sun, 29 Apr 2018 20:16:03 +0100 Subject: [PATCH] Revert "Replace EmuX86's interpreter with Unicorn" --- .gitmodules | 3 - build/win32/Cxbx.sln | 49 -- build/win32/Cxbx.vcxproj | 10 +- import/distorm/include/distorm.h | 482 +++++++++++++ import/distorm/include/mnemonics.h | 301 ++++++++ import/distorm/lib/Win32/distorm.lib | Bin 0 -> 116438 bytes import/unicorn | 1 - src/CxbxKrnl/CxbxKrnl.cpp | 1 + src/CxbxKrnl/Emu.cpp | 2 +- src/CxbxKrnl/EmuX86.cpp | 984 ++++++++++++++++++++++++--- src/CxbxKrnl/EmuX86.h | 1 + src/devices/video/nv2a.cpp | 2 +- 12 files changed, 1680 insertions(+), 156 deletions(-) create mode 100644 import/distorm/include/distorm.h create mode 100644 import/distorm/include/mnemonics.h create mode 100644 import/distorm/lib/Win32/distorm.lib delete mode 160000 import/unicorn 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 0000000000000000000000000000000000000000..fa0d7537b7a43b27fb2abad4a36f1226340ec4d2 GIT binary patch literal 116438 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 literal 0 HcmV?d00001 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