diff --git a/.gitignore b/.gitignore index 67cafea4..1bce4887 100644 --- a/.gitignore +++ b/.gitignore @@ -3,19 +3,14 @@ ################################################################################ -/src/Release -/src/Debug -*.sln -/Debug -/Release +/src/x64 +/x64 *.exp *.iobj *.ipdb *.pdb -*.lib *.dll *.aps *.zip /.vs -/src/.vs/BlockTheSpot/v16 -/src/.vs/BlockTheSpot +/src/.vs diff --git a/BlockTheSpot.sln b/BlockTheSpot.sln new file mode 100644 index 00000000..c4bd989e --- /dev/null +++ b/BlockTheSpot.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33829.357 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BlockTheSpot", "src\BlockTheSpot.vcxproj", "{DCC156A5-5810-4C3B-B95D-A168CEAA3629}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DCC156A5-5810-4C3B-B95D-A168CEAA3629}.Debug|x64.ActiveCfg = Debug|x64 + {DCC156A5-5810-4C3B-B95D-A168CEAA3629}.Debug|x64.Build.0 = Debug|x64 + {DCC156A5-5810-4C3B-B95D-A168CEAA3629}.Release|x64.ActiveCfg = Release|x64 + {DCC156A5-5810-4C3B-B95D-A168CEAA3629}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {AA3D23C9-D1E4-4F39-A15C-42B6F2FD8E76} + EndGlobalSection +EndGlobal diff --git a/README.md b/README.md index 32e5dad2..6641f129 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,13 @@

BlockTheSpot

-

A multi-purpose adblocker and skip-bypass for the Spotify for Windows (32 bit)

+

A multi-purpose adblocker and skip-bypass for the Spotify for Windows (64 bit)

Please support Spotify by purchasing premium

- Last updated: 17 July 2023
- Last tested version:1.2.15.828.g79f41970 + Last updated: 24 July 2023
+ Last tested version:1.2.16.947.gcfbaa410

-### *** -See https://github.com/mrpond/BlockTheSpot/issues/461 if you got ads back. -I will make 64 bit version when I had time. ### Features: * Unlocks all premium features except downloads. diff --git a/config.ini b/config.ini index 15b6144b..51381a4b 100644 --- a/config.ini +++ b/config.ini @@ -1,6 +1,6 @@ [Config] +Block_Ads=1 +Block_Banner=1 +Enable_Developer=1 ;Log system -Log = 0 -BlockAds = 1 -Developer = 1 -Banner = 1 \ No newline at end of file +Enable_Log=0 diff --git a/packages/Detours.4.0.1/.signature.p7s b/packages/Detours.4.0.1/.signature.p7s new file mode 100644 index 00000000..d01d5ef1 Binary files /dev/null and b/packages/Detours.4.0.1/.signature.p7s differ diff --git a/packages/Detours.4.0.1/Detours.4.0.1.nupkg b/packages/Detours.4.0.1/Detours.4.0.1.nupkg new file mode 100644 index 00000000..26f6fa3f Binary files /dev/null and b/packages/Detours.4.0.1/Detours.4.0.1.nupkg differ diff --git a/packages/Detours.4.0.1/build/native/Detours.targets b/packages/Detours.4.0.1/build/native/Detours.targets new file mode 100644 index 00000000..bba8e7c3 --- /dev/null +++ b/packages/Detours.4.0.1/build/native/Detours.targets @@ -0,0 +1,13 @@ + + + + + $(MSBuildThisFileDirectory)..\..\lib\native\include\;%(AdditionalIncludeDirectories) + + + $(MSBuildThisFileDirectory)..\..\lib\native\libs\x64;%(AdditionalLibraryDirectories) + $(MSBuildThisFileDirectory)..\..\lib\native\libs\x86;%(AdditionalLibraryDirectories) + detours.lib;%(AdditionalDependencies) + + + \ No newline at end of file diff --git a/packages/Detours.4.0.1/lib/native/include/detours.h b/packages/Detours.4.0.1/lib/native/include/detours.h new file mode 100644 index 00000000..adb34ebd --- /dev/null +++ b/packages/Detours.4.0.1/lib/native/include/detours.h @@ -0,0 +1,1080 @@ +///////////////////////////////////////////////////////////////////////////// +// +// Core Detours Functionality (detours.h of detours.lib) +// +// Microsoft Research Detours Package, Version 4.0.1 +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#pragma once +#ifndef _DETOURS_H_ +#define _DETOURS_H_ + +#define DETOURS_VERSION 0x4c0c1 // 0xMAJORcMINORcPATCH + +////////////////////////////////////////////////////////////////////////////// +// + +#undef DETOURS_X64 +#undef DETOURS_X86 +#undef DETOURS_IA64 +#undef DETOURS_ARM +#undef DETOURS_ARM64 +#undef DETOURS_BITS +#undef DETOURS_32BIT +#undef DETOURS_64BIT + +#if defined(_X86_) +#define DETOURS_X86 +#define DETOURS_OPTION_BITS 64 + +#elif defined(_AMD64_) +#define DETOURS_X64 +#define DETOURS_OPTION_BITS 32 + +#elif defined(_IA64_) +#define DETOURS_IA64 +#define DETOURS_OPTION_BITS 32 + +#elif defined(_ARM_) +#define DETOURS_ARM + +#elif defined(_ARM64_) +#define DETOURS_ARM64 + +#else +#error Unknown architecture (x86, amd64, ia64, arm, arm64) +#endif + +#ifdef _WIN64 +#undef DETOURS_32BIT +#define DETOURS_64BIT 1 +#define DETOURS_BITS 64 +// If all 64bit kernels can run one and only one 32bit architecture. +//#define DETOURS_OPTION_BITS 32 +#else +#define DETOURS_32BIT 1 +#undef DETOURS_64BIT +#define DETOURS_BITS 32 +// If all 64bit kernels can run one and only one 32bit architecture. +//#define DETOURS_OPTION_BITS 32 +#endif + +#define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) + +////////////////////////////////////////////////////////////////////////////// +// + +#if (_MSC_VER < 1299) +typedef LONG LONG_PTR; +typedef ULONG ULONG_PTR; +#endif + +///////////////////////////////////////////////// SAL 2.0 Annotations w/o SAL. +// +// These definitions are include so that Detours will build even if the +// compiler doesn't have full SAL 2.0 support. +// +#ifndef DETOURS_DONT_REMOVE_SAL_20 + +#ifdef DETOURS_TEST_REMOVE_SAL_20 +#undef _Analysis_assume_ +#undef _Benign_race_begin_ +#undef _Benign_race_end_ +#undef _Field_range_ +#undef _Field_size_ +#undef _In_ +#undef _In_bytecount_ +#undef _In_count_ +#undef _In_opt_ +#undef _In_opt_bytecount_ +#undef _In_opt_count_ +#undef _In_opt_z_ +#undef _In_range_ +#undef _In_reads_ +#undef _In_reads_bytes_ +#undef _In_reads_opt_ +#undef _In_reads_opt_bytes_ +#undef _In_reads_or_z_ +#undef _In_z_ +#undef _Inout_ +#undef _Inout_opt_ +#undef _Inout_z_count_ +#undef _Out_ +#undef _Out_opt_ +#undef _Out_writes_ +#undef _Outptr_result_maybenull_ +#undef _Readable_bytes_ +#undef _Success_ +#undef _Writable_bytes_ +#undef _Pre_notnull_ +#endif + +#if defined(_Deref_out_opt_z_) && !defined(_Outptr_result_maybenull_) +#define _Outptr_result_maybenull_ _Deref_out_opt_z_ +#endif + +#if defined(_In_count_) && !defined(_In_reads_) +#define _In_reads_(x) _In_count_(x) +#endif + +#if defined(_In_opt_count_) && !defined(_In_reads_opt_) +#define _In_reads_opt_(x) _In_opt_count_(x) +#endif + +#if defined(_In_opt_bytecount_) && !defined(_In_reads_opt_bytes_) +#define _In_reads_opt_bytes_(x) _In_opt_bytecount_(x) +#endif + +#if defined(_In_bytecount_) && !defined(_In_reads_bytes_) +#define _In_reads_bytes_(x) _In_bytecount_(x) +#endif + +#ifndef _In_ +#define _In_ +#endif + +#ifndef _In_bytecount_ +#define _In_bytecount_(x) +#endif + +#ifndef _In_count_ +#define _In_count_(x) +#endif + +#ifndef _In_opt_ +#define _In_opt_ +#endif + +#ifndef _In_opt_bytecount_ +#define _In_opt_bytecount_(x) +#endif + +#ifndef _In_opt_count_ +#define _In_opt_count_(x) +#endif + +#ifndef _In_opt_z_ +#define _In_opt_z_ +#endif + +#ifndef _In_range_ +#define _In_range_(x,y) +#endif + +#ifndef _In_reads_ +#define _In_reads_(x) +#endif + +#ifndef _In_reads_bytes_ +#define _In_reads_bytes_(x) +#endif + +#ifndef _In_reads_opt_ +#define _In_reads_opt_(x) +#endif + +#ifndef _In_reads_opt_bytes_ +#define _In_reads_opt_bytes_(x) +#endif + +#ifndef _In_reads_or_z_ +#define _In_reads_or_z_ +#endif + +#ifndef _In_z_ +#define _In_z_ +#endif + +#ifndef _Inout_ +#define _Inout_ +#endif + +#ifndef _Inout_opt_ +#define _Inout_opt_ +#endif + +#ifndef _Inout_z_count_ +#define _Inout_z_count_(x) +#endif + +#ifndef _Out_ +#define _Out_ +#endif + +#ifndef _Out_opt_ +#define _Out_opt_ +#endif + +#ifndef _Out_writes_ +#define _Out_writes_(x) +#endif + +#ifndef _Outptr_result_maybenull_ +#define _Outptr_result_maybenull_ +#endif + +#ifndef _Writable_bytes_ +#define _Writable_bytes_(x) +#endif + +#ifndef _Readable_bytes_ +#define _Readable_bytes_(x) +#endif + +#ifndef _Success_ +#define _Success_(x) +#endif + +#ifndef _Pre_notnull_ +#define _Pre_notnull_ +#endif + +#ifdef DETOURS_INTERNAL + +#pragma warning(disable:4615) // unknown warning type (suppress with older compilers) + +#ifndef _Benign_race_begin_ +#define _Benign_race_begin_ +#endif + +#ifndef _Benign_race_end_ +#define _Benign_race_end_ +#endif + +#ifndef _Field_size_ +#define _Field_size_(x) +#endif + +#ifndef _Field_range_ +#define _Field_range_(x,y) +#endif + +#ifndef _Analysis_assume_ +#define _Analysis_assume_(x) +#endif + +#endif // DETOURS_INTERNAL +#endif // DETOURS_DONT_REMOVE_SAL_20 + +////////////////////////////////////////////////////////////////////////////// +// +#ifndef GUID_DEFINED +#define GUID_DEFINED +typedef struct _GUID +{ + DWORD Data1; + WORD Data2; + WORD Data3; + BYTE Data4[ 8 ]; +} GUID; + +#ifdef INITGUID +#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + const GUID name \ + = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } +#else +#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ + const GUID name +#endif // INITGUID +#endif // !GUID_DEFINED + +#if defined(__cplusplus) +#ifndef _REFGUID_DEFINED +#define _REFGUID_DEFINED +#define REFGUID const GUID & +#endif // !_REFGUID_DEFINED +#else // !__cplusplus +#ifndef _REFGUID_DEFINED +#define _REFGUID_DEFINED +#define REFGUID const GUID * const +#endif // !_REFGUID_DEFINED +#endif // !__cplusplus + +#ifndef ARRAYSIZE +#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0])) +#endif + +// +////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/////////////////////////////////////////////////// Instruction Target Macros. +// +#define DETOUR_INSTRUCTION_TARGET_NONE ((PVOID)0) +#define DETOUR_INSTRUCTION_TARGET_DYNAMIC ((PVOID)(LONG_PTR)-1) +#define DETOUR_SECTION_HEADER_SIGNATURE 0x00727444 // "Dtr\0" + +extern const GUID DETOUR_EXE_RESTORE_GUID; +extern const GUID DETOUR_EXE_HELPER_GUID; + +#define DETOUR_TRAMPOLINE_SIGNATURE 0x21727444 // Dtr! +typedef struct _DETOUR_TRAMPOLINE DETOUR_TRAMPOLINE, *PDETOUR_TRAMPOLINE; + +/////////////////////////////////////////////////////////// Binary Structures. +// +#pragma pack(push, 8) +typedef struct _DETOUR_SECTION_HEADER +{ + DWORD cbHeaderSize; + DWORD nSignature; + DWORD nDataOffset; + DWORD cbDataSize; + + DWORD nOriginalImportVirtualAddress; + DWORD nOriginalImportSize; + DWORD nOriginalBoundImportVirtualAddress; + DWORD nOriginalBoundImportSize; + + DWORD nOriginalIatVirtualAddress; + DWORD nOriginalIatSize; + DWORD nOriginalSizeOfImage; + DWORD cbPrePE; + + DWORD nOriginalClrFlags; + DWORD reserved1; + DWORD reserved2; + DWORD reserved3; + + // Followed by cbPrePE bytes of data. +} DETOUR_SECTION_HEADER, *PDETOUR_SECTION_HEADER; + +typedef struct _DETOUR_SECTION_RECORD +{ + DWORD cbBytes; + DWORD nReserved; + GUID guid; +} DETOUR_SECTION_RECORD, *PDETOUR_SECTION_RECORD; + +typedef struct _DETOUR_CLR_HEADER +{ + // Header versioning + ULONG cb; + USHORT MajorRuntimeVersion; + USHORT MinorRuntimeVersion; + + // Symbol table and startup information + IMAGE_DATA_DIRECTORY MetaData; + ULONG Flags; + + // Followed by the rest of the IMAGE_COR20_HEADER +} DETOUR_CLR_HEADER, *PDETOUR_CLR_HEADER; + +typedef struct _DETOUR_EXE_RESTORE +{ + DWORD cb; + DWORD cbidh; + DWORD cbinh; + DWORD cbclr; + + PBYTE pidh; + PBYTE pinh; + PBYTE pclr; + + IMAGE_DOS_HEADER idh; + union { + IMAGE_NT_HEADERS inh; // all environments have this +#ifdef IMAGE_NT_OPTIONAL_HDR32_MAGIC // some environments do not have this + IMAGE_NT_HEADERS32 inh32; +#endif +#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this + IMAGE_NT_HEADERS64 inh64; +#endif +#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC // some environments do not have this + BYTE raw[sizeof(IMAGE_NT_HEADERS64) + + sizeof(IMAGE_SECTION_HEADER) * 32]; +#else + BYTE raw[0x108 + sizeof(IMAGE_SECTION_HEADER) * 32]; +#endif + }; + DETOUR_CLR_HEADER clr; + +} DETOUR_EXE_RESTORE, *PDETOUR_EXE_RESTORE; + +#ifdef IMAGE_NT_OPTIONAL_HDR64_MAGIC +C_ASSERT(sizeof(IMAGE_NT_HEADERS64) == 0x108); +#endif + +// The size can change, but assert for clarity due to the muddying #ifdefs. +#ifdef _WIN64 +C_ASSERT(sizeof(DETOUR_EXE_RESTORE) == 0x688); +#else +C_ASSERT(sizeof(DETOUR_EXE_RESTORE) == 0x678); +#endif + +typedef struct _DETOUR_EXE_HELPER +{ + DWORD cb; + DWORD pid; + DWORD nDlls; + CHAR rDlls[4]; +} DETOUR_EXE_HELPER, *PDETOUR_EXE_HELPER; + +#pragma pack(pop) + +#define DETOUR_SECTION_HEADER_DECLARE(cbSectionSize) \ +{ \ + sizeof(DETOUR_SECTION_HEADER),\ + DETOUR_SECTION_HEADER_SIGNATURE,\ + sizeof(DETOUR_SECTION_HEADER),\ + (cbSectionSize),\ + \ + 0,\ + 0,\ + 0,\ + 0,\ + \ + 0,\ + 0,\ + 0,\ + 0,\ +} + +/////////////////////////////////////////////////////////////// Helper Macros. +// +#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) +#define DETOURS_STRINGIFY_(x) #x + +///////////////////////////////////////////////////////////// Binary Typedefs. +// +typedef BOOL (CALLBACK *PF_DETOUR_BINARY_BYWAY_CALLBACK)( + _In_opt_ PVOID pContext, + _In_opt_ LPCSTR pszFile, + _Outptr_result_maybenull_ LPCSTR *ppszOutFile); + +typedef BOOL (CALLBACK *PF_DETOUR_BINARY_FILE_CALLBACK)( + _In_opt_ PVOID pContext, + _In_ LPCSTR pszOrigFile, + _In_ LPCSTR pszFile, + _Outptr_result_maybenull_ LPCSTR *ppszOutFile); + +typedef BOOL (CALLBACK *PF_DETOUR_BINARY_SYMBOL_CALLBACK)( + _In_opt_ PVOID pContext, + _In_ ULONG nOrigOrdinal, + _In_ ULONG nOrdinal, + _Out_ ULONG *pnOutOrdinal, + _In_opt_ LPCSTR pszOrigSymbol, + _In_opt_ LPCSTR pszSymbol, + _Outptr_result_maybenull_ LPCSTR *ppszOutSymbol); + +typedef BOOL (CALLBACK *PF_DETOUR_BINARY_COMMIT_CALLBACK)( + _In_opt_ PVOID pContext); + +typedef BOOL (CALLBACK *PF_DETOUR_ENUMERATE_EXPORT_CALLBACK)(_In_opt_ PVOID pContext, + _In_ ULONG nOrdinal, + _In_opt_ LPCSTR pszName, + _In_opt_ PVOID pCode); + +typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FILE_CALLBACK)(_In_opt_ PVOID pContext, + _In_opt_ HMODULE hModule, + _In_opt_ LPCSTR pszFile); + +typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK)(_In_opt_ PVOID pContext, + _In_ DWORD nOrdinal, + _In_opt_ LPCSTR pszFunc, + _In_opt_ PVOID pvFunc); + +// Same as PF_DETOUR_IMPORT_FUNC_CALLBACK but extra indirection on last parameter. +typedef BOOL (CALLBACK *PF_DETOUR_IMPORT_FUNC_CALLBACK_EX)(_In_opt_ PVOID pContext, + _In_ DWORD nOrdinal, + _In_opt_ LPCSTR pszFunc, + _In_opt_ PVOID* ppvFunc); + +typedef VOID * PDETOUR_BINARY; +typedef VOID * PDETOUR_LOADED_BINARY; + +//////////////////////////////////////////////////////////// Transaction APIs. +// +LONG WINAPI DetourTransactionBegin(VOID); +LONG WINAPI DetourTransactionAbort(VOID); +LONG WINAPI DetourTransactionCommit(VOID); +LONG WINAPI DetourTransactionCommitEx(_Out_opt_ PVOID **pppFailedPointer); + +LONG WINAPI DetourUpdateThread(_In_ HANDLE hThread); + +LONG WINAPI DetourAttach(_Inout_ PVOID *ppPointer, + _In_ PVOID pDetour); + +LONG WINAPI DetourAttachEx(_Inout_ PVOID *ppPointer, + _In_ PVOID pDetour, + _Out_opt_ PDETOUR_TRAMPOLINE *ppRealTrampoline, + _Out_opt_ PVOID *ppRealTarget, + _Out_opt_ PVOID *ppRealDetour); + +LONG WINAPI DetourDetach(_Inout_ PVOID *ppPointer, + _In_ PVOID pDetour); + +BOOL WINAPI DetourSetIgnoreTooSmall(_In_ BOOL fIgnore); +BOOL WINAPI DetourSetRetainRegions(_In_ BOOL fRetain); +PVOID WINAPI DetourSetSystemRegionLowerBound(_In_ PVOID pSystemRegionLowerBound); +PVOID WINAPI DetourSetSystemRegionUpperBound(_In_ PVOID pSystemRegionUpperBound); + +////////////////////////////////////////////////////////////// Code Functions. +// +PVOID WINAPI DetourFindFunction(_In_ LPCSTR pszModule, + _In_ LPCSTR pszFunction); +PVOID WINAPI DetourCodeFromPointer(_In_ PVOID pPointer, + _Out_opt_ PVOID *ppGlobals); +PVOID WINAPI DetourCopyInstruction(_In_opt_ PVOID pDst, + _Inout_opt_ PVOID *ppDstPool, + _In_ PVOID pSrc, + _Out_opt_ PVOID *ppTarget, + _Out_opt_ LONG *plExtra); +BOOL WINAPI DetourSetCodeModule(_In_ HMODULE hModule, + _In_ BOOL fLimitReferencesToModule); +PVOID WINAPI DetourAllocateRegionWithinJumpBounds(_In_ LPCVOID pbTarget, + _Out_ PDWORD pcbAllocatedSize); + +///////////////////////////////////////////////////// Loaded Binary Functions. +// +HMODULE WINAPI DetourGetContainingModule(_In_ PVOID pvAddr); +HMODULE WINAPI DetourEnumerateModules(_In_opt_ HMODULE hModuleLast); +PVOID WINAPI DetourGetEntryPoint(_In_opt_ HMODULE hModule); +ULONG WINAPI DetourGetModuleSize(_In_opt_ HMODULE hModule); +BOOL WINAPI DetourEnumerateExports(_In_ HMODULE hModule, + _In_opt_ PVOID pContext, + _In_ PF_DETOUR_ENUMERATE_EXPORT_CALLBACK pfExport); +BOOL WINAPI DetourEnumerateImports(_In_opt_ HMODULE hModule, + _In_opt_ PVOID pContext, + _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, + _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK pfImportFunc); + +BOOL WINAPI DetourEnumerateImportsEx(_In_opt_ HMODULE hModule, + _In_opt_ PVOID pContext, + _In_opt_ PF_DETOUR_IMPORT_FILE_CALLBACK pfImportFile, + _In_opt_ PF_DETOUR_IMPORT_FUNC_CALLBACK_EX pfImportFuncEx); + +_Writable_bytes_(*pcbData) +_Readable_bytes_(*pcbData) +_Success_(return != NULL) +PVOID WINAPI DetourFindPayload(_In_opt_ HMODULE hModule, + _In_ REFGUID rguid, + _Out_ DWORD *pcbData); + +_Writable_bytes_(*pcbData) +_Readable_bytes_(*pcbData) +_Success_(return != NULL) +PVOID WINAPI DetourFindPayloadEx(_In_ REFGUID rguid, + _Out_ DWORD * pcbData); + +DWORD WINAPI DetourGetSizeOfPayloads(_In_opt_ HMODULE hModule); + +///////////////////////////////////////////////// Persistent Binary Functions. +// + +PDETOUR_BINARY WINAPI DetourBinaryOpen(_In_ HANDLE hFile); + +_Writable_bytes_(*pcbData) +_Readable_bytes_(*pcbData) +_Success_(return != NULL) +PVOID WINAPI DetourBinaryEnumeratePayloads(_In_ PDETOUR_BINARY pBinary, + _Out_opt_ GUID *pGuid, + _Out_ DWORD *pcbData, + _Inout_ DWORD *pnIterator); + +_Writable_bytes_(*pcbData) +_Readable_bytes_(*pcbData) +_Success_(return != NULL) +PVOID WINAPI DetourBinaryFindPayload(_In_ PDETOUR_BINARY pBinary, + _In_ REFGUID rguid, + _Out_ DWORD *pcbData); + +PVOID WINAPI DetourBinarySetPayload(_In_ PDETOUR_BINARY pBinary, + _In_ REFGUID rguid, + _In_reads_opt_(cbData) PVOID pData, + _In_ DWORD cbData); +BOOL WINAPI DetourBinaryDeletePayload(_In_ PDETOUR_BINARY pBinary, _In_ REFGUID rguid); +BOOL WINAPI DetourBinaryPurgePayloads(_In_ PDETOUR_BINARY pBinary); +BOOL WINAPI DetourBinaryResetImports(_In_ PDETOUR_BINARY pBinary); +BOOL WINAPI DetourBinaryEditImports(_In_ PDETOUR_BINARY pBinary, + _In_opt_ PVOID pContext, + _In_opt_ PF_DETOUR_BINARY_BYWAY_CALLBACK pfByway, + _In_opt_ PF_DETOUR_BINARY_FILE_CALLBACK pfFile, + _In_opt_ PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbol, + _In_opt_ PF_DETOUR_BINARY_COMMIT_CALLBACK pfCommit); +BOOL WINAPI DetourBinaryWrite(_In_ PDETOUR_BINARY pBinary, _In_ HANDLE hFile); +BOOL WINAPI DetourBinaryClose(_In_ PDETOUR_BINARY pBinary); + +/////////////////////////////////////////////////// Create Process & Load Dll. +// +typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEA)( + _In_opt_ LPCSTR lpApplicationName, + _Inout_opt_ LPSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOA lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation); + +typedef BOOL (WINAPI *PDETOUR_CREATE_PROCESS_ROUTINEW)( + _In_opt_ LPCWSTR lpApplicationName, + _Inout_opt_ LPWSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCWSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOW lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation); + +BOOL WINAPI DetourCreateProcessWithDllA(_In_opt_ LPCSTR lpApplicationName, + _Inout_opt_ LPSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOA lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ LPCSTR lpDllName, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); + +BOOL WINAPI DetourCreateProcessWithDllW(_In_opt_ LPCWSTR lpApplicationName, + _Inout_opt_ LPWSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCWSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOW lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ LPCSTR lpDllName, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); + +#ifdef UNICODE +#define DetourCreateProcessWithDll DetourCreateProcessWithDllW +#define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEW +#else +#define DetourCreateProcessWithDll DetourCreateProcessWithDllA +#define PDETOUR_CREATE_PROCESS_ROUTINE PDETOUR_CREATE_PROCESS_ROUTINEA +#endif // !UNICODE + +BOOL WINAPI DetourCreateProcessWithDllExA(_In_opt_ LPCSTR lpApplicationName, + _Inout_opt_ LPSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOA lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ LPCSTR lpDllName, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); + +BOOL WINAPI DetourCreateProcessWithDllExW(_In_opt_ LPCWSTR lpApplicationName, + _Inout_opt_ LPWSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCWSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOW lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ LPCSTR lpDllName, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); + +#ifdef UNICODE +#define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExW +#else +#define DetourCreateProcessWithDllEx DetourCreateProcessWithDllExA +#endif // !UNICODE + +BOOL WINAPI DetourCreateProcessWithDllsA(_In_opt_ LPCSTR lpApplicationName, + _Inout_opt_ LPSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOA lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ DWORD nDlls, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); + +BOOL WINAPI DetourCreateProcessWithDllsW(_In_opt_ LPCWSTR lpApplicationName, + _Inout_opt_ LPWSTR lpCommandLine, + _In_opt_ LPSECURITY_ATTRIBUTES lpProcessAttributes, + _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, + _In_ BOOL bInheritHandles, + _In_ DWORD dwCreationFlags, + _In_opt_ LPVOID lpEnvironment, + _In_opt_ LPCWSTR lpCurrentDirectory, + _In_ LPSTARTUPINFOW lpStartupInfo, + _Out_ LPPROCESS_INFORMATION lpProcessInformation, + _In_ DWORD nDlls, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_opt_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); + +#ifdef UNICODE +#define DetourCreateProcessWithDlls DetourCreateProcessWithDllsW +#else +#define DetourCreateProcessWithDlls DetourCreateProcessWithDllsA +#endif // !UNICODE + +BOOL WINAPI DetourProcessViaHelperA(_In_ DWORD dwTargetPid, + _In_ LPCSTR lpDllName, + _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); + +BOOL WINAPI DetourProcessViaHelperW(_In_ DWORD dwTargetPid, + _In_ LPCSTR lpDllName, + _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); + +#ifdef UNICODE +#define DetourProcessViaHelper DetourProcessViaHelperW +#else +#define DetourProcessViaHelper DetourProcessViaHelperA +#endif // !UNICODE + +BOOL WINAPI DetourProcessViaHelperDllsA(_In_ DWORD dwTargetPid, + _In_ DWORD nDlls, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_ PDETOUR_CREATE_PROCESS_ROUTINEA pfCreateProcessA); + +BOOL WINAPI DetourProcessViaHelperDllsW(_In_ DWORD dwTargetPid, + _In_ DWORD nDlls, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_ PDETOUR_CREATE_PROCESS_ROUTINEW pfCreateProcessW); + +#ifdef UNICODE +#define DetourProcessViaHelperDlls DetourProcessViaHelperDllsW +#else +#define DetourProcessViaHelperDlls DetourProcessViaHelperDllsA +#endif // !UNICODE + +BOOL WINAPI DetourUpdateProcessWithDll(_In_ HANDLE hProcess, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_ DWORD nDlls); + +BOOL WINAPI DetourUpdateProcessWithDllEx(_In_ HANDLE hProcess, + _In_ HMODULE hImage, + _In_ BOOL bIs32Bit, + _In_reads_(nDlls) LPCSTR *rlpDlls, + _In_ DWORD nDlls); + +BOOL WINAPI DetourCopyPayloadToProcess(_In_ HANDLE hProcess, + _In_ REFGUID rguid, + _In_reads_bytes_(cbData) PVOID pvData, + _In_ DWORD cbData); +BOOL WINAPI DetourRestoreAfterWith(VOID); +BOOL WINAPI DetourRestoreAfterWithEx(_In_reads_bytes_(cbData) PVOID pvData, + _In_ DWORD cbData); +BOOL WINAPI DetourIsHelperProcess(VOID); +VOID CALLBACK DetourFinishHelperProcess(_In_ HWND, + _In_ HINSTANCE, + _In_ LPSTR, + _In_ INT); + +// +////////////////////////////////////////////////////////////////////////////// +#ifdef __cplusplus +} +#endif // __cplusplus + +//////////////////////////////////////////////// Detours Internal Definitions. +// +#ifdef __cplusplus +#ifdef DETOURS_INTERNAL + +#define NOTHROW +// #define NOTHROW (nothrow) + +////////////////////////////////////////////////////////////////////////////// +// +#if (_MSC_VER < 1299) +#include +typedef IMAGEHLP_MODULE IMAGEHLP_MODULE64; +typedef PIMAGEHLP_MODULE PIMAGEHLP_MODULE64; +typedef IMAGEHLP_SYMBOL SYMBOL_INFO; +typedef PIMAGEHLP_SYMBOL PSYMBOL_INFO; + +static inline +LONG InterlockedCompareExchange(_Inout_ LONG *ptr, _In_ LONG nval, _In_ LONG oval) +{ + return (LONG)::InterlockedCompareExchange((PVOID*)ptr, (PVOID)nval, (PVOID)oval); +} +#else +#pragma warning(push) +#pragma warning(disable:4091) // empty typedef +#include +#pragma warning(pop) +#endif + +#ifdef IMAGEAPI // defined by DBGHELP.H +typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(_In_ LPAPI_VERSION AppVersion); + +typedef BOOL (NTAPI *PF_SymInitialize)(_In_ HANDLE hProcess, + _In_opt_ LPCSTR UserSearchPath, + _In_ BOOL fInvadeProcess); +typedef DWORD (NTAPI *PF_SymSetOptions)(_In_ DWORD SymOptions); +typedef DWORD (NTAPI *PF_SymGetOptions)(VOID); +typedef DWORD64 (NTAPI *PF_SymLoadModule64)(_In_ HANDLE hProcess, + _In_opt_ HANDLE hFile, + _In_ LPSTR ImageName, + _In_opt_ LPSTR ModuleName, + _In_ DWORD64 BaseOfDll, + _In_opt_ DWORD SizeOfDll); +typedef BOOL (NTAPI *PF_SymGetModuleInfo64)(_In_ HANDLE hProcess, + _In_ DWORD64 qwAddr, + _Out_ PIMAGEHLP_MODULE64 ModuleInfo); +typedef BOOL (NTAPI *PF_SymFromName)(_In_ HANDLE hProcess, + _In_ LPSTR Name, + _Out_ PSYMBOL_INFO Symbol); + +typedef struct _DETOUR_SYM_INFO +{ + HANDLE hProcess; + HMODULE hDbgHelp; + PF_ImagehlpApiVersionEx pfImagehlpApiVersionEx; + PF_SymInitialize pfSymInitialize; + PF_SymSetOptions pfSymSetOptions; + PF_SymGetOptions pfSymGetOptions; + PF_SymLoadModule64 pfSymLoadModule64; + PF_SymGetModuleInfo64 pfSymGetModuleInfo64; + PF_SymFromName pfSymFromName; +} DETOUR_SYM_INFO, *PDETOUR_SYM_INFO; + +PDETOUR_SYM_INFO DetourLoadImageHlp(VOID); + +#endif // IMAGEAPI + +#if defined(_INC_STDIO) && !defined(_CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS) +#error detours.h must be included before stdio.h (or at least define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS earlier) +#endif +#define _CRT_STDIO_ARBITRARY_WIDE_SPECIFIERS 1 + +#ifndef DETOUR_TRACE +#if DETOUR_DEBUG +#define DETOUR_TRACE(x) printf x +#define DETOUR_BREAK() __debugbreak() +#include +#include +#else +#define DETOUR_TRACE(x) +#define DETOUR_BREAK() +#endif +#endif + +#if 1 || defined(DETOURS_IA64) + +// +// IA64 instructions are 41 bits, 3 per bundle, plus 5 bit bundle template => 128 bits per bundle. +// + +#define DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE (3) + +#define DETOUR_IA64_TEMPLATE_OFFSET (0) +#define DETOUR_IA64_TEMPLATE_SIZE (5) + +#define DETOUR_IA64_INSTRUCTION_SIZE (41) +#define DETOUR_IA64_INSTRUCTION0_OFFSET (DETOUR_IA64_TEMPLATE_SIZE) +#define DETOUR_IA64_INSTRUCTION1_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) +#define DETOUR_IA64_INSTRUCTION2_OFFSET (DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTION_SIZE + DETOUR_IA64_INSTRUCTION_SIZE) + +C_ASSERT(DETOUR_IA64_TEMPLATE_SIZE + DETOUR_IA64_INSTRUCTIONS_PER_BUNDLE * DETOUR_IA64_INSTRUCTION_SIZE == 128); + +__declspec(align(16)) struct DETOUR_IA64_BUNDLE +{ + public: + union + { + BYTE data[16]; + UINT64 wide[2]; + }; + + enum { + A_UNIT = 1u, + I_UNIT = 2u, + M_UNIT = 3u, + B_UNIT = 4u, + F_UNIT = 5u, + L_UNIT = 6u, + X_UNIT = 7u, + }; + struct DETOUR_IA64_METADATA + { + ULONG nTemplate : 8; // Instruction template. + ULONG nUnit0 : 4; // Unit for slot 0 + ULONG nUnit1 : 4; // Unit for slot 1 + ULONG nUnit2 : 4; // Unit for slot 2 + }; + + protected: + static const DETOUR_IA64_METADATA s_rceCopyTable[33]; + + UINT RelocateBundle(_Inout_ DETOUR_IA64_BUNDLE* pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; + + bool RelocateInstruction(_Inout_ DETOUR_IA64_BUNDLE* pDst, + _In_ BYTE slot, + _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra) const; + + // 120 112 104 96 88 80 72 64 56 48 40 32 24 16 8 0 + // f. e. d. c. b. a. 9. 8. 7. 6. 5. 4. 3. 2. 1. 0. + + // 00 + // f.e. d.c. b.a. 9.8. 7.6. 5.4. 3.2. 1.0. + // 0000 0000 0000 0000 0000 0000 0000 001f : Template [4..0] + // 0000 0000 0000 0000 0000 03ff ffff ffe0 : Zero [ 41.. 5] + // 0000 0000 0000 0000 0000 3c00 0000 0000 : Zero [ 45.. 42] + // 0000 0000 0007 ffff ffff c000 0000 0000 : One [ 82.. 46] + // 0000 0000 0078 0000 0000 0000 0000 0000 : One [ 86.. 83] + // 0fff ffff ff80 0000 0000 0000 0000 0000 : Two [123.. 87] + // f000 0000 0000 0000 0000 0000 0000 0000 : Two [127..124] + BYTE GetTemplate() const; + // Get 4 bit opcodes. + BYTE GetInst0() const; + BYTE GetInst1() const; + BYTE GetInst2() const; + BYTE GetUnit(BYTE slot) const; + BYTE GetUnit0() const; + BYTE GetUnit1() const; + BYTE GetUnit2() const; + // Get 37 bit data. + UINT64 GetData0() const; + UINT64 GetData1() const; + UINT64 GetData2() const; + + // Get/set the full 41 bit instructions. + UINT64 GetInstruction(BYTE slot) const; + UINT64 GetInstruction0() const; + UINT64 GetInstruction1() const; + UINT64 GetInstruction2() const; + void SetInstruction(BYTE slot, UINT64 instruction); + void SetInstruction0(UINT64 instruction); + void SetInstruction1(UINT64 instruction); + void SetInstruction2(UINT64 instruction); + + // Get/set bitfields. + static UINT64 GetBits(UINT64 Value, UINT64 Offset, UINT64 Count); + static UINT64 SetBits(UINT64 Value, UINT64 Offset, UINT64 Count, UINT64 Field); + + // Get specific read-only fields. + static UINT64 GetOpcode(UINT64 instruction); // 4bit opcode + static UINT64 GetX(UINT64 instruction); // 1bit opcode extension + static UINT64 GetX3(UINT64 instruction); // 3bit opcode extension + static UINT64 GetX6(UINT64 instruction); // 6bit opcode extension + + // Get/set specific fields. + static UINT64 GetImm7a(UINT64 instruction); + static UINT64 SetImm7a(UINT64 instruction, UINT64 imm7a); + static UINT64 GetImm13c(UINT64 instruction); + static UINT64 SetImm13c(UINT64 instruction, UINT64 imm13c); + static UINT64 GetSignBit(UINT64 instruction); + static UINT64 SetSignBit(UINT64 instruction, UINT64 signBit); + static UINT64 GetImm20a(UINT64 instruction); + static UINT64 SetImm20a(UINT64 instruction, UINT64 imm20a); + static UINT64 GetImm20b(UINT64 instruction); + static UINT64 SetImm20b(UINT64 instruction, UINT64 imm20b); + + static UINT64 SignExtend(UINT64 Value, UINT64 Offset); + + BOOL IsMovlGp() const; + + VOID SetInst(BYTE Slot, BYTE nInst); + VOID SetInst0(BYTE nInst); + VOID SetInst1(BYTE nInst); + VOID SetInst2(BYTE nInst); + VOID SetData(BYTE Slot, UINT64 nData); + VOID SetData0(UINT64 nData); + VOID SetData1(UINT64 nData); + VOID SetData2(UINT64 nData); + BOOL SetNop(BYTE Slot); + BOOL SetNop0(); + BOOL SetNop1(); + BOOL SetNop2(); + + public: + BOOL IsBrl() const; + VOID SetBrl(); + VOID SetBrl(UINT64 target); + UINT64 GetBrlTarget() const; + VOID SetBrlTarget(UINT64 target); + VOID SetBrlImm(UINT64 imm); + UINT64 GetBrlImm() const; + + UINT64 GetMovlGp() const; + VOID SetMovlGp(UINT64 gp); + + VOID SetStop(); + + UINT Copy(_Out_ DETOUR_IA64_BUNDLE *pDst, _Inout_opt_ DETOUR_IA64_BUNDLE* pBundleExtra = NULL) const; +}; +#endif // DETOURS_IA64 + +#ifdef DETOURS_ARM + +#define DETOURS_PFUNC_TO_PBYTE(p) ((PBYTE)(((ULONG_PTR)(p)) & ~(ULONG_PTR)1)) +#define DETOURS_PBYTE_TO_PFUNC(p) ((PBYTE)(((ULONG_PTR)(p)) | (ULONG_PTR)1)) + +#endif // DETOURS_ARM + +////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#define DETOUR_OFFLINE_LIBRARY(x) \ +PVOID WINAPI DetourCopyInstruction##x(_In_opt_ PVOID pDst, \ + _Inout_opt_ PVOID *ppDstPool, \ + _In_ PVOID pSrc, \ + _Out_opt_ PVOID *ppTarget, \ + _Out_opt_ LONG *plExtra); \ + \ +BOOL WINAPI DetourSetCodeModule##x(_In_ HMODULE hModule, \ + _In_ BOOL fLimitReferencesToModule); \ + +DETOUR_OFFLINE_LIBRARY(X86) +DETOUR_OFFLINE_LIBRARY(X64) +DETOUR_OFFLINE_LIBRARY(ARM) +DETOUR_OFFLINE_LIBRARY(ARM64) +DETOUR_OFFLINE_LIBRARY(IA64) + +#undef DETOUR_OFFLINE_LIBRARY + +////////////////////////////////////////////////////////////////////////////// +// +// Helpers for manipulating page protection. +// + +_Success_(return != FALSE) +BOOL WINAPI DetourVirtualProtectSameExecuteEx(_In_ HANDLE hProcess, + _In_ PVOID pAddress, + _In_ SIZE_T nSize, + _In_ DWORD dwNewProtect, + _Out_ PDWORD pdwOldProtect); + +_Success_(return != FALSE) +BOOL WINAPI DetourVirtualProtectSameExecute(_In_ PVOID pAddress, + _In_ SIZE_T nSize, + _In_ DWORD dwNewProtect, + _Out_ PDWORD pdwOldProtect); +#ifdef __cplusplus +} +#endif // __cplusplus + +////////////////////////////////////////////////////////////////////////////// + +#define MM_ALLOCATION_GRANULARITY 0x10000 + +////////////////////////////////////////////////////////////////////////////// + +#endif // DETOURS_INTERNAL +#endif // __cplusplus + +#endif // _DETOURS_H_ +// +//////////////////////////////////////////////////////////////// End of File. diff --git a/packages/Detours.4.0.1/lib/native/include/detver.h b/packages/Detours.4.0.1/lib/native/include/detver.h new file mode 100644 index 00000000..f0aae9bd --- /dev/null +++ b/packages/Detours.4.0.1/lib/native/include/detver.h @@ -0,0 +1,27 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Common version parameters. +// +// Microsoft Research Detours Package, Version 4.0.1 +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#define _USING_V110_SDK71_ 1 +#include "winver.h" +#if 0 +#include +#include +#else +#ifndef DETOURS_STRINGIFY +#define DETOURS_STRINGIFY(x) DETOURS_STRINGIFY_(x) +#define DETOURS_STRINGIFY_(x) #x +#endif + +#define VER_FILEFLAGSMASK 0x3fL +#define VER_FILEFLAGS 0x0L +#define VER_FILEOS 0x00040004L +#define VER_FILETYPE 0x00000002L +#define VER_FILESUBTYPE 0x00000000L +#endif +#define VER_DETOURS_BITS DETOUR_STRINGIFY(DETOURS_BITS) diff --git a/packages/Detours.4.0.1/lib/native/include/syelog.h b/packages/Detours.4.0.1/lib/native/include/syelog.h new file mode 100644 index 00000000..7cfa9f3d --- /dev/null +++ b/packages/Detours.4.0.1/lib/native/include/syelog.h @@ -0,0 +1,89 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Detours Test Program (syelog.h of syelog.lib) +// +// Microsoft Research Detours Package +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +#pragma once +#ifndef _SYELOGD_H_ +#define _SYELOGD_H_ +#include + +#pragma pack(push, 1) +#pragma warning(push) +#pragma warning(disable: 4200) + +////////////////////////////////////////////////////////////////////////////// +// +// +#define SYELOG_PIPE_NAMEA "\\\\.\\pipe\\syelog" +#define SYELOG_PIPE_NAMEW L"\\\\.\\pipe\\syelog" +#ifdef UNICODE +#define SYELOG_PIPE_NAME SYELOG_PIPE_NAMEW +#else +#define SYELOG_PIPE_NAME SYELOG_PIPE_NAMEA +#endif + +////////////////////////////////////////////////////////////////////////////// +// +#define SYELOG_MAXIMUM_MESSAGE 4086 // 4096 - sizeof(header stuff) + +typedef struct _SYELOG_MESSAGE +{ + USHORT nBytes; + BYTE nFacility; + BYTE nSeverity; + DWORD nProcessId; + FILETIME ftOccurance; + BOOL fTerminate; + CHAR szMessage[SYELOG_MAXIMUM_MESSAGE]; +} SYELOG_MESSAGE, *PSYELOG_MESSAGE; + + +// Facility Codes. +// +#define SYELOG_FACILITY_KERNEL 0x10 // OS Kernel +#define SYELOG_FACILITY_SECURITY 0x20 // OS Security +#define SYELOG_FACILITY_LOGGING 0x30 // OS Logging-internal +#define SYELOG_FACILITY_SERVICE 0x40 // User-mode system daemon +#define SYELOG_FACILITY_APPLICATION 0x50 // User-mode application +#define SYELOG_FACILITY_USER 0x60 // User self-generated. +#define SYELOG_FACILITY_LOCAL0 0x70 // Locally defined. +#define SYELOG_FACILITY_LOCAL1 0x71 // Locally defined. +#define SYELOG_FACILITY_LOCAL2 0x72 // Locally defined. +#define SYELOG_FACILITY_LOCAL3 0x73 // Locally defined. +#define SYELOG_FACILITY_LOCAL4 0x74 // Locally defined. +#define SYELOG_FACILITY_LOCAL5 0x75 // Locally defined. +#define SYELOG_FACILITY_LOCAL6 0x76 // Locally defined. +#define SYELOG_FACILITY_LOCAL7 0x77 // Locally defined. +#define SYELOG_FACILITY_LOCAL8 0x78 // Locally defined. +#define SYELOG_FACILITY_LOCAL9 0x79 // Locally defined. + +// Severity Codes. +// +#define SYELOG_SEVERITY_FATAL 0x00 // System is dead. +#define SYELOG_SEVERITY_ALERT 0x10 // Take action immediately. +#define SYELOG_SEVERITY_CRITICAL 0x20 // Critical condition. +#define SYELOG_SEVERITY_ERROR 0x30 // Error +#define SYELOG_SEVERITY_WARNING 0x40 // Warning +#define SYELOG_SEVERITY_NOTICE 0x50 // Significant condition. +#define SYELOG_SEVERITY_INFORMATION 0x60 // Informational +#define SYELOG_SEVERITY_AUDIT_FAIL 0x66 // Audit Failed +#define SYELOG_SEVERITY_AUDIT_PASS 0x67 // Audit Succeeeded +#define SYELOG_SEVERITY_DEBUG 0x70 // Debugging + +// Logging Functions. +// +VOID SyelogOpen(PCSTR pszIdentifier, BYTE nFacility); +VOID Syelog(BYTE nSeverity, PCSTR pszMsgf, ...); +VOID SyelogV(BYTE nSeverity, PCSTR pszMsgf, va_list args); +VOID SyelogClose(BOOL fTerminate); + +#pragma warning(pop) +#pragma pack(pop) + +#endif // _SYELOGD_H_ +// +///////////////////////////////////////////////////////////////// End of File. diff --git a/packages/Detours.4.0.1/lib/native/libs/x64/detours.lib b/packages/Detours.4.0.1/lib/native/libs/x64/detours.lib new file mode 100644 index 00000000..2ca1c3ab Binary files /dev/null and b/packages/Detours.4.0.1/lib/native/libs/x64/detours.lib differ diff --git a/packages/Detours.4.0.1/lib/native/libs/x64/syelog.lib b/packages/Detours.4.0.1/lib/native/libs/x64/syelog.lib new file mode 100644 index 00000000..5ea748e6 Binary files /dev/null and b/packages/Detours.4.0.1/lib/native/libs/x64/syelog.lib differ diff --git a/packages/Detours.4.0.1/lib/native/libs/x86/detours.lib b/packages/Detours.4.0.1/lib/native/libs/x86/detours.lib new file mode 100644 index 00000000..268f7ad9 Binary files /dev/null and b/packages/Detours.4.0.1/lib/native/libs/x86/detours.lib differ diff --git a/packages/Detours.4.0.1/lib/native/libs/x86/syelog.lib b/packages/Detours.4.0.1/lib/native/libs/x86/syelog.lib new file mode 100644 index 00000000..798bcd17 Binary files /dev/null and b/packages/Detours.4.0.1/lib/native/libs/x86/syelog.lib differ diff --git a/src/BasicUtils/Console.cpp b/src/BasicUtils/Console.cpp new file mode 100644 index 00000000..0cd2d0e2 --- /dev/null +++ b/src/BasicUtils/Console.cpp @@ -0,0 +1,3 @@ +#include "Console.h" + +std::mutex Console::cout_mutex; diff --git a/src/BasicUtils/Console.h b/src/BasicUtils/Console.h new file mode 100644 index 00000000..4d0f1da1 --- /dev/null +++ b/src/BasicUtils/Console.h @@ -0,0 +1,180 @@ +#ifndef _CONSOLE_H +#define _CONSOLE_H + +#include +#include +#include +#include +#include +//#include +#include +#include "Utils.h" + +namespace Console { + extern std::mutex cout_mutex; + + enum class Color : WORD { + Red = FOREGROUND_RED, + Green = FOREGROUND_GREEN, + Blue = FOREGROUND_BLUE, + Yellow = FOREGROUND_RED | FOREGROUND_GREEN, + Cyan = FOREGROUND_GREEN | FOREGROUND_BLUE, + Magenta = FOREGROUND_RED | FOREGROUND_BLUE, + White = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, + Black = 0, + Gray = FOREGROUND_INTENSITY, + DarkRed = FOREGROUND_RED | FOREGROUND_INTENSITY, + DarkGreen = FOREGROUND_GREEN | FOREGROUND_INTENSITY, + DarkBlue = FOREGROUND_BLUE | FOREGROUND_INTENSITY, + DarkYellow = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, + DarkCyan = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, + DarkMagenta = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY + }; + +#if defined(_DEBUG) || defined(_CONSOLE) + // Converts a value to the appropriate type for std::vformat() + template + constexpr auto TypeConvert(const T& arg) { + if constexpr (std::is_same_v) { + return std::wstring_view(arg); + } + else if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v) { + return Utils::ToString(arg); + } + else if constexpr (std::is_same_v < T, void*>) { + return reinterpret_cast(arg); + } + else if constexpr (std::is_pointer_v) { + return *arg; + } + else { + return arg; + } + } +#endif + + /** + * The format string can contain various format specifiers such as: + * - "{}": Default representation of the argument. + * - "{:d}": Decimal integer. + * - "{:x}/{:X}": Hexadecimal integer (lowercase/uppercase). + * - "{:#x}/{:#X}": Hexadecimal integer with "0x"/"0X" prefix. + * - "{:.2f}": Fixed-point floating-point with 2 digits after the decimal point. + */ + void Print(std::wstring_view fmt, const auto&... args) + { +#if defined(_DEBUG) || defined(_CONSOLE) + //try { + std::scoped_lock lock(cout_mutex); + std::wcout << std::vformat(fmt, std::make_wformat_args(TypeConvert(args)...)) << std::endl; + //} + //catch (const std::exception& e) { + // throw std::runtime_error("Failed to format string: " + std::string(e.what())); + //} +#endif + } + + /** + * The format string can contain various format specifiers such as: + * - "{}": Default representation of the argument. + * - "{:d}": Decimal integer. + * - "{:x}/{:X}": Hexadecimal integer (lowercase/uppercase). + * - "{:#x}/{:#X}": Hexadecimal integer with "0x"/"0X" prefix. + * - "{:.2f}": Fixed-point floating-point with 2 digits after the decimal point. + */ + void Print(const std::vector& colors, std::wstring fmt, const auto&... args) { +#if defined(_DEBUG) || defined(_CONSOLE) + try { + std::scoped_lock lock(cout_mutex); + HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); + if (hConsole == INVALID_HANDLE_VALUE) { + throw std::runtime_error("Failed to get console handle"); + } + + size_t start = 0; + size_t pos = fmt.find(L"{"); + size_t colorIndex = 0; + + auto printArg = [&](const auto& arg) { + if (pos != std::wstring::npos) { + std::wcout << fmt.substr(start, pos - start); + if (colorIndex < colors.size()) { + if (!SetConsoleTextAttribute(hConsole, static_cast(colors[colorIndex]))) { + throw std::runtime_error("Failed to set console text attribute"); + } + ++colorIndex; + } + + // Check for format specifiers within the braces + size_t end = fmt.find(L"}", pos); + if (end != std::wstring::npos) { + std::wstring formatSpecifier = fmt.substr(pos, end - pos + 1); + std::wcout << std::vformat(formatSpecifier, std::make_wformat_args(TypeConvert(arg))); + pos = fmt.find(L"{", end + 1); + } + else { + throw std::runtime_error("Invalid format string"); + } + + if (!SetConsoleTextAttribute(hConsole, static_cast(Color::White))) { + throw std::runtime_error("Failed to set console text attribute"); + } + start = end + 1; + } + else { + std::wcout << fmt.substr(start); + } + }; + + (printArg(args), ...); + std::wcout << fmt.substr(start) << std::endl; + } + catch (const std::exception& e) { + throw std::runtime_error("Failed to format string: " + std::string(e.what())); + } +#endif + } +// void Print(const std::vector& colors, std::wstring fmt, const auto&... args) +// { +//#if defined(_DEBUG) || defined(_CONSOLE) +// try { +// std::scoped_lock lock(cout_mutex); +// HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); +// if (hConsole == INVALID_HANDLE_VALUE) { +// throw std::runtime_error("Failed to get console handle"); +// } +// size_t start = 0; +// std::wregex re(L"\\{(.*?)\\}"); +// auto it = std::wsregex_iterator(fmt.begin(), fmt.end(), re); +// size_t colorIndex = 0; +// auto printArg = [&](const auto& arg) { +// if (it != std::wsregex_iterator()) { +// std::wcout << fmt.substr(start, it->position() - start); +// if (colorIndex < colors.size()) { +// if (!SetConsoleTextAttribute(hConsole, static_cast(colors[colorIndex]))) { +// throw std::runtime_error("Failed to set console text attribute"); +// } +// ++colorIndex; +// } +// std::wcout << std::vformat(it->str(), std::make_wformat_args(TypeConvert(arg))); +// if (!SetConsoleTextAttribute(hConsole, static_cast(Color::White))) { +// throw std::runtime_error("Failed to set console text attribute"); +// } +// start = it->position() + it->length(); +// ++it; +// } +// else { +// std::wcout << fmt.substr(start); +// } +// }; +// (printArg(args), ...); +// std::wcout << fmt.substr(start) << std::endl; +// } +// catch (const std::exception& e) { +// throw std::runtime_error("Failed to format string: " + std::string(e.what())); +// } +//#endif +// } +} + +#endif // _CONSOLE_H \ No newline at end of file diff --git a/src/BasicUtils/Hooking.cpp b/src/BasicUtils/Hooking.cpp new file mode 100644 index 00000000..b63f7a69 --- /dev/null +++ b/src/BasicUtils/Hooking.cpp @@ -0,0 +1,97 @@ +#include "Hooking.h" +#include +#include + +bool Hooking::HookFunction(std::vector ppPointers, std::vector pDetours) { + if (Begin()) + { + for (size_t i = 0; i < ppPointers.size(); i++) { + if (FindHookFunction(ppPointers[i]) != nullptr) { + throw std::runtime_error("DetourAttach failed"); + } + + if (DetourAttach(ppPointers[i], pDetours[i]) != NO_ERROR) { + throw std::runtime_error("DetourAttach failed"); + } + + InsertHookFunction(ppPointers[i], pDetours[i]); + } + return Commit(); + } + return false; +} + +bool Hooking::HookFunction(PVOID* ppPointers, PVOID pDetours) { + auto _ppPointers = { ppPointers }; + auto _pDetours = { pDetours }; + return HookFunction(_ppPointers, _pDetours); +} + +bool Hooking::UnhookFunction(std::vector ppPointers, std::vector pDetours) { + if (Begin()) + { + for (size_t i = 0; i < ppPointers.size(); i++) { + if (pDetours[i] == nullptr) { + pDetours[i] = FindHookFunction(ppPointers[i]); + if (pDetours[i] == nullptr) { + throw std::runtime_error("DetourDetach failed"); + } + } + + if (DetourDetach(ppPointers[i], pDetours[i]) != NO_ERROR) { + throw std::runtime_error("DetourDetach failed"); + } + + EraseHookFunction(ppPointers[i]); + } + return Commit(); + } + return false; +} + +bool Hooking::UnhookFunction(PVOID* ppPointers, PVOID pDetours) { + auto _ppPointers = { ppPointers }; + auto _pDetours = { pDetours }; + return UnhookFunction(_ppPointers, _pDetours); +} + +bool Hooking::Begin() { + if (DetourIsHelperProcess()) { + throw std::runtime_error("DetourIsHelperProcess failed"); + } + + DetourRestoreAfterWith(); + + if (DetourTransactionBegin() != NO_ERROR) { + throw std::runtime_error("DetourTransactionBegin failed"); + } + + return true; +} + +bool Hooking::Commit() { + if (DetourTransactionCommit() != NO_ERROR) { + throw std::runtime_error("DetourTransactionCommit failed"); + } + return true; +} + +void Hooking::InsertHookFunction(PVOID* ppPointers, PVOID pDetours) +{ + HookFunctionList[ppPointers] = pDetours; +} + +void Hooking::EraseHookFunction(PVOID* ppPointers) +{ + HookFunctionList.erase(ppPointers); +} + +PVOID Hooking::FindHookFunction(PVOID* ppPointers) { + auto iter = HookFunctionList.find(ppPointers); + if (iter != HookFunctionList.end()) { + return iter->second; + } + return nullptr; +} + +std::map Hooking::HookFunctionList; \ No newline at end of file diff --git a/src/BasicUtils/Hooking.h b/src/BasicUtils/Hooking.h new file mode 100644 index 00000000..dc232d18 --- /dev/null +++ b/src/BasicUtils/Hooking.h @@ -0,0 +1,25 @@ +#ifndef _HOOKING_H +#define _HOOKING_H + +#include +#include +#include + +class Hooking { +public: + static bool HookFunction(std::vector ppPointers, std::vector pDetours); + static bool HookFunction(PVOID* ppPointers, PVOID pDetours); + static bool UnhookFunction(std::vector ppPointers, std::vector pDetours = {}); + static bool UnhookFunction(PVOID* ppPointers, PVOID pDetours = nullptr); + + +private: + static bool Begin(); + static bool Commit(); + static void InsertHookFunction(PVOID* ppPointers, PVOID pDetours); + static void EraseHookFunction(PVOID* ppPointers); + static PVOID FindHookFunction(PVOID* ppPointers); + static std::map HookFunctionList; +}; + +#endif //_HOOKING_H diff --git a/src/BasicUtils/Logger.cpp b/src/BasicUtils/Logger.cpp new file mode 100644 index 00000000..17bfd9b1 --- /dev/null +++ b/src/BasicUtils/Logger.cpp @@ -0,0 +1,86 @@ +#define _CRT_SECURE_NO_WARNINGS +#define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS + +#include "Logger.h" +#include "Console.h" +#include +#include + +#include +#include + +using namespace Console; + +namespace Logger +{ + std::wofstream file; + std::wstringstream buffer; + + void Init(std::wstring_view log_file, bool log_enable) + { + if (log_enable) + { + file.open(log_file.data(), std::ios::out | std::ios::trunc); + + std::locale utf8_locale("en_US.UTF-8"); + file.imbue(utf8_locale); + buffer.imbue(utf8_locale); + + if (!file.is_open()) { + Print({ Color::Red }, L"[{}] Failed to open log file.", L"ERROR"); + } + } + } + + void Flush() + { + if (file.is_open()) + { + file << buffer.str(); + buffer.str(L""); + file.flush(); + } + } + + void Close() + { + if (file.is_open()) + { + Flush(); + file.close(); + } + } + + std::wstring GetLevelInfo(LogLevel level) + { + switch (level) { + case LogLevel::Info: + return L"INFO"; + case LogLevel::Error: + return L"ERROR"; + default: + return L"UNKNOWN"; + } + } + + void Log(std::wstring_view message, LogLevel level) + { + auto level_str = GetLevelInfo(level); + +#ifndef NDEBUG + if (level == LogLevel::Error) { + Print({ Color::Red }, L"[{}] {}", level_str, message); + } +#endif + + if (file.is_open()) + { + auto now_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + std::wostringstream ss; + ss << std::put_time(std::localtime(&now_time), L"%Y-%m-%d %H:%M:%S"); + std::wstring time_str = ss.str(); + buffer << time_str << L" | " << level_str << L" | " << message << std::endl; + Flush(); + } + } +} \ No newline at end of file diff --git a/src/BasicUtils/Logger.h b/src/BasicUtils/Logger.h new file mode 100644 index 00000000..c4e6575b --- /dev/null +++ b/src/BasicUtils/Logger.h @@ -0,0 +1,14 @@ +#ifndef _LOGGER_H +#define _LOGGER_H + +#include + +namespace Logger +{ + enum class LogLevel { Info, Error }; + void Init(std::wstring_view file, bool enable); + void Close(); + void Log(std::wstring_view message, LogLevel level); +} + +#endif //_LOGGER_H \ No newline at end of file diff --git a/src/BasicUtils/Memory.h b/src/BasicUtils/Memory.h new file mode 100644 index 00000000..e788f5dc --- /dev/null +++ b/src/BasicUtils/Memory.h @@ -0,0 +1,85 @@ +#ifndef _MEMORY_H +#define _MEMORY_H + +#include +#include +#include +#include +#include "Console.h" +using namespace Console; + +namespace Memory { + template + bool Read(LPVOID address, T& buffer, std::size_t bufferSize = -1) + { + if (address == nullptr) + throw std::runtime_error("Invalid address"); + + if (bufferSize == static_cast(-1)) + bufferSize = sizeof(buffer); // error + + DWORD oldProtect = 0; + if (!VirtualProtect(address, bufferSize, PAGE_EXECUTE_READWRITE, &oldProtect)) + throw std::runtime_error("Failed to set memory protection for reading"); + + std::memcpy(static_cast(&buffer), address, bufferSize); + + if (!VirtualProtect(address, bufferSize, oldProtect, &oldProtect)) + throw std::runtime_error("Failed to restore memory protection after reading"); + return true; + } + + template + bool Write(LPVOID address, const T& buffer, std::size_t bufferSize = -1) + { + if (address == nullptr) + throw std::runtime_error("Invalid address"); + + const void* data = nullptr; + + if (bufferSize == static_cast(-1)) + { + if constexpr (std::is_integral_v) { + data = &buffer; + bufferSize = sizeof(buffer); + } + else if constexpr (std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v) { + data = buffer.data(); + bufferSize = buffer.size() * sizeof(typename T::value_type); + } + else if constexpr (std::is_same_v) + { + bufferSize = std::strlen(buffer); + data = buffer; + } + else if constexpr (std::is_same_v) { + bufferSize = std::wcslen(buffer); + data = buffer; + } + else if constexpr (std::is_same_v>) { + data = buffer.data(); + bufferSize = buffer.size() * sizeof(typename T::value_type); + } + else { + throw std::runtime_error("Unsupported type"); + } + } + else + { + data = &buffer; + } + + DWORD oldProtect = 0; + if (!VirtualProtect(address, bufferSize, PAGE_EXECUTE_READWRITE, &oldProtect)) + throw std::runtime_error("Failed to set memory protection for writing"); + + std::memcpy(address, data, bufferSize); + + if (!VirtualProtect(address, bufferSize, oldProtect, &oldProtect)) + throw std::runtime_error("Failed to restore memory protection after writing"); + + return true; + } +} + +#endif //_MEMORY_H diff --git a/src/BasicUtils/PatternScanner.cpp b/src/BasicUtils/PatternScanner.cpp new file mode 100644 index 00000000..a199f807 --- /dev/null +++ b/src/BasicUtils/PatternScanner.cpp @@ -0,0 +1,438 @@ +#include "PatternScanner.h" +#include "Memory.h" +#include "Console.h" +#include "Hooking.h" +#include "Utils.h" +#include +#include +#include +#include +#include + +using namespace Console; + +PatternScanner::ModuleInfo PatternScanner::GetModuleInfo(std::wstring_view module_name) +{ + const HMODULE module_handle = GetModuleHandleW(module_name.empty() ? nullptr : module_name.data()); + if (!module_handle) { + const auto error_code = GetLastError(); + throw std::runtime_error(Utils::ToString(Utils::FormatString(L"Could not get module handle for {}. Error code: {}", + module_name.empty() ? L"main module" : module_name, error_code)).c_str()); + } + MODULEINFO module_info; + if (!GetModuleInformation(GetCurrentProcess(), module_handle, &module_info, sizeof(module_info))) { + const auto error_code = GetLastError(); + throw std::runtime_error(Utils::ToString(Utils::FormatString(L"Could not get module information for {}. Error code: {}", + module_name.empty() ? L"main module" : module_name, error_code)).c_str()); + } + + return { reinterpret_cast(module_info.lpBaseOfDll), static_cast(module_info.SizeOfImage) }; +} + +Scan PatternScanner::GetFunctionAddress(std::wstring_view module_name, std::wstring_view function_name) +{ + HMODULE module_handle = GetModuleHandleW(module_name.data()); + if (!module_handle) { + module_handle = LoadLibraryW(module_name.data()); + if (!module_handle) { + throw std::runtime_error("Failed to load module"); + } + } + + FARPROC function_address = GetProcAddress(module_handle, Utils::ToString(function_name).c_str()); + if (!function_address) { + throw std::runtime_error("Failed to get function address"); + } + + MODULEINFO module_info; + if (!GetModuleInformation(GetCurrentProcess(), module_handle, &module_info, sizeof(module_info))) { + throw std::runtime_error("Failed to get module information"); + } + + return Scan(reinterpret_cast(function_address), { reinterpret_cast(module_info.lpBaseOfDll), static_cast(module_info.SizeOfImage) }); +} + +template +bool ScanMatchNumeric(const T& val, const T& first, const T& second, ScanType scan_type) { + if constexpr (std::is_same_v || std::is_same_v) { + switch (scan_type) { + case ScanType::Unknown: + return true; + case ScanType::Exact: + return val == first; + case ScanType::Contains: + return std::search(val.begin(), val.end(), first.begin(), first.end()) != val.end(); + default: + return false; + } + } + else { + switch (scan_type) { + case ScanType::Unknown: + return true; + case ScanType::Exact: + return val == first; + case ScanType::GreaterThan: + return val > first; + case ScanType::LessThan: + return val < first; + case ScanType::Between: + return val >= first && val <= second; + default: + return false; + } + } +} + +bool PatternScanner::ScanMatch(const void* value, ScanTargets targets, ValueType value_type, ScanType scan_type) +{ + switch (value_type) { + case ValueType::Byte: { + std::int8_t val(*reinterpret_cast(value)); + std::int8_t first(*reinterpret_cast(targets.first.data())); + std::int8_t second(targets.second.empty() ? 0 : *reinterpret_cast(targets.second.data())); + return ScanMatchNumeric(val, first, second, scan_type); + } + case ValueType::Int: { + std::int32_t val(*reinterpret_cast(value)); + std::int32_t first(*reinterpret_cast(targets.first.data())); + std::int32_t second(targets.second.empty() ? 0 : *reinterpret_cast(targets.second.data())); + return ScanMatchNumeric(val, first, second, scan_type); + } + case ValueType::Float: { + float val(*reinterpret_cast(value)); + float first(*reinterpret_cast(targets.first.data())); + float second(targets.second.empty() ? 0.0f : *reinterpret_cast(targets.second.data())); + return ScanMatchNumeric(val, first, second, scan_type); + } + case ValueType::Double: { + double val(*reinterpret_cast(value)); + double first(*reinterpret_cast(targets.first.data())); + double second(targets.second.empty() ? 0.0 : *reinterpret_cast(targets.second.data())); + return ScanMatchNumeric(val, first, second, scan_type); + } + case ValueType::String: { + std::string_view val(reinterpret_cast(value)); + std::string_view first(reinterpret_cast(targets.first.data()), targets.first.size()); + std::string_view second(targets.second.empty() ? "" : reinterpret_cast(targets.second.data()), targets.second.size()); + + //std::wstring_view val(reinterpret_cast(value)); + //std::wstring_view first(reinterpret_cast(targets.first.data()), targets.first.size()); + //std::wstring_view second(targets.second.empty() ? L"" : reinterpret_cast(targets.second.data()), targets.second.size()); + + return ScanMatchNumeric(val, first, second, scan_type); + } + default: + return false; + } +} + +std::vector PatternScanner::SignatureToByteArray(std::wstring_view signature) +{ + std::vector signature_bytes; + std::wstring word; + std::wistringstream iss(signature.data()); + + while (iss >> word) { + if ((word.size() == 1 && word[0] == L'?') || (word.size() == 2 && word[0] == L'?' && word[1] == L'?')) { + signature_bytes.push_back(0); + } + else if (word.size() == 2 && std::isxdigit(word[0]) && std::isxdigit(word[1])) { + unsigned long value = std::stoul(word, nullptr, 16); + if (value <= 255) { + uint8_t byte = static_cast(value); + signature_bytes.push_back(byte); + } + else { + throw std::invalid_argument("Value out of range"); + } + } + else { + for (wchar_t c : word) { + if (c >= 0 && c <= 255) { + signature_bytes.push_back(static_cast(c)); + } + else { + throw std::runtime_error("Value out of range"); + } + } + } + } + + return signature_bytes; +} + +//std::vector PatternScanner::SignatureToByteArray(std::wstring_view signature) +//{ +// std::vector signature_bytes; +// std::wstring word; +// std::wistringstream iss(signature.data()); +// +// while (iss >> word) { +// if ((word.size() == 1 && word[0] == L'?') || (word.size() == 2 && word[0] == L'?' && word[1] == L'?')) { +// signature_bytes.push_back(0); +// } +// else if (word.size() == 2 && std::isxdigit(word[0]) && std::isxdigit(word[1])) { +// unsigned long value = std::stoul(word, nullptr, 16); +// if (value <= 65535) { +// uint16_t byte = static_cast(value); +// signature_bytes.push_back(byte); +// } +// else { +// throw std::invalid_argument("Value out of range"); +// } +// } +// else { +// for (wchar_t c : word) { +// if (c >= 0 && c <= 65535) { +// signature_bytes.push_back(static_cast(c)); +// } +// else { +// throw std::runtime_error("Value out of range"); +// } +// } +// } +// } +// +// return signature_bytes; +//} + +std::vector PatternScanner::ScanAll(std::size_t base_address, std::size_t image_size, ScanTargets byte_pattern, ValueType value_type, ScanType scan_type, bool forward) +{ + if (!base_address) + throw std::invalid_argument(Utils::FormatString("Invalid base address ({})", value_type == ValueType::String ? std::string(byte_pattern.first.begin(), byte_pattern.first.end()) : Utils::ToHexString(byte_pattern.first.data(), byte_pattern.first.size()))); + + if (!image_size) + throw std::invalid_argument(Utils::FormatString("Invalid image size ({})", value_type == ValueType::String ? std::string(byte_pattern.first.begin(), byte_pattern.first.end()) : Utils::ToHexString(byte_pattern.first.data(), byte_pattern.first.size()))); + + if (byte_pattern.first.empty() || byte_pattern.first.size() > image_size) + throw std::invalid_argument(Utils::FormatString("Invalid pattern size ({})", value_type == ValueType::String ? std::string(byte_pattern.first.begin(), byte_pattern.first.end()) : Utils::ToHexString(byte_pattern.first.data(), byte_pattern.first.size()))); + + const auto pattern_size = byte_pattern.first.size(); + const auto end_address = base_address + image_size - pattern_size; + const auto first_byte = byte_pattern.first[0]; + std::vector addresses; + addresses.reserve(256); + + auto scan = [&](auto start, auto end, auto step) { + for (std::size_t address = start; address != end; address += step) { + if (reinterpret_cast(address)[0] != first_byte) { + continue; + } + + bool found = true; + for (size_t i = 1; i < pattern_size; ++i) { + if (byte_pattern.first[i] != 0 && byte_pattern.first[i] != reinterpret_cast(address)[i]) { + found = false; + break; + } + } + + if (found && ScanMatch(reinterpret_cast(address), byte_pattern, value_type, scan_type)) { + addresses.push_back(Scan(address, { base_address, image_size })); + } + } + }; + + if (forward) { + scan(base_address, end_address + 1, 1); + } + else { + scan(end_address + 1, base_address - 1, -1); + } + + return addresses; +} + +std::vector PatternScanner::ScanAll(std::size_t base_address, std::size_t image_size, std::wstring_view value, ScanType scan_type, bool forward) +{ + return ScanAll(base_address, image_size, { SignatureToByteArray(value) }, ValueType::String, scan_type, forward); +} + +std::vector PatternScanner::ScanAll(std::wstring_view value, std::wstring_view module_name, ScanType scan_type, bool forward) +{ + auto module = GetModuleInfo(module_name); + return ScanAll(module.base_address, module.image_size, value, scan_type, forward); +} + +Scan PatternScanner::ScanFirst(std::size_t base_address, std::size_t image_size, ScanTargets byte_pattern, ValueType value_type, ScanType scan_type, bool forward) +{ + if (!base_address) + throw std::invalid_argument(Utils::FormatString("Invalid base address ({})", value_type == ValueType::String ? std::string(byte_pattern.first.begin(), byte_pattern.first.end()) : Utils::ToHexString(byte_pattern.first.data(), byte_pattern.first.size()))); + + if (!image_size) + throw std::invalid_argument(Utils::FormatString("Invalid image size ({})", value_type == ValueType::String ? std::string(byte_pattern.first.begin(), byte_pattern.first.end()) : Utils::ToHexString(byte_pattern.first.data(), byte_pattern.first.size()))); + + if (byte_pattern.first.empty() || byte_pattern.first.size() > image_size) + throw std::invalid_argument(Utils::FormatString("Invalid pattern size ({})", value_type == ValueType::String ? std::string(byte_pattern.first.begin(), byte_pattern.first.end()) : Utils::ToHexString(byte_pattern.first.data(), byte_pattern.first.size()))); + + const auto pattern_size = byte_pattern.first.size(); + const auto end_address = base_address + image_size - pattern_size; + const auto first_byte = byte_pattern.first[0]; + + auto scan = [&](auto start, auto end, auto step) { + for (std::size_t address = start; address != end; address += step) { + if (reinterpret_cast(address)[0] != first_byte) { + continue; + } + + bool found = true; + for (size_t i = 1; i < pattern_size; ++i) { + if (byte_pattern.first[i] != 0 && byte_pattern.first[i] != reinterpret_cast(address)[i]) { + found = false; + break; + } + } + + if (found && ScanMatch(reinterpret_cast(address), byte_pattern, value_type, scan_type)) { + return Scan(address, { base_address, image_size }); + } + } + return Scan(NULL, { base_address, image_size }); + }; + + if (forward) { + return scan(base_address, end_address + 1, 1); + } + else { + return scan(end_address + 1, base_address - 1, -1); + } +} + +Scan PatternScanner::ScanFirst(std::size_t base_address, std::size_t image_size, std::wstring_view value, ScanType scan_type, bool forward) +{ + return ScanFirst(base_address, image_size, { SignatureToByteArray(value) }, ValueType::String, scan_type, forward); +} + +Scan PatternScanner::ScanFirst(std::wstring_view value, std::wstring_view module_name, ScanType scan_type, bool forward) +{ + auto module = GetModuleInfo(module_name); + return ScanFirst(module.base_address, module.image_size, value, scan_type, forward); +} + +Scan::Scan(std::uintptr_t address, std::pair module_info) : m_address(address), m_module_info(module_info)/*, m_value(reinterpret_cast(address))*/ +{ + //... +} + +Scan::operator std::uintptr_t() const +{ + return m_address; +} + +void Scan::print_address(std::wstring_view name) const +{ + Print({ Color::Yellow , Color::Cyan }, L"{:X} {}", m_address, !name.empty() ? L" : " + std::wstring(name.data()) : L""); +} + +bool Scan::is_found() const +{ + return m_address != NULL; +} + +std::uint8_t* Scan::data() const +{ + return reinterpret_cast(m_address); +} + +Scan Scan::rva() const +{ + return is_found() ? Scan(m_address - m_module_info.first, m_module_info) : Scan(NULL, m_module_info); +} + +Scan Scan::offset(std::size_t value) const +{ + if (is_found()) { + if (value > 0) { + return Scan(m_address + value, m_module_info); + } + else { + return Scan(m_address - value, m_module_info); + } + } + else { + return Scan(NULL, m_module_info); + } +} + +Scan Scan::disassemble() const +{ + uint8_t opcode = *(uint8_t*)m_address; + + struct Instruction { + std::wstring_view mnemonic; + std::uintptr_t operand_value; + } _Instruction{}; + + switch (opcode) { + case 0x68: + _Instruction = { L"PUSH", *(uint32_t*)(m_address + 1) }; break; + case 0x8B: + _Instruction = { L"MOV", *(uint32_t*)(m_address + 2) }; break; + case 0xB8: + _Instruction = { L"MOV", *(uint32_t*)(m_address + 1) }; break; + case 0xC7: + _Instruction = { L"MOV", *(uint32_t*)(m_address + 2) }; break; + case 0xE8: + _Instruction = { L"CALL", *(uint32_t*)(m_address + 1) + m_address + 5 }; break; + case 0x74: + _Instruction = { L"JE", m_address + 2 + *(int8_t*)(m_address + 1) }; break; + case 0x75: + _Instruction = { L"JNE", m_address + 2 + *(int8_t*)(m_address + 1) }; break; + case 0x3B: + _Instruction = { L"CMP", *(uint32_t*)(m_address + 2) }; break; + case 0xEB: + _Instruction = { L"JMP", m_address + 2 + *(int8_t*)(m_address + 1) }; break; + case 0xE9: + _Instruction = { L"JMP", *(uint32_t*)(m_address + 1) + m_address + 5 }; break; + case 0x7F: + _Instruction = { L"JG", m_address + 6 + *(int32_t*)(m_address + 2) }; break; + case 0x7D: + _Instruction = { L"JGE", m_address + 6 + *(int32_t*)(m_address + 2) }; break; + case 0x7C: + _Instruction = { L"JL", m_address + 6 + *(int32_t*)(m_address + 2) }; break; + case 0x7E: + _Instruction = { L"JLE", m_address + 6 + *(int32_t*)(m_address + 2) }; break; + case 0x7A: + _Instruction = { L"JP", m_address + 6 + *(int32_t*)(m_address + 2) }; break; + case 0x7B: + _Instruction = { L"JNP", m_address + 6 + *(int32_t*)(m_address + 2) }; break; + case 0x83: + _Instruction = { L"ADD", (uint8_t)(m_address + 1) }; break; + case 0x81: + _Instruction = { L"ADD", (uint32_t)(m_address + 2) }; break; + default: + throw std::runtime_error(Utils::FormatString("Unknown opcode encountered: {:X}", opcode)); + } + + //Print(L"{:X} | {} {:X}", m_address, _Instruction.mnemonic, _Instruction.operand_value); + return Scan(_Instruction.operand_value, m_module_info); +} + +bool Scan::hook(PVOID pDetours) const +{ + return is_found() ? Hooking::HookFunction(&(PVOID&)m_address, pDetours) : false; +} + +bool Scan::unhook() const +{ + return is_found() ? Hooking::UnhookFunction(&(PVOID&)m_address) : false; +} + +std::vector Scan::get_all_matching_codes(AssemblyCode code, std::size_t base_address, std::size_t image_size) const +{ + std::vector pattern = { static_cast(code) }; + auto offset = pattern.size(); + pattern.resize(pattern.size() + sizeof(m_address)); + *reinterpret_cast(pattern.data() + offset) = m_address; + return PatternScanner::ScanAll(base_address == 0 ? m_module_info.first : base_address, image_size == 0 ? m_module_info.second : image_size, Utils::ToHexWideString(pattern, pattern.size()), ScanType::Unknown, true); +} + +Scan Scan::get_first_matching_code(AssemblyCode code, std::size_t base_address, std::size_t image_size) const +{ + std::vector pattern = { static_cast(code) }; + auto offset = pattern.size(); + pattern.resize(pattern.size() + sizeof(m_address)); + *reinterpret_cast(pattern.data() + offset) = m_address; + return PatternScanner::ScanFirst(base_address == 0 ? m_module_info.first : base_address, image_size == 0 ? m_module_info.second : image_size, Utils::ToHexWideString(pattern, pattern.size()), ScanType::Unknown, true); +} \ No newline at end of file diff --git a/src/BasicUtils/PatternScanner.h b/src/BasicUtils/PatternScanner.h new file mode 100644 index 00000000..e63390a6 --- /dev/null +++ b/src/BasicUtils/PatternScanner.h @@ -0,0 +1,119 @@ +#ifndef _PATTERNSCANNER_H +#define _PATTERNSCANNER_H + +#include +#include +#include +#include +#include + +enum class AssemblyCode { + PUSH_VALUE = 0x68, + JUMP_IF_EQUAL = 0x74, + JUMP_IF_NOT_EQUAL = 0x75, + JUMP_RELATIVE_SHORT = 0xEB, + JUMP_RELATIVE_LONG = 0xE9, + CALL_RELATIVE = 0xE8 +}; + +enum class ScanType { + Unknown, // The scan type is unknown + Exact, // The value must be exactly equal to the target value + GreaterThan,// The value must be greater than the target value + LessThan, // The value must be less than the target value + Between, // The value must be between two target values + Contains // The value must contain the target value (only for string types) +}; + +enum class ValueType { + Byte, + Int, + Float, + Double, + String, +}; + +class Scan { +public: + Scan() = default; + explicit Scan(std::uintptr_t address, std::pair module_info); + operator std::uintptr_t() const; + + void print_address(std::wstring_view name = {}) const; + + bool is_found() const; + std::uint8_t* data() const; + Scan rva() const; + Scan offset(std::size_t value) const; + Scan disassemble() const; + + bool hook(PVOID p_detours) const; + bool unhook() const; + + std::vector get_all_matching_codes(AssemblyCode code, std::size_t base_address = 0, std::size_t image_size = 0) const; + Scan get_first_matching_code(AssemblyCode code, std::size_t base_address = 0, std::size_t image_size = 0) const; + + template + T read() const { + if constexpr (std::is_pointer_v) + return reinterpret_cast(m_address); + else if constexpr (std::is_same_v || std::is_same_v) + return T(reinterpret_cast(m_address)); + else + return *reinterpret_cast(m_address); + } + + template + bool write(const T& value) const { + if constexpr (std::is_pointer_v || std::is_same_v || std::is_same_v) + return ::WriteProcessMemory(::GetCurrentProcess(), reinterpret_cast(m_address), value, (std::char_traits::length(reinterpret_cast(value)) + 1) * sizeof(wchar_t), nullptr) != 0; + else + return ::WriteProcessMemory(::GetCurrentProcess(), reinterpret_cast(m_address), std::addressof(value), sizeof(value), nullptr) != 0; + } + +private: + std::uintptr_t m_address; + std::pair m_module_info; + //const void* m_value; +}; + +class PatternScanner { +protected: + struct ScanTargets { + std::span first; + std::span second; + //std::span first; + //std::span second; + }; + + static bool ScanMatch(const void* value, ScanTargets targets, ValueType value_type, ScanType scan_type); +public: + struct ModuleInfo { + std::size_t base_address; + std::size_t image_size; + }; + + static ModuleInfo GetModuleInfo(std::wstring_view module_name = {}); + static Scan GetFunctionAddress(std::wstring_view module_name, std::wstring_view function_name); + + static std::vector SignatureToByteArray(std::wstring_view signature); + //static std::vector SignatureToByteArray(std::wstring_view signature); + static std::vector ScanAll(std::size_t base_address, std::size_t image_size, ScanTargets byte_pattern, ValueType value_type, ScanType scan_type, bool forward); + static std::vector ScanAll(std::size_t base_address, std::size_t image_size, std::wstring_view value, ScanType scan_type = ScanType::Unknown, bool forward = true); + static std::vector ScanAll(std::wstring_view value, std::wstring_view module_name = {}, ScanType scan_type = ScanType::Unknown, bool forward = true); + + static Scan ScanFirst(std::size_t base_address, std::size_t image_size, ScanTargets byte_pattern, ValueType value_type, ScanType scan_type, bool forward); + static Scan ScanFirst(std::size_t base_address, std::size_t image_size, std::wstring_view value, ScanType scan_type = ScanType::Unknown, bool forward = true); + static Scan ScanFirst(std::wstring_view value, std::wstring_view module_name = {}, ScanType scan_type = ScanType::Unknown, bool forward = true); +}; + +namespace std { + template<> + struct formatter : formatter { + auto format(const Scan& scan, format_context& ctx) { + return formatter::format(scan, ctx); + } + }; +} + +#endif // _PATTERNSCANNER_H \ No newline at end of file diff --git a/src/BasicUtils/Utils.cpp b/src/BasicUtils/Utils.cpp new file mode 100644 index 00000000..e5a1b679 --- /dev/null +++ b/src/BasicUtils/Utils.cpp @@ -0,0 +1,276 @@ +#define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-variable" +#endif + +#include "Utils.h" +#include "Console.h" +#include +#include +#include +#include + +using namespace Console; + +namespace Utils +{ + std::wstring ToHexWideString(const std::vector& byte_array, const bool insert_spaces) + { + std::wostringstream oss; + oss << std::hex << std::setfill(L'0'); + + for (size_t i = 0; i < byte_array.size(); ++i) + { + if (i > 0 && insert_spaces) + { + oss << L' '; + } + oss << std::setw(2) << static_cast(byte_array[i]); + } + + std::wstring hex_string = oss.str(); + std::transform(hex_string.begin(), hex_string.end(), hex_string.begin(), ::towupper); + + return hex_string; + } + + std::string ToHexString(const std::vector& byte_array, const bool insert_spaces) + { + std::ostringstream oss; + oss << std::hex << std::setfill('0'); + + for (size_t i = 0; i < byte_array.size(); ++i) + { + if (i > 0 && insert_spaces) + { + oss << ' '; + } + oss << std::setw(2) << static_cast(byte_array[i]); + } + + std::string hex_string = oss.str(); + std::transform(hex_string.begin(), hex_string.end(), hex_string.begin(), ::toupper); + + return hex_string; + } + + std::string ToHexString(const uint8_t* data, size_t size, const bool insert_spaces) + { + if (data == nullptr) + throw std::invalid_argument("The data pointer is null."); + + if (size == 0) + size = std::strlen(reinterpret_cast(data)); + + return ToHexString(std::vector(data, data + size), insert_spaces); + } + + std::wstring ToHexWideString(const uint8_t* data, size_t size, const bool insert_spaces) + { + if (data == nullptr) + throw std::invalid_argument("The data pointer is null."); + + if (size == 0) + size = std::wcslen(reinterpret_cast(data)); + + return ToHexWideString(std::vector(data, data + size), insert_spaces); + } + + std::string ConvertUInt8ArrayToString(std::uint8_t* data) + { + return std::string(reinterpret_cast(data), reinterpret_cast(data + std::strlen(reinterpret_cast(data)))); + } + + std::wstring ConvertUInt8ArrayToWideString(std::uint8_t* data) + { + return std::wstring(reinterpret_cast(data), reinterpret_cast(data + std::wcslen(reinterpret_cast(data)))); + } + + std::string ToString(std::wstring_view wide_string) + { + std::wstring_convert> converter; + return converter.to_bytes(wide_string.data(), wide_string.data() + wide_string.size()); + } + + std::wstring ToString(std::string_view narrow_string) + { + std::wstring_convert> converter; + return converter.from_bytes(narrow_string.data(), narrow_string.data() + narrow_string.size()); + } + + bool Contains(std::string_view str1, std::string_view str2, bool case_sensitive) + { + auto it = std::search( + str1.begin(), str1.end(), + str2.begin(), str2.end(), + [case_sensitive](char ch1, char ch2) { + return case_sensitive ? ch1 == ch2 : std::toupper(ch1) == std::toupper(ch2); + } + ); + return (it != str1.end()); + } + + bool Contains(std::wstring_view str1, std::wstring_view str2, bool case_sensitive) + { + auto it = std::search( + str1.begin(), str1.end(), + str2.begin(), str2.end(), + [case_sensitive](wchar_t ch1, wchar_t ch2) { + return case_sensitive ? ch1 == ch2 : std::toupper(ch1) == std::toupper(ch2); + } + ); + return (it != str1.end()); + } + + bool Equals(std::string_view str1, std::string_view str2, bool case_sensitive) + { + return std::equal(str1.begin(), str1.end(), str2.begin(), str2.end(), + [case_sensitive](char ch1, char ch2) { + return case_sensitive ? ch1 == ch2 : std::toupper(ch1) == std::toupper(ch2); + }); + } + + bool Equals(std::wstring_view str1, std::wstring_view str2, bool case_sensitive) + { + return std::equal(str1.begin(), str1.end(), str2.begin(), str2.end(), + [case_sensitive](wchar_t ch1, wchar_t ch2) { + return case_sensitive ? ch1 == ch2 : std::toupper(ch1) == std::toupper(ch2); + }); + } + + void MeasureExecutionTime(std::function func, std::wstring_view name) + { + const auto start_time = std::chrono::high_resolution_clock::now(); + func(); + const auto end_time = std::chrono::high_resolution_clock::now(); + const auto duration = std::chrono::duration_cast(end_time - start_time).count(); + + CONSOLE_SCREEN_BUFFER_INFO info; + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info); + Print({ Color::White, Color::White, Color::Yellow, Color::White }, L"{}{}{}{}Execution time: {:d}ms\n", info.dwCursorPosition.Y != 0 ? L"\n" : L"", + !name.empty() ? L"[" : L"", + !name.empty() ? FormatString(L"{}", name).c_str() : L"", + !name.empty() ? L"] " : L"", duration); + } + + IniData ReadIniFile(const std::wstring& fileName) + { + IniData data; + std::wstring currentSection; + + std::wifstream file(fileName); + + if (!file) { + throw std::runtime_error("Failed to open ini file."); + } + + for (std::wstring line; getline(file, line);) { + if (line.empty() || line[0] == ';') { + continue; + } + + if (line[0] == '[' && line.back() == ']') { + currentSection = line.substr(1, line.size() - 2); + data[currentSection] = {}; + } + else { + size_t pos = line.find('='); + if (pos == std::wstring::npos) { + continue; + } + + std::wstring key = line.substr(0, pos); + std::wstring valueStr = line.substr(pos + 1); + + if (key.empty() || valueStr.empty()) { + continue; + } + + bool value = (valueStr == L"true" || valueStr == L"1"); + + data[currentSection][key] = value; + } + } + + return data; + } + + void AppendIniFile(const std::wstring& fileName, IniData& data) + { + IniData existingData; + + if (std::wifstream existingFile(fileName); existingFile) { + existingData = ReadIniFile(fileName); + } + + // Remove any key-value pairs from existingData that are not present in data + for (auto& [sectionName, sectionData] : existingData) { + for (auto it = sectionData.begin(); it != sectionData.end();) { + const auto& [key, value] = *it; + if (data[sectionName].find(key) == data[sectionName].end()) { + it = sectionData.erase(it); + } + else { + ++it; + } + } + } + + std::wofstream file(fileName); + + if (!file.is_open()) { + throw std::runtime_error("Failed to open ini file."); + } + + for (const auto& [sectionName, sectionData] : existingData) { + file << L"[" << sectionName << L"]" << '\n'; + + for (const auto& [key, value] : sectionData) { + file << key << L"=" << (value ? L"1" : L"0") << '\n'; + data[sectionName][key] = value; + } + } + + for (const auto& [sectionName, sectionData] : data) { + if (existingData.find(sectionName) == existingData.end()) { + file << L"[" << sectionName << L"]" << '\n'; + } + + for (const auto& [key, value] : sectionData) { + if (existingData[sectionName].find(key) == existingData[sectionName].end()) { + file << key << L"=" << (value ? L"1" : L"0") << '\n'; + } + } + } + } + +#ifndef NDEBUG + void PrintSymbols(std::wstring_view module_name) + { + HMODULE hModule = GetModuleHandleW(module_name.data()); + if (!hModule && !(hModule = LoadLibraryW(module_name.data()))) + throw std::runtime_error("Failed to load module."); + + PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule; + PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((BYTE*)dosHeader + dosHeader->e_lfanew); + PIMAGE_EXPORT_DIRECTORY exportDirectory = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)dosHeader + ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); + PDWORD functions = (PDWORD)((BYTE*)dosHeader + exportDirectory->AddressOfFunctions); + PDWORD names = (PDWORD)((BYTE*)dosHeader + exportDirectory->AddressOfNames); + PWORD ordinals = (PWORD)((BYTE*)dosHeader + exportDirectory->AddressOfNameOrdinals); + + for (DWORD i = 0; i < exportDirectory->NumberOfNames; i++) { + Print(L"{}", reinterpret_cast((BYTE*)dosHeader + names[i])); + } + } +#endif + + void SetLocaleToUTF8() + { +#if defined(_DEBUG) || defined(_CONSOLE) + SetConsoleOutputCP(CP_UTF8); + SetConsoleCP(CP_UTF8); +#endif + std::locale::global(std::locale("en_US.UTF-8")); + } +} \ No newline at end of file diff --git a/src/BasicUtils/Utils.h b/src/BasicUtils/Utils.h new file mode 100644 index 00000000..2273f011 --- /dev/null +++ b/src/BasicUtils/Utils.h @@ -0,0 +1,82 @@ +#ifndef _UTILS_H +#define _UTILS_H + +#include +#include +#include + +namespace Utils +{ + std::string ToHexString(const std::vector& byte_array, const bool insert_spaces = true); + std::wstring ToHexWideString(const std::vector& byte_array, const bool insert_spaces = true); + + std::string ToHexString(const uint8_t* data, size_t size, const bool insert_spaces = true); + std::wstring ToHexWideString(const uint8_t* data, size_t size, const bool insert_spaces = true); + + std::string ConvertUInt8ArrayToString(std::uint8_t* data); + std::wstring ConvertUInt8ArrayToWideString(std::uint8_t* data); + + std::string ToString(std::wstring_view wide_string); + std::wstring ToString(std::string_view narrow_string); + + bool Contains(std::string_view str1, std::string_view str2, bool case_sensitive = false); + bool Contains(std::wstring_view str1, std::wstring_view str2, bool case_sensitive = false); + + bool Equals(std::string_view str1, std::string_view str2, bool case_sensitive = false); + bool Equals(std::wstring_view str1, std::wstring_view str2, bool case_sensitive = false); + + //Example 1: MeasureExecutionTime(std::bind(Function, arg1, arg2), name); + //Example 2: MeasureExecutionTime([&]() { Function(arg1, arg2); }, name); + void MeasureExecutionTime(std::function func, std::wstring_view name = {}); + using IniData = std::map>; + IniData ReadIniFile(const std::wstring& fileName); + void AppendIniFile(const std::wstring& fileName, IniData& data); + +#ifndef NDEBUG + void PrintSymbols(std::wstring_view module_name); +#endif + + void SetLocaleToUTF8(); + + template + std::vector ToBytes(const T& val) + { + struct is_string_type : std::disjunction, std::is_same, std::is_same, std::is_same> {}; + if constexpr (is_string_type::value) + { + std::wstring_view str_view(val); + return std::vector(str_view.begin(), str_view.end()); + } + else if constexpr (std::is_trivially_copyable_v) { + auto bytes = std::bit_cast>(val); + return { bytes.begin(), bytes.end() }; + } + else { + throw std::runtime_error("Invalid type for ToBytes function"); + } + } + + template + std::wstring FormatString(std::wstring_view fmt, const Args&... args) + { + try { + return std::vformat(fmt, std::make_wformat_args(args...)); + } + catch (const std::exception& e) { + throw std::runtime_error("Failed to format string: " + std::string(e.what())); + } + } + + template + std::string FormatString(std::string_view fmt, const Args&... args) + { + try { + return std::vformat(fmt, std::make_format_args(args...)); + } + catch (const std::exception& e) { + throw std::runtime_error("Failed to format string: " + std::string(e.what())); + } + } +}; + +#endif // _UTILS_H \ No newline at end of file diff --git a/src/BlockTheSpot.cpp b/src/BlockTheSpot.cpp index 3de879b0..767dfa3e 100644 --- a/src/BlockTheSpot.cpp +++ b/src/BlockTheSpot.cpp @@ -1,27 +1,33 @@ -// BlockTheSpot.cpp : Defines the exported functions for the DLL application. -// +#include "pch.h" -#include "stdafx.h" -#include - -void __stdcall LoadAPI (LPVOID* destination, const char* apiName) +void __stdcall LoadAPI(LPVOID* destination, const char* apiName) { - if (*destination) - return; - - static constexpr auto path{ L"dpapi.dll" }; - static std::map function_map; - static HMODULE hModule = GetModuleHandle (path); - if (!hModule) - hModule = LoadLibrary(path); - if (!hModule) - return; - if (function_map[apiName] == nullptr) { - function_map[apiName] = GetProcAddress (hModule, apiName); - } - *destination = function_map[apiName]; + if (*destination) + return; + + static std::wstring_view path{ L"dpapi.dll" }; + static HMODULE hModule = GetModuleHandleW(path.data()); + static std::map function_map; + if (!hModule && !(hModule = LoadLibraryW(path.data()))) + return; + if (function_map[apiName] == nullptr) { + function_map[apiName] = GetProcAddress(hModule, apiName); + } + *destination = reinterpret_cast(function_map[apiName]); } +#ifdef _WIN64 +typedef void(__stdcall* FunctionType)(); + +#define API_EXPORT_ORIG(N) \ + static LPVOID _##N = nullptr; \ + extern "C" __declspec(dllexport) void N() \ + { \ + LoadAPI(&_##N, #N); \ + FunctionType func = reinterpret_cast(_##N); \ + func(); \ + } +#else #define API_EXPORT_ORIG(N) \ static LPVOID _##N = NULL; \ char S_##N[] = "" # N; \ @@ -33,7 +39,8 @@ void __stdcall LoadAPI (LPVOID* destination, const char* apiName) __asm call LoadAPI \ __asm popad \ __asm jmp [_##N] \ - } \ + } +#endif API_EXPORT_ORIG(CryptProtectData) API_EXPORT_ORIG(CryptProtectMemory) @@ -70,7 +77,6 @@ API_EXPORT_ORIG(CryptUpdateProtectedState) #define API_COPY(M, N) \ _##N = GetProcAddress(M, #N); - /* //bool AddDllToBlacklist (const wchar_t* dll_name) { return true; } void ClearReportsBetween_ExportThunk (time_t begin, time_t end) {} diff --git a/src/BlockTheSpot.vcxproj b/src/BlockTheSpot.vcxproj index fc145f22..e4b2821c 100644 --- a/src/BlockTheSpot.vcxproj +++ b/src/BlockTheSpot.vcxproj @@ -1,137 +1,121 @@ - - + + - + Debug - Win32 + x64 - + Release - Win32 + x64 - {82F7E20E-D166-4474-8EB1-81160355B5B2} + 16.0 Win32Proj - SpotifyAdBlock + {dcc156a5-5810-4c3b-b95d-a168ceaa3629} + BlockTheSpot 10.0 - BlockTheSpot - + DynamicLibrary + true v143 Unicode - + DynamicLibrary + false v143 true Unicode + - - + - + - - false + dpapi - $(ProjectDir)..\ - + dpapi - $(ProjectDir)..\ - false - + - Disabled - WIN32;_DEBUG;_WINDOWS;_USRDLL;BLOCKTHESPOT_EXPORTS;%(PreprocessorDefinitions) + Level3 + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) stdcpp20 - ./cef_binary_109.1.13+g18f6895+chromium-109.0.5414.87_windows32_minimal - MultiThreadedDebugDLL - Sync - false + false - dpapi.def - ./cef_binary_109.1.13+g18f6895+chromium-109.0.5414.87_windows32_minimal/release - libcef.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) - false + Console + true - + - MaxSpeed + Level3 true - WIN32;NDEBUG;_WINDOWS;_USRDLL;BLOCKTHESPOT_EXPORTS;%(PreprocessorDefinitions) - MultiThreadedDLL - Speed - AnySuitable - Sync - true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) stdcpp20 - - - false + false + Console true true - dpapi.def - UseFastLinkTimeCodeGeneration - false - false - ./cef_binary_109.1.13+g18f6895+chromium-109.0.5414.87_windows32_minimal/release - $(CoreLibraryDependencies);%(AdditionalDependencies) - Windows + true - - - - - - - + + + + + + + + - - + - - CompileAsC - - - CompileAsC - - - CompileAsC - - - false - - - false - - - + + + + + - + + - - + + + + + + - + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + \ No newline at end of file diff --git a/src/BlockTheSpot.vcxproj.filters b/src/BlockTheSpot.vcxproj.filters index 13a09645..c1af70d5 100644 --- a/src/BlockTheSpot.vcxproj.filters +++ b/src/BlockTheSpot.vcxproj.filters @@ -1,56 +1,95 @@  - - - - - - disasm-lib - - - disasm-lib - - - disasm-lib - - - mhook-lib - + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {425b6aec-2197-4fab-b550-dc107e983f17} + - - - - - - disasm-lib + + Header Files + + + Header Files + + + Header Files - - disasm-lib + + Header Files - - disasm-lib + + BasicUtils - - disasm-lib + + BasicUtils - - disasm-lib + + BasicUtils - - mhook-lib + + BasicUtils + + + BasicUtils + + + BasicUtils - + + Source Files + + + Source Files + + + Source Files + + + BasicUtils + + + BasicUtils + + + BasicUtils + + + BasicUtils + + + BasicUtils + + + Source Files + - - {3162897c-8c49-439a-bea3-bd980758f058} - - - {3fe47c7b-0eca-4f27-b472-57049590c4de} - + + Source Files + + + + + Source Files + + + Source Files + + \ No newline at end of file diff --git a/src/BlockTheSpot.vcxproj.user b/src/BlockTheSpot.vcxproj.user index 5df420f5..88a55094 100644 --- a/src/BlockTheSpot.vcxproj.user +++ b/src/BlockTheSpot.vcxproj.user @@ -1,6 +1,4 @@  - - false - + \ No newline at end of file diff --git a/src/Debug.cpp b/src/Debug.cpp new file mode 100644 index 00000000..84b8b90d --- /dev/null +++ b/src/Debug.cpp @@ -0,0 +1,57 @@ +#include "pch.h" + +#ifndef NDEBUG + +void print_test() { + // Example colors vector + std::vector colors = { Color::Red, Color::Green, Color::Blue }; + + // Example 6: Uppercase hexadecimal formatting + int hex_value = 255; + Print(colors, L"The uppercase hexadecimal value is {:X}.", hex_value); + // Output: The uppercase hexadecimal value is FF. + + // Example 7: Hexadecimal formatting with "0x" prefix + int hex_value_with_prefix = 123; + Print(colors, L"The hexadecimal value with prefix is {:#x}.", hex_value_with_prefix); + // Output: The hexadecimal value with prefix is 0x7b. + + // Example 8: Multiple arguments with different format specifiers + double temperature = 23.5; + int year = 2023; + std::wstring location = L"New York"; + Print(colors, L"Date: {}, Temperature: {:.1f} °C, Year: {:d}, Location: {}.", L"July 22", temperature, year, location); + // Output: Date: July 22, Temperature: 23.5 °C, Year: 2023, Location: New York. + + // Example 9: Handling missing arguments + Print(colors, L"{} + {} = {}.", 2, 3); + // Output: 2 + 3 = {}. + + // Example 10: Using the same argument multiple times + int value = 7; + Print(colors, L"{} * {} = {} and {} + {} = {}.", value, 3, value * 3, value, 5, value + 5); + // Output: 7 * 3 = 21 and 7 + 5 = 12. + + // Example 11: Using non-default colors + std::vector custom_colors = { Color::Yellow, Color::Magenta }; + Print(custom_colors, L"Custom colors: {} and {}.", L"Yellow", L"Magenta"); + // Output: Custom colors: Yellow and Magenta. +} + +DWORD WINAPI Debug(LPVOID lpParam) +{ + try + { + Utils::MeasureExecutionTime([&]() { + //Utils::PrintSymbols(L"chrome_elf.dll"); + //print_test(); + + }, L"DEBUG"); + } + catch (const std::exception& e) + { + std::cerr << e.what() << std::endl; + } + return 0; +} +#endif \ No newline at end of file diff --git a/src/Debug.h b/src/Debug.h new file mode 100644 index 00000000..83c3f287 --- /dev/null +++ b/src/Debug.h @@ -0,0 +1,4 @@ +#pragma once +#ifndef NDEBUG +DWORD WINAPI Debug(LPVOID lpParam); +#endif diff --git a/src/Logger.h b/src/Logger.h deleted file mode 100644 index 004e994c..00000000 --- a/src/Logger.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once -#include "stdafx.h" - -class Logger { -private: - static const auto& current_datetime () - { - static struct tm newtime; - static __time64_t long_time; - _time64 (&long_time); - localtime_s (&newtime, &long_time); - return newtime; - } - - std::wofstream log_wstream; - -public: - - const bool read(std::wstring_view app, std::wstring_view key, const int def_value = 0) { - if (1 == GetPrivateProfileInt(app.data(), key.data(), def_value, L"./config.ini")) { - return true; - } - return false; - } - - Logger () { - if (true == read (L"Config", L"Log")) { - log_wstream.open (L"blockthespot_log.txt", std::ios::out | std::ios::app); - //m_log << "BlockTheSpot - Build date: " << __TIMESTAMP__ << std::endl; - } - } - - ~Logger () { - if (true == log_wstream.is_open()) { - log_wstream.flush (); - log_wstream.close (); - } - } - - void Log (std::wstring_view log) { - if (true == log_wstream.is_open ()) { - std::wstringstream message; - const auto& time = current_datetime(); - message << L"LOG | " << std::put_time(&time, L"%d-%b-%Y %H:%M:%S") << L" - " << log; - log_wstream << message.str() << std::endl; - } - - } - - -}; diff --git a/src/Modify.cpp b/src/Modify.cpp index 3f6dac79..2873a673 100644 --- a/src/Modify.cpp +++ b/src/Modify.cpp @@ -1,54 +1,39 @@ +#include "pch.h" -#include "Modify.h" -#include "Logger.h" -#include -#ifndef NDEBUG -#include -#endif /* -* +* * Black banner still show even libcef hooked. -* +* */ -static Logger g_Logger; //using _cef_urlrequest_create = cef_urlrequest_t * (*)(struct _cef_request_t* request, // struct _cef_urlrequest_client_t* client, // struct _cef_request_context_t* request_context); -using _cef_urlrequest_create = void* (*)(void* request, - void* client, - void* request_context); - -using _cef_string_userfree_utf16_free = void* (*)(/*void* str*/void* addr); - - +using _cef_urlrequest_create = void* (*)(void* request, void* client, void* request_context); static _cef_urlrequest_create cef_urlrequest_create_orig; +using _cef_string_userfree_utf16_free = void * (*)(/*void* str*/void* addr); static _cef_string_userfree_utf16_free cef_string_userfree_utf16_free_orig; -static constexpr auto block_list = { L"/ads/", L"/ad-logic/", L"/gabo-receiver-service/" }; -static constexpr auto localhost_str = "localhost"; -static constexpr auto sp_localhost_str = "sp://localhost//"; -static constexpr auto premium_free_str = "\"premium\"===e.session?.productState?.catalogue?.toLowerCase(),s=e=>null!==e.session?.productState&&1===parseInt(e.session?.productState?.ads,10),r=e=>\"free\""; -//static constexpr char search_str[] = {0x61,0x70,0x70,0x2D,0x64,0x65,0x76,0x65,0x6C,0x6F,0x70,0x65,0x72,0x09,0x01,0x30,0x78}; -static constexpr auto sponsorship_str = ".set(\"allSponsorships\",t.sponsorships)}}(e,t);"; -static constexpr auto hpto_str = ".WiPggcPDzbwGxoxwLWFf{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-ms-flexbox;display:none;"; +static constexpr std::array block_list = { L"/ads/", L"/ad-logic/", L"/gabo-receiver-service/" }; +//static DWORD ret_addr = 0; +PatternScanner::ModuleInfo ZipScan; -static bool xpui_found = false; -static bool hptocss_found = false; -static DWORD ret_addr = 0; -static DWORD buff_addr = 0; -static DWORD buff_size = 0; - +#ifdef _WIN64 +static std::wstring file_name; +std::uint64_t file_name_rcx = 0; +std::uint64_t ret_addr_file_name = 0; +std::uint64_t ret_addr_file_source = 0; +#else DWORD WINAPI get_url(DWORD pRequest) { - DWORD retval; + DWORD retval = 0; __asm { mov eax, pRequest - mov ecx, dword ptr ds : [eax + 0x18] + mov ecx, dword ptr ds:[eax+0x18] mov edx, eax push edx call ecx @@ -57,10 +42,9 @@ DWORD WINAPI get_url(DWORD pRequest) return retval; } - DWORD WINAPI get_str(DWORD pRequest) { - DWORD retval; + DWORD retval = 0; __asm { // get url str @@ -70,240 +54,347 @@ DWORD WINAPI get_str(DWORD pRequest) } return retval; } +#endif + #ifndef NDEBUG -void* cef_urlrequest_create_hook(struct _cef_request_t* request, void* client, void* request_context) +void* cef_urlrequest_create_hook (struct _cef_request_t* request, void* client, void* request_context) #else void* cef_urlrequest_create_hook(void* request, void* client, void* request_context) #endif { #ifndef NDEBUG - cef_string_utf16_t* url_utf16 = request->get_url(request); + cef_string_utf16_t* url_utf16 = request->get_url (request); std::wstring url(url_utf16->str); #else + +#ifdef _WIN64 + auto get_url = *(std::uint64_t(__fastcall**)(std::uint64_t))((std::uint64_t)request + 48); + auto url_utf16 = get_url((std::uint64_t)request); + std::wstring url(reinterpret_cast(*reinterpret_cast(url_utf16))); +#else auto url_utf16 = get_url(reinterpret_cast(request)); std::wstring url(reinterpret_cast(get_str(url_utf16))); #endif - cef_string_userfree_utf16_free_orig(reinterpret_cast(url_utf16)); - //cef_string_userfree_utf16_free(url_utf16); - for (auto blockurl : block_list) { - if (std::wstring_view::npos != url.find(blockurl)) { - g_Logger.Log(L"blocked - " + url); - + +#endif + for (const auto& blockurl : block_list) { + if (std::wstring_view::npos != url.find (blockurl)) { + Logger::Log(L"blocked - " + url, Logger::LogLevel::Info); + //cef_string_userfree_utf16_free(url_utf16); + cef_string_userfree_utf16_free_orig((void*)url_utf16); return nullptr; } } - - g_Logger.Log(L"allow - " + url); - return cef_urlrequest_create_orig(request, client, request_context); + //cef_string_userfree_utf16_free(url_utf16); + cef_string_userfree_utf16_free_orig((void*)url_utf16); + Logger::Log(L"allow - " + url, Logger::LogLevel::Info); + return cef_urlrequest_create_orig (request, client, request_context); } - -// https://www.unknowncheats.me/forum/1064672-post23.html -bool DataCompare(BYTE* pData, BYTE* bSig, const char* szMask) +void WINAPI get_file_name() { - for (; *szMask; ++szMask, ++pData, ++bSig) - { - if (*szMask == 'x' && *pData != *bSig) - return false; + try { + file_name = *reinterpret_cast(file_name_rcx); + //MessageBoxW(0,file_name.c_str(), 0, 0); + //Print(L"{}", zip_file_name); + //system("pause"); + } + catch (const std::exception& e) { + Print({ Color::Red }, L"[{}] {}", L"ERROR", e.what()); } - return (*szMask) == NULL; } -BYTE* FindPattern(BYTE* dwAddress, const DWORD dwSize, BYTE* pbSig, const char* szMask) +void WINAPI modify_source() { - const DWORD length = strlen(szMask); - for (DWORD i = NULL; i < dwSize - length; i++) - { - __try + try { + if (file_name == L"home-hpto.css") { - if (DataCompare(dwAddress + i, pbSig, szMask)) - return dwAddress + i; - } - __except (EXCEPTION_EXECUTE_HANDLER) { - return nullptr; + //Print(L"{}", zip_file_name); + const auto hpto = PatternScanner::ScanFirst(ZipScan.base_address, ZipScan.image_size, L".WiPggcPDzbwGxoxwLWFf{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-ms-flexbox;display:flex;"); + if (hpto.is_found()) { + if (Memory::Write(hpto.data(), ".WiPggcPDzbwGxoxwLWFf{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-ms-flexbox;display:none;")) { + Logger::Log(L"hptocss patched!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"hptocss patch failed!", Logger::LogLevel::Error); + } + } + else { + Logger::Log(L"hptocss - failed not found!", Logger::LogLevel::Error); + } } - } - return 0; -} -DWORD WINAPI KillAds(LPVOID) -{ - if (true == g_Logger.read(L"Config", L"BlockAds")) { - constexpr auto libcef_str{ L"libcef.dll" }; - auto hModule = GetModuleHandle(libcef_str); - if (!hModule) - hModule = LoadLibrary(libcef_str); + if (file_name == L"xpui-routes-profile.js") + { + //Print(L"{}", zip_file_name); + const auto isModalOpen = PatternScanner::ScanAll(ZipScan.base_address, ZipScan.image_size, L"isModalOpen:!0"); + if (isModalOpen[0].is_found()) { + for (const auto& it : isModalOpen) { + if (Memory::Write(it.offset(13).data(), '1')) { + Logger::Log(L"isModalOpen patched!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"isModalOpen - patch failed!", Logger::LogLevel::Error); + } + } + } + else { + Logger::Log(L"isModalOpen - failed not found!", Logger::LogLevel::Error); + } + } - if (hModule) + if (file_name == L"xpui.js") { - cef_urlrequest_create_orig = /*cef_urlrequest_create;*/reinterpret_cast<_cef_urlrequest_create>(GetProcAddress(hModule, "cef_urlrequest_create")); + //Print(L"{}", zip_file_name); + const auto skipads = PatternScanner::ScanFirst(ZipScan.base_address, ZipScan.image_size, L"adsEnabled:!0"); + if (skipads.is_found()) { + if (Memory::Write(skipads.offset(12).data(), '1')) { + Logger::Log(L"adsEnabled patched!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"adsEnabled - patch failed!", Logger::LogLevel::Error); + } + } + else { + Logger::Log(L"adsEnabled - failed not found!", Logger::LogLevel::Error); + } - cef_string_userfree_utf16_free_orig = /*_cef_string_userfree_utf16_free;*/reinterpret_cast<_cef_string_userfree_utf16_free>(GetProcAddress(hModule, "cef_string_userfree_utf16_free")); + const auto sponsorship = PatternScanner::ScanFirst(ZipScan.base_address, ZipScan.image_size, L".set(\"allSponsorships\",t.sponsorships)}}(e,t);"); + if (sponsorship.is_found()) + { + memset((char*)sponsorship.data() + 6, 0x22, 1); + memset((char*)sponsorship.data() + 7, 0x20, 15); + Logger::Log(L"sponsorship patched!", Logger::LogLevel::Info); + //if (Memory::Write(sponsorship.offset(6).data(), ' ', 15)) { + // Logger::Log(L"sponsorship patched!", Logger::LogLevel::Info); + //} + //else { + // Logger::Log(L"sponsorship patch failed!", Logger::LogLevel::Error); + //} + } + else { + Logger::Log(L"sponsorship - failed not found!", Logger::LogLevel::Error); + } - if (cef_urlrequest_create_orig && cef_string_userfree_utf16_free_orig) { - const auto result = Mhook_SetHook(reinterpret_cast(&cef_urlrequest_create_orig), cef_urlrequest_create_hook); - result ? g_Logger.Log(L"libcef.dll patch success!") : g_Logger.Log(L"libcef.dll patch failed!"); + const auto skipsentry = PatternScanner::ScanFirst(ZipScan.base_address, ZipScan.image_size, L"sentry.io"); + if (skipsentry.is_found()) { + if (Memory::Write(skipsentry.data(), "localhost")) { + Logger::Log(L"sentry.io -> localhost patched!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"sentry.io -> localhost - patch failed!", Logger::LogLevel::Error); + } + } + else { + Logger::Log(L"sentry.io -> localhost - failed not found!", Logger::LogLevel::Error); + } + + const auto ishptoenable = PatternScanner::ScanFirst(ZipScan.base_address, ZipScan.image_size, L"hptoEnabled:!0"); + if (ishptoenable.is_found()) + { + if (Memory::Write(ishptoenable.offset(13).data(), '1')) { + Logger::Log(L"hptoEnabled patched!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"hptoEnabled - patch failed!", Logger::LogLevel::Error); + } + } + else { + Logger::Log(L"hptoEnabled - failed not found!", Logger::LogLevel::Error); + } + + const auto ishptohidden = PatternScanner::ScanFirst(ZipScan.base_address, ZipScan.image_size, L"isHptoHidden:!0"); + if (ishptohidden.is_found()) { + if (Memory::Write(ishptohidden.offset(14).data(), '1')) { + Logger::Log(L"isHptoHidden patched!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"isHptoHidden - patch failed!", Logger::LogLevel::Error); + } + } + else { + Logger::Log(L"isHptoHidden - failed not found!", Logger::LogLevel::Error); + } + + const auto sp_localhost = PatternScanner::ScanFirst(ZipScan.base_address, ZipScan.image_size, L"sp://ads/v1/ads/"); + if (sp_localhost.is_found()) { + if (Memory::Write(sp_localhost.data(), "sp://localhost//")) { + Logger::Log(L"sp://ads/v1/ads/ patched!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"sp://ads/v1/ads/ - patch failed!", Logger::LogLevel::Error); + } + } + else { + Logger::Log(L"sp://ads/v1/ads/ - failed not found!", Logger::LogLevel::Error); + } + + const auto premium_free = PatternScanner::ScanFirst(ZipScan.base_address, ZipScan.image_size, L"\"free\"===e.session?.productState?.catalogue?.toLowerCase(),r=e=>null!==e.session?.productState&&1===parseInt(e.session?.productState?.ads,10),o=e=>\"premium\"===e.session?.productState?.catalogue?.toLowerCase(),"); + if (premium_free.is_found()) { + //Print(L"{}", premium_free.read()); + //system("pause"); + if (Memory::Write(premium_free.data(), "\"premium\"===e.session?.productState?.catalogue?.toLowerCase(),r=e=>null!==e.session?.productState&&1===parseInt(e.session?.productState?.ads,10),o=e=>\"free\"===e.session?.productState?.catalogue?.toLowerCase(),")) { + Logger::Log(L"premium patched!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"premium - patch failed!", Logger::LogLevel::Error); + } + } + else { + Logger::Log(L"premium - failed not found!", Logger::LogLevel::Error); } } } - return 0; + catch (const std::exception& e) { + Print({ Color::Red }, L"[{}] {}", L"ERROR", e.what()); + } } -void WINAPI modify_buffer2() +#ifdef _WIN64 + +extern "C" void hook_file_name(); +extern "C" void hook_zip_buffer(); + +#else +// 8B45 EC | mov eax,dword ptr ss:[ebp-14] | +// 03C7 | add eax,edi | [+3] +// 50 | push eax | +// FFD2 | call edx | +// 03F8 | add edi,eax | [+5] + +__declspec(naked) void hook_zip_buffer() { - const auto hpto = FindPattern((uint8_t*)buff_addr, buff_size, (BYTE*)".WiPggcPDzbwGxoxwLWFf{-webkit-box-pack:center;-ms-flex-pack:center;display:-webkit-box;display:-ms-flexbox;display:flex;", - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); - if (hpto) + __asm { - for (size_t i = 0; i < strnlen_s(hpto_str, 200); i++) { - memset((char*)hpto + i, hpto_str[i], 1); - } - g_Logger.Log(L"hptocss patched!"); - hptocss_found = true; + add eax, edi + mov ZipScan.base_address, eax + push eax + call edx + mov ZipScan.image_size, eax + cmp xpui_found, 0 + jne skip + + //------------ preparation -------------------- + pushad + + //------------ function call ------------------ + call modify_buffer + + //------------ end call ------------------ + popad + + //------------ finish ------------------------- + skip: + push ret_addr + retn } } +#endif -void WINAPI modify_buffer() +DWORD WINAPI EnableDeveloper(LPVOID lpParam) { - const auto skipads = FindPattern((uint8_t*)buff_addr, buff_size, (BYTE*)"adsEnabled:!0", "xxxxxxxxxxxxx"); - if (skipads) + try { - memset((char*)skipads + 12, 0x31, 1); // 122 to 000 - g_Logger.Log(L"adsEnabled patched!"); - xpui_found = true; - } - const auto sponsorship = FindPattern((uint8_t*)buff_addr, buff_size, (BYTE*)".set(\"allSponsorships\",t.sponsorships)}}(e,t);", - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); - if (sponsorship) - { - memset((char*)sponsorship + 6, 0x22, 1); // 122 to 000 - memset((char*)sponsorship + 7, 0x20, 15); // 122 to 000 - g_Logger.Log(L"sponsorship patched!"); - } - const auto skipsentry = FindPattern((uint8_t*)buff_addr, buff_size, (BYTE*)"sentry.io", "xxxxxxxxx"); - if (skipsentry) - { - for (size_t i = 0; i < strnlen_s(localhost_str, 15); i++) { - memset((char*)skipsentry + i, localhost_str[i], 1); +#ifdef _WIN64 + const auto developer = PatternScanner::ScanFirst(L"41 22 DE 48 8B 95 40 05 00 00"); + if (Memory::Write>(developer.data(), { 0xB3, 0x03, 0x90 })) { + Logger::Log(L"Developer - patch success!", Logger::LogLevel::Info); } - g_Logger.Log(L"sentry.io -> localhost patched!"); - } - const auto ishptohidden = FindPattern((uint8_t*)buff_addr, buff_size, (BYTE*)"isHptoHidden:!0", "xxxxxxxxxxxxxxx"); - if (ishptohidden) - { - memset((char*)ishptohidden + 14, 0x31, 1); // 122 to 000 - g_Logger.Log(L"isHptoHidden patched!"); - } - const auto ishptoenable = FindPattern((uint8_t*)buff_addr, buff_size, (BYTE*)"hptoEnabled:!0", "xxxxxxxxxxxxxx"); - if (ishptoenable) - { - memset((char*)ishptoenable + 13, 0x31, 1); // 122 to 000 - g_Logger.Log(L"hptoEnabled patched!"); - } - const auto sp_localhost = FindPattern((uint8_t*)buff_addr, buff_size, (BYTE*)"sp://ads/v1/ads/", "xxxxxxxxxxxxxxxx"); - if (sp_localhost) - { - for (size_t i = 0; i < strnlen_s(sp_localhost_str, 19); i++) { - memset((char*)sp_localhost + i, sp_localhost_str[i], 1); + else { + Logger::Log(L"Developer - patch failed!", Logger::LogLevel::Error); + } +#else + const auto developer = PatternScanner::ScanFirst(L"25 01 FF FF FF 89 ?? ?? ?? FF FF"); + if (Memory::Write>(developer.data(), { 0xB8, 0x03, 0x00 })) { + Logger::Log(L"Developer - patch success!", Logger::LogLevel::Info); } - g_Logger.Log(L"sp://ads/v1/ads/ patched!"); + else { + Logger::Log(L"Developer - patch failed!", Logger::LogLevel::Error); + } +#endif } - - const auto premium_free = FindPattern((uint8_t*)buff_addr, buff_size, (BYTE*)"\"free\"===e.session?.productState?.catalogue?.toLowerCase(),s=e=>null!==e.session?.productState&&1===parseInt(e.session?.productState?.ads,10),r=e=>\"premium\"", - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); - if (premium_free) + catch (const std::exception& e) { - for (size_t i = 0; i < strnlen_s(premium_free_str, 200); i++) { - memset((char*)premium_free + i, premium_free_str[i], 1); - } - g_Logger.Log(L"premium patched!"); + Print({ Color::Red }, L"[{}] {}", L"ERROR", e.what()); } + return 0; } -__declspec(naked) void hook_zip_buffer() +DWORD WINAPI BlockAds(LPVOID lpParam) { - __asm + try { - add eax, edi; - mov buff_addr, eax; - push eax; - call edx; - mov buff_size, eax; - cmp xpui_found, 0; - jne skip; - //------------ preparation -------------------- - pushad; - //------------ function call ------------------ - call modify_buffer; - //------------ end call ------------------ - popad; - //------------ finish ------------------------- - skip: - cmp hptocss_found, 0; - jne skip2; - //------------ preparation -------------------- - pushad; - //------------ function call ------------------ - call modify_buffer2; - //------------ end call ------------------ - popad; - //------------ finish ------------------------- - skip2: - push ret_addr; - retn; - } -} +#if 0 + const auto pod = PatternScanner::ScanFirst(L"80 7C 24 70 07 0F 85 ?? ?? ?? ?? 48 8D").offset(5); + if (Memory::Write>(pod.data(), { 0x90, 0xE9 })) { + Logger::Log(L"Block Audio Ads - patch success!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"Block Audio Ads - patch failed!", Logger::LogLevel::Error); + } +#else + auto hModule = GetModuleHandleW(L"libcef.dll"); + if (!hModule) + hModule = LoadLibraryW(L"libcef.dll"); -DWORD WINAPI Developer(LPVOID) -{ - const HMODULE hModule = GetModuleHandle(NULL); - MODULEINFO mInfo = { 0 }; - if (TRUE == GetModuleInformation(GetCurrentProcess(), hModule, &mInfo, sizeof(MODULEINFO))) { - if (true == g_Logger.read(L"Config", L"Developer")) { - const auto skipPod = FindPattern((uint8_t*)hModule, mInfo.SizeOfImage, (BYTE*)"\x25\x01\xFF\xFF\xFF\x89\x85\xF8\xFB\xFF\xFF", "xxxxxx???xx"); - if (skipPod) - { - DWORD oldProtect; - VirtualProtect((char*)skipPod, 5, PAGE_EXECUTE_READWRITE, &oldProtect); - memset((char*)skipPod, 0xB8, 1); - memset((char*)skipPod + 1, 0x03, 1); - memset((char*)skipPod + 2, 0x00, 3); - VirtualProtect((char*)skipPod, 5, oldProtect, &oldProtect); - g_Logger.Log(L"Developer - patch success!"); - } - else { - g_Logger.Log(L"Developer - patch failed!"); + if (hModule) { + cef_urlrequest_create_orig = /*cef_urlrequest_create;*/(_cef_urlrequest_create)GetProcAddress(hModule, "cef_urlrequest_create"); + cef_string_userfree_utf16_free_orig = /*cef_urlrequest_create;*/(_cef_string_userfree_utf16_free)GetProcAddress(hModule, "cef_string_userfree_utf16_free"); + + if (cef_urlrequest_create_orig && cef_string_userfree_utf16_free_orig) { + if (!Hooking::HookFunction(&(PVOID&)cef_urlrequest_create_orig, (PVOID)cef_urlrequest_create_hook)) { + Logger::Log(L"BlockAds - patch failed!", Logger::LogLevel::Error); + } + else { + Logger::Log(L"BlockAds - patch success!", Logger::LogLevel::Info); + } } } +#endif + } + catch (const std::exception& e) + { + Print({ Color::Red }, L"[{}] {}", L"ERROR", e.what()); } return 0; } - -DWORD WINAPI KillBanner(LPVOID) +DWORD WINAPI BlockBanner(LPVOID lpParam) { - const HMODULE hModule = GetModuleHandle(NULL); - MODULEINFO mInfo = { 0 }; - if (TRUE == GetModuleInformation(GetCurrentProcess(), hModule, &mInfo, sizeof(MODULEINFO))) { - if (true == g_Logger.read(L"Config", L"Banner")) { - const auto skipPod = FindPattern((uint8_t*)hModule, mInfo.SizeOfImage, (BYTE*)"\x8B\x45\xEC\x03\xC7\x50\xFF\xD2\x03\xF8", "xxxxxxxxxx"); - if (skipPod) - { - const DWORD dwTmp = reinterpret_cast(skipPod) + 3; - ret_addr = dwTmp + 5; - DWORD oldProtect; -#pragma region Zip_buffer_hook - VirtualProtect((LPVOID)dwTmp, 5, PAGE_EXECUTE_READWRITE, &oldProtect); - *(BYTE*)dwTmp = 0xE9; // jmp - *(DWORD*)(dwTmp + 1) = (DWORD)hook_zip_buffer - dwTmp - 5; - VirtualProtect((LPVOID)dwTmp, 5, oldProtect, &oldProtect); -#pragma endregion - g_Logger.Log(L"Banner - patch success!"); - } - else { - g_Logger.Log(L"Banner - patch failed!"); - } + try + { +#ifdef _WIN64 + const auto FileName = PatternScanner::ScanFirst(L"48 85 C9 74 23 38 5C 24 48 74 14 E8 ?? ?? ?? ?? BA 18 00 00 00 48 8B 4C 24 40 E8 ?? ?? ?? ?? 48 89 5C 24 40 88 5C 24 48 48 8D 5E 08"); + ret_addr_file_name = FileName + 5; + if (FileName.hook((PVOID)hook_file_name)) { + Logger::Log(L"FileName - patch success!", Logger::LogLevel::Info); } + else { + Logger::Log(L"FileName - patch failed!", Logger::LogLevel::Error); + } + + const auto SourceCode = PatternScanner::ScanFirst(L"48 63 C8 48 03 F1 49 3B F4 73 25 41 F6 C6 04"); + ret_addr_file_source = SourceCode + 6; + if (SourceCode.hook((PVOID)hook_zip_buffer)) { + Logger::Log(L"SourceCode - patch success!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"SourceCode - patch failed!", Logger::LogLevel::Error); + } +#else + const auto SourceCode = PatternScanner::ScanFirst(L"8B 45 EC 03 C7 50 FF D2 03 F8").offset(3); + ret_addr_file_source = SourceCode + 5; + if (SourceCode.hook(hook_zip_buffer)) { + Logger::Log(L"SourceCode - patch success!", Logger::LogLevel::Info); + } + else { + Logger::Log(L"SourceCode - patch failed!", Logger::LogLevel::Error); + } +#endif + } + catch (const std::exception& e) + { + Print({ Color::Red }, L"[{}] {}", L"ERROR", e.what()); } return 0; } \ No newline at end of file diff --git a/src/Modify.h b/src/Modify.h index e3167ca8..891c15f8 100644 --- a/src/Modify.h +++ b/src/Modify.h @@ -1,6 +1,14 @@ #pragma once -#include "stdafx.h" -DWORD WINAPI KillAds (LPVOID); -DWORD WINAPI KillBanner (LPVOID); -DWORD WINAPI Developer (LPVOID); +DWORD WINAPI EnableDeveloper(LPVOID lpParam); +DWORD WINAPI BlockAds(LPVOID lpParam); +DWORD WINAPI BlockBanner(LPVOID lpParam); + +extern "C" void WINAPI get_file_name(); +extern "C" void WINAPI modify_source(); + +extern "C" PatternScanner::ModuleInfo ZipScan; + +extern "C" std::uint64_t file_name_rcx; +extern "C" std::uint64_t ret_addr_file_name; +extern "C" std::uint64_t ret_addr_file_source; diff --git a/src/assembly_code.asm b/src/assembly_code.asm new file mode 100644 index 00000000..089292fd --- /dev/null +++ b/src/assembly_code.asm @@ -0,0 +1,123 @@ +.DATA +; External declarations +EXTERN get_file_name : PROC +EXTERN modify_source : PROC +EXTERN ZipScan : QWORD +EXTERN file_name_rcx : QWORD +EXTERN ret_addr_file_name : QWORD +EXTERN ret_addr_file_source : QWORD + +.CODE + +; get_str - C++ to MASM conversion +; RCX = pRequest +; Return value in RAX + +; get_str PROC +; mov rax, rcx +; mov rdx, qword ptr [rax] +; mov rax, rdx +; ret +; get_str ENDP + +; PUSH_ALL_REGISTERS MACRO +; sub rsp, 120 ; Reserve space for 15 registers (8 bytes each) +; mov [rsp], rax ; Store rax on the stack +; mov [rsp+8], rbx +; mov [rsp+16], rcx +; mov [rsp+24], rdx +; mov [rsp+32], rsi +; mov [rsp+40], rdi +; mov [rsp+48], rbp +; mov [rsp+56], r8 +; mov [rsp+64], r9 +; mov [rsp+72], r10 +; mov [rsp+80], r11 +; mov [rsp+88], r12 +; mov [rsp+96], r13 +; mov [rsp+104], r14 +; mov [rsp+112], r15 +; ENDM +; +; POP_ALL_REGISTERS MACRO +; mov rax, [rsp] ; Restore r15 from the stack +; mov rbx, [rsp+8] +; mov rcx, [rsp+16] +; mov rdx, [rsp+24] +; mov rsi, [rsp+32] +; mov rdi, [rsp+40] +; mov rbp, [rsp+48] +; mov r8, [rsp+56] +; mov r9, [rsp+64] +; mov r10, [rsp+72] +; mov r11, [rsp+80] +; mov r12, [rsp+88] +; mov r13, [rsp+96] +; mov r14, [rsp+104] +; mov r15, [rsp+112] +; add rsp, 120 ; Adjust the stack pointer to remove the stored values +; ENDM + +; Macro to push all registers onto the stack +PUSH_ALL_REGISTERS MACRO + push rax + push rbx + push rcx + push rdx + push rsi + push rdi + push rbp + push r8 + push r9 + push r10 + push r11 + push r12 + push r13 + push r14 + push r15 +ENDM +; Macro to pop all registers from the stack +POP_ALL_REGISTERS MACRO + pop r15 + pop r14 + pop r13 + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rbp + pop rdi + pop rsi + pop rdx + pop rcx + pop rbx + pop rax +ENDM + +; Procedure to hook file name + +hook_file_name PROC + test rcx, rcx + mov file_name_rcx, rcx + PUSH_ALL_REGISTERS + call get_file_name + POP_ALL_REGISTERS + push ret_addr_file_name + ret +hook_file_name ENDP + +; Procedure to hook zip buffer + +hook_zip_buffer PROC + movsxd rcx, eax + mov ZipScan, r15 + mov ZipScan+8, rcx + ; PUSH_ALL_REGISTERS + call modify_source + ; POP_ALL_REGISTERS + push ret_addr_file_source + ret +hook_zip_buffer ENDP + +END \ No newline at end of file diff --git a/src/disasm-lib/cpu.c b/src/disasm-lib/cpu.c deleted file mode 100644 index e30852eb..00000000 --- a/src/disasm-lib/cpu.c +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (C) 2003, Matt Conover (mconover@gmail.com) -#include "cpu.h" -#include - -// NOTE: this assumes default scenarios (i.e., we assume CS/DS/ES/SS and flat -// and all have a base of 0 and limit of 0xffffffff, we don't try to verify -// that in the GDT) -// -// TODO: use inline assembly to get selector for segment -// Segment = x86 segment register (SEG_ES = 0, SEG_CS = 1, ...) -BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset) -{ - switch (Segment) - { - // Windows uses a flat address space (except FS for x86 and GS for x64) - case 0: // SEG_ES - case 1: // SEG_CS - case 2: // SEG_SS - case 3: // SEG_DS - return (BYTE *)(DWORD_PTR)Offset; - case 4: // SEG_FS - case 5: // SEG_GS - return (BYTE *)(DWORD_PTR)Offset; - // Note: we're really supposed to do this, but get_teb is not implemented - // in this bastardized version of the disassembler. - // return (BYTE *)get_teb() + Offset; - default: - assert(0); - return (BYTE *)(DWORD_PTR)Offset; - } -} - -// This is an GDT/LDT selector (pGDT+Selector) -BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset) -{ - DESCRIPTOR_ENTRY Entry; - GATE_ENTRY *Gate; - ULONG_PTR Base; - - assert(Selector < 0x10000); - if (!GetThreadSelectorEntry(GetCurrentThread(), Selector, (LDT_ENTRY *)&Entry)) return NULL; - if (!Entry.Present) return NULL; - if (Entry.System) - { - Base = 0; -#ifdef _WIN64 - Base |= (ULONG_PTR)Entry.HighOffset64 << 32; -#endif - Base |= Entry.BaseHi << 24; - Base |= Entry.BaseMid << 16; - Base |= Entry.BaseLow; - } - else - { - switch (Entry.Type) - { - case 1: // 16-bit TSS (available) - case 2: // LDT - case 3: // 16-bit TSS (busy) - case 9: // 32-bit TSS (available) - case 11: // 32-bit TSS (busy) - Base = 0; -#ifdef _WIN64 - Base |= (ULONG_PTR)Entry.HighOffset64 << 32; -#endif - Base |= Entry.BaseHi << 24; - Base |= Entry.BaseMid << 16; - Base |= Entry.BaseLow; - break; - - case 4: // 16-bit call gate - case 5: // task gate - case 6: // 16-bit interrupt gate - case 7: // 16-bit task gate - case 12: // 32-bit call gate - case 14: // 32-bit interrupt gate - case 15: // 32-bit trap gate - Gate = (GATE_ENTRY *)&Entry; -#ifdef _WIN64 - Base = ((ULONG_PTR)Gate->HighOffset64 << 32) | (Gate->HighOffset << 16) | Gate->LowOffset; -#else - Base = (Gate->HighOffset << 16) | Gate->LowOffset; -#endif - assert(!Offset); Offset = 0; - break; - default: - assert(0); - return NULL; - } - } - return (BYTE *)Base + Offset; -} - diff --git a/src/disasm-lib/cpu.h b/src/disasm-lib/cpu.h deleted file mode 100644 index 753bb49e..00000000 --- a/src/disasm-lib/cpu.h +++ /dev/null @@ -1,279 +0,0 @@ -// Copyright (C) 2003, Matt Conover (mconover@gmail.com) -#ifndef CPU_H -#define CPU_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include "misc.h" - -// Windows SDK assumes default alignment. -#pragma pack(push,1) - -//////////////////////////////////////////////////////// -// System descriptors -//////////////////////////////////////////////////////// - -#define GDT_NULL 0 -#define GDT_R0_CODE 0x08 -#define GDT_R0_DATA 0x10 -#define GDT_R3_CODE 0x18 -#define GDT_R3_DATA 0x20 -#define GDT_TSS 0x28 -#define GDT_PCR 0x30 -#define GDT_R3_TEB 0x38 -#define GDT_VDM 0x40 -#define GDT_LDT 0x48 -#define GDT_DOUBLEFAULT_TSS 0x50 -#define GDT_NMI_TSS 0x58 - -// 16-bit GDT entries: -// TODO: #define GDT_ABIOS_UNKNOWN 0x60 (22F30-32F2F) -#define GDT_ABIOS_VIDEO 0x68 -#define GDT_ABIOS_GDT 0x70 // descriptor describing ABIOS GDT itself -#define GDT_ABIOS_NTOS 0x78 // first 64K of NTOSKRNL -#define GDT_ABIOS_CDA 0xE8 // common data area -#define GDT_ABIOS_CODE 0xF0 // KiI386AbiosCall -#define GDT_ABIOS_STACK 0xF8 - -#define SELECTOR_RPL_MASK 0x03 // bits 0-1 -#define SELECTOR_LDT 0x04 // bit 2 - -// for data selectors -#define DATA_ACCESS_MASK (1<<0) -#define DATA_WRITE_ENABLE_MASK (1<<1) -#define DATA_EXPAND_DOWN_MASK (1<<2) - -// for code selectors -#define CODE_ACCESS_MASK (1<<0) -#define CODE_READ_MASK (1<<1) -#define CODE_CONFORMING_MASK (1<<2) -#define CODE_FLAG (1<<3) - -#define TASK_GATE 5 -#define INTERRUPT_GATE 6 -#define TRAP_GATE 7 - -typedef struct _IDT_ENTRY -{ - USHORT LowOffset; - USHORT Selector; - UCHAR Ignored : 5; - UCHAR Zero : 3; - UCHAR Type : 3; - UCHAR Is32Bit : 1; - UCHAR Ignored2 : 1; - UCHAR DPL : 2; - UCHAR Present : 1; - USHORT HighOffset; -#ifdef _WIN64 - ULONG HighOffset64; - ULONG Reserved; -#endif -} IDT_ENTRY, TRAP_GATE_ENTRY; - -typedef struct _CALL_GATE_ENTRY -{ - USHORT LowOffset; - USHORT Selector; - UCHAR ParameterCount: 4; - UCHAR Ignored : 3; - UCHAR Type : 5; - UCHAR DPL : 2; - UCHAR Present : 1; - USHORT HighOffset; -#ifdef _WIN64 - ULONG HighOffset64; - ULONG Reserved; -#endif -} CALL_GATE_ENTRY; - -typedef struct _TASK_GATE_ENTRY -{ - USHORT Ignored; - USHORT Selector; - UCHAR Ignored2 : 5; - UCHAR Zero : 3; - UCHAR Type : 5; - UCHAR DPL : 2; - UCHAR Present : 1; - USHORT Ignored3; -} TASK_GATE_ENTRY; - -typedef struct _DESCRIPTOR_ENTRY -{ - USHORT LimitLow; - USHORT BaseLow; - UCHAR BaseMid; - UCHAR Type : 4; // 10EWA (code), E=ExpandDown, W=Writable, A=Accessed - // 11CRA (data), C=Conforming, R=Readable, A=Accessed - UCHAR System : 1; // if 1 then it is a gate or LDT - UCHAR DPL : 2; // descriptor privilege level; - // for data selectors, MAX(CPL, RPL) must be <= DPL to access (or else GP# fault) - // for non-conforming code selectors (without callgate), MAX(CPL, RPL) must be <= DPL to access (or else GP# fault) - // for conforming code selectors, MAX(CPL, RPL) must be >= DPL (i.e., CPL 0-2 cannot access if DPL is 3) - // for non-conforming code selectors (with call gate), DPL indicates lowest privilege allowed to access gate - UCHAR Present : 1; - UCHAR LimitHigh : 4; - UCHAR Available: 1; // aka AVL - UCHAR Reserved : 1; - UCHAR Is32Bit : 1; // aka B flag - UCHAR Granularity : 1; // aka G flag - UCHAR BaseHi : 8; -#ifdef _WIN64 - ULONG HighOffset64; - ULONG Reserved2; -#endif -} DESCRIPTOR_ENTRY; - -typedef struct _GATE_ENTRY -{ - USHORT LowOffset; - UCHAR Skip; - UCHAR Type : 5; - UCHAR DPL : 2; - UCHAR Present : 1; - USHORT HighOffset; -#ifdef _WIN64 - ULONG HighOffset64; - ULONG Reserved; -#endif -} GATE_ENTRY; - -// TODO: update for X64 -typedef struct _PTE_ENTRY -{ - ULONG Present : 1; - ULONG Write : 1; - ULONG Owner : 1; // E.g., user mode or supervisor mode - ULONG WriteThrough : 1; - ULONG CacheDisable : 1; - ULONG Accessed : 1; - ULONG Dirty : 1; - ULONG PAT : 1; - ULONG Global : 1; - ULONG CopyOnWrite : 1; - ULONG Prototype : 1; - ULONG Transition : 1; - ULONG Address : 20; -} PTE_ENTRY; - -// TODO: update for X64 -typedef struct _PDE_ENTRY -{ - ULONG Present : 1; - ULONG Write : 1; - ULONG Owner : 1; - ULONG WriteThrough : 1; - ULONG CacheDisable : 1; - ULONG Accessed : 1; - ULONG Reserved1 : 1; - ULONG PageSize : 1; - ULONG Global : 1; - ULONG Reserved : 3; - ULONG Address : 20; -} PDE_ENTRY; - -// TODO: update for X64 -typedef struct _IO_ACCESS_MAP -{ - UCHAR DirectionMap[32]; - UCHAR IoMap[8196]; -} IO_ACCESS_MAP; - -#define MIN_TSS_SIZE FIELD_OFFSET(TSS_ENTRY, IoMaps) -// TODO: update for X64 -typedef struct _TSS_ENTRY -{ - USHORT Backlink; - USHORT Reserved0; - ULONG Esp0; - USHORT Ss0; - USHORT Reserved1; - ULONG NotUsed1[4]; - ULONG CR3; - ULONG Eip; - ULONG NotUsed2[9]; - USHORT Es; - USHORT Reserved2; - USHORT Cs; - USHORT Reserved3; - USHORT Ss; - USHORT Reserved4; - USHORT Ds; - USHORT Reserved5; - USHORT Fs; - USHORT Reserved6; - USHORT Gs; - USHORT Reserved7; - USHORT LDT; - USHORT Reserved8; - USHORT Flags; - USHORT IoMapBase; - IO_ACCESS_MAP IoMaps[1]; - UCHAR IntDirectionMap[32]; -} TSS_ENTRY; - -// TODO: update for X64 -typedef struct _TSS16_ENTRY -{ - USHORT Backlink; - USHORT Sp0; - USHORT Ss0; - USHORT Sp1; - USHORT Ss1; - USHORT Sp2; - USHORT Ss3; - USHORT Ip; - USHORT Flags; - USHORT Ax; - USHORT Cx; - USHORT Dx; - USHORT Bx; - USHORT Sp; - USHORT Bp; - USHORT Si; - USHORT Di; - USHORT Es; - USHORT Cs; - USHORT Ss; - USHORT Ds; - USHORT LDT; -} TSS16_ENTRY; - -// TODO: update for X64 -typedef struct _GDT_ENTRY -{ - USHORT LimitLow; - USHORT BaseLow; - union { - struct { - UCHAR BaseMid; - UCHAR Flags1; - UCHAR Flags2; - UCHAR BaseHi; - } Bytes; - struct { - ULONG BaseMid : 8; - ULONG Type : 5; - ULONG Dpl : 2; - ULONG Pres : 1; - ULONG LimitHi : 4; - ULONG Sys : 1; - ULONG Reserved_0 : 1; - ULONG Default_Big : 1; - ULONG Granularity : 1; - ULONG BaseHi : 8; - } Bits; - } HighWord; -} GDT_ENTRY; - -BYTE *GetAbsoluteAddressFromSegment(BYTE Segment, DWORD Offset); -BYTE *GetAbsoluteAddressFromSelector(WORD Selector, DWORD Offset); - -#pragma pack(pop) -#ifdef __cplusplus -} -#endif -#endif // CPU_H diff --git a/src/disasm-lib/disasm.c b/src/disasm-lib/disasm.c deleted file mode 100644 index 76a62bd0..00000000 --- a/src/disasm-lib/disasm.c +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (C) 2004, Matt Conover (mconover@gmail.com) -#undef NDEBUG -#include -#include -#include "disasm.h" - -#ifdef NO_SANITY_CHECKS -#define NDEBUG -#undef assert -#define assert(x) -#endif - -////////////////////////////////////////////////////////////////////// -// Global variables -////////////////////////////////////////////////////////////////////// - -ARCHITECTURE_FORMAT SupportedArchitectures[] = -{ - { ARCH_X86, &X86 }, - { ARCH_X86_16, &X86 }, - { ARCH_X64, &X86 }, - { ARCH_UNKNOWN, NULL } -}; - -typedef struct _DISASM_ARG_INFO -{ - INSTRUCTION *MatchedInstruction; - BOOL MatchPrefix; - U8 *Opcode; - U32 OpcodeLength; - INSTRUCTION_TYPE InstructionType; - U32 Count; -} DISASM_ARG_INFO; - -////////////////////////////////////////////////////////////////////// -// Function prototypes -////////////////////////////////////////////////////////////////////// - -BOOL InitInstruction(INSTRUCTION *Instruction, DISASSEMBLER *Disassembler); -static struct _ARCHITECTURE_FORMAT *GetArchitectureFormat(ARCHITECTURE_TYPE Type); - -////////////////////////////////////////////////////////////////////// -// Disassembler setup -////////////////////////////////////////////////////////////////////// - -BOOL InitDisassembler(DISASSEMBLER *Disassembler, ARCHITECTURE_TYPE Architecture) -{ - ARCHITECTURE_FORMAT *ArchFormat; - - memset(Disassembler, 0, sizeof(DISASSEMBLER)); - Disassembler->Initialized = DISASSEMBLER_INITIALIZED; - - ArchFormat = GetArchitectureFormat(Architecture); - if (!ArchFormat) { assert(0); return FALSE; } - Disassembler->ArchType = ArchFormat->Type; - Disassembler->Functions = ArchFormat->Functions; - return TRUE; -} - -void CloseDisassembler(DISASSEMBLER *Disassembler) -{ - memset(Disassembler, 0, sizeof(DISASSEMBLER)); -} - -////////////////////////////////////////////////////////////////////// -// Instruction setup -////////////////////////////////////////////////////////////////////// - -BOOL InitInstruction(INSTRUCTION *Instruction, DISASSEMBLER *Disassembler) -{ - memset(Instruction, 0, sizeof(INSTRUCTION)); - Instruction->Initialized = INSTRUCTION_INITIALIZED; - Instruction->Disassembler = Disassembler; - memset(Instruction->String, ' ', MAX_OPCODE_DESCRIPTION-1); - Instruction->String[MAX_OPCODE_DESCRIPTION-1] = '\0'; - return TRUE; -} - -// If Decode = FALSE, only the following fields are valid: -// Instruction->Length, Instruction->Address, Instruction->Prefixes, Instruction->PrefixCount, -// Instruction->OpcodeBytes, Instruction->Instruction->OpcodeLength, Instruction->Groups, -// Instruction->Type, Instruction->OperandCount -// -// If Disassemble = TRUE, then Instruction->String is valid (also requires Decode = TRUE) -// -// WARNING: This will overwrite the previously obtained instruction -INSTRUCTION *GetInstruction(DISASSEMBLER *Disassembler, U64 VirtualAddress, U8 *Address, U32 Flags) -{ - if (Disassembler->Initialized != DISASSEMBLER_INITIALIZED) { assert(0); return NULL; } - assert(Address); - InitInstruction(&Disassembler->Instruction, Disassembler); - Disassembler->Instruction.Address = Address; - Disassembler->Instruction.VirtualAddressDelta = VirtualAddress - (U64)Address; - if (!Disassembler->Functions->GetInstruction(&Disassembler->Instruction, Address, Flags)) - { - assert(Disassembler->Instruction.Address == Address); - assert(Disassembler->Instruction.Length < MAX_INSTRUCTION_LENGTH); - - // Save the address that failed, in case the lower-level disassembler didn't - Disassembler->Instruction.Address = Address; - Disassembler->Instruction.ErrorOccurred = TRUE; - return NULL; - } - return &Disassembler->Instruction; -} - -/////////////////////////////////////////////////////////////////////////// -// Miscellaneous -/////////////////////////////////////////////////////////////////////////// - -static ARCHITECTURE_FORMAT *GetArchitectureFormat(ARCHITECTURE_TYPE Type) -{ - ARCHITECTURE_FORMAT *Format; - for (Format = SupportedArchitectures; Format->Type != ARCH_UNKNOWN; Format++) - { - if (Format->Type == Type) return Format; - } - - assert(0); - return NULL; -} - diff --git a/src/disasm-lib/disasm.h b/src/disasm-lib/disasm.h deleted file mode 100644 index f7b80f8e..00000000 --- a/src/disasm-lib/disasm.h +++ /dev/null @@ -1,578 +0,0 @@ -// Copyright (C) 2004, Matt Conover (mconover@gmail.com) -// -// WARNING: -// I wouldn't recommend changing any flags like OP_*, ITYPE_*, or *_MASK -// aside from those marked as UNUSED. This is because the flags parts of -// the flags are architecture independent and other are left to specific -// architectures to define, so unless you understand the relationships -// between them, I would leave them as is. - -#ifndef DISASM_H -#define DISASM_H -#ifdef __cplusplus -extern "C" { -#endif -#include -#include -#include "misc.h" - -typedef signed char S8; -typedef unsigned char U8; -typedef signed short S16; -typedef unsigned short U16; -typedef signed long S32; -typedef unsigned long U32; -typedef LONG64 S64; -typedef ULONG64 U64; - -#ifdef SPEEDY -// On Visual Studio 6, making the internal functions inline makes compiling take forever -#define INTERNAL static _inline -#define INLINE _inline -#else -#define INTERNAL static -#define INLINE -#endif - -#define VALID_INSTRUCTION(i) ((i) && !((i)->ErrorOccurred)) -#define NEXT_INSTRUCTION(i) ((i)->Address + (i)->Length) -#define DISASM_ARCH_TYPE(dis) ((dis)->ArchType) -#define INS_ARCH_TYPE(ins) DISASM_ARCH_TYPE((ins)->Disassembler) - -// NOTE: these should be as big set to the maximum of the supported architectures -#define MAX_PREFIX_LENGTH 15 -#define MAX_OPERAND_COUNT 3 -#define MAX_INSTRUCTION_LENGTH 25 -#define MAX_OPCODE_LENGTH 3 -#define MAX_OPCODE_DESCRIPTION 256 - -///////////////////////////////////////////////////////////////////// -// Code branch -///////////////////////////////////////////////////////////////////// - -#define MAX_CODE_REFERENCE_COUNT 3 - -typedef struct _CODE_BRANCH -{ - U64 Addresses[MAX_CODE_REFERENCE_COUNT]; // NULL if multiple to addresses - U32 Count; - U8 IsLoop : 1; - U8 IsCall : 1; // branch if false - U8 IsIndirect : 1; // call/jmp [Address] - U8 AddressOffset: 5; - struct _INSTRUCTION_OPERAND *Operand; // the operand containg the address -} CODE_BRANCH; - -///////////////////////////////////////////////////////////////////// -// Data references -///////////////////////////////////////////////////////////////////// - -#define MAX_DATA_REFERENCE_COUNT 3 - -typedef struct _DATA_REFERENCE -{ - U64 Addresses[MAX_DATA_REFERENCE_COUNT]; // NULL if multiple to addresses - U32 Count; - ULONG_PTR DataSize; - struct _INSTRUCTION_OPERAND *Operand; // the operand containg the address -} DATA_REFERENCE; - -//////////////////////////////////////////////////////////////////// -// Instruction -///////////////////////////////////////////////////////////////////// - -// -// Instruction types (bits 0-7) -// Instruction groups (bits 8-26) -// -#define ITYPE_EXEC_OFFSET (1<<8) -#define ITYPE_ARITH_OFFSET (1<<9) -#define ITYPE_LOGIC_OFFSET (1<<10) -#define ITYPE_STACK_OFFSET (1<<11) -#define ITYPE_TESTCOND_OFFSET (1<<12) -#define ITYPE_LOAD_OFFSET (1<<13) -#define ITYPE_ARRAY_OFFSET (1<<14) -#define ITYPE_BIT_OFFSET (1<<15) -#define ITYPE_FLAG_OFFSET (1<<16) -#define ITYPE_FPU_OFFSET (1<<17) -#define ITYPE_TRAPS_OFFSET (1<<18) -#define ITYPE_SYSTEM_OFFSET (1<<19) -#define ITYPE_OTHER_OFFSET (1<<20) -#define ITYPE_UNUSED1_OFFSET (1<<21) -#define ITYPE_UNUSED2_OFFSET (1<<22) -#define ITYPE_UNUSED3_OFFSET (1<<23) -#define ITYPE_UNUSED4_OFFSET (1<<24) -#define ITYPE_UNUSED5_OFFSET (1<<25) -#define ITYPE_UNUSED6_OFFSET (1<<26) -#define ITYPE_EXT_UNUSED1 (1<<27) -#define ITYPE_EXT_UNUSED2 (1<<28) -#define ITYPE_EXT_UNUSED3 (1<<29) -#define ITYPE_EXT_UNUSED4 (1<<30) -#define ITYPE_EXT_UNUSED5 (1<<31) - -// -// X86-specific flags (bits 27-31) -// - -#define ITYPE_EXT_64 ITYPE_EXT_UNUSED1 // Use index 1 if in 64-bit mode and 0 otherwise -#define ITYPE_EXT_MODRM ITYPE_EXT_UNUSED2 // ModRM byte may extend the opcode -#define ITYPE_EXT_SUFFIX ITYPE_EXT_UNUSED3 // byte after ModRM/SIB/displacement is the third opcode -#define ITYPE_EXT_PREFIX ITYPE_EXT_UNUSED4 // prefix -#define ITYPE_EXT_FPU ITYPE_EXT_UNUSED5 // FPU instructions require special handling - -#define ITYPE_3DNOW_OFFSET ITYPE_UNUSED1_OFFSET -#define ITYPE_MMX_OFFSET ITYPE_UNUSED2_OFFSET -#define ITYPE_SSE_OFFSET ITYPE_UNUSED3_OFFSET -#define ITYPE_SSE2_OFFSET ITYPE_UNUSED4_OFFSET -#define ITYPE_SSE3_OFFSET ITYPE_UNUSED5_OFFSET - -// -// Instruction types -// - -#define ITYPE_TYPE_MASK 0x7FFFFFFF -#define ITYPE_GROUP_MASK 0x7FFFFF00 - -typedef enum _INSTRUCTION_TYPE -{ - // ITYPE_EXEC group - ITYPE_EXEC = ITYPE_EXEC_OFFSET, - ITYPE_BRANCH, - ITYPE_BRANCHCC, // conditional (not necessarily just flags) - ITYPE_CALL, - ITYPE_CALLCC, // conditional (not necessarily just flags) - ITYPE_RET, - ITYPE_LOOPCC, - - // ITYPE_ARITH group - ITYPE_ARITH = ITYPE_ARITH_OFFSET, - ITYPE_XCHGADD, - ITYPE_ADD, - ITYPE_SUB, - ITYPE_MUL, - ITYPE_DIV, - ITYPE_INC, - ITYPE_DEC, - ITYPE_SHL, - ITYPE_SHR, - ITYPE_ROL, - ITYPE_ROR, - - // ITYPE_LOGIC group - ITYPE_LOGIC=ITYPE_LOGIC_OFFSET, - ITYPE_AND, - ITYPE_OR, - ITYPE_XOR, - ITYPE_NOT, - ITYPE_NEG, - - // ITYPE_STACK group - ITYPE_STACK=ITYPE_STACK_OFFSET, - ITYPE_PUSH, - ITYPE_POP, - ITYPE_PUSHA, - ITYPE_POPA, - ITYPE_PUSHF, - ITYPE_POPF, - ITYPE_ENTER, - ITYPE_LEAVE, - - // ITYPE_TESTCOND group - ITYPE_TESTCOND=ITYPE_TESTCOND_OFFSET, - ITYPE_TEST, - ITYPE_CMP, - - // ITYPE_LOAD group - ITYPE_LOAD=ITYPE_LOAD_OFFSET, - ITYPE_MOV, - ITYPE_MOVCC, // conditional - ITYPE_LEA, - ITYPE_XCHG, - ITYPE_XCHGCC, // conditional - - // ITYPE_ARRAY group - ITYPE_ARRAY=ITYPE_ARRAY_OFFSET, - ITYPE_STRCMP, - ITYPE_STRLOAD, - ITYPE_STRMOV, - ITYPE_STRSTOR, - ITYPE_XLAT, - - // ITYPE_BIT group - ITYPE_BIT=ITYPE_BIT_OFFSET, - ITYPE_BITTEST, - ITYPE_BITSET, - ITYPE_BITCLR, - - // ITYPE_FLAG group - // PF = parify flag - // ZF = zero flag - // OF = overflow flag - // DF = direction flag - // SF = sign flag - ITYPE_FLAG=ITYPE_FLAG_OFFSET, - // clear - ITYPE_CLEARCF, - ITYPE_CLEARZF, - ITYPE_CLEAROF, - ITYPE_CLEARDF, - ITYPE_CLEARSF, - ITYPE_CLEARPF, - // set - ITYPE_SETCF, - ITYPE_SETZF, - ITYPE_SETOF, - ITYPE_SETDF, - ITYPE_SETSF, - ITYPE_SETPF, - // toggle - ITYPE_TOGCF, - ITYPE_TOGZF, - ITYPE_TOGOF, - ITYPE_TOGDF, - ITYPE_TOGSF, - ITYPE_TOGPF, - - // ITYPE_FPU group - ITYPE_FPU=ITYPE_FPU_OFFSET, - ITYPE_FADD, - ITYPE_FSUB, - ITYPE_FMUL, - ITYPE_FDIV, - ITYPE_FCOMP, - ITYPE_FEXCH, - ITYPE_FLOAD, - ITYPE_FLOADENV, - ITYPE_FSTORE, - ITYPE_FSTOREENV, - ITYPE_FSAVE, - ITYPE_FRESTORE, - ITYPE_FMOVCC, - - ITYPE_UNUSED1=ITYPE_UNUSED1_OFFSET, - ITYPE_UNUSED2=ITYPE_UNUSED2_OFFSET, - ITYPE_UNUSED3=ITYPE_UNUSED3_OFFSET, - - // ITYPE_MMX group - ITYPE_MMX=ITYPE_MMX_OFFSET, - ITYPE_MMX_MOV, - ITYPE_MMX_ADD, - ITYPE_MMX_SUB, - ITYPE_MMX_MUL, - ITYPE_MMX_DIV, - ITYPE_MMX_AND, - ITYPE_MMX_OR, - ITYPE_MMX_XOR, - ITYPE_MMX_CMP, - - // ITYPE_SSE group - ITYPE_SSE=ITYPE_SSE_OFFSET, - ITYPE_SSE_MOV, - ITYPE_SSE_ADD, - ITYPE_SSE_SUB, - ITYPE_SSE_MUL, - ITYPE_SSE_DIV, - ITYPE_SSE_AND, - ITYPE_SSE_OR, - ITYPE_SSE_XOR, - ITYPE_SSE_CMP, - - // ITYPE_SSE2 group - ITYPE_SSE2=ITYPE_SSE2_OFFSET, - ITYPE_SSE2_MOV, - ITYPE_SSE2_ADD, - ITYPE_SSE2_SUB, - ITYPE_SSE2_MUL, - ITYPE_SSE2_DIV, - ITYPE_SSE2_AND, - ITYPE_SSE2_OR, - ITYPE_SSE2_XOR, - ITYPE_SSE2_CMP, - - // ITYPE_SSE3 group - ITYPE_SSE3=ITYPE_SSE3_OFFSET, - ITYPE_SSE3_MOV, - ITYPE_SSE3_ADD, - ITYPE_SSE3_SUB, - ITYPE_SSE3_MUL, - ITYPE_SSE3_DIV, - ITYPE_SSE3_AND, - ITYPE_SSE3_OR, - ITYPE_SSE3_XOR, - ITYPE_SSE3_CMP, - - // ITYPE_3DNOW group - ITYPE_3DNOW=ITYPE_3DNOW_OFFSET, - ITYPE_3DNOW_ADD, - ITYPE_3DNOW_SUB, - ITYPE_3DNOW_MUL, - ITYPE_3DNOW_DIV, - ITYPE_3DNOW_CMP, - ITYPE_3DNOW_XCHG, - - // ITYPE_TRAP - ITYPE_TRAPS=ITYPE_TRAPS_OFFSET, - ITYPE_TRAP, // generate trap - ITYPE_TRAPCC, // conditional trap gen - ITYPE_TRAPRET, // return from trap - ITYPE_BOUNDS, // gen bounds trap - ITYPE_DEBUG, // gen breakpoint trap - ITYPE_TRACE, // gen single step trap - ITYPE_INVALID, // gen invalid instruction - ITYPE_OFLOW, // gen overflow trap - - // ITYPE_SYSTEM group - ITYPE_SYSTEM=ITYPE_SYSTEM_OFFSET, - ITYPE_HALT, // halt machine - ITYPE_IN, // input form port - ITYPE_OUT, // output to port - ITYPE_CPUID, // identify cpu - ITYPE_SETIF, // allow interrupts - ITYPE_CLEARIF, // block interrupts - ITYPE_SYSCALL, - ITYPE_SYSCALLRET, - - // ITYPE_OTHER group - ITYPE_OTHER = ITYPE_OTHER_OFFSET, - ITYPE_NOP, - ITYPE_BCDCONV, // convert to/from BCD - ITYPE_SZCONV // convert size of operand -} INSTRUCTION_TYPE; - -// -// Operand flags -// - -// Type = bits 0-6 (these are mutually exclusive -- bits 0-6 will always be a power of 2)) -#define OPTYPE_NONE 0x00 -#define OPTYPE_IMM 0x01 // immediate value -#define OPTYPE_OFFSET 0x02 // relative offset -#define OPTYPE_FLOAT 0x03 // floating point -#define OPTYPE_BCD 0x04 -#define OPTYPE_STRING 0x05 -#define OPTYPE_SPECIAL 0x06 -#define OPTYPE_MASK 0x7F - -// Flags = bits 7-23 (these can be combinations) -// These are used in the X86 opcode table -#define OP_REG (1<<7) // 0x80 -#define OP_SIGNED (1<<8) -#define OP_SYS (1<<9) // parameter is an index into some system structure -#define OP_CONDR (1<<10) -#define OP_CONDW (1<<11) -#define OP_UNUSED (1<<12) -#define OP_SRC (1<<13) // operand is source operand -#define OP_DST (1<<14) // operand is destination operand -#define OP_EXEC (1<<15) // operand is executed - -#define OP_CONDE OP_CONDR -#define OP_COND_EXEC (OP_CONDE|OP_EXEC) // executed only if the pre-conditions are met -#define OP_COND_SRC (OP_CONDR|OP_SRC) // set only if pre-conditions are met -#define OP_COND_DST (OP_CONDW|OP_DST) // set only if pre-conditions are met -#define OP_COND (OP_CONDR|OP_CONDW) - -// Bits 16-31 are available for use outside of the opcode table, but they can only -// be used in INSTRUCTION_OPERAND.Flags, they may conflit with the architecture specific -// operands. For example, bits 16-31 are used in X86 for AMODE_* and OPTYPE_* -#define OP_ADDRESS (1<<16) -#define OP_LOCAL (1<<17) -#define OP_PARAM (1<<18) -#define OP_GLOBAL (1<<19) -#define OP_FAR (1<<20) -#define OP_IPREL (1<<21) - -// -// X86-specific flags (bits 27-31) -// -#define OP_MSR (OP_SYS|OP_UNUSED) - -// -// Other architecture flags -// -#define OP_DELAY OP_UNUSED // delayed instruction (e.g., delayed branch that executes after the next instruction) - -///////////////////////////////////////////////////////////////////// -// Architectures -///////////////////////////////////////////////////////////////////// - -typedef enum _ARCHITECTURE_TYPE -{ - ARCH_UNKNOWN=0, - - // x86-based - ARCH_X86, // 32-bit x86 - ARCH_X86_16, // 16-bit x86 - ARCH_X64, // AMD64 and Intel EMD64 - - // everything else - ARCH_ALPHA, - ARCH_ARM, - ARCH_DOTNET, - ARCH_EFI, - ARCH_IA64, - ARCH_M68K, - ARCH_MIPS, - ARCH_PPC, - ARCH_SH3, - ARCH_SH4, - ARCH_SPARC, - ARCH_THUMB - -} ARCHITECTURE_TYPE; - -typedef BOOL (*INIT_INSTRUCTION)(struct _INSTRUCTION *Instruction); -typedef void (*DUMP_INSTRUCTION)(struct _INSTRUCTION *Instruction, BOOL ShowBytes, BOOL Verbose); -typedef BOOL (*GET_INSTRUCTION)(struct _INSTRUCTION *Instruction, U8 *Address, U32 Flags); -typedef U8 *(*FIND_FUNCTION_BY_PROLOGUE)(struct _INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, U32 Flags); - -typedef struct _ARCHITECTURE_FORMAT_FUNCTIONS -{ - INIT_INSTRUCTION InitInstruction; - DUMP_INSTRUCTION DumpInstruction; - GET_INSTRUCTION GetInstruction; - FIND_FUNCTION_BY_PROLOGUE FindFunctionByPrologue; -} ARCHITECTURE_FORMAT_FUNCTIONS; - -typedef struct _ARCHITECTURE_FORMAT -{ - ARCHITECTURE_TYPE Type; - ARCHITECTURE_FORMAT_FUNCTIONS *Functions; -} ARCHITECTURE_FORMAT; - -#define DISASSEMBLER_INITIALIZED 0x1234566F -#define INSTRUCTION_INITIALIZED 0x1234567F - -#include "disasm_x86.h" - -typedef struct DECLSPEC_ALIGN(16) _S128 -{ - U64 Low; - S64 High; -} S128; -typedef struct DECLSPEC_ALIGN(16) _U128 -{ - U64 Low; - U64 High; -} U128; - -typedef struct _INSTRUCTION_OPERAND -{ - U32 Flags; - U8 Type : 6; - U8 Unused : 2; - U16 Length; - - - // If non-NULL, this indicates the target address of the instruction (e.g., a branch or - // a displacement with no base register). However, this address is only reliable if the - // image is mapped correctly (e.g., the executable is mapped as an image and fixups have - // been applied if it is not at its preferred image base). - // - // If disassembling a 16-bit DOS application, TargetAddress is in the context of - // X86Instruction->Segment. For example, if TargetAddress is the address of a code branch, - // it is in the CS segment (unless X86Instruction->HasSegmentOverridePrefix is set). If - // TargetAddress is a data pointer, it is in the DS segment (unless - // X86Instruction->HasSegmentOverridePrefix is set) - U64 TargetAddress; - U32 Register; - - union - { - // All 8/16/32-bit operands are extended to 64-bits automatically - // If you want to downcast, check whether Flags & OP_SIGNED is set - // Like this: - // U32 GetOperand32(OPERAND *Operand) - // { - // if (Operand->Flags & OP_SIGNED) return (S32)Operand->Value_S64; - // else return (U32)Operand->Value_U64; - //} - U64 Value_U64; - S64 Value_S64; - U128 Value_U128; - U128 Float128; - U8 Float80[80]; - U8 BCD[10]; - }; -} INSTRUCTION_OPERAND; - -typedef struct _INSTRUCTION -{ - U32 Initialized; - struct _DISASSEMBLER *Disassembler; - - char String[MAX_OPCODE_DESCRIPTION]; - U8 StringIndex; - U64 VirtualAddressDelta; - - U32 Groups; // ITYPE_EXEC, ITYPE_ARITH, etc. -- NOTE groups can be OR'd together - INSTRUCTION_TYPE Type; // ITYPE_ADD, ITYPE_RET, etc. -- NOTE there is only one possible type - - U8 *Address; - U8 *OpcodeAddress; - U32 Length; - - U8 Prefixes[MAX_PREFIX_LENGTH]; - U32 PrefixCount; - - U8 LastOpcode; // last byte of opcode - U8 OpcodeBytes[MAX_OPCODE_LENGTH]; - U32 OpcodeLength; // excludes any operands and prefixes - - INSTRUCTION_OPERAND Operands[MAX_OPERAND_COUNT]; - U32 OperandCount; - - X86_INSTRUCTION X86; - - DATA_REFERENCE DataSrc; - DATA_REFERENCE DataDst; - CODE_BRANCH CodeBranch; - - // Direction depends on which direction the stack grows - // For example, on x86 a push results in StackChange < 0 since the stack grows down - // This is only relevant if (Group & ITYPE_STACK) is true - // - // If Groups & ITYPE_STACK is set but StackChange = 0, it means that the change - // couldn't be determined (non-constant) - LONG StackChange; - - // Used to assist in debugging - // If set, the current instruction is doing something that requires special handling - // For example, popf can cause tracing to be disabled - - U8 StringAligned : 1; // internal only - U8 NeedsEmulation : 1; // instruction does something that re - U8 Repeat : 1; // instruction repeats until some condition is met (e.g., REP prefix on X86) - U8 ErrorOccurred : 1; // set if instruction is invalid - U8 AnomalyOccurred : 1; // set if instruction is anomalous - U8 LastInstruction : 1; // tells the iterator callback it is the last instruction - U8 CodeBlockFirst: 1; - U8 CodeBlockLast : 1; -} INSTRUCTION; - -typedef struct _DISASSEMBLER -{ - U32 Initialized; - ARCHITECTURE_TYPE ArchType; - ARCHITECTURE_FORMAT_FUNCTIONS *Functions; - INSTRUCTION Instruction; - U32 Stage1Count; // GetInstruction called - U32 Stage2Count; // Opcode fully decoded - U32 Stage3CountNoDecode; // made it through all checks when DISASM_DECODE is not set - U32 Stage3CountWithDecode; // made it through all checks when DISASM_DECODE is set -} DISASSEMBLER; - -#define DISASM_DISASSEMBLE (1<<1) -#define DISASM_DECODE (1<<2) -#define DISASM_SUPPRESSERRORS (1<<3) -#define DISASM_SHOWFLAGS (1<<4) -#define DISASM_ALIGNOUTPUT (1<<5) -#define DISASM_DISASSEMBLE_MASK (DISASM_ALIGNOUTPUT|DISASM_SHOWBYTES|DISASM_DISASSEMBLE) - -BOOL InitDisassembler(DISASSEMBLER *Disassembler, ARCHITECTURE_TYPE Architecture); -void CloseDisassembler(DISASSEMBLER *Disassembler); -INSTRUCTION *GetInstruction(DISASSEMBLER *Disassembler, U64 VirtualAddress, U8 *Address, U32 Flags); - -#ifdef __cplusplus -} -#endif -#endif // DISASM_H diff --git a/src/disasm-lib/disasm_x86.c b/src/disasm-lib/disasm_x86.c deleted file mode 100644 index e8453856..00000000 --- a/src/disasm-lib/disasm_x86.c +++ /dev/null @@ -1,4658 +0,0 @@ -// Copyright (C) 2004, Matt Conover (mconover@gmail.com) -#undef NDEBUG -#include -#include "disasm.h" -#include "cpu.h" - -// Since addresses are internally represented as 64-bit, we need to specially handle -// cases where IP + Displacement wraps around for 16-bit/32-bit operand size -// Otherwise, ignorethe possibility of wraparounds -#define SUPPORT_WRAPAROUND - -#ifdef NO_SANITY_CHECKS -#undef NDEBUG -#undef DEBUG_DISASM -#undef assert -#define assert(x) -#endif - -#ifdef DEBUG_DISASM -#define DISASM_OUTPUT(x) printf x -#else -#define DISASM_OUTPUT(x) -#endif - -#include "disasm_x86_tables.h" - -#ifdef _WIN64 -#pragma warning(disable:4311 4312) -#endif - -//////////////////////////////////////////////////////////////////////// -// Internal macros -//////////////////////////////////////////////////////////////////////// - -#define VIRTUAL_ADDRESS ((U64)Instruction->Address + Instruction->VirtualAddressDelta) - -#define AMD64_DIFF (AMD64_8BIT_OFFSET-X86_8BIT_OFFSET) -#define IS_AMD64() (INS_ARCH_TYPE(Instruction) == ARCH_X64) -#define IS_X86_32() (INS_ARCH_TYPE(Instruction) == ARCH_X86) -#define IS_X86_16() (INS_ARCH_TYPE(Instruction) == ARCH_X86_16) - -#define X86_BOUND 0x62 -#define X86_PUSH_REG 0x50 -#define X86_PUSH_CS 0x0e -#define X86_PUSH_DS 0x1e -#define X86_PUSH_SS 0x16 -#define X86_PUSH_ES 0x06 -#define X86_PUSH_FS 0xa0 -#define X86_PUSH_GS 0xa8 -#define X86_PUSH_U8 0x6a -#define X86_PUSH_U32 0x68 -#define X86_POP_DS 0x1f -#define X86_POP_ES 0x07 -#define X86_POP_SS 0x17 -#define X86_POP_FS 0xa1 -#define X86_POP_GS 0xa9 -#define X86_POP_REG 0x58 - -#define OPCSTR Instruction->String+Instruction->StringIndex -#define APPEND Instruction->StringIndex += (U8)_snprintf -#define APPENDPAD(x) \ -{ \ - if (Instruction->StringAligned) \ - { \ - if (Instruction->StringIndex > x) assert(0); \ - while (x != Instruction->StringIndex) APPENDB(' '); \ - } \ - else if (Instruction->StringIndex) \ - { \ - APPENDB(' '); \ - } \ -} - -#define APPENDB(a) Instruction->String[Instruction->StringIndex++] = a -#define APPENDS(a) APPEND(OPCSTR, SIZE_LEFT, a); - -#define SIZE_LEFT (MAX_OPCODE_DESCRIPTION-1 > Instruction->StringIndex ? MAX_OPCODE_DESCRIPTION-Instruction->StringIndex : 0) - -// If an address size prefix is used for an instruction that doesn't make sense, restore it -// to the default - -#define SANITY_CHECK_OPERAND_SIZE() \ -{ \ - if (!Instruction->AnomalyOccurred && X86Instruction->HasOperandSizePrefix) \ - { \ - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected operand size prefix\n", VIRTUAL_ADDRESS); \ - Instruction->AnomalyOccurred = TRUE; \ - X86Instruction->HasOperandSizePrefix = FALSE; \ - switch (X86Instruction->OperandSize) \ - { \ - case 4: X86Instruction->OperandSize = 2; break; \ - case 2: X86Instruction->OperandSize = 4; break; \ - default: assert(0); \ - } \ - } \ -} - -#define SANITY_CHECK_ADDRESS_SIZE() \ -{ \ - if (!Instruction->AnomalyOccurred && X86Instruction->HasAddressSizePrefix) \ - { \ - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected address size prefix\n", VIRTUAL_ADDRESS); \ - Instruction->AnomalyOccurred = TRUE; \ - } \ - X86Instruction->HasAddressSizePrefix = FALSE; \ - switch (INS_ARCH_TYPE(Instruction)) \ - { \ - case ARCH_X64: X86Instruction->AddressSize = 8; break; \ - case ARCH_X86: X86Instruction->AddressSize = 4; break; \ - case ARCH_X86_16: X86Instruction->AddressSize = 2; break; \ - } \ -} - -#define SANITY_CHECK_SEGMENT_OVERRIDE() \ - if (!Instruction->AnomalyOccurred && X86Instruction->HasSegmentOverridePrefix) \ - { \ - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected segment override\n", VIRTUAL_ADDRESS); \ - Instruction->AnomalyOccurred = TRUE; \ - } - -#define INSTR_INC(size) \ -{ \ - Instruction->Length += size; \ - Address += size; \ -} - -#define X86_SET_TARGET() \ -{ \ - if (X86Instruction->HasSelector) \ - { \ - if (!Instruction->AnomalyOccurred) \ - { \ - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: unexpected segment 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->Selector); \ - Instruction->AnomalyOccurred = TRUE; \ - } \ - } \ - else \ - { \ - switch (X86Instruction->Segment) \ - { \ - case SEG_CS: \ - case SEG_DS: \ - case SEG_SS: \ - case SEG_ES: \ - assert(!X86Instruction->HasSelector); \ - Operand->TargetAddress = (U64)X86Instruction->Displacement; \ - /* assert(!GetAbsoluteAddressFromSegment((BYTE)X86Instruction->Segment, (DWORD)X86Instruction->Displacement) || GetAbsoluteAddressFromSegment(X86Instruction->Segment, (DWORD)X86Instruction->Displacement) == Operand->TargetAddress); */ \ - break; \ - case SEG_FS: \ - case SEG_GS: \ - assert(!X86Instruction->HasSelector); \ - Operand->TargetAddress = (U64)GetAbsoluteAddressFromSegment((BYTE)X86Instruction->Segment, (DWORD)X86Instruction->Displacement); \ - break; \ - default: \ - assert(0); /* shouldn't be possible */ \ - break; \ - } \ - } \ -} - -#define X86_SET_SEG(reg) \ -{ \ - if (!X86Instruction->HasSegmentOverridePrefix && (reg == REG_EBP || reg == REG_ESP)) \ - { \ - assert(!X86Instruction->HasSelector); \ - X86Instruction->Segment = SEG_SS; \ - } \ -} - -#define X86_SET_ADDR() \ -{ \ - if (Operand->Flags & OP_DST) \ - { \ - assert(!X86Instruction->HasDstAddressing); \ - X86Instruction->HasDstAddressing = TRUE; \ - X86Instruction->DstOpIndex[X86Instruction->DstOpCount] = (U8)OperandIndex; \ - X86Instruction->DstOpCount++; \ - X86Instruction->DstAddressIndex = (U8)OperandIndex; \ - } \ - if (Operand->Flags & OP_SRC) \ - { \ - if (Instruction->Type != ITYPE_STRCMP) assert(!X86Instruction->HasSrcAddressing); \ - X86Instruction->HasSrcAddressing = TRUE; \ - X86Instruction->SrcOpIndex[X86Instruction->SrcOpCount] = (U8)OperandIndex; \ - X86Instruction->SrcOpCount++; \ - X86Instruction->SrcAddressIndex = (U8)OperandIndex; \ - } \ -} - -#define X86_SET_REG(reg) \ -{ \ - if (Operand->Flags & OP_DST) \ - { \ - X86Instruction->DstOpIndex[X86Instruction->DstOpCount] = (U8)OperandIndex; \ - X86Instruction->DstOpCount++; \ - assert(OperandIndex < 2); \ - if (Operand->Length > 1 && reg == REG_ESP) Instruction->Groups |= ITYPE_STACK; \ - } \ - if (Operand->Flags & OP_SRC) \ - { \ - X86Instruction->SrcOpIndex[X86Instruction->SrcOpCount] = (U8)OperandIndex; \ - X86Instruction->SrcOpCount++; \ - } \ -} - -#define CHECK_AMD64_REG() { if (IS_AMD64()) Operand->Register += AMD64_DIFF; } - -//////////////////////////////////////////////////////////////////////// -// Internal structures/variables -//////////////////////////////////////////////////////////////////////// - -ARCHITECTURE_FORMAT_FUNCTIONS X86 = -{ - X86_InitInstruction, - NULL, - X86_GetInstruction, - X86_FindFunctionByPrologue -}; - -char *X86_Registers[0xE0] = -{ - // Segments - "es", // 0x00 - "cs", // 0x01 - "ss", // 0x02 - "ds", // 0x03 - "fs", // 0x04 - "gs", // 0x05 - "flags", // 0x06 - "eflags", // 0x07 - "rflags", // 0x08 - "ip+ilen", // 0x09 - "eip+ilen", // 0x0A - "rip+ilen", // 0x0B - NULL, // 0x0C - NULL, // 0x0D - NULL, // 0x0E - NULL, // 0x0F - - // Test - "tr0", // 0x10 - "tr1", // 0x11 - "tr2", // 0x12 - "tr3", // 0x13 - "tr4", // 0x14 - "tr5", // 0x15 - "tr6", // 0x16 - "tr7", // 0x17 - "tr8", // 0x18 - "tr9", // 0x19 - "tr10", // 0x1A - "tr11", // 0x1B - "tr12", // 0x1C - "tr13", // 0x1D - "tr14", // 0x1E - "tr15", // 0x1F - - // Control - "cr0", // 0x20 - "cr1", // 0x21 - "cr2", // 0x22 - "cr3", // 0x23 - "cr4", // 0x24 - "cr5", // 0x25 - "cr6", // 0x26 - "cr7", // 0x27 - "cr8", // 0x18 - "cr9", // 0x19 - "cr10", // 0x1A - "cr11", // 0x1B - "cr12", // 0x1C - "cr13", // 0x1D - "cr14", // 0x1E - "cr15", // 0x1F - - // Debug - "dr0", // 0x30 - "dr1", // 0x31 - "dr2", // 0x32 - "dr3", // 0x33 - "dr4", // 0x34 - "dr5", // 0x35 - "dr6", // 0x36 - "dr7", // 0x37 - "dr8", // 0x38 - "dr9", // 0x39 - "dr10", // 0x3A - "dr11", // 0x3B - "dr12", // 0x3C - "dr13", // 0x3D - "dr14", // 0x3E - "dr15", // 0x3F - - // FPU - "st(0)", // 0x40 - "st(1)", // 0x41 - "st(2)", // 0x42 - "st(3)", // 0x43 - "st(4)", // 0x44 - "st(5)", // 0x45 - "st(6)", // 0x46 - "st(7)", // 0x47 - NULL, // 0x48 - NULL, // 0x49 - NULL, // 0x4A - NULL, // 0x4B - NULL, // 0x4C - NULL, // 0x4D - NULL, // 0x4E - NULL, // 0x4F - - // MMX - "mm0", // 0x50 - "mm1", // - "mm2", - "mm3", - "mm4", - "mm5", - "mm6", - "mm7", - NULL, // 0x58 - NULL, // 0x59 - NULL, // 0x5A - NULL, // 0x5B - NULL, // 0x5C - NULL, // 0x5D - NULL, // 0x5E - NULL, // 0x5F - - // XMM - "xmm0", // 0x60 - "xmm1", // 0x61 - "xmm2", // 0x62 - "xmm3", // 0x63 - "xmm4", // 0x64 - "xmm5", // 0x65 - "xmm6", // 0x66 - "xmm7", // 0x67 - "xmm8", // 0x68 - "xmm9", // 0x69 - "xmm10", // 0x6a - "xmm11", // 0x6b - "xmm12", // 0x6c - "xmm13", // 0x6d - "xmm14", // 0x6e - "xmm15", // 0x6f - - // 8-bit - "al", // 0x70 - "cl", // 0x71 - "dl", // 0x72 - "bl", // 0x73 - "ah", // 0x74 - "ch", // 0x75 - "dh", // 0x76 - "bh", // 0x77 - NULL, // 0x78 - NULL, // 0x79 - NULL, // 0x7A - NULL, // 0x7B - NULL, // 0x7C - NULL, // 0x7D - NULL, // 0x7E - NULL, // 0x7F - - // 16-bit - "ax", // 0x80 - "cx", // 0x81 - "dx", // 0x82 - "bx", // 0x83 - "sp", // 0x84 - "bp", // 0x85 - "si", // 0x86 - "di", // 0x87 - NULL, // 0x88 - NULL, // 0x89 - NULL, // 0x8A - NULL, // 0x8B - NULL, // 0x8C - NULL, // 0x8D - NULL, // 0x8E - NULL, // 0x8F - - // 32-bit - "eax", // 0x90 - "ecx", // 0x91 - "edx", // 0x92 - "ebx", // 0x93 - "esp", // 0x94 - "ebp", // 0x95 - "esi", // 0x96 - "edi", // 0x97 - NULL, // 0x98 - NULL, // 0x99 - NULL, // 0x9A - NULL, // 0x9B - NULL, // 0x9C - NULL, // 0x9D - NULL, // 0x9E - NULL, // 0x9F - - // X86-64 8-bit register - "al", // 0xA0 - "cl", // 0xA1 - "dl", // 0xA2 - "bl", // 0xA3 - "spl", // 0xA4 - "bpl", // 0xA5 - "sil", // 0xA6 - "dil", // 0xA7 - "r8b", // 0xA8 - "r9b", // 0xA9 - "r10b", // 0xAA - "r11b", // 0xAB - "r12b", // 0xAC - "r13b", // 0xAD - "r14b", // 0xAE - "r15b", // 0xAF - - // X86-64 16-bit register - "ax", // 0xB0 - "cx", // 0xB1 - "dx", // 0xB2 - "bx", // 0xB3 - "sp", // 0xB4 - "bp", // 0xB5 - "si", // 0xB6 - "di", // 0xB7 - "r8w", // 0xB8 - "r9w", // 0xB9 - "r10w", // 0xBA - "r11w", // 0xBB - "r12w", // 0xBC - "r13w", // 0xBD - "r14w", // 0xBE - "r15w", // 0xBF - - // X86-64 32-bit register - "eax", // 0xC0 - "ecx", // 0xC1 - "edx", // 0xC2 - "ebx", // 0xC3 - "esp", // 0xC4 - "ebp", // 0xC5 - "esi", // 0xC6 - "edi", // 0xC7 - "r8d", // 0xC8 - "r9d", // 0xC9 - "r10d", // 0xCA - "r11d", // 0xCB - "r12d", // 0xCC - "r13d", // 0xCD - "r14d", // 0xCE - "r15d", // 0xCF - - // X86-64 64-bit register - "rax", // 0xD0 - "rcx", // 0xD1 - "rdx", // 0xD2 - "rbx", // 0xD3 - "rsp", // 0xD4 - "rbp", // 0xD5 - "rsi", // 0xD6 - "rdi", // 0xD7 - "r8", // 0xD8 - "r9", // 0xD9 - "r10", // 0xDA - "r11", // 0xDB - "r12", // 0xDC - "r13", // 0xDD - "r14", // 0xDE - "r15" // 0xDF -}; - -void OutputBounds(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputDescriptor(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputSegOffset(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputPackedReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputPackedBCD(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputScalarReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputScalarGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputFPUEnvironment(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputFPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -void OutputCPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); - -typedef void (*OUTPUT_OPTYPE)(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex); -#define OPTYPE_SHIFT 24 -#define MAX_OPTYPE_INDEX 26 -OUTPUT_OPTYPE OptypeHandlers[] = -{ - NULL, - OutputBounds, // 01 OPTYPE_a - OutputGeneral, // 02 OPTYPE_b - OutputGeneral, // 03 OPTYPE_d - OutputSegOffset, // 04 OPTYPE_p - OutputGeneral, // 05 OPTYPE_q - OutputDescriptor, // 06 OPTYPE_dt - OutputGeneral, // 07 OPTYPE_v - OutputGeneral, // 08 OPTYPE_w - OutputPackedReal, // 09 OPTYPE_ps - OutputPackedReal, // 0A OPTYPE_pd - OutputPackedBCD, // 0B OPTYPE_pb - OutputScalarReal, // 0C OPTYPE_ss - OutputScalarReal, // 0D OPTYPE_sd - OutputScalarReal, // 0E OPTYPE_se - OutputFPUEnvironment, // 0F OPTYPE_fev - OutputFPUState, // 10 OPTYPE_fst1 - OutputFPUState, // 11 OPTYPE_fst2 - OutputGeneral, // 12 OPTYPE_z - OutputGeneral, // 13 OPTYPE_o - OutputGeneral, // 14 OPTYPE_dq - OutputGeneral, // 15 OPTYPE_mw - OutputScalarGeneral, // 16 OPTYPE_sso - OutputScalarGeneral, // 17 OPTYPE_sdo - OutputCPUState, // 18 OPTYPE_cpu - OutputGeneral, // 19 OPTYPE_lea -}; - -#define OPTYPE_a 0x01000000 -#define OPTYPE_b 0x02000000 -#define OPTYPE_d 0x03000000 -#define OPTYPE_p 0x04000000 -#define OPTYPE_q 0x05000000 -#define OPTYPE_dt 0x06000000 -#define OPTYPE_v 0x07000000 -#define OPTYPE_w 0x08000000 -#define OPTYPE_ps 0x09000000 // packed 128-bit single real -#define OPTYPE_pd 0x0A000000 // packed 128-bit double real -#define OPTYPE_pb 0x0B000000 // packed BCD (10 bytes, 18-bit precision) -#define OPTYPE_ss 0x0C000000 // scalar single real -#define OPTYPE_sd 0x0D000000 // scalar double real -#define OPTYPE_se 0x0E000000 // scalar extended real -#define OPTYPE_fev 0x0F000000 // FPU environment (28 bytes if 32-bit modes, 14 bytes in 16-bit mode) -#define OPTYPE_fst1 0x10000000 // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode) -#define OPTYPE_fst2 0x11000000 // FPU/MMX/XMM/MXCSR state (512 bytes) -#define OPTYPE_z 0x12000000 -#define OPTYPE_o 0x13000000 -#define OPTYPE_dq 0x14000000 // OPTYPE_d or OPTYPE_o -#define OPTYPE_mw 0x15000000 // word if memory, register size otherwise -#define OPTYPE_sso 0x16000000 // OPTYPE_ss or OPTYPE_o -#define OPTYPE_sdo 0x17000000 // OPTYPE_ss or OPTYPE_o -#define OPTYPE_cpu 0x18000000 // pointer to CPU state structure -#define OPTYPE_lea 0x19000000 // size set by other operand - -//////////////////////////////////////////////////////////////////////// -// Internal functions -//////////////////////////////////////////////////////////////////////// - -#ifdef TEST_DISASM // TODO: remove -U32 X86_GetLength(INSTRUCTION *Instruction, U8 *Address); -#endif - -INTERNAL BOOL IsValidLockPrefix(X86_INSTRUCTION *Instruction, U8 Opcode, U32 OpcodeLength, U8 Group, U8 OpcodeExtension); -INTERNAL U8 *SetOperands(INSTRUCTION *Instruction, U8 *Address, U32 Flags); -INTERNAL U8 *SetModRM32(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors); -INTERNAL U8 *SetModRM16(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors); -INTERNAL U8 *SetSIB(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors); -INTERNAL U64 ApplyDisplacement(U64 Address, INSTRUCTION *Instruction); - -////////////////////////////////////////////////////////// -// Instruction setup -////////////////////////////////////////////////////////// - -#define APPLY_OFFSET(addr) \ -{ \ - switch (X86Instruction->OperandSize) \ - { \ - case 8: addr = ((U64)(addr + Instruction->VirtualAddressDelta)); break; \ - case 4: addr = (U64)((U32)(addr + Instruction->VirtualAddressDelta)); break; \ - case 2: addr = (U64)((U8)(addr + Instruction->VirtualAddressDelta)); break; \ - default: assert(0); break; \ - } \ -} - -BOOL X86_InitInstruction(INSTRUCTION *Instruction) -{ - X86_INSTRUCTION *X86Instruction; -#ifdef NO_SANITY_CHECKS - assert(0); // be sure assertions are disabled -#endif - X86Instruction = &Instruction->X86; - memset(X86Instruction, 0, sizeof(X86_INSTRUCTION)); - - switch (INS_ARCH_TYPE(Instruction)) - { - case ARCH_X64: - X86Instruction->AddressSize = 8; - X86Instruction->OperandSize = 4; - break; - case ARCH_X86: - X86Instruction->AddressSize = 4; - X86Instruction->OperandSize = 4; - break; - case ARCH_X86_16: - X86Instruction->AddressSize = 2; - X86Instruction->OperandSize = 2; - break; - default: - assert(0); - return FALSE; - } - X86Instruction->Instruction = Instruction; - X86Instruction->Segment = SEG_DS; - return TRUE; -} - -//////////////////////////////////////////////////////////// -// Formatting -// You can change these to whatever you prefer -//////////////////////////////////////////////////////////// - -#define X86_WRITE_OPFLAGS() \ - if (Flags & DISASM_SHOWFLAGS) \ - { \ - APPENDB('{'); \ - assert(Operand->Flags & (OP_EXEC|OP_SRC|OP_DST)); \ - if (Operand->Flags & OP_IPREL) APPENDB('r'); \ - if (Operand->Flags & OP_FAR) APPENDB('f'); \ - if (Operand->Flags & OP_CONDR) APPENDB('c'); \ - if (Operand->Flags & OP_EXEC) APPENDB('X'); \ - else if (Operand->Flags & OP_SRC) APPENDB('R'); \ - if (Operand->Flags & OP_CONDW) APPENDB('c'); \ - if (Operand->Flags & OP_DST) APPENDB('W'); \ - if (Operand->Flags & OP_SYS) APPENDB('S'); \ - if (Operand->Flags & OP_ADDRESS) APPENDB('A'); \ - if (Operand->Flags & OP_PARAM) APPENDB('P'); \ - if (Operand->Flags & OP_LOCAL) APPENDB('L'); \ - if (Operand->Flags & OP_GLOBAL) APPENDB('G'); \ - APPENDB('}'); \ - } - -#define X86_WRITE_IMMEDIATE() \ -{ \ - switch (Operand->Length) \ - { \ - case 8: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%02I64X=", Operand->Value_U64); \ - if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%I64u", Operand->Value_U64); \ - /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02I64X=%I64d", -Operand->Value_S64, Operand->Value_S64);*/ \ - else APPEND(OPCSTR, SIZE_LEFT, "%I64d", Operand->Value_S64); \ - break; \ - case 4: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%02lX=", (U32)Operand->Value_U64); \ - if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%lu", (U32)Operand->Value_U64); \ - /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02lX=%ld", (U32)-Operand->Value_S64, (S32)Operand->Value_S64);*/ \ - else APPEND(OPCSTR, SIZE_LEFT, "%ld", (S32)Operand->Value_S64); \ - break; \ - case 2: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%02X=", (U16)Operand->Value_U64); \ - if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%u", (U16)Operand->Value_U64); \ - /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X=%d", (U16)-Operand->Value_S64, (S16)Operand->Value_S64);*/ \ - else APPEND(OPCSTR, SIZE_LEFT, "%d", (S16)Operand->Value_S64); \ - break; \ - case 1: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%02X=", (U8)Operand->Value_U64); \ - if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%u", (U8)Operand->Value_U64); \ - /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X=%d", (U8)-Operand->Value_S64, (S8)Operand->Value_S64);*/ \ - else APPEND(OPCSTR, SIZE_LEFT, "%d", (S8)Operand->Value_S64); \ - break; \ - default: assert(0); break; \ - } \ -} - -#define X86_WRITE_ABSOLUTE_DISPLACEMENT() \ -{ \ - switch (X86Instruction->AddressSize) \ - { \ - case 8: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%04I64X", X86Instruction->Displacement); \ - break; \ - case 4: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%04lX", (U32)X86Instruction->Displacement); \ - break; \ - case 2: \ - APPEND(OPCSTR, SIZE_LEFT, "0x%04X", (U16)X86Instruction->Displacement); \ - break; \ - default: assert(0); break; \ - } \ -} - -#define X86_WRITE_RELATIVE_DISPLACEMENT64() \ - if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02I64X", X86Instruction->Displacement); \ - else APPEND(OPCSTR, SIZE_LEFT, "-0x%02I64X", -X86Instruction->Displacement); - -#define X86_WRITE_RELATIVE_DISPLACEMENT32() \ - if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02lX", (U32)X86Instruction->Displacement); \ - else APPEND(OPCSTR, SIZE_LEFT, "-0x%02lX", (U32)-X86Instruction->Displacement); - -#define X86_WRITE_RELATIVE_DISPLACEMENT16() \ - if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02X", (U16)X86Instruction->Displacement); \ - else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X", (U16)-X86Instruction->Displacement); - -#define X86_WRITE_RELATIVE_DISPLACEMENT() \ -{ \ - switch (X86Instruction->AddressSize) \ - { \ - case 8: \ - X86_WRITE_RELATIVE_DISPLACEMENT64() \ - break; \ - case 4: \ - X86_WRITE_RELATIVE_DISPLACEMENT32() \ - break; \ - case 2: \ - X86_WRITE_RELATIVE_DISPLACEMENT16() \ - break; \ - default: assert(0); break; \ - } \ -} - -#define X86_WRITE_IP_OFFSET(op) \ -{ \ - switch (X86Instruction->OperandSize) \ - { \ - case 8: \ - APPENDS("[rip+ilen"); \ - assert((op)->TargetAddress); \ - X86_WRITE_RELATIVE_DISPLACEMENT64() \ - APPEND(OPCSTR, SIZE_LEFT, "]=0x%04I64X", (op)->TargetAddress+Instruction->VirtualAddressDelta); \ - break; \ - case 4: \ - APPENDS("[eip+ilen"); \ - assert((op)->TargetAddress); \ - X86_WRITE_RELATIVE_DISPLACEMENT32() \ - APPEND(OPCSTR, SIZE_LEFT, "]=0x%04lX", (U32)((op)->TargetAddress+Instruction->VirtualAddressDelta)); \ - break; \ - case 2: \ - APPENDS("[ip+ilen"); \ - X86_WRITE_RELATIVE_DISPLACEMENT16() \ - APPEND(OPCSTR, SIZE_LEFT, "]=0x%04X", (U16)((op)->TargetAddress+Instruction->VirtualAddressDelta)); \ - break; \ - default: assert(0); break; \ - } \ -} - -#define X86_WRITE_OFFSET(op) \ -{ \ - assert((op)->Length <= 8); \ - if (X86Instruction->HasSelector) \ - { \ - assert((op)->Flags & OP_FAR); \ - APPEND(OPCSTR, SIZE_LEFT, "%s 0x%02X:[", DataSizes[((op)->Length >> 1)], X86Instruction->Selector); \ - } \ - else \ - { \ - assert(!((op)->Flags & OP_FAR)); \ - assert(X86Instruction->Segment < SEG_MAX) ; \ - APPEND(OPCSTR, SIZE_LEFT, "%s %s:[", DataSizes[((op)->Length >> 1)], Segments[X86Instruction->Segment]); \ - } \ - X86_WRITE_ABSOLUTE_DISPLACEMENT() \ - APPENDB(']'); \ -} - -void OutputAddress(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - BOOL ShowDisplacement = FALSE; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - - assert(!X86Instruction->HasSelector); - assert(X86Instruction->SrcAddressIndex == OperandIndex || X86Instruction->DstAddressIndex == OperandIndex); - if (Operand->Length > 16 || (Operand->Length > 1 && (Operand->Length & 1))) APPEND(OPCSTR, SIZE_LEFT, "%d_byte ptr ", Operand->Length); - else APPEND(OPCSTR, SIZE_LEFT, "%s ", DataSizes[Operand->Length >> 1]); - - // - // This attempts to display the address intelligently - // If it has a positive 32-bit displacement, it is shown as seg:Displacement[base+index*scale] - // If it is a negative displacement or 8-bit, it is shown as seg:[base+index*scale+displacement] - // - APPEND(OPCSTR, SIZE_LEFT, "%s:", Segments[X86Instruction->Segment]); - if (X86Instruction->HasBaseRegister) - { - if (X86Instruction->Displacement) - { - if (X86Instruction->HasFullDisplacement) X86_WRITE_ABSOLUTE_DISPLACEMENT() - else ShowDisplacement = TRUE; - } - APPEND(OPCSTR, SIZE_LEFT, "[%s", X86_Registers[X86Instruction->BaseRegister]); - if (X86Instruction->HasIndexRegister) - { - APPEND(OPCSTR, SIZE_LEFT, "+%s", X86_Registers[X86Instruction->IndexRegister]); - if (X86Instruction->Scale > 1) APPEND(OPCSTR, SIZE_LEFT, "*%d", X86Instruction->Scale); - } - if (ShowDisplacement) X86_WRITE_RELATIVE_DISPLACEMENT() - APPENDB(']'); - if (X86Instruction->Relative) - { - U64 Address = Operand->TargetAddress; - assert(Address); - APPLY_OFFSET(Address) - APPEND(OPCSTR, SIZE_LEFT, "=[0x%04I64X]", Address); - } - } - else if (X86Instruction->HasIndexRegister) - { - if (X86Instruction->Displacement) - { - if (X86Instruction->HasFullDisplacement) X86_WRITE_ABSOLUTE_DISPLACEMENT() - else ShowDisplacement = TRUE; - } - APPEND(OPCSTR, SIZE_LEFT, "[%s", X86_Registers[X86Instruction->IndexRegister]); - if (X86Instruction->Scale > 1) APPEND(OPCSTR, SIZE_LEFT, "*%d", X86Instruction->Scale); - if (ShowDisplacement) X86_WRITE_RELATIVE_DISPLACEMENT() - APPENDB(']'); - } - else // just a displacement - { - APPENDB('['); - X86_WRITE_ABSOLUTE_DISPLACEMENT() - APPENDB(']'); - } -} - -void OutputBounds(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing); - assert(!(Operand->Length & 1)); - Operand->Length >>= 1; - APPENDB('('); - OutputAddress(Instruction, Operand, OperandIndex); - APPENDS(", "); - X86Instruction->Displacement += Operand->Length; - OutputAddress(Instruction, Operand, OperandIndex); - X86Instruction->Displacement -= Operand->Length; - APPENDB(')'); - Operand->Length <<= 1; -} - -void OutputGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) || - (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex)) - { - OutputAddress(Instruction, Operand, OperandIndex); - } - else - { - APPENDS(X86_Registers[Operand->Register]); - } -} - -void OutputDescriptor(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing); - OutputAddress(Instruction, Operand, OperandIndex); -} - -void OutputPackedReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) || - (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex)) - { - OutputAddress(Instruction, Operand, OperandIndex); - } - else - { - APPENDS(X86_Registers[Operand->Register]); - } -} - -void OutputPackedBCD(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) || - (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex)) - { - OutputAddress(Instruction, Operand, OperandIndex); - } - else - { - APPENDS(X86_Registers[Operand->Register]); - } -} - -void OutputScalarReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) || - (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex)) - { - OutputAddress(Instruction, Operand, OperandIndex); - } - else - { - APPENDS(X86_Registers[Operand->Register]); - } -} - -void OutputScalarGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - if (Operand->Type == OPTYPE_FLOAT) - { - OutputScalarReal(Instruction, Operand, OperandIndex); - } - else - { - OutputGeneral(Instruction, Operand, OperandIndex); - } -} - -void OutputFPUEnvironment(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing); - OutputAddress(Instruction, Operand, OperandIndex); -} - -void OutputFPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing); - OutputAddress(Instruction, Operand, OperandIndex); -} - -void OutputCPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing); - OutputAddress(Instruction, Operand, OperandIndex); -} - -void OutputSegOffset(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - assert(X86Instruction->HasSrcAddressing); - OutputAddress(Instruction, Operand, OperandIndex); -} - -//////////////////////////////////////////////////////////// -// Prologue support -//////////////////////////////////////////////////////////// - -typedef struct _PROLOGUE -{ - char *Data; - U32 Length; -} PROLOGUE; - -PROLOGUE StandardPrologues[] = -{ - { "\x55\x8b\xec", 3 }, - { "\x55\x89\xe5", 3 }, - { "\x83\xec", 2 }, - { "\x81\xec", 2 }, - // TODO: add AMD64 prologues - // TODO: add VS2003/VS2003 prologues - // TODO: add any unique prologues from other compilers - { NULL, 0 } -}; - -// Find the first function between StartAddress and EndAddress -// -// This will match a standard prologue and then analyze the following instructions to verify -// it is a valid function -U8 *X86_FindFunctionByPrologue(INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, U32 Flags) -{ - assert(0); // TODO - return NULL; -} - -////////////////////////////////////////////////////////// -// Instruction decoder -////////////////////////////////////////////////////////// - -BOOL X86_GetInstruction(INSTRUCTION *Instruction, U8 *Address, U32 Flags) -{ - BOOL SpecialExtension = FALSE; - U8 Opcode = 0, OpcodeExtension = 0, Group = 0, SSE_Prefix = 0, Suffix; - U32 i = 0, Result = 0, tmpScale; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - X86_OPCODE *X86Opcode; -#ifdef TEST_DISASM - U32 InstructionLength = 0; -#endif - INSTRUCTION_OPERAND *Operand, *Operand1 = NULL; - DISASSEMBLER *Disassembler = Instruction->Disassembler; - BOOL Decode = Flags & DISASM_DECODE; - BOOL Disassemble = Flags & DISASM_DISASSEMBLE; -#if _DEBUG - BOOL SuppressErrors = Flags & DISASM_SUPPRESSERRORS; -#else - BOOL SuppressErrors = TRUE; -#endif - - if (Disassemble && !Decode) - { - assert(0); - Decode = TRUE; - } - - if (!Address || !X86_InitInstruction(Instruction)) - { - assert(0); - goto abort; - } - - assert(Instruction->Address == Address); - assert(!Instruction->StringIndex && !Instruction->Length); - - Disassembler->Stage1Count++; - if (Flags & DISASM_ALIGNOUTPUT) Instruction->StringAligned = TRUE; - - // - // Get prefixes or three byte opcode - // - while (TRUE) - { - Opcode = *Address; - INSTR_INC(1); // increment Instruction->Length and address - X86Opcode = &X86_Opcodes_1[Opcode]; - - // Handle a misplaced REX prefix -- AMD64 manual says it is just ignored - if (IS_AMD64() && (Opcode >= REX_PREFIX_START && Opcode <= REX_PREFIX_END) && X86_PREFIX((&X86_Opcodes_1[*Address]))) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: REX prefix before legacy prefix 0x%02X\n", VIRTUAL_ADDRESS, Opcode); - Instruction->AnomalyOccurred = TRUE; - } - continue; - } - - if (X86_PREFIX(X86Opcode)) - { - if (!Instruction->AnomalyOccurred) - { - for (i = 0; i < Instruction->PrefixCount; i++) - { - if (Instruction->Prefixes[i] == Opcode) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Duplicate prefix 0x%02X\n", VIRTUAL_ADDRESS, Opcode); - Instruction->AnomalyOccurred = TRUE; - break; - } - } - } - - switch (Opcode) - { - case PREFIX_REPNE: // may be three byte opcode - SSE_Prefix = Opcode; - if (!Instruction->AnomalyOccurred && X86Instruction->HasRepeatWhileEqualPrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - Instruction->Repeat = TRUE; - X86Instruction->HasRepeatWhileEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileNotEqualPrefix = TRUE; - break; - case PREFIX_REP: // may be three byte opcode - SSE_Prefix = Opcode; - if (!Instruction->AnomalyOccurred && X86Instruction->HasRepeatWhileNotEqualPrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - - Instruction->Repeat = TRUE; - X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileEqualPrefix = TRUE; - break; - - case PREFIX_OPERAND_SIZE: // may be three byte opcode - SSE_Prefix = Opcode; - if (!Instruction->AnomalyOccurred && X86Instruction->HasOperandSizePrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - - if (X86Instruction->HasOperandSizePrefix) break; - else X86Instruction->HasOperandSizePrefix = TRUE; - switch (X86Instruction->OperandSize) - { - case 4: X86Instruction->OperandSize = 2; break; - case 2: X86Instruction->OperandSize = 4; break; - default: assert(0); goto abort; - } - break; - - case PREFIX_ADDRESS_SIZE: - if (!Instruction->AnomalyOccurred && X86Instruction->HasAddressSizePrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - - if (X86Instruction->HasAddressSizePrefix) break; - else X86Instruction->HasAddressSizePrefix = TRUE; - switch (X86Instruction->AddressSize) - { - case 8: - X86Instruction->AddressSize = 4; - break; - case 4: - assert(!IS_AMD64()); // this should not be possible - X86Instruction->AddressSize = 2; - break; - case 2: - X86Instruction->AddressSize = 4; - break; - default: - assert(0); goto abort; - } - break; - - case PREFIX_SEGMENT_OVERRIDE_ES: - SANITY_CHECK_SEGMENT_OVERRIDE(); - if (!IS_AMD64()) - { - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_ES; - } - else if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - break; - case PREFIX_SEGMENT_OVERRIDE_CS: - SANITY_CHECK_SEGMENT_OVERRIDE(); - if (!IS_AMD64()) - { - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_CS; - } - else if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - break; - case PREFIX_SEGMENT_OVERRIDE_SS: - SANITY_CHECK_SEGMENT_OVERRIDE(); - if (!IS_AMD64()) - { - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_SS; - } - else if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - break; - case PREFIX_SEGMENT_OVERRIDE_DS: - SANITY_CHECK_SEGMENT_OVERRIDE(); - if (!IS_AMD64()) - { - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_DS; - } - else if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - break; - case PREFIX_SEGMENT_OVERRIDE_FS: - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_FS; - break; - case PREFIX_SEGMENT_OVERRIDE_GS: - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSegmentOverridePrefix = TRUE; - X86Instruction->Segment = SEG_GS; - break; - - case PREFIX_LOCK: - if (!Instruction->AnomalyOccurred && X86Instruction->HasLockPrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasLockPrefix = TRUE; - break; - - default: - assert(0); - goto abort; - } - - if (Instruction->PrefixCount >= X86_MAX_INSTRUCTION_LEN) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH); - goto abort; - } - else if (Instruction->PrefixCount == X86_MAX_PREFIX_LENGTH) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH); - Instruction->AnomalyOccurred = TRUE; - } - - assert(Instruction->AnomalyOccurred || Instruction->PrefixCount < X86_MAX_PREFIX_LENGTH); - Instruction->Prefixes[Instruction->PrefixCount] = Opcode; - Instruction->PrefixCount++; - //DISASM_OUTPUT(("[0x%08I64X] Prefix 0x%02X (prefix count %d)\n", VIRTUAL_ADDRESS, Opcode, Instruction->PrefixCount)); - } - else - { - break; - } - } - - // Check for REX opcode - // This is checked here instead of the prefix loop above because it must be the - // last prefix - if (IS_AMD64() && (Opcode >= REX_PREFIX_START && Opcode <= REX_PREFIX_END)) - { - if (Instruction->PrefixCount >= X86_MAX_INSTRUCTION_LEN) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH); - goto abort; - } - else if (!Instruction->AnomalyOccurred && Instruction->PrefixCount == AMD64_MAX_PREFIX_LENGTH) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH); - Instruction->AnomalyOccurred = TRUE; - } - - assert(Instruction->AnomalyOccurred || Instruction->PrefixCount < AMD64_MAX_PREFIX_LENGTH); - - Instruction->Prefixes[Instruction->PrefixCount] = Opcode; - Instruction->PrefixCount++; - X86Instruction->rex_b = Opcode; - SET_REX(X86Instruction->rex, X86Instruction->rex_b); - DISASM_OUTPUT(("[0x%08I64X] REX prefix 0x%02X (prefix count %d, w=%d, r=%d, x=%d, b=%d)\n", VIRTUAL_ADDRESS, Opcode, Instruction->PrefixCount, X86Instruction->rex.w, X86Instruction->rex.r, X86Instruction->rex.x, X86Instruction->rex.b)); - - assert(X86Instruction->AddressSize >= 4); - if (X86Instruction->rex.w) - { - X86Instruction->OperandSize = 8; - X86Instruction->HasOperandSizePrefix = FALSE; - } - else if (X86Instruction->HasOperandSizePrefix) - { - assert(X86Instruction->OperandSize == 2); - } - else if (X86Instruction->rex_b == REX_PREFIX_START) - { - X86Instruction->rex_b = 0; - } - - Opcode = *Address; - INSTR_INC(1); // increment Instruction->Length and address - - X86Opcode = &X86_Opcodes_1[Opcode]; - assert(!X86_PREFIX(X86Opcode)); - } - //DISASM_OUTPUT(("[0x%08I64X] OperandSize = %d, AddressSize = %d\n", VIRTUAL_ADDRESS, X86Instruction->OperandSize, X86Instruction->AddressSize)); - Instruction->LastOpcode = Opcode; - Instruction->OpcodeAddress = Address-1; - - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid opcode 0x%02X\n", VIRTUAL_ADDRESS, Opcode); - goto abort; - } - - if (Opcode == X86_TWO_BYTE_OPCODE) - { - // - // Handle case that it is a group (with opcode extension), floating point, or two byte opcode - // - assert(!Instruction->OpcodeLength); - Instruction->LastOpcode = Opcode = *Address; - INSTR_INC(1); // increment Instruction->Length and address - assert(X86Opcode->Table == X86_Opcodes_2); - X86Opcode = &X86_Opcodes_2[Opcode]; - - // - // Check for errors - // - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid two byte opcode 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode); - goto abort; - } - - if (X86Instruction->AddressSize == 8) - { - if (X86_Invalid_Addr64_2[Opcode]) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X 0x%02X (\"%s\") illegal in 64-bit mode\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic); - goto abort; - } -#if 0 - if (X86Instruction->rex_b && - (GET_REX_B(X86Instruction->rex_b) && !GET_REX_B(X86_REX_2[Opcode]) || - GET_REX_X(X86Instruction->rex_b) && !GET_REX_X(X86_REX_2[Opcode]) || - GET_REX_R(X86Instruction->rex_b) && !GET_REX_R(X86_REX_2[Opcode]) || - GET_REX_W(X86Instruction->rex_b) && !GET_REX_W(X86_REX_2[Opcode]))) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal REX prefix 0x%02X for opcode 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->rex_b, X86_TWO_BYTE_OPCODE, Opcode); - assert(0); - goto abort; - } -#endif - } - - if (X86Instruction->OperandSize == 2 && X86_Invalid_Op16_2[Opcode]) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X 0x%02X (\"%s\") illegal with 16-bit operand size\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic); - goto abort; - } - - X86Instruction->HasModRM = X86_ModRM_2[Opcode]; - if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address; - Instruction->OpcodeBytes[0] = X86_TWO_BYTE_OPCODE; - Instruction->OpcodeBytes[1] = Opcode; - Instruction->OpcodeLength = 2; - - if (X86_SPECIAL_EXTENSION(X86Opcode)) - { - DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode)); - SpecialExtension = TRUE; - goto HasSpecialExtension; - } - else if (SSE_Prefix && !X86_INVALID(&X86_SSE[Opcode])) // SSEx instruction - { - Instruction->OpcodeLength = 3; - Instruction->OpcodeBytes[2] = SSE_Prefix; - assert(Instruction->OpcodeBytes[1] == Opcode); - - // Since the prefix was really an opcode extension, remove it from - // the prefix list - for (i = 0; i < Instruction->PrefixCount; i++) - { - if (Instruction->Prefixes[i]) break; - } - assert(i != Instruction->PrefixCount); - Instruction->PrefixCount--; - Instruction->Prefixes[i] = 0; - - // Slide any prefixes following the removed prefix down by 1 - memmove(&Instruction->Prefixes[i], &Instruction->Prefixes[i+1], Instruction->PrefixCount-i); - Instruction->Prefixes[Instruction->PrefixCount] = 0; - Instruction->Repeat = FALSE; - X86Instruction->HasRepeatWhileEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE; - X86Instruction->HasOperandSizePrefix = FALSE; - if (SSE_Prefix == PREFIX_OPERAND_SIZE) - { - if (IS_AMD64() && X86Instruction->rex.w) X86Instruction->OperandSize = 8; - else X86Instruction->OperandSize = 4; - } - - if (IS_X86_16()) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: SSE invalid in 16-bit mode\n", VIRTUAL_ADDRESS); - goto abort; - } - - assert(X86Instruction->HasModRM); - switch (SSE_Prefix) - { - case PREFIX_OPERAND_SIZE: X86Opcode = &X86_SSE[0x000+Opcode]; break; - case PREFIX_REPNE: X86Opcode = &X86_SSE[0x100+Opcode]; break; - case PREFIX_REP: X86Opcode = &X86_SSE[0x200+Opcode]; break; - } - - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal SSE instruction opcode 0x%02X 0x%02X + prefix 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Instruction->OpcodeBytes[2]); - goto abort; - } - else if (X86_EXTENDED_OPCODE(X86Opcode)) - { - // SSE in group (13, 14, or 15) - OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b); - Group = X86_Groups_2[Opcode]; - X86Instruction->Group = (U8)Group; - assert(Group >= 13 && Group <= 15 && X86Opcode->Table); - switch (SSE_Prefix) - { - case PREFIX_OPERAND_SIZE: X86Opcode = &X86Opcode->Table[0x00+OpcodeExtension]; break; - case PREFIX_REPNE: X86Opcode = &X86Opcode->Table[0x08+OpcodeExtension]; break; - case PREFIX_REP: X86Opcode = &X86Opcode->Table[0x10+OpcodeExtension]; break; - } - - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal SSE instruction opcode 0x%02X 0x%02X + prefix 0x%02X + extension %d\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Instruction->OpcodeBytes[2], OpcodeExtension); - goto abort; - } - } - - Instruction->Repeat = FALSE; - X86Instruction->HasRepeatWhileEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE; - X86Instruction->HasOperandSizePrefix = FALSE; - switch (X86_GET_CATEGORY(X86Opcode)) - { - case ITYPE_SSE: case ITYPE_SSE2: case ITYPE_SSE3: break; - default: assert(0); goto abort; - } - } - else if (X86_EXTENDED_OPCODE(X86Opcode)) // 2 byte group - { - assert(!X86Opcode->MnemonicFlags); - OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b); - - assert(X86Opcode->Table); - X86Opcode = &X86Opcode->Table[OpcodeExtension]; - if (X86_INVALID(X86Opcode)) - { - Instruction->Length++; - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension); - goto abort; - } - - assert(!X86_SPECIAL_EXTENSION(X86Opcode)); - Group = X86_Groups_2[Opcode]; - X86Instruction->Group = (U8)Group; - assert(Group > 0 && Group <= 19); - assert(X86Opcode->Mnemonic); - DISASM_OUTPUT(("[0x%08I64X] Group %d (bytes 0x%02X 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension, X86Opcode->Mnemonic)); - } - else - { - assert(X86Opcode->Mnemonic); - DISASM_OUTPUT(("[0x%08I64X] Two byte opcode 0x%02X 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic)); - X86Instruction->HasModRM = X86_ModRM_2[Opcode]; - if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address; - } - } - else // 1-byte opcode - { - if (X86Instruction->AddressSize == 8) - { - if (X86_Invalid_Addr64_1[Opcode]) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X (\"%s\") illegal in 64-bit mode\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic); - goto abort; - } - -#if 0 - if (X86Instruction->rex_b && - (GET_REX_B(X86Instruction->rex_b) && !GET_REX_B(X86_REX_1[Opcode]) || - GET_REX_X(X86Instruction->rex_b) && !GET_REX_X(X86_REX_1[Opcode]) || - GET_REX_R(X86Instruction->rex_b) && !GET_REX_R(X86_REX_1[Opcode]) || - GET_REX_W(X86Instruction->rex_b) && !GET_REX_W(X86_REX_1[Opcode]))) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal REX prefix 0x%02X for opcode 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->rex_b, Opcode); - assert(0); - goto abort; - } -#endif - } - - if (X86Instruction->OperandSize == 2 && X86_Invalid_Op16_1[Opcode]) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X (\"%s\") illegal with 16-bit operand size\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic); - goto abort; - } - - Instruction->OpcodeBytes[0] = Opcode; - Instruction->OpcodeLength = 1; - X86Instruction->HasModRM = X86_ModRM_1[Opcode]; - if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address; - - if (X86_EXTENDED_OPCODE(X86Opcode)) // a group - { - assert(X86Instruction->HasModRM); - OpcodeExtension = GET_MODRM_EXT(*Address); // leave Address pointing at ModRM byte - - if (X86_SPECIAL_EXTENSION(X86Opcode)) - { - DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode)); - SpecialExtension = TRUE; - goto HasSpecialExtension; - } - - assert(X86Opcode->Table); - X86Opcode = &X86Opcode->Table[OpcodeExtension]; - if (X86_INVALID(X86Opcode)) - { - Instruction->Length++; - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, Opcode, OpcodeExtension); - goto abort; - } - - Group = X86_Groups_1[Opcode]; - X86Instruction->Group = (U8)Group; - DISASM_OUTPUT(("[0x%08I64X] Group %d (byte 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, Opcode, OpcodeExtension, X86Opcode->Mnemonic)); - assert(Group > 0 && Group <= 17); - assert(X86Opcode->Mnemonic); - } - else - { - if (X86_SPECIAL_EXTENSION(X86Opcode)) - { - DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X\n", VIRTUAL_ADDRESS, Opcode)); - SpecialExtension = TRUE; - goto HasSpecialExtension; - } - - DISASM_OUTPUT(("[0x%08I64X] One byte opcode 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic)); - } - } - -HasSpecialExtension: - if (SpecialExtension) - { - if (X86Opcode->MnemonicFlags & ITYPE_EXT_MODRM) - { - assert(X86Opcode->Table); - assert(Instruction->OpcodeLength == 2); - assert(X86Instruction->HasModRM); - X86Opcode = &X86Opcode->Table[*Address]; - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal opcode 0x%02X 0x%02X + modrm 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], *Address); - goto abort; - } - else if (X86_EXTENDED_OPCODE(X86Opcode)) - { - assert(!X86Opcode->MnemonicFlags); - OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b); - - assert(X86Opcode->Table); - X86Opcode = &X86Opcode->Table[OpcodeExtension]; - if (X86_INVALID(X86Opcode)) - { - Instruction->Length++; - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension); - goto abort; - } - - assert(!X86_SPECIAL_EXTENSION(X86Opcode)); - Group = X86_Groups_2[Opcode]; - X86Instruction->Group = (U8)Group; - assert(Group > 0 && Group <= 19); - assert(X86Opcode->Mnemonic); - DISASM_OUTPUT(("[0x%08I64X] Group %d (bytes 0x%02X 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension, X86Opcode->Mnemonic)); - } - else if (!X86_OPERAND_COUNT(X86Opcode)) - { - INSTR_INC(1); // increment Instruction->Length and address - } - } - else if (X86Opcode->MnemonicFlags & ITYPE_EXT_FPU) - { - assert(X86Opcode->Table); - if (X86Instruction->modrm_b < 0xC0) - { - // It is an opcode extension, use the X86Opcode->Table - OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b); - X86Opcode = &X86Opcode->Table[OpcodeExtension]; - } - else - { - // The whole ModRM byte is used, these start at index 0x08 in X86Opcode->Table - OpcodeExtension = (X86Instruction->modrm_b & 0x3F); - X86Opcode = &X86Opcode->Table[0x08 + OpcodeExtension]; - } - - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid FPU opcode 0x%02X + modrm extension 0x%02X (index 0x%02X)\n", VIRTUAL_ADDRESS, Opcode, X86Instruction->modrm_b, 0x08 + OpcodeExtension); - goto abort; - } - - DISASM_OUTPUT(("[0x%08I64X] FPU instruction is (\"%s\"): 0x%02X + modrm 0x%02X (index 0x%02X)\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Opcode, X86Instruction->modrm_b, 0x08 + OpcodeExtension)); - if (!X86_OPERAND_COUNT(X86Opcode)) INSTR_INC(1); // increment Instruction->Length and address - } - else if (X86Opcode->MnemonicFlags & ITYPE_EXT_SUFFIX) - { - if (X86Instruction->HasOperandSizePrefix) - { - if (!Instruction->AnomalyOccurred && X86Opcode->Table == X86_3DNOW_0F) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: operand size prefix used with 3DNOW instruction\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasOperandSizePrefix = FALSE; - X86Instruction->OperandSize = 4; - } - Instruction->OperandCount = X86_OPERAND_COUNT(X86Opcode); - assert(Instruction->OpcodeLength == 2 && X86Instruction->HasModRM && Instruction->OperandCount == 2); - memcpy(&X86Instruction->Opcode, X86Opcode, sizeof(X86_OPCODE)); - Instruction->Operands[0].Flags = X86Opcode->OperandFlags[0] & X86_OPFLAGS_MASK; - Instruction->Operands[1].Flags = X86Opcode->OperandFlags[1] & X86_OPFLAGS_MASK; - Instruction->Operands[2].Flags = X86Opcode->OperandFlags[2] & X86_OPFLAGS_MASK; - assert(Address == Instruction->Address + Instruction->Length); - if (!SetOperands(Instruction, Address, SuppressErrors)) goto abort; - Suffix = Instruction->Address[Instruction->Length++]; - Instruction->OpcodeBytes[2] = Suffix; - Instruction->OpcodeLength = 3; - X86Opcode = &X86Opcode->Table[Suffix]; - - if (X86_INVALID(X86Opcode)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal opcode 0x%02X 0x%02X + suffix 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Suffix); - goto abort; - } - assert(Instruction->Length >= 4 + Instruction->PrefixCount); - } - else if (X86Opcode->MnemonicFlags & ITYPE_EXT_64) - { - assert(X86Opcode->Table); - if (IS_AMD64()) X86Opcode = &X86Opcode->Table[1]; - else X86Opcode = &X86Opcode->Table[0]; - assert(!X86_INVALID(X86Opcode)); - } - } - - // Detect incompatibilities - if (IS_X86_16() && X86Opcode->CPU > CPU_I386) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Instruction \"%s\" (opcode 0x%02X) can't be used in 16-bit X86\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->LastOpcode); - goto abort; - } - if (!IS_AMD64() && X86Opcode->CPU >= CPU_AMD64) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Instruction \"%s\" (opcode 0x%02X) can only be used in X86-64\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->LastOpcode); - goto abort; - } - - // Copy the opcode into the local structure and set the fields - assert(Instruction->OpcodeLength && !X86_INVALID(X86Opcode)); - memcpy(&X86Instruction->Opcode, X86Opcode, sizeof(X86_OPCODE)); - Instruction->Groups |= X86_GET_CATEGORY(X86Opcode); - assert(Instruction->Groups); - Instruction->Type |= X86_GET_TYPE(X86Opcode); - assert((U32)Instruction->Type >= Instruction->Groups); - Instruction->OperandCount = X86_OPERAND_COUNT(X86Opcode); - - // - // Sanity check prefixes now that opcode is known and prefixes are resolved - // - - // Instructions that implicitly reference the CS/DS can't have segment override prefixes - switch (Instruction->Type) - { - case ITYPE_PUSHF: case ITYPE_POPF: - case ITYPE_ENTER: case ITYPE_LEAVE: - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSegmentOverridePrefix = FALSE; - X86Instruction->Segment = SEG_SS; - break; - case ITYPE_RET: case ITYPE_DEBUG: - case ITYPE_OFLOW: case ITYPE_TRAP: - case ITYPE_TRAPRET: - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSegmentOverridePrefix = FALSE; - X86Instruction->Segment = SEG_CS; - break; - } - - // Check illegal prefixes used with FPU/MMX/SSEx - if (Instruction->Groups & (ITYPE_FPU|ITYPE_MMX|ITYPE_SSE|ITYPE_SSE2|ITYPE_SSE3)) - { - // Check for prefixes that produce unpredictable results - for (i = 0; i < Instruction->PrefixCount; i++) - { - switch (Instruction->Prefixes[i]) - { - case PREFIX_OPERAND_SIZE: - switch (Instruction->Type) - { - case ITYPE_FSTOREENV: case ITYPE_FLOADENV: case ITYPE_FSAVE: case ITYPE_FRESTORE: continue; - default: break; - } - - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: operand size prefix used with FPU/MMX/SSEx\n", VIRTUAL_ADDRESS); - goto abort; - } - X86Instruction->HasOperandSizePrefix = FALSE; - if (X86Instruction->OperandSize == 2) X86Instruction->OperandSize = 2; - break; - - case PREFIX_REPNE: - case PREFIX_REP: - if (Instruction->Groups & ITYPE_FPU) { assert(Instruction->Repeat); continue; } - // The Intel manual says this results in unpredictable behavior -- it's not even - // clear which SSE prefix is used as the third opcode byte in this case - // (e.g., is it the first or last SSE prefix?) - if (!SuppressErrors) printf("[0x%08I64X] ERROR: rep/repne used with MMX/SSEx\n", VIRTUAL_ADDRESS); - goto abort; - - default: - break; - } - } - } - - // Check for conflicts involving operand size - if (IS_AMD64()) - { - // Check for use of rex.w=1 with an operand size prefix - if (X86Instruction->rex.w) - { - assert(X86Instruction->OperandSize == 8); - for (i = 0; i < Instruction->PrefixCount; i++) - { - if (Instruction->Prefixes[i] == PREFIX_OPERAND_SIZE) - { - X86Instruction->HasOperandSizePrefix = FALSE; - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of operand size prefix meaningless when REX.w=1\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - } - } - } - - // Set default operand size to 64 instead of 32 for some instructions - switch (Instruction->Type) - { - case ITYPE_PUSH: case ITYPE_POP: - case ITYPE_PUSHF: case ITYPE_POPF: - case ITYPE_ENTER: case ITYPE_LEAVE: - case ITYPE_CALL: case ITYPE_BRANCH: - case ITYPE_LOOPCC: case ITYPE_RET: - X86Instruction->HasDefault64Operand = TRUE; - break; - - case ITYPE_SYSTEM: - if (Instruction->OpcodeLength != 2) break; - - // lgdt/lidt/lldt/ltr - if ((Instruction->LastOpcode == 0x00 || Instruction->LastOpcode == 0x01) && - (OpcodeExtension == 0x02 || OpcodeExtension == 0x03)) - { - X86Instruction->HasDefault64Operand = TRUE; - } - break; - - default: - break; - } - - if (X86Instruction->HasDefault64Operand) - { - if (X86Instruction->rex.w) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of REX.w is meaningless (default operand size is 64)\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->rex_b &= ~8; - X86Instruction->rex.w = 0; - } - - if (X86Instruction->HasOperandSizePrefix) - { - assert(X86Instruction->OperandSize == 2); - X86Instruction->HasDefault64Operand = FALSE; - } - else - { - assert(X86Instruction->OperandSize >= 4); - X86Instruction->OperandSize = 8; - } - } - } - - // Make sure rep/repe/repne is set correctly based on instruction - if (Instruction->Repeat) - { - switch (Instruction->Type) - { - case ITYPE_IN: - case ITYPE_OUT: - case ITYPE_STRMOV: - case ITYPE_STRSTOR: - case ITYPE_STRLOAD: - if (X86Instruction->HasRepeatWhileNotEqualPrefix) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: REPNE should only be used with cmps/scas\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - // Treat it as just a "rep" - X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileEqualPrefix = TRUE; - } - break; - case ITYPE_STRCMP: - break; - default: - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Repeat prefix used with non-string instruction\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - Instruction->Repeat = FALSE; - X86Instruction->HasRepeatWhileEqualPrefix = FALSE; - X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE; - break; - } - } - - if (Disassemble) - { - assert(!Instruction->StringIndex); - if (X86Instruction->HasRepeatWhileEqualPrefix) - { - if (Instruction->Type == ITYPE_STRCMP) { APPENDS("repe "); } - else { APPENDS("rep "); } - } - if (X86Instruction->HasRepeatWhileNotEqualPrefix) APPENDS("repne "); - if (X86Instruction->HasLockPrefix) APPENDS("lock "); - if (X86Instruction->HasBranchTakenPrefix) APPENDS("hinttake "); - if (X86Instruction->HasBranchNotTakenPrefix) APPENDS("hintskip "); - APPENDPAD(12); - APPEND(OPCSTR, SIZE_LEFT, "%s", X86Opcode->Mnemonic); - APPENDPAD(24); - } - - if (Instruction->OperandCount) - { - Instruction->Operands[0].Flags = X86Opcode->OperandFlags[0] & X86_OPFLAGS_MASK; - Instruction->Operands[1].Flags = X86Opcode->OperandFlags[1] & X86_OPFLAGS_MASK; - Instruction->Operands[2].Flags = X86Opcode->OperandFlags[2] & X86_OPFLAGS_MASK; - Address = SetOperands(Instruction, Address, Flags); - if (!Address) goto abort; - assert(!(Instruction->Operands[0].Flags & 0x7F)); - assert(!(Instruction->Operands[1].Flags & 0x7F)); - assert(!(Instruction->Operands[2].Flags & 0x7F)); - } - - Disassembler->Stage2Count++; - -#ifdef TEST_DISASM - ////////////////////////////////////////////////////////////////////// - // Test against other disassemblers - ////////////////////////////////////////////////////////////////////// - - if (IS_X86_32()) - { - InstructionLength = X86_GetLength(Instruction, Instruction->Address); - if (InstructionLength && Instruction->Length != InstructionLength) - { - printf("[0x%08I64X] WARNING: instruction lengths differ (%d vs %d)\n", VIRTUAL_ADDRESS, Instruction->Length, InstructionLength); - DumpInstruction(Instruction, TRUE, TRUE); - assert(0); - } - } - else if (IS_AMD64()) - { - // TODO: need other amd64 (x86-64) disassembler to test against - } - else if (IS_X86_16()) - { - // TODO: need other x86 16-bit disassembler to test against - } -#endif - - ////////////////////////////////////////////////////////////////////// - // Post-operand sanity checks - ////////////////////////////////////////////////////////////////////// - - if (!X86Instruction->HasDstAddressing && !X86Instruction->HasSrcAddressing) - { - if (X86Instruction->HasAddressSizePrefix) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: address size prefix used with no addressing\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasAddressSizePrefix = FALSE; - } - - if (X86Instruction->HasSegmentOverridePrefix) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: segment override used with no addressing\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasSegmentOverridePrefix = FALSE; - } - } - - // Detect use of unusual segments - if (!Instruction->AnomalyOccurred && !IS_X86_16()) - { - switch (X86Instruction->Segment) - { - case SEG_CS: case SEG_DS: case SEG_SS: - break; - case SEG_ES: - switch (Instruction->Type) - { - case ITYPE_IN: case ITYPE_STRMOV: case ITYPE_STRCMP: case ITYPE_STRSTOR: - break; - default: - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment ES\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - break; - } - break; - case SEG_FS: - if (IS_X86_32() && !(Instruction->Groups & ITYPE_EXEC)) break; - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment FS\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - break; - case SEG_GS: - if (IS_AMD64() && !(Instruction->Groups & ITYPE_EXEC)) break; - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment GS\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - break; - default: - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: unexpected segment 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->Selector); - Instruction->AnomalyOccurred = TRUE; - break; - } - } - - if ((X86Opcode->OperandFlags[0] & OP_COND_EXEC) == OP_COND_EXEC) - { - assert(Instruction->Type == ITYPE_BRANCHCC || Instruction->Type == ITYPE_LOOPCC); - for (i = 0; i < Instruction->PrefixCount; i++) - { - switch (Instruction->Prefixes[i]) - { - case PREFIX_BRANCH_NOT_TAKEN: - if (!Instruction->AnomalyOccurred && X86Instruction->Segment != SEG_CS) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used with conditional branch\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasSegmentOverridePrefix = FALSE; - X86Instruction->Segment = SEG_CS; - X86Instruction->HasBranchNotTakenPrefix = TRUE; - break; - case PREFIX_BRANCH_TAKEN: - if (!Instruction->AnomalyOccurred && X86Instruction->Segment != SEG_DS) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used with conditional branch\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - X86Instruction->HasSegmentOverridePrefix = FALSE; - X86Instruction->Segment = SEG_CS; - X86Instruction->HasBranchTakenPrefix = TRUE; - break; - } - } - } - - // - // If lock prefix is enabled, verify it is valid - // - if (X86Instruction->HasLockPrefix && - !IsValidLockPrefix(X86Instruction, Opcode, Instruction->OpcodeLength, Group, OpcodeExtension)) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal use of lock prefix for instruction \"%s\"\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic); - goto abort; - } - - ////////////////////////////////////////////////////////////////////// - // Generate disassembly output - ////////////////////////////////////////////////////////////////////// - - if (Disassemble) - { - if ((Flags & DISASM_SHOWFLAGS) && - (X86Instruction->Opcode.Preconditions || X86Instruction->Opcode.FlagsChanged || X86Instruction->Opcode.ResultsIfTrue)) - { - APPENDPAD(124); - if (X86Instruction->Opcode.Preconditions) - { - Result = X86Instruction->Opcode.Preconditions; - APPENDS("COND:{ "); - if (Result & COND_L) APPENDS("L "); - if (Result & COND_NL) APPENDS("NL "); - if (Result & COND_LE) APPENDS("LE "); - if (Result & COND_NLE) APPENDS("NLE "); - if (Result & COND_G) APPENDS("G "); - if (Result & COND_NG) APPENDS("NG "); - if (Result & COND_GE) APPENDS("GE "); - if (Result & COND_NGE) APPENDS("NGE "); - if (Result & COND_A) APPENDS("A "); - if (Result & COND_NA) APPENDS("NA "); - if (Result & COND_AE) APPENDS("AE "); - if (Result & COND_NAE) APPENDS("NAE "); - if (Result & COND_B) APPENDS("B "); - if (Result & COND_NB) APPENDS("NB "); - if (Result & COND_BE) APPENDS("BE "); - if (Result & COND_NBE) APPENDS("NBE "); - if (Result & COND_E) APPENDS("E "); - if (Result & COND_NE) APPENDS("NE "); - if (Result & COND_C) APPENDS("C "); - if (Result & COND_NC) APPENDS("NC "); - if (Result & COND_Z) APPENDS("Z "); - if (Result & COND_NZ) APPENDS("NZ "); - if (Result & COND_P) APPENDS("P "); - if (Result & COND_NP) APPENDS("NP "); - if (Result & COND_PE) APPENDS("PE "); - if (Result & COND_PO) APPENDS("PO "); - if (Result & COND_O) APPENDS("O "); - if (Result & COND_NO) APPENDS("NO "); - if (Result & COND_U) APPENDS("U "); - if (Result & COND_NU) APPENDS("NU "); - if (Result & COND_S) APPENDS("S "); - if (Result & COND_NS) APPENDS("NS "); - if (Result & COND_D) APPENDS("D "); - APPENDB('}'); - } - - if (X86Instruction->Opcode.FlagsChanged) - { - Result = X86Instruction->Opcode.FlagsChanged; - - if (Result & FLAG_SET_MASK) - { - APPENDS("SET:{ "); - if (Result & FLAG_CF_SET) APPENDS("C "); - if (Result & FLAG_DF_SET) APPENDS("D "); - if (Result & FLAG_IF_SET) APPENDS("I "); - APPENDB('}'); - } - - if (Result & FLAG_CLR_MASK) - { - APPENDS("CLR:{ "); - if (Result & FLAG_SF_CLR) APPENDS("S "); - if (Result & FLAG_ZF_CLR) APPENDS("Z "); - if (Result & FLAG_AF_CLR) APPENDS("A "); - if (Result & FLAG_CF_CLR) APPENDS("C "); - if (Result & FLAG_DF_CLR) APPENDS("D "); - if (Result & FLAG_IF_CLR) APPENDS("I "); - if (Result & FLAG_OF_CLR) APPENDS("O "); - if ((Result & FPU_ALL_CLR) == FPU_ALL_CLR) - { - APPENDS("FPU_ALL "); - } - else - { - if (Result & FPU_C0_CLR) APPENDS("FPU_C0 "); - if (Result & FPU_C1_CLR) APPENDS("FPU_C1 "); - if (Result & FPU_C2_CLR) APPENDS("FPU_C2 "); - if (Result & FPU_C3_CLR) APPENDS("FPU_C3 "); - } - APPENDB('}'); - } - - if ((Result & FLAG_MOD_MASK) == FLAG_MOD_MASK) - { - APPENDS("MOD:{ "); - if ((Result & FLAG_ALL_MOD) == FLAG_ALL_MOD) - { - APPENDS("FLAGS_ALL "); - } - else if ((Result & FLAG_COMMON_MOD) == FLAG_COMMON_MOD) - { - APPENDS("FLAGS_COMMON "); - } - else - { - if (Result & FLAG_OF_MOD) APPENDS("O "); - if (Result & FLAG_SF_MOD) APPENDS("S "); - if (Result & FLAG_ZF_MOD) APPENDS("Z "); - if (Result & FLAG_AF_MOD) APPENDS("A "); - if (Result & FLAG_PF_MOD) APPENDS("P "); - if (Result & FLAG_CF_MOD) APPENDS("C "); - if (Result & FLAG_DF_MOD) APPENDS("D "); - if (Result & FLAG_IF_MOD) APPENDS("I "); - } - if ((Result & FPU_ALL_MOD) == FPU_ALL_MOD) - { - APPENDS("FPU_ALL "); - } - else - { - if (Result & FPU_C0_MOD) APPENDS("FPU_C0 "); - if (Result & FPU_C1_MOD) APPENDS("FPU_C1 "); - if (Result & FPU_C2_MOD) APPENDS("FPU_C2 "); - if (Result & FPU_C3_MOD) APPENDS("FPU_C3 "); - } - APPENDB('}'); - } - - if (Result & FLAG_TOG_MASK) - { - APPENDS("TOG:{ "); - if (Result & FLAG_CF_TOG) APPENDS("C "); - APPENDB('}'); - } - } - } - - APPENDS("\n"); - } - else - { - Instruction->String[0] = '\0'; - } - - if (!Instruction->Length || Instruction->Length > X86_MAX_INSTRUCTION_LEN) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: maximum instruction length reached (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - - if (!Decode) - { - Disassembler->Stage3CountNoDecode++; - return TRUE; // all work is done - } - - ////////////////////////////////////////////////////////////////////// - // Detect particularly interesting intructions - ////////////////////////////////////////////////////////////////////// - - Operand1 = &Instruction->Operands[0]; - if (Instruction->Groups & ITYPE_EXEC) - { - // If it is a negative offset with a 1-byte or 2-byte offset, assume it is a loop - if (Operand1->Type == OPTYPE_OFFSET && - Operand1->Length <= 2 && X86Instruction->Displacement < 0) - { - Instruction->CodeBranch.IsLoop = TRUE; - Instruction->CodeBranch.Operand = Operand1; - } - - if (!Instruction->AnomalyOccurred && - Operand1->TargetAddress >= (U64)Instruction->Address && - Operand1->TargetAddress < (U64)Instruction->Address + Instruction->Length) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: branch into the middle of an instruction\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - - switch (Instruction->Type) - { - case ITYPE_BRANCH: - Operand1->Flags |= OP_ADDRESS; - assert(Instruction->OperandCount == 1); - if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR))) - { - assert(!X86Instruction->HasSelector); - X86Instruction->Segment = SEG_CS; - } - - if (Operand1->TargetAddress) - { - assert(!Instruction->CodeBranch.AddressOffset); - Instruction->CodeBranch.Count = 1; - Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress; - Instruction->CodeBranch.Operand = Operand1; - } - // If there is both a base and index register, the Result will probably be too wrong - // to even guess - else if (X86Instruction->HasFullDisplacement && - (X86Instruction->HasBaseRegister != X86Instruction->HasIndexRegister)) - { - assert(Operand1->Length <= 0xFF); - if (!X86Instruction->Scale) - { - if (Operand1->Length) X86Instruction->Scale = (U8)Operand1->Length; - else X86Instruction->Scale = X86Instruction->OperandSize; - } - assert(Operand1->Length <= 0xFF); - tmpScale = MAX(X86Instruction->Scale, Operand1->Length); - - assert(tmpScale <= 16); - Instruction->CodeBranch.AddressOffset = (U8)tmpScale; - for (i = 0; i < MAX_CODE_REFERENCE_COUNT; i++) Instruction->CodeBranch.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale); - Instruction->CodeBranch.Count = i; - Instruction->CodeBranch.IsIndirect = TRUE; - Instruction->CodeBranch.Operand = Operand1; - } - break; - - case ITYPE_CALL: - Instruction->Groups |= ITYPE_STACK; - Instruction->CodeBranch.IsCall = TRUE; - Operand1->Flags |= OP_ADDRESS; - assert(Instruction->OperandCount == 1); - if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR))) - { - assert(!X86Instruction->HasSelector); - X86Instruction->Segment = SEG_CS; - } - - if (Operand1->TargetAddress) - { - assert(!Instruction->CodeBranch.AddressOffset); - Instruction->CodeBranch.Count = 1; - Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress; - Instruction->CodeBranch.Operand = Operand1; - } - // If there is both a base and index register, the Result will probably be too wrong - // to even guess - else if (X86Instruction->HasFullDisplacement && - (X86Instruction->HasBaseRegister != X86Instruction->HasIndexRegister)) - { - //DISASM_OUTPUT(("[0x%08I64X] Scale %d, displacement 0x%08I64x\n", VIRTUAL_ADDRESS, X86Instruction->Scale, X86Instruction->Displacement)); - if (!X86Instruction->Scale) - { - assert(Operand1->Length <= 0xFF); - if (Operand1->Length) X86Instruction->Scale = (U8)Operand1->Length; - else X86Instruction->Scale = X86Instruction->OperandSize; - } - tmpScale = MAX(X86Instruction->Scale, Operand1->Length); - - assert(tmpScale <= 16); - Instruction->CodeBranch.AddressOffset = (U8)tmpScale; - assert(X86Instruction->Scale > 1); - for (i = 0; i < MAX_CODE_REFERENCE_COUNT; i++) Instruction->CodeBranch.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale); - Instruction->CodeBranch.Count = i; - Instruction->CodeBranch.IsIndirect = TRUE; - Instruction->CodeBranch.Operand = Operand1; - } - break; - - case ITYPE_BRANCHCC: - assert(Instruction->OperandCount == 1); - assert(Operand1->Flags & OP_ADDRESS); - assert(Operand1->Type == OPTYPE_OFFSET); - if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR))) - { - assert(!X86Instruction->HasSelector); - X86Instruction->Segment = SEG_CS; - } - - if (Operand1->TargetAddress) - { - assert(!Instruction->CodeBranch.AddressOffset); - Instruction->CodeBranch.Count = 2; - Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress; - Instruction->CodeBranch.Addresses[1] = (U64)Instruction->Address + Instruction->Length; - Instruction->CodeBranch.Operand = Operand1; - } - break; - - case ITYPE_LOOPCC: - Instruction->CodeBranch.IsLoop = TRUE; - assert(Instruction->OperandCount == 1); - assert(Operand1->Flags & OP_ADDRESS); - assert(Operand1->Type == OPTYPE_OFFSET); - assert(!(Operand1->Flags & (OP_GLOBAL|OP_FAR))); - if (Operand1->TargetAddress) - { - assert(!Instruction->CodeBranch.AddressOffset); - Instruction->CodeBranch.Count = 2; - Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress; - Instruction->CodeBranch.Addresses[1] = (U64)Instruction->Address + Instruction->Length; - Instruction->CodeBranch.Operand = Operand1; - } - break; - - case ITYPE_RET: - Instruction->Groups |= ITYPE_STACK; - break; - - default: - break; // do nothing - } - } - else // possible data instruction - { - for (i = 0, Operand = Instruction->Operands; i < Instruction->OperandCount; i++, Operand++) - { - if (Operand->TargetAddress) - { - if (Operand->Flags & OP_DST) - { - assert(!Instruction->DataDst.Count); - Instruction->DataDst.Count = 1; - Instruction->DataDst.Addresses[0] = Operand->TargetAddress; - Instruction->DataDst.DataSize = Operand->Length; - Instruction->DataDst.Operand = Operand; - DISASM_OUTPUT(("[0x%08I64X] Write of size %d to 0x%04I64X\n", VIRTUAL_ADDRESS, Operand->Length, Operand->TargetAddress)); - } - if (Operand->Flags & OP_SRC) - { - assert(!Instruction->DataSrc.Count); - Instruction->DataSrc.Count = 1; - Instruction->DataSrc.Addresses[0] = Operand->TargetAddress; - Instruction->DataSrc.DataSize = Operand->Length; - Instruction->DataSrc.Operand = Operand; - DISASM_OUTPUT(("[0x%08I64X] Read of size %d to 0x%04I64X\n", VIRTUAL_ADDRESS, Operand->Length, Operand->TargetAddress)); - } - } - - // If there is both a base and index register, the Result will probably be too wrong - // to even guess - else if (Operand->Flags & OP_GLOBAL && - (X86Instruction->HasBaseRegister != X86Instruction->HasIndexRegister)) - { - DISASM_OUTPUT(("[0x%08I64X] Data reference (scale %d, size %d, displacement 0x%08I64x)\n", VIRTUAL_ADDRESS, X86Instruction->Scale, Operand->Length, X86Instruction->Displacement)); - if (!X86Instruction->Scale) - { - assert(Operand->Length <= 0xFF); - if (Operand->Length) X86Instruction->Scale = (U8)Operand->Length; - else X86Instruction->Scale = X86Instruction->OperandSize; - } - tmpScale = MAX(X86Instruction->Scale, Operand->Length); - - assert(X86Instruction->HasFullDisplacement); - if (Operand->Flags & OP_DST) - { - assert(!Instruction->DataDst.Count); - assert(tmpScale <= 16); - Instruction->CodeBranch.AddressOffset = (U8)tmpScale; - for (i = 0; i < MAX_DATA_REFERENCE_COUNT; i++) Instruction->DataDst.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale); - Instruction->DataDst.Count = i; - Instruction->DataDst.DataSize = Operand->Length; - Instruction->DataDst.Operand = Operand; - } - if (Operand->Flags & OP_SRC) - { - assert(!Instruction->DataSrc.Count); - assert(tmpScale <= 16); - Instruction->CodeBranch.AddressOffset = (U8)tmpScale; - for (i = 0; i < MAX_DATA_REFERENCE_COUNT; i++) Instruction->DataSrc.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale); - Instruction->DataSrc.Count = i; - Instruction->DataSrc.DataSize = Operand->Length; - Instruction->DataSrc.Operand = Operand; - } - } - } - } - - if (Instruction->Groups & ITYPE_STACK) - { - switch (Instruction->Type) - { - case ITYPE_PUSH: - assert(Instruction->OperandCount == 1 && Operand1->Length); - Instruction->StackChange = -Operand1->Length; - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_POP: - assert(Instruction->OperandCount == 1 && Operand1->Length); - Instruction->StackChange = Operand1->Length; - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_PUSHA: - Instruction->StackChange = -(X86Instruction->OperandSize * 8); // xAX, xCX, xDX, xBX, xBP, xSP, xSI, xDI - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_POPA: - Instruction->StackChange = X86Instruction->OperandSize * 8; // xDI, xSI, xSP, xBP, xBX, xDX, xCX, xAX - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_PUSHF: - Instruction->StackChange = -Operand1->Length; - Instruction->NeedsEmulation = TRUE; - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_POPF: - Instruction->StackChange = Operand1->Length; - Instruction->NeedsEmulation = TRUE; - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_ENTER: - if (!Instruction->AnomalyOccurred) - { - if (Instruction->Operands[1].Value_U64 & 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ENTER has invalid operand 2\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - if (Instruction->Operands[2].Value_U64 & ~0x1F) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ENTER has invalid operand 3\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - } - SANITY_CHECK_ADDRESS_SIZE(); - Instruction->Operands[2].Value_U64 &= 0x1F; - - // frame pointer + stack space - i = Operand1->Length + (U32)Instruction->Operands[1].Value_U64; - Instruction->StackChange = -((LONG)i); - i = (U32)Instruction->Operands[2].Value_U64 * Operand1->Length; - Instruction->StackChange -= i; - break; - - case ITYPE_LEAVE: - // This will do "mov esp, ebp; pop ebp" so the StackChange size is dynamic - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_CALL: - Instruction->StackChange = -X86Instruction->OperandSize; - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_RET: - Instruction->StackChange = X86Instruction->OperandSize; - - switch (Opcode) - { - case 0xC3: // ret with no args - break; - - case 0xC2: // ret with 1 arg - if (!Instruction->AnomalyOccurred && (Operand1->Value_U64 & 3)) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ret has invalid operand 1\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - Instruction->StackChange += (LONG)Operand1->Value_U64; - break; - - case 0xCB: // far ret with no args - Instruction->StackChange *= 2; // account for segment - Instruction->StackChange += (LONG)Operand1->Value_U64; - break; - - case 0xCA: // far ret with 1 arg - if (!Instruction->AnomalyOccurred && (Operand1->Value_U64 & 3)) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: retf has invalid operand 1\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - Instruction->StackChange *= 2; // account for segment - Instruction->StackChange += (LONG)Operand1->Value_U64; - break; - } - SANITY_CHECK_ADDRESS_SIZE(); - break; - - case ITYPE_ADD: - case ITYPE_XCHGADD: - if (Instruction->Operands[1].Value_S64) Instruction->StackChange = (LONG)(Instruction->Operands[1].Value_S64); - break; - case ITYPE_SUB: - if (Instruction->Operands[1].Value_S64) Instruction->StackChange = (LONG)(-Instruction->Operands[1].Value_S64); - break; - case ITYPE_MOV: - case ITYPE_AND: - break; - - default: - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Instruction \"%s\" is modifying the stack\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic); - Instruction->AnomalyOccurred = TRUE; - } - break; - } - - if (!Instruction->AnomalyOccurred && - ((X86Instruction->OperandSize != 2 && (Instruction->StackChange & 3)) || (Instruction->StackChange & 1))) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: \"%s\" has invalid stack change 0x%02X\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->StackChange); - Instruction->AnomalyOccurred = TRUE; - } - } - - if (Instruction->Groups & ITYPE_TRAPS) - { - switch (Instruction->Type) - { - case ITYPE_TRAP: - case ITYPE_TRAPCC: - case ITYPE_TRAPRET: - case ITYPE_BOUNDS: - case ITYPE_DEBUG: - case ITYPE_TRACE: - case ITYPE_INVALID: - case ITYPE_OFLOW: - Instruction->NeedsEmulation = TRUE; - break; - default: - assert(0); - break; - } - } - - if (Instruction->Groups & ITYPE_SYSTEM) - { - switch (Instruction->Type) - { - case ITYPE_CPUID: - case ITYPE_SYSCALL: - case ITYPE_SYSCALLRET: - // This doesn't require privileges - break; - - case ITYPE_HALT: - case ITYPE_IN: - case ITYPE_OUT: - default: - Instruction->NeedsEmulation = TRUE; - break; - } - } - - Disassembler->Stage3CountWithDecode++; - return TRUE; - -abort: - if (!SuppressErrors) - { -#ifdef TEST_DISASM - printf("Dump of 0x%04I64X:\n", VIRTUAL_ADDRESS); - __try { DumpAsBytes(stdout, Instruction->Address, (ULONG_PTR)VIRTUAL_ADDRESS, 16, TRUE); } - __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {} -#endif - fflush(stdout); - } - return FALSE; -} - -// Address = address to first byte after the opcode (e.g., first byte of ModR/M byte or -// immediate value -// -// Returns the address immediately following the operand (e.g., the next operand or the -// start of the next instruction -INTERNAL U8 *SetOperands(INSTRUCTION *Instruction, U8 *Address, U32 Flags) -{ - INSTRUCTION_OPERAND *Operand; - U32 Index, OperandIndex; - S64 Displacement = 0; - U8 Register; - U32 OperandFlags, OperandType, AddressMode, Segment; - U8 Opcode; - MODRM modrm; - REX rex; - REX_MODRM rex_modrm; - X86_OPCODE *X86Opcode; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - BOOL Decode = Flags & DISASM_DECODE; - BOOL Disassemble = Flags & DISASM_DISASSEMBLE; - BOOL SuppressErrors = Flags & DISASM_SUPPRESSERRORS; - - Opcode = Instruction->LastOpcode; - X86Opcode = &X86Instruction->Opcode; - - // Setup Mod R/M byte - if (X86Instruction->HasModRM) - { - SET_MODRM(X86Instruction->modrm, X86Instruction->modrm_b); - modrm = X86Instruction->modrm; - rex = X86Instruction->rex; - SET_REX_MODRM(X86Instruction->rex_modrm, rex, modrm); - rex_modrm = X86Instruction->rex_modrm; - //DISASM_OUTPUT(("[0x%08I64X] ModRM = 0x%02X (mod=%d, reg=%d, rm=%d)\n", VIRTUAL_ADDRESS, X86Instruction->modrm_b, modrm.mod, rex_modrm.reg, rex_modrm.rm)); - INSTR_INC(1); // increment Instruction->Length and address - } - else - { - // initialize them to 0 - modrm = X86Instruction->modrm; - rex = X86Instruction->rex; - rex_modrm = X86Instruction->rex_modrm; - } - - for (OperandIndex = 0; OperandIndex < Instruction->OperandCount; OperandIndex++) - { - Operand = &Instruction->Operands[OperandIndex]; - assert(!(Operand->Flags & 0x7F)); - - OperandFlags = X86Opcode->OperandFlags[OperandIndex] & X86_OPFLAGS_MASK; - OperandType = X86Opcode->OperandFlags[OperandIndex] & X86_OPTYPE_MASK; - AddressMode = X86Opcode->OperandFlags[OperandIndex] & X86_AMODE_MASK; - if (Decode && OperandIndex != 0) APPENDS(", "); - - switch (OperandType) - { - //////////////////////////////////////////////////////////// - // Special operand types with no associated addressing mode - //////////////////////////////////////////////////////////// - - case OPTYPE_0: - if (!Decode) continue; - Operand->Value_U64 = 0; - Operand->Type = OPTYPE_IMM; - //DISASM_OUTPUT(("[SetOperand] const 0\n")); - if (Disassemble) - { - APPENDS("<0>"); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_1: - if (!Decode) continue; - Operand->Value_U64 = 1; - Operand->Type = OPTYPE_IMM; - //DISASM_OUTPUT(("[SetOperand] const 1\n")); - if (Disassemble) - { - APPENDS("<1>"); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FF: - if (!Decode) continue; - Operand->Value_U64 = 0xFF; - Operand->Type = OPTYPE_IMM; - //DISASM_OUTPUT(("[SetOperand] const 0xff\n")); - if (Disassemble) - { - APPENDS("<0xFF>"); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_TSC: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] TSC\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_CS_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] CS MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_EIP_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] EIP MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_ESP_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] ESP MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_KERNELBASE_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] KernelBase MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_STAR_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] KernelBase MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_CSTAR_MSR: - assert(!IS_AMD64()); - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] CSTAR MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_LSTAR_MSR: - assert(IS_AMD64()); - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] LSTAR MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FMASK_MSR: - if (!Decode) continue; - Operand->Length = 8; - Operand->Type = OPTYPE_SPECIAL; - //DISASM_OUTPUT(("[SetOperand] FMASK MSR\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OP_REG: - if (!Decode) continue; - // The reg field is included in the opcode - Operand->Length = X86Instruction->OperandSize; - Register = X86_GET_REG64(Opcode); - switch (X86Instruction->OperandSize) - { - case 8: - Operand->Register = AMD64_64BIT_OFFSET + Register; - break; - case 4: - Operand->Register = X86_32BIT_OFFSET + Register; - CHECK_AMD64_REG(); - break; - case 2: - Operand->Register = X86_16BIT_OFFSET + Register; - CHECK_AMD64_REG(); - break; - case 1: - Operand->Register = X86_8BIT_OFFSET + Register; - if (X86Instruction->rex_b) CHECK_AMD64_REG(); - break; - default: - assert(0); - return NULL; - } - X86_SET_REG(Register); - - //DISASM_OUTPUT(("[SetOperand] OP_REG %s\n", X86_Registers[Operand->Register])); - if (Disassemble) - { - APPENDB('<'); APPENDS(X86_Registers[Operand->Register]); APPENDB('>'); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_REG8: - if (!Decode) continue; - // The reg field is included in the opcode - Operand->Length = 1; - Register = X86_GET_REG64(Opcode); - Operand->Register = X86_8BIT_OFFSET + Register; - CHECK_AMD64_REG(); - X86_SET_REG(Register); - - //DISASM_OUTPUT(("[SetOperand] OP_REG %s\n", X86_Registers[Operand->Register])); - if (Disassemble) - { - APPENDB('<'); APPENDS(X86_Registers[Operand->Register]); APPENDB('>'); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_REG_AL: - if (!Decode) continue; - Operand->Length = 1; - Operand->Register = X86_REG_AL; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg AL\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_CL: - if (!Decode) continue; - Operand->Length = 1; - Operand->Register = X86_REG_CL; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg CL\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_AH: - if (!Decode) continue; - Operand->Length = 1; - Operand->Register = X86_REG_AH; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg AH\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_AX: - if (!Decode) continue; - Operand->Length = 2; - Operand->Register = X86_REG_AX; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg AX\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_DX: - if (!Decode) continue; - Operand->Length = 2; - Operand->Register = X86_REG_DX; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg DX\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_ECX: - if (!Decode) continue; - Operand->Length = 4; - Operand->Register = X86_REG_ECX; - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] reg ECX\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_REG_xBP: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize; - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = AMD64_REG_RBP; break; - case 4: Operand->Register = X86_REG_EBP; break; - case 2: Operand->Register = X86_REG_BP; break; - default: assert(0); return NULL; - } - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] xAX_BIG (size = %d)\n", Operand->Length)); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_REG_xAX_BIG: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize; - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = AMD64_REG_RAX; break; - case 4: Operand->Register = X86_REG_EAX; break; - case 2: Operand->Register = X86_REG_AX; break; - default: assert(0); return NULL; - } - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] xAX_BIG (size = %d)\n", Operand->Length)); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_REG_xAX_SMALL: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize >> 1; - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = X86_REG_EAX; break; - case 4: Operand->Register = X86_REG_AX; break; - case 2: Operand->Register = X86_REG_AL; break; - default: assert(0); return NULL; - } - X86_SET_REG(0); - //DISASM_OUTPUT(("[SetOperand] xAX_SMALL (size = %d)\n", Operand->Length)); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_xCX_HI_xBX_LO: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize << 1; - if (Disassemble) - { - switch (X86Instruction->OperandSize) - { - case 8: APPENDS(""); break; - case 4: APPENDS(""); break; - case 2: APPENDS(""); break; - default: assert(0); return NULL; - } - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] xCX_BIG:xBX_BIG (size = %d)\n", Operand->Length)); - continue; - case OPTYPE_xDX_HI_xAX_LO: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize << 1; - if (Disassemble) - { - switch (X86Instruction->OperandSize) - { - case 8: APPENDS(""); break; - case 4: APPENDS(""); break; - case 2: APPENDS(""); break; - default: assert(0); return NULL; - } - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] xDX_BIG:xAX_BIG (size = %d)\n", Operand->Length)); - continue; - - case OPTYPE_EDX_HI_EAX_LO: - if (!Decode) continue; - Operand->Length = 8; - //DISASM_OUTPUT(("[SetOperand] EDX:EAX\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_EDX_ECX_EBX_EAX: - Operand->Length = 32; - //DISASM_OUTPUT(("[SetOperand] EDX:ECX:EBX:EAX\n")); - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_FLAGS: - if (!Decode) continue; - Operand->Length = 2; - Operand->Flags |= OP_REG; - Operand->Register = X86_REG_FLAGS; - //DISASM_OUTPUT(("[SetOperand] reg FLAGS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_xFLAGS: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize; - Operand->Flags |= OP_REG; - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = AMD64_REG_RFLAGS; break; - case 4: Operand->Register = X86_REG_EFLAGS; break; - case 2: Operand->Register = X86_REG_FLAGS; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] reg xFLAGS (size = %d)\n", Operand->Length)); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_CS: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_CS; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg CS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_DS: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_DS; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg DS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_ES: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_ES; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg ES\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FS: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_FS; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg FS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_GS: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_GS; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg GS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_SS: - if (!Decode) continue; - if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2; - else Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_SEG_SS; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] seg SS\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_CR0: - if (!Decode) continue; - Operand->Length = X86Instruction->OperandSize; - Operand->Register = X86_REG_CR0; - Operand->Flags |= OP_REG; - //DISASM_OUTPUT(("[SetOperand] reg CR0\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_STx: - if (!Decode) continue; - Operand->Length = 10; - Operand->Type = OPTYPE_FLOAT; - Operand->Flags |= OP_REG; - Register = X86_GET_REG(X86Instruction->modrm_b); - Operand->Register = X86_FPU_OFFSET + Register; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_STx: reg st(%d)\n", Register)); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_ST0: - if (!Decode) continue; - Operand->Length = 10; - Operand->Type = OPTYPE_FLOAT; - Operand->Flags |= OP_REG; - Operand->Register = X86_REG_ST0; - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_ST1: - if (!Decode) continue; - Operand->Length = 10; - Operand->Type = OPTYPE_FLOAT; - Operand->Flags |= OP_REG; - Operand->Register = X86_REG_ST1; - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_FPU_STATUS: - if (!Decode) continue; - Operand->Length = 2; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_FPU_CONTROL: - if (!Decode) continue; - Operand->Length = 2; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_FPU_TAG: - if (!Decode) continue; - Operand->Length = 2; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - case OPTYPE_FLDZ: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS("<0.0>"); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLD1: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS("<1.0>"); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLDPI: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLDL2T: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLDL2E: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLDLG2: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - case OPTYPE_FLDLN2: - if (!Decode) continue; - Operand->Type = OPTYPE_FLOAT; - Operand->Length = 10; - if (Disassemble) - { - APPENDS(""); - X86_WRITE_OPFLAGS(); - } - continue; - - //////////////////////////////////////////////////////////// - // Fixed sizes regardless of operand size - //////////////////////////////////////////////////////////// - - case OPTYPE_b: // byte regardless of operand size - Operand->Length = 1; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_b (size 1, signed %d)\n", ((OperandFlags & OP_SIGNED) != 0))); - break; - - case OPTYPE_w: // word regardless of operand size - Operand->Length = 2; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_w (size 2)\n")); - break; - - case OPTYPE_d: // dword regardless of operand size - Operand->Length = 4; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_d (size 4)\n")); - break; - - case OPTYPE_q: // qword regardless of operand size - Operand->Length = 8; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_q (size 8)\n")); - break; - - case OPTYPE_o: // oword regardless of operand size - Operand->Length = 16; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_o (size 16)\n")); - break; - - case OPTYPE_dt: // 6-byte or 10-byte pseudo descriptor (sgdt, lgdt, sidt, lidt) - if (IS_AMD64()) Operand->Length = 10; - else Operand->Length = 6; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_dt (%d bytes)\n", Operand->Length)); - break; - - case OPTYPE_cpu: - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Undocumented loadall instruction?\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - Operand->Length = 204; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_cpu (size 204)\n")); - break; - - //////////////////////////////////////////////////////////// - // Sizes depending on the operand size - //////////////////////////////////////////////////////////// - - case OPTYPE_z: // word if operand size is 16 bits and dword otherwise - switch (X86Instruction->OperandSize) - { - case 8: case 4: Operand->Length = 4; break; - case 2: Operand->Length = 2; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_z (length %d)\n", Operand->Length)); - break; - - case OPTYPE_v: // word, dword, or qword - Operand->Length = X86Instruction->OperandSize; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_v (size %d, signed = %d)\n", Operand->Length, ((OperandFlags & OP_SIGNED) != 0))); - break; - - case OPTYPE_a: // two word or dword operands in memory (used only by bound) - assert(Instruction->OpcodeBytes[0] == X86_BOUND); - switch (X86Instruction->OperandSize) - { - case 8: case 4: Operand->Length = 8; break; - case 2: Operand->Length = 4; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_a (size %d)\n", Operand->Length)); - break; - - case OPTYPE_p: // 32-bit or 48-bit pointer depending on operand size - if (!Instruction->AnomalyOccurred && X86Instruction->HasSegmentOverridePrefix) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used when segment is explicit\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - switch (X86Instruction->OperandSize) - { - case 8: case 4: Operand->Length = 6; break; - case 2: Operand->Length = 4; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_p (length %d)\n", Operand->Length)); - break; - - case OPTYPE_dq: // dword or qword - //DISASM_OUTPUT(("[SetOperand] OPTYPE_dq (size 4 or 8)\n")); - switch (X86Instruction->OperandSize) - { - case 8: Operand->Length = 8; break; - case 4: case 2: Operand->Length = 4; break; - default: assert(0); return NULL; - } - break; - - case OPTYPE_mw: // a word if the destination operand is memory - //DISASM_OUTPUT(("[SetOperand] OPTYPE_mw (size 0)\n")); - assert(X86Instruction->HasModRM); - if (modrm.mod == 3) Operand->Length = X86Instruction->OperandSize; // using register - else Operand->Length = 2; // using memory - break; - - case OPTYPE_lea: - //DISASM_OUTPUT(("[SetOperand] OPTYPE_lea (size 0)\n")); - assert(OperandIndex == 1); - Operand->Length = Instruction->Operands[0].Length; - break; - - //////////////////////////////////////////////////////////// - // FPU types - //////////////////////////////////////////////////////////// - - case OPTYPE_ps: // packed single real - Operand->Length = 4; - Operand->Type = OPTYPE_FLOAT; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_ps (packed single real)\n")); - break; - case OPTYPE_pd: // packed double real - Operand->Length = 8; - Operand->Type = OPTYPE_FLOAT; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_pd (packed double real)\n")); - break; - case OPTYPE_pb: // packed BCD - Operand->Length = 10; - Operand->Type = OPTYPE_BCD; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_pb (packed BCD)\n")); - break; - case OPTYPE_ss: // scalar single real - Operand->Length = 4; - Operand->Type = OPTYPE_FLOAT; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_ss (single real)\n")); - break; - case OPTYPE_sd: // scalar double real - Operand->Length = 8; - Operand->Type = OPTYPE_FLOAT; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_sd (double real)\n")); - break; - case OPTYPE_se: // extended real - Operand->Length = 10; - Operand->Type = OPTYPE_FLOAT; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_se (extended real)\n")); - break; - - case OPTYPE_fev: // FPU environment (28 bytes in 32-bit modes, 14 bytes in 16-bit real mode) - switch (X86Instruction->OperandSize) - { - case 8: case 4: Operand->Length = 28; break; - case 2: Operand->Length = 14; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_fev (FPU environment, length %d)\n", Operand->Length)); - break; - - case OPTYPE_fst1: // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode) - switch (X86Instruction->OperandSize) - { - case 8: case 4: Operand->Length = 108; break; - case 2: Operand->Length = 94; break; - default: assert(0); return NULL; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_fst1 (FPU state, length %d)\n", Operand->Length)); - break; - - case OPTYPE_fst2: // 512 bytes for FPU state (FPU + MMX + XXM + MXCSR) - Operand->Length = 512; - //DISASM_OUTPUT(("[SetOperand] OPTYPE_fst2 (FPU + MMX + XXM + MXCSR state, length 512)\n")); - break; - - case OPTYPE_sso: - if (modrm.mod == 3) // from register - { - Operand->Length = 16; - } - else // from memory - { - Operand->Length = 4; - Operand->Type = OPTYPE_FLOAT; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_sso (single real or oword)\n")); - break; - - case OPTYPE_sdo: - if (modrm.mod == 3) // from register - { - Operand->Length = 16; - } - else // from memory - { - Operand->Length = 8; - Operand->Type = OPTYPE_FLOAT; - } - //DISASM_OUTPUT(("[SetOperand] OPTYPE_sso (double real or oword)\n")); - break; - - default: - assert(0); - return NULL; - } - - switch (AddressMode) - { - //////////////////////////////////////////////////////////// - // Special types - //////////////////////////////////////////////////////////// - - case AMODE_xlat: // DS:[EBX+AL] - if (!Decode) continue; - assert(Operand->Length == 1); - Operand->Flags |= OP_ADDRESS | OP_REG; - Operand->Type = OPTYPE_STRING; - - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_REG_RBX; break; - case 4: Operand->Register = X86_REG_EBX; break; - case 2: Operand->Register = X86_REG_BX; break; - default: assert(0); return NULL; - } - X86_SET_ADDR(); - X86Instruction->Scale = 1; - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - X86Instruction->IndexRegister = X86_REG_AL; - X86Instruction->HasIndexRegister = TRUE; - - //DISASM_OUTPUT(("[SetOperand] AMODE_xlat (DS:[EBX+AL])\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]", - Segments[X86Instruction->Segment], X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - //////////////////////////////////////////////////////////// - // Without mod R/M byte - //////////////////////////////////////////////////////////// - - case AMODE_I: // immediate value - if (Decode) - { - Operand->Type = OPTYPE_IMM; - switch (Operand->Length) - { - case 8: - if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S64 *)Address); - else Operand->Value_U64 = (U64)*((U64 *)Address); - break; - case 4: - if (!(OperandFlags & OP_SIGNED) && OperandIndex == 1 && - (Instruction->Operands[0].Flags & (OP_REG|OP_ADDRESS)) && - Instruction->Operands[0].Length == 8) - { - // For some opcodes the second operand is a sign-extended imm32 value - assert(X86Instruction->OperandSize == 8); - switch (Instruction->Type) - { - case ITYPE_AND: - case ITYPE_ADD: - case ITYPE_XCHGADD: - case ITYPE_CMP: - case ITYPE_MOV: - case ITYPE_SUB: - case ITYPE_TEST: - case ITYPE_OR: - case ITYPE_XOR: - assert(OperandIndex == 1); - Operand->Value_S64 = (S64)*((S32 *)Address); - break; - default: - assert(0); - if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S32 *)Address); - else Operand->Value_U64 = (U64)*((U32 *)Address); - break; - } - } - else - { - if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S32 *)Address); - else Operand->Value_U64 = (U64)*((U32 *)Address); - } - break; - case 2: - if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S16 *)Address); - else Operand->Value_U64 = (U64)*((U16 *)Address); - break; - case 1: - if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S8 *)Address); - else Operand->Value_U64 = (U64)*((U8 *)Address); - break; - default: - assert(0); - return NULL; - } - } - INSTR_INC(Operand->Length); // increment Instruction->Length and address - assert(X86Instruction->OperandSize >= Operand->Length); - if (Instruction->Type == ITYPE_PUSH) Operand->Length = X86Instruction->OperandSize; - - //DISASM_OUTPUT(("[SetOperand] AMODE_I (immediate data)\n")); - if (Disassemble) - { - X86_WRITE_IMMEDIATE(); - X86_WRITE_OPFLAGS(); - } - continue; - - case AMODE_J: // IP-relative jump offset - SANITY_CHECK_ADDRESS_SIZE(); - if (Decode) - { - Operand->Flags |= OP_IPREL | OP_SIGNED | OP_REG | OP_ADDRESS; - Operand->Type = OPTYPE_OFFSET; - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = AMD64_REG_RIP; break; - case 4: Operand->Register = X86_REG_EIP; break; - case 2: Operand->Register = X86_REG_IP; break; - default: assert(0); return NULL; - } - switch (Operand->Length) - { - case 8: X86Instruction->Displacement = *((S64 *)Address); break; - case 4: X86Instruction->Displacement = (S64)*((S32 *)Address); break; - case 2: X86Instruction->Displacement = (S64)*((S16 *)Address); break; - case 1: X86Instruction->Displacement = (S64)*((S8 *)Address); break; - default: assert(0); return NULL; - } - - Operand->Value_S64 = X86Instruction->Displacement; - X86Instruction->Relative = TRUE; - - if ((Operand->Flags & OP_COND) && !X86Instruction->Displacement) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Both conditions of branch go to same address\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - } - - INSTR_INC(Operand->Length); // increment Instruction->Length and address - if (!Decode) continue; - - assert((Operand->Flags & OP_EXEC) && (Instruction->Groups & ITYPE_EXEC)); - Operand->TargetAddress = ApplyDisplacement((U64)Address, Instruction); - X86Instruction->Relative = TRUE; - X86_SET_ADDR(); - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSegmentOverridePrefix = FALSE; - X86Instruction->Segment = SEG_CS; - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - assert(Instruction->OperandCount == 1); - //DISASM_OUTPUT(("[SetOperand] AMODE_J (branch with relative offset)\n")); - if (Disassemble) - { - X86_WRITE_IP_OFFSET(Operand); - X86_WRITE_OPFLAGS(); - } - continue; - - case AMODE_O: // word/dword offset - Operand->Type = OPTYPE_OFFSET; - Operand->Flags |= OP_ADDRESS; - SANITY_CHECK_OPERAND_SIZE(); - switch (X86Instruction->AddressSize) - { - case 8: - if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = *((S64 *)Address); - else X86Instruction->Displacement = (S64)*((U64 *)Address); - break; - case 4: - if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = (S64)*((S32 *)Address); - else X86Instruction->Displacement = (S64)*((U32 *)Address); - break; - case 2: - if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = (S64)*((S16 *)Address); - else X86Instruction->Displacement = (S64)*((U16 *)Address); - break; - default: - assert(0); - return FALSE; - } - - INSTR_INC(X86Instruction->AddressSize); // increment Instruction->Length and address - if (!Decode) continue; - - X86Instruction->HasFullDisplacement = TRUE; - X86_SET_ADDR(); - X86_SET_TARGET(); - assert(X86Instruction->Segment == SEG_DS || X86Instruction->HasSegmentOverridePrefix); - //DISASM_OUTPUT(("[SetOperand] AMODE_O (offset)\n")); - if (Disassemble) - { - X86_WRITE_OFFSET(Operand); - X86_WRITE_OPFLAGS(); - } - continue; - - case AMODE_A: // absolute address - Operand->Flags |= OP_ADDRESS | OP_FAR; - SANITY_CHECK_ADDRESS_SIZE(); - SANITY_CHECK_SEGMENT_OVERRIDE(); - X86Instruction->HasSelector = TRUE; - X86Instruction->HasSegmentOverridePrefix = FALSE; - switch (Operand->Length) - { - case 6: - X86Instruction->Segment = *((U16 *)Address); INSTR_INC(2); - X86Instruction->Displacement = (S64)*((S32 *)Address); INSTR_INC(4); - break; - case 4: - X86Instruction->Segment = *((U16 *)Address); INSTR_INC(2); - X86Instruction->Displacement = (S64)*((S16 *)Address); INSTR_INC(2); - break; - default: - assert(0); - return FALSE; - } - if (!Decode) continue; - X86Instruction->HasFullDisplacement = TRUE; - X86_SET_ADDR(); - X86_SET_TARGET(); - //DISASM_OUTPUT(("[SetOperand] AMODE_A (absolute address)\n")); - if (Disassemble) - { - X86_WRITE_OFFSET(Operand); - X86_WRITE_OPFLAGS(); - } - continue; - - case AMODE_X: // DS:[ESI] - if (!Decode) continue; - Operand->Flags |= OP_ADDRESS | OP_REG; - Operand->Type = OPTYPE_STRING; - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_REG_RSI; break; - case 4: Operand->Register = X86_REG_ESI; break; - case 2: Operand->Register = X86_REG_SI; break; - default: assert(0); return NULL; - } - - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - X86_SET_ADDR(); - if (!X86Instruction->HasSegmentOverridePrefix) X86Instruction->Segment = SEG_DS; - - //DISASM_OUTPUT(("[SetOperand] AMODE_X (addressing via DS:[ESI])\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]", - Segments[X86Instruction->Segment], X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - case AMODE_Y: // ES:[EDI] - if (!Decode) continue; - Operand->Flags |= OP_ADDRESS | OP_REG; - Operand->Type = OPTYPE_STRING; - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_REG_RDI; break; - case 4: Operand->Register = X86_REG_EDI; break; - case 2: Operand->Register = X86_REG_DI; break; - default: assert(0); return NULL; - } - - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - X86_SET_ADDR(); - if (X86Instruction->HasSegmentOverridePrefix) - { - if (!Instruction->AnomalyOccurred) - { - if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: segment override used with AMODE_Y\n", VIRTUAL_ADDRESS); - Instruction->AnomalyOccurred = TRUE; - } - Segment = X86Instruction->DstSegment = SEG_ES; - X86Instruction->HasDstSegment = TRUE; - } - else - { - Segment = X86Instruction->Segment = SEG_ES; - } - - //DISASM_OUTPUT(("[SetOperand] AMODE_Y (addressing via ES:[EDI])\n")); - if (Disassemble) - { - APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]", - Segments[Segment], X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - continue; - - //////////////////////////////////////////////////////////// - // Mod R/M byte with only registers - // Handle that case here since it is straightforward - //////////////////////////////////////////////////////////// - - case AMODE_PR: // modrm.rm = mmx register and modrm.mod = 11 - assert(X86Instruction->HasModRM); - if (modrm.mod != 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_PR (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - else if (rex_modrm.rm > 7) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_PR (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic); - goto abort; - } - else if (X86Instruction->OperandSize == 2) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_PR illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - if (!Decode) continue; - - Operand->Flags |= OP_REG; - Operand->Register = X86_MMX_OFFSET + rex_modrm.rm; - X86_SET_REG(0); - - if (Disassemble) - { - assert(X86_Registers[Operand->Register]); - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_PR (MMX register)\n")); - continue; - - case AMODE_VR: // modrm.rm = xmm register and modrm.mod = 11 - assert(X86Instruction->HasModRM); - if (modrm.mod != 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_VR (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - else if (X86Instruction->OperandSize == 2) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_VR illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - if (!Decode) continue; - - Operand->Flags |= OP_REG; - Operand->Register = X86_XMM_OFFSET + rex_modrm.rm; - X86_SET_REG(0); - - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_VR (XMM register)\n")); - continue; - - case AMODE_P: // modrm.reg = mmx register - assert(X86Instruction->HasModRM); - if (rex_modrm.reg > 7) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_P (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.reg, X86Instruction->Opcode.Mnemonic); - goto abort; - } - else if (X86Instruction->OperandSize == 2) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_P illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - if (!Decode) continue; - - Operand->Flags |= OP_REG; - Operand->Register = X86_MMX_OFFSET + rex_modrm.reg; - X86_SET_REG(0); - - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_P (MMX register)\n")); - continue; - - case AMODE_V: // modrm.reg = xmm register - assert(X86Instruction->HasModRM); - if (X86Instruction->OperandSize == 2) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_P illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - if (!Decode) continue; - - Operand->Flags |= OP_REG; - Operand->Register = X86_XMM_OFFSET + rex_modrm.reg; break; - X86_SET_REG(0); - - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_V (XMM register)\n")); - continue; - - case AMODE_R: // modrm.rm is general register and modrm.mod = 11 - assert(X86Instruction->HasModRM); - if (modrm.mod != 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_R (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - if (!Decode) continue; - Operand->Flags |= OP_REG; - switch (Operand->Length) - { - case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break; - case 4: Operand->Register = X86_32BIT_OFFSET, rex_modrm.rm; CHECK_AMD64_REG(); break; - case 2: Operand->Register = X86_16BIT_OFFSET, rex_modrm.rm; CHECK_AMD64_REG(); break; - case 1: Operand->Register = X86_8BIT_OFFSET, rex_modrm.rm; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break; - default: assert(0); return NULL; - } - X86_SET_REG(rex_modrm.rm); - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_R (general register)\n")); - continue; - - case AMODE_G: // modrm.reg = general register - assert(X86Instruction->HasModRM); - if (!Decode) continue; - Operand->Flags |= OP_REG; - switch (Operand->Length) - { - case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.reg; break; - case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.reg; CHECK_AMD64_REG(); break; - case 2: Operand->Register = X86_16BIT_OFFSET + rex_modrm.reg; CHECK_AMD64_REG(); break; - case 1: Operand->Register = X86_8BIT_OFFSET + rex_modrm.reg; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break; - default: assert(0); return NULL; - } - X86_SET_REG(rex_modrm.reg); - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_G (general register)\n")); - continue; - - case AMODE_S: // modrm.reg = segment register - assert(X86Instruction->HasModRM); - if (!Decode) continue; - Operand->Flags |= OP_REG; - switch (X86Instruction->OperandSize) - { - case 8: - case 4: - case 2: - if (rex_modrm.reg <= 5) Operand->Register = X86_SEGMENT_OFFSET + rex_modrm.reg; - break; - default: - assert(0); - return NULL; - } - - X86_SET_REG(0); - if (Disassemble) - { - if (rex_modrm.reg > 5) APPEND(OPCSTR, SIZE_LEFT, "seg_%02X", rex_modrm.reg); - else APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_S (segment register)\n")); - continue; - - case AMODE_T: // modrm.reg = test register - assert(X86Instruction->HasModRM); - if (!Decode) continue; - Instruction->Groups |= ITYPE_SYSTEM; - Instruction->NeedsEmulation = TRUE; - Operand->Flags |= OP_REG; - switch (X86Instruction->OperandSize) - { - case 8: - case 4: - case 2: - Operand->Register = X86_TEST_OFFSET + rex_modrm.reg; - break; - default: - assert(0); - return NULL; - } - - X86_SET_REG(0); - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_T (test register)\n")); - continue; - - case AMODE_C: // modrm.reg = control register - assert(X86Instruction->HasModRM); - assert(Instruction->Type == ITYPE_MOV); - if (!Decode) continue; - Instruction->Groups |= ITYPE_SYSTEM; - Instruction->NeedsEmulation = TRUE; - Operand->Flags |= OP_REG; - if (IS_AMD64()) X86Instruction->OperandSize = 8; - switch (X86Instruction->OperandSize) - { - case 8: - case 4: - case 2: - Operand->Register = X86_CONTROL_OFFSET + rex_modrm.reg; - break; - default: - assert(0); - return NULL; - } - - X86_SET_REG(0); - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_C (control register)\n")); - continue; - - case AMODE_D: // modrm.reg = debug register - assert(X86Instruction->HasModRM); - assert(Instruction->Type == ITYPE_MOV); - if (!Decode) continue; - Instruction->NeedsEmulation = TRUE; - Operand->Flags |= OP_REG; - Instruction->Groups |= ITYPE_SYSTEM; - Instruction->NeedsEmulation = TRUE; - if (IS_AMD64()) X86Instruction->OperandSize = 8; - switch (X86Instruction->OperandSize) - { - case 8: - case 4: - case 2: - Operand->Register = X86_DEBUG_OFFSET + rex_modrm.reg; - break; - default: - assert(0); - return NULL; - } - - X86_SET_REG(0); - if (Disassemble) - { - APPENDS(X86_Registers[Operand->Register]); - X86_WRITE_OPFLAGS(); - } - //DISASM_OUTPUT(("[SetOperand] AMODE_D (debug register)\n")); - continue; - - //////////////////////////////////////////////////////////// - // Mod R/M byte with memory or register - //////////////////////////////////////////////////////////// - - case AMODE_M: // memory only - assert(X86Instruction->HasModRM); - if (modrm.mod == 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod = 3 for AMODE_M (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - assert(X86Instruction->Segment == SEG_DS || X86Instruction->HasSegmentOverridePrefix); - //DISASM_OUTPUT(("[SetOperand] AMODE_M (memory only)\n")); - Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors); - if (!Address) return NULL; - break; - - case AMODE_E: // general register or memory - assert(X86Instruction->HasModRM); - if (OperandType == OPTYPE_p && modrm.mod == 3) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod = 3 for AMODE_E with OPTYPE_p (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic); - goto abort; - } - - //DISASM_OUTPUT(("[SetOperand] AMODE_E (general register or memory)\n")); - Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors); - if (!Address) return NULL; - if (Decode && (Instruction->Type == ITYPE_PUSH || Instruction->Type == ITYPE_POP)) - { - assert(X86Instruction->OperandSize >= Operand->Length); - Operand->Length = X86Instruction->OperandSize; - } - break; - - case AMODE_Q: // mmx register or memory address - assert(X86Instruction->HasModRM); - //DISASM_OUTPUT(("[SetOperand] AMODE_Q (MMX register or memory address)\n")); - if (modrm.mod == 3) // it is a register - { - if (rex_modrm.rm > 7) - { - if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_P (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic); - goto abort; - } - Operand->Register = X86_MMX_OFFSET + rex_modrm.rm; - Operand->Flags |= OP_REG; - X86_SET_REG(0); - } - else - { - Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors); - if (!Address) return NULL; - } - break; - - case AMODE_W: // xmm register or memory address - assert(X86Instruction->HasModRM); - //DISASM_OUTPUT(("[SetOperand] AMODE_W (XMM register or memory address)\n")); - if (modrm.mod == 3) // it is a register - { - Operand->Register = X86_XMM_OFFSET + rex_modrm.rm; - Operand->Flags |= OP_REG; - X86_SET_REG(0); - } - else - { - Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors); - if (!Address) return NULL; - } - break; - - default: - assert(0); - return NULL; - } - - if (!Decode) continue; - - // If this is reached then SetModRM32 was called - if ((Operand->Flags & OP_ADDRESS)) - { - assert(Operand->Length); - switch (Operand->Register) - { - case X86_REG_BP: - case X86_REG_EBP: - case AMD64_REG_RBP: - if (X86Instruction->Displacement > 0) Operand->Flags |= OP_PARAM; - else Operand->Flags |= OP_LOCAL; - break; - default: - break; - } - } - - if (Disassemble) - { - Index = OperandType >> OPTYPE_SHIFT; - assert(Index > 0 && Index < MAX_OPTYPE_INDEX && OptypeHandlers[Index]); - OptypeHandlers[Index](Instruction, Operand, OperandIndex); - X86_WRITE_OPFLAGS(); - } - } - - return Address; - -abort: - if (!SuppressErrors) - { -#ifdef TEST_DISASM - printf("Dump of 0x%04I64X:\n", VIRTUAL_ADDRESS); - __try { DumpAsBytes(stdout, Instruction->Address, (ULONG_PTR)VIRTUAL_ADDRESS, 16, TRUE); } - __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {} -#endif - fflush(stdout); - } - return NULL; -} - -// NOTE: Address points one byte after ModRM -INTERNAL U8 *SetModRM16(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors) -{ - MODRM modrm; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - - DISASM_OUTPUT(("[SetModRM16] Current instruction length = %d\n", Instruction->Length)); - modrm = X86Instruction->modrm; - assert(!X86Instruction->rex_b); - - // - // Both operands are registers - // Condition: mod = 3 - // - if (modrm.mod == 3) - { - //DISASM_OUTPUT(("[SetModRM16] Both regs (rm_reg %d)\n", modrm.rm)); - switch (Operand->Length) - { - case 4: Operand->Register = X86_32BIT_OFFSET + modrm.rm; break; - case 2: Operand->Register = X86_16BIT_OFFSET + modrm.rm; break; - case 1: Operand->Register = X86_8BIT_OFFSET + modrm.rm; break; - default: assert(0); return NULL; - } - Operand->Flags |= OP_REG; - } - - // - // Address is an absolute address (technically a 16-bit offset from DS:0) - // Condition: mod = 0 and rm = 6 - // - else if (modrm.mod == 0 && modrm.rm == 6) - { - //DISASM_OUTPUT(("[SetModRM16] Absolute addressing (displacement 0x%04X)\n", *(S16 *)Address)); - X86Instruction->Displacement = (S64)(*((S16 *)Address)); - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - X86Instruction->HasFullDisplacement = TRUE; - X86_SET_TARGET(); - Operand->Flags |= OP_GLOBAL; - } - X86_SET_ADDR(); - Operand->Flags |= OP_ADDRESS; - INSTR_INC(2); - } - - // Conditions: - // (1) mod = 0 and rm != 6 - // (2) mod = 1-2 and rm = 0-7 - else - { - switch (modrm.mod) - { - case 0: // no displacement - //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (no displacement)\n")); - break; - case 1: // 8-bit signed displacement - //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (displacement = 0x%02X, reg_rm = %d)\n", *(S8 *)Address, modrm.rm)); - X86Instruction->Displacement = (S64)(*((S8 *)Address)); - INSTR_INC(1); // increment Instruction->Length and address - break; - case 2: // 16-bit displacement - //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (displacement = 0x%04X, reg_rm = %d)\n", *(S16 *)Address, modrm.rm)); - X86Instruction->Displacement = (S64)(*((S16 *)Address)); - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - Operand->Flags |= OP_GLOBAL; - X86Instruction->HasFullDisplacement = TRUE; - } - INSTR_INC(2); - break; - } - - switch (modrm.rm) - { - case 0: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX+SI]\n")); - X86Instruction->BaseRegister = X86_REG_BX; - X86Instruction->IndexRegister = X86_REG_SI; - X86Instruction->HasIndexRegister = TRUE; - break; - case 1: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX+DI]\n")); - X86Instruction->BaseRegister = X86_REG_BX; - X86Instruction->IndexRegister = X86_REG_DI; - X86Instruction->HasIndexRegister = TRUE; - break; - case 2: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP+SI]\n")); - X86Instruction->BaseRegister = X86_REG_BP; - X86Instruction->IndexRegister = X86_REG_SI; - X86Instruction->HasIndexRegister = TRUE; - X86_SET_SEG(REG_BP); - break; - case 3: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP+DI]\n")); - X86Instruction->BaseRegister = X86_REG_BP; - X86Instruction->IndexRegister = X86_REG_DI; - X86Instruction->HasIndexRegister = TRUE; - X86_SET_SEG(REG_BP); - break; - case 4: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [SI]\n")); - X86Instruction->BaseRegister = X86_REG_SI; - break; - case 5: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [DI]\n")); - X86Instruction->BaseRegister = X86_REG_DI; - break; - case 6: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP]\n")); - X86Instruction->BaseRegister = X86_REG_BP; - break; - case 7: - //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX]\n")); - X86Instruction->BaseRegister = X86_REG_BX; - break; - } - - X86Instruction->HasBaseRegister = TRUE; - Operand->Flags |= OP_ADDRESS | OP_REG; - X86_SET_ADDR(); - } - - return Address; -} - -// NOTE: Address points one byte after ModRM -INTERNAL U8 *SetModRM32(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors) -{ - MODRM modrm; - REX_MODRM rex_modrm; - U32 i, ImmediateSize = 0; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - - if (X86Instruction->AddressSize == 2) - { - return SetModRM16(Instruction, Address, Operand, OperandIndex, SuppressErrors); - } - - //DISASM_OUTPUT(("[SetModRM32] Length %d, modrm = 0x%02X\n", Instruction->Length, X86Instruction->modrm_b)); - modrm = X86Instruction->modrm; - rex_modrm = X86Instruction->rex_modrm; - - // - // Both operands are registers - // Condition: mod = 3 - // - if (modrm.mod == 3) - { - switch (Operand->Length) - { - case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break; - case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break; - case 2: Operand->Register = X86_16BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break; - case 1: Operand->Register = X86_8BIT_OFFSET + rex_modrm.rm; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break; - default: assert(0); return NULL; - } - X86_SET_REG(rex_modrm.rm); - Operand->Flags |= OP_REG; - } - - // - // Address is an absolute address (technically a 32-bit offset from DS:0) - // mod = 0 and rm = 5 - // - else if (modrm.mod == 0 && modrm.rm == 5) - { - //DISASM_OUTPUT(("[SetModRM32] Absolute addressing (displacement 0x%08lX)\n", *(S32 *)Address)); - Operand->Flags |= OP_ADDRESS; - X86Instruction->Displacement = (S64)*((S32 *)Address); - INSTR_INC(4); // increment Instruction->Length and address - - if (IS_AMD64()) - { - // RIP-relative addressing always replaced Disp32, even when using a 32-bit address space - // (via address size override prefix) - switch (X86Instruction->OperandSize) - { - case 8: Operand->Register = AMD64_REG_RIP; break; - case 4: Operand->Register = X86_REG_EIP; break; - case 2: Operand->Register = X86_REG_IP; break; - default: assert(0); return NULL; - } - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - X86Instruction->Relative = TRUE; - Operand->Flags |= OP_IPREL | OP_SIGNED | OP_REG; - SANITY_CHECK_SEGMENT_OVERRIDE(); - if (!X86Instruction->HasSegmentOverridePrefix) X86Instruction->Segment = SEG_CS; - X86Instruction->HasFullDisplacement = TRUE; - - // Since there may be an immediate value to follow, it is necessary - // to determine the length in order get the proper offset - // - // Maybe there is a better way to do this, since this is wasteful - // (the size of the immediate value will have to be decoded again later - // in SetOperands) - - for (ImmediateSize = 0, i = OperandIndex+1; i < Instruction->OperandCount; i++) - { - if ((X86Instruction->Opcode.OperandFlags[i] & X86_AMODE_MASK) != AMODE_I) continue; - else assert(!ImmediateSize); - switch (X86Instruction->Opcode.OperandFlags[i] & X86_OPTYPE_MASK) - { - case OPTYPE_v: - ImmediateSize = X86Instruction->OperandSize; - break; - case OPTYPE_z: - switch (X86Instruction->OperandSize) - { - case 8: case 4: ImmediateSize = 4; break; - case 2: ImmediateSize = 2; break; - default: assert(0); return NULL; - } - break; - case OPTYPE_b: - ImmediateSize = 1; - break; - case OPTYPE_w: - ImmediateSize = 2; - break; - case OPTYPE_1: - break; - default: - assert(0); - break; - } - } - - Operand->TargetAddress = ApplyDisplacement((U64)Address + ImmediateSize, Instruction); - } - else if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - X86_SET_TARGET(); - Operand->Flags |= OP_GLOBAL; - X86Instruction->HasFullDisplacement = TRUE; - } - - X86_SET_ADDR(); - } - - // - // Addressing mode indicated by SIB byte - // Condition: mod = 0-2 and rm = 4 - // - else if (modrm.rm == 4) - { - // The X86_SET_*() is called from within SetSIB() - Address = SetSIB(Instruction, Address, Operand, OperandIndex, SuppressErrors); - if (!Address) - { - assert(0); - return NULL; - } - - if (X86Instruction->sib.base != 5) // if base == 5, the displacement is handled in SetSIB - { - switch (modrm.mod) - { - case 1: // 8-bit displacement - //DISASM_OUTPUT(("[SetModRM32] After SIB: displacement 0x%02X\n", *((S8 *)Address))); - X86Instruction->Displacement = (S64)(*((S8 *)Address)); - INSTR_INC(1); // increment Instruction->Length and address - break; - case 2: // 32-bit displacement - //DISASM_OUTPUT(("[SetModRM32] After SIB: displacement 0x%08lX\n", *((S32 *)Address))); - X86Instruction->Displacement = (S64)*((S32 *)Address); - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - Operand->Flags |= OP_GLOBAL; - X86Instruction->HasFullDisplacement = TRUE; - } - INSTR_INC(4); // increment Instruction->Length and address - break; - } - } - } - - // Indirect addressing - // Conditions: - // (1) mod = 0 and (rm = 0-3 or 6-7) - // (2) mod = 1-2 and rm != 4 - else - { - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break; - case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break; - default: assert(0); return NULL; - } - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - Operand->Flags |= OP_ADDRESS | OP_REG; - X86_SET_SEG(rex_modrm.rm); - X86_SET_ADDR(); - - switch (modrm.mod) - { - case 0: // no displacement - //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (no displacement, reg_rm = %d)\n", rex_modrm.rm)); - break; - case 1: // 8-bit signed displacement - //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (displacement = 0x%02X, reg_rm = %d)\n", *(S8 *)Address, rex_modrm.rm)); - X86Instruction->Displacement = (S64)(*((S8 *)Address)); - INSTR_INC(1); // increment Instruction->Length and address - break; - case 2: // 32-bit displacement - //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (displacement = 0x%08lX, reg_rm = %d)\n", *(S32 *)Address, rex_modrm.rm)); - X86Instruction->Displacement = (S64)*((S32 *)Address); - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - Operand->Flags |= OP_GLOBAL; - X86Instruction->HasFullDisplacement = TRUE; - } - INSTR_INC(4); // increment Instruction->Length and address - break; - } - } - - return Address; -} - -// NOTE: Address points at SIB -INTERNAL U8 *SetSIB(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors) -{ - REX rex; - SIB sib; - REX_SIB rex_sib; - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - - X86Instruction->sib_b = *Address; - SET_SIB(X86Instruction->sib, *Address); - sib = X86Instruction->sib; - rex = X86Instruction->rex; - SET_REX_SIB(X86Instruction->rex_sib, rex, sib); - rex_sib = X86Instruction->rex_sib; - - //if (!X86Instruction->rex_b) DISASM_OUTPUT(("[0x%08I64X] SIB = 0x%02X (scale=%d, index=%d, base=%d)\n", VIRTUAL_ADDRESS, *Address, sib.scale, sib.index, sib.base)); \ - //else DISASM_OUTPUT(("[0x%08I64X] SIB = 0x%02X (scale=%d, index=%d, base=%d)\n", VIRTUAL_ADDRESS, *Address, sib.scale, rex_sib.index, rex_sib.base)); \ - //DISASM_OUTPUT(("[SetSIB] Current instruction length = %d\n", Instruction->Length)); - - Operand->Flags |= OP_ADDRESS; - X86_SET_ADDR(); - INSTR_INC(1); // increment Instruction->Length and address - - if (sib.base == 5) - { - switch (X86Instruction->modrm.mod) - { - case 0: - X86Instruction->Displacement = (S64)*((S32 *)Address); - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - X86Instruction->HasFullDisplacement = TRUE; - X86_SET_TARGET(); - Operand->Flags |= OP_GLOBAL; - } - INSTR_INC(4); - break; - case 1: - X86Instruction->Displacement = (S64)(*((S8 *)Address)); - if (rex_sib.base == 5) - { - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_REG_RBP; break; - case 4: Operand->Register = X86_REG_EBP; break; - default: assert(0); return NULL; - } - X86_SET_SEG(REG_EBP); - } - else - { - Operand->Register = AMD64_REG_R13; - } - - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - Operand->Flags |= OP_REG; - INSTR_INC(1); - break; - case 2: - X86Instruction->Displacement = (S64)*((S32 *)Address); - if (rex_sib.base == 5) - { - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_REG_RBP; break; - case 4: Operand->Register = X86_REG_EBP; break; - default: assert(0); return NULL; - } - X86_SET_SEG(REG_EBP); - } - else - { - Operand->Register = AMD64_REG_R13; - } - - if (IS_VALID_ADDRESS(X86Instruction->Displacement)) - { - Operand->Flags |= OP_GLOBAL; - X86Instruction->HasFullDisplacement = TRUE; - } - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - Operand->Flags |= OP_REG; - INSTR_INC(4); - break; - } - } - else - { - switch (X86Instruction->AddressSize) - { - case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_sib.base; break; - case 4: Operand->Register = X86_32BIT_OFFSET + rex_sib.base; CHECK_AMD64_REG(); break; - default: assert(0); return NULL; - } - X86Instruction->BaseRegister = Operand->Register; - X86Instruction->HasBaseRegister = TRUE; - X86_SET_SEG(rex_sib.base); - Operand->Flags |= OP_REG; - } - - if (rex_sib.index != 4) - { - switch (X86Instruction->AddressSize) - { - case 8: - X86Instruction->IndexRegister = AMD64_64BIT_OFFSET + rex_sib.index; - break; - case 4: - X86Instruction->IndexRegister = X86_32BIT_OFFSET + rex_sib.index; - break; - default: - fflush(stdout); - assert(0); - return NULL; - } - - Operand->TargetAddress = 0; - X86Instruction->HasIndexRegister = TRUE; - //DISASM_OUTPUT(("[SetSIB] Index register = %s\n", X86_Registers[X86_32BIT_OFFSET + rex_sib.index])); - - switch (sib.scale) - { - case 0: X86Instruction->Scale = 1; break; - case 1: X86Instruction->Scale = 2; break; - case 2: X86Instruction->Scale = 4; break; - case 3: X86Instruction->Scale = 8; break; - } - //DISASM_OUTPUT(("[SetSIB] Scale = %d\n", X86Instruction->Scale)); - } - - return Address; -} - -INTERNAL U64 ApplyDisplacement(U64 Address, INSTRUCTION *Instruction) -{ - X86_INSTRUCTION *X86Instruction = &Instruction->X86; - -#ifdef SUPPORT_WRAPAROUND - U64 VirtualAddress = Address + Instruction->VirtualAddressDelta; - switch (X86Instruction->OperandSize) - { - case 8: - { - U64 PreAddr = VirtualAddress; - U64 PostAddr = PreAddr + X86Instruction->Displacement; - return Address + (PostAddr - PreAddr); - } - case 4: - { - // We have to do this carefully... - // If EIP = FFFFF000 and Displacement=2000 then the final IP should be 1000 - // due to wraparound - U32 PreAddr = (U32)VirtualAddress; - U32 PostAddr = PreAddr + (S32)X86Instruction->Displacement; - return Address + (PostAddr - PreAddr); - } - case 2: - { - // We have to do this carefully... - // If IP = F000 and Displacement=2000 then the final IP should be 1000 - // due to wraparound - U16 PreAddr = (U16)VirtualAddress; - U16 PostAddr = PreAddr + (S16)X86Instruction->Displacement; - return Address + (PostAddr - PreAddr); - } - default: - assert(0); - return 0; - } -#else - return (Address + X86Instruction->Displacement); -#endif -} - - - -INTERNAL BOOL IsValidLockPrefix(X86_INSTRUCTION *X86Instruction, U8 Opcode, U32 OpcodeLength, U8 Group, U8 OpcodeExtension) -{ - switch (OpcodeLength) - { - case 1: - switch (X86_LockPrefix_1[Opcode]) - { - case 0: // instruction can't be locked - return FALSE; - case 1: // instruction can be locked - break; - case GR: - assert(Group); - if (!X86_LockPrefix_Groups[Group-1][OpcodeExtension]) return FALSE; - break; - default: - assert(0); - return FALSE; - } - break; - - case 2: - case 3: - switch (X86_LockPrefix_2[Opcode]) - { - case 0: // lock prefix is not acceptable - return FALSE; - case 1: // lock prefix allowed - break; - case GR: - assert(Group); - if (!X86_LockPrefix_Groups[Group-1][OpcodeExtension]) return FALSE; - break; - default: - assert(0); - return FALSE; - } - break; - - default: - assert(0); - return FALSE; - } - - if (!X86Instruction->HasModRM || X86Instruction->modrm.mod == 3 || !X86Instruction->HasDstAddressing) - { - DISASM_OUTPUT(("[0x%08I64X] ERROR: Instruction \"%s\" with LOCK prefix has invalid ModRM addressing\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic, X86Instruction->Instruction->Address)); - return FALSE; - } - - return TRUE; -} diff --git a/src/disasm-lib/disasm_x86.h b/src/disasm-lib/disasm_x86.h deleted file mode 100644 index 11a6d9ac..00000000 --- a/src/disasm-lib/disasm_x86.h +++ /dev/null @@ -1,837 +0,0 @@ -// Copyright (C) 2004, Matt Conover (mconover@gmail.com) -#ifndef X86_DISASM_H -#define X86_DISASM_H -#ifdef __cplusplus -extern "C" { -#endif - -// NOTE: the processor may actually accept less than this amount (officially 15) -// #define AMD64_MAX_INSTRUCTION_LEN 15 // theoretical max 25=5+2+1+1+8+8 -#define AMD64_MAX_PREFIX_LENGTH 5 // 4 legacy + 1 rex -#define AMD64_MAX_ADDRESS_LENGTH 18 // modrm + sib + 8 byte displacement + 8 byte immediate value - -// NOTE: the processor may actually accept less than this amount (officially 15) -#define X86_MAX_INSTRUCTION_LEN 15 // theoretical 16=4+2+1+1+4+4 -#define X86_MAX_PREFIX_LENGTH 4 -#define X86_MAX_OPCODE_LENGTH 3 // third byte is either a suffix or prefix -#define X86_MAX_ADDRESS_LENGTH 10 // modrm + sib + 4 byte displacement + 4 byte immediate value -#define X86_MAX_OPERANDS 3 - -#define X86_PREFIX(a) ((a)->MnemonicFlags == ITYPE_EXT_PREFIX) -#define X86_SPECIAL_EXTENSION(a) ((a)->MnemonicFlags & (ITYPE_EXT_MODRM|ITYPE_EXT_FPU|ITYPE_EXT_SUFFIX|ITYPE_EXT_64)) -#define X86_EXTENDED_OPCODE(a) ((a)->Table) -#define X86_INVALID(a) (!(a)->MnemonicFlags && !(a)->Table) -#define X86_OPERAND_COUNT(a) ((a)->OperandFlags[0] ? ((a)->OperandFlags[1] ? ((a)->OperandFlags[2] ? 3 : 2) : 1) : 0) -#define X86_GET_CATEGORY(p) ((p)->MnemonicFlags & ITYPE_GROUP_MASK) -#define X86_GET_TYPE(p) ((p)->MnemonicFlags & ITYPE_TYPE_MASK) - -// Various instructions being specially decoded -#define X86_TWO_BYTE_OPCODE 0x0f -#define PREFIX_SEGMENT_OVERRIDE_ES 0x26 -#define PREFIX_SEGMENT_OVERRIDE_CS 0x2e -#define PREFIX_BRANCH_NOT_TAKEN 0x2e // used only with conditional jumps -#define PREFIX_SEGMENT_OVERRIDE_SS 0x36 -#define PREFIX_SEGMENT_OVERRIDE_DS 0x3e -#define PREFIX_BRANCH_TAKEN 0x3e // used only with conditional jumps -#define PREFIX_SEGMENT_OVERRIDE_FS 0x64 -#define PREFIX_SEGMENT_OVERRIDE_GS 0x65 -#define PREFIX_OPERAND_SIZE 0x66 -#define PREFIX_ADDRESS_SIZE 0x67 -#define PREFIX_LOCK 0xf0 -#define PREFIX_REPNE 0xf2 -#define PREFIX_REP 0xf3 - -////////////////////////////////////////////////////////////////// -// Implicit operand handling -////////////////////////////////////////////////////////////////// - -#define X86_AMODE_MASK 0x00FF0000 // bits 16-23 (AMODE_*) -#define X86_OPFLAGS_MASK 0x0000FF80 // bits 7-15 (OPTYPE_*) -#define X86_OPTYPE_MASK 0xFF0000FF // bits 0-7 (OPTYPE_* below + OP_REG) and 24-31 (OPTYPE_* above) - -#define OPTYPE_0 0x01 -#define OPTYPE_1 0x02 -#define OPTYPE_FF 0x03 -//... -#define OPTYPE_CS 0x10 -#define OPTYPE_DS 0x11 -#define OPTYPE_ES 0x12 -#define OPTYPE_FS 0x13 -#define OPTYPE_GS 0x14 -#define OPTYPE_SS 0x15 -#define OPTYPE_CR0 0x16 -#define OPTYPE_TSC 0x17 // time stamp counter -//... -#define OPTYPE_FLAGS 0x20 -#define OPTYPE_xFLAGS 0x21 // RFLAGS/EFLAGS (depending on operand size) -#define OPTYPE_xCX_HI_xBX_LO 0x22 // represented by 2 registers CX:BX or ECX:EBX (depending on operand size) -#define OPTYPE_xDX_HI_xAX_LO 0x23 // DX:AX or EDX:EAX (depending on operand size) -#define OPTYPE_EDX_HI_EAX_LO 0x24 // DX:AX or EDX:EAX (depending on operand size) -#define OPTYPE_EDX_ECX_EBX_EAX 0x25 // all registers are set -//... -#define OPTYPE_STx 0x30 -#define OPTYPE_ST0 0x31 -#define OPTYPE_ST1 0x32 -#define OPTYPE_FPU_STATUS 0x33 -#define OPTYPE_FPU_CONTROL 0x34 -#define OPTYPE_FPU_TAG 0x35 -#define OPTYPE_FLDZ 0x36 // 0 -#define OPTYPE_FLD1 0x37 // 1 -#define OPTYPE_FLDPI 0x38 // pi -#define OPTYPE_FLDL2T 0x39 // lg 10 -#define OPTYPE_FLDL2E 0x3A // lg e -#define OPTYPE_FLDLG2 0x3B // log_10 2 -#define OPTYPE_FLDLN2 0x3C // log_e 2 -//... -#define OPTYPE_CS_MSR 0x40 -#define OPTYPE_EIP_MSR 0x41 -#define OPTYPE_ESP_MSR 0x42 -#define OPTYPE_KERNELBASE_MSR 0x43 -#define OPTYPE_FMASK_MSR 0x44 -#define OPTYPE_STAR_MSR 0x45 -#define OPTYPE_CSTAR_MSR 0x46 // 32-bit mode -#define OPTYPE_LSTAR_MSR 0x47 // 64-bit mode - - -// NOTE: OPTYPES >= 0x80 reserved for registers (OP_REG+XX) -#define OPTYPE_REG_AL OP_REG+0x01 -#define OPTYPE_REG_CL OP_REG+0x02 -#define OPTYPE_REG_AH OP_REG+0x03 -#define OPTYPE_REG_AX OP_REG+0x04 -#define OPTYPE_REG_DX OP_REG+0x05 -#define OPTYPE_REG_ECX OP_REG+0x06 -#define OPTYPE_REG8 OP_REG+0x07 - -// If address size is 2, use BP -// If address size is 4, use EBP -// If address size is 8, use RBP -#define OPTYPE_REG_xBP OP_REG+0x08 - -// If address size is 2, use BP -// If address size is 4, use EBP -// If address size is 8, use RBP -#define OPTYPE_REG_xSP OP_REG+0x09 - -// If operand size is 2, take 8-bit register -// If operand size is 4, take 16-bit register -// If operand size is 8, take 32-bit register -#define OPTYPE_REG_xAX_SMALL OP_REG+0x0a - -// If operand size is 2, take 16-bit register -// If operand size is 4, take 32-bit register -// If operand size is 8, take 64-bit register -#define OPTYPE_REG_xAX_BIG OP_REG+0x0b - -typedef enum _CPU_TYPE -{ - CPU_UNKNOWN=0, - - /////////////////////////////////////// - // 1st generation - /////////////////////////////////////// - // 1978 - //CPU_8086 = 1MB address limit, 16-bit registers - // 1982 - //CPU_i186 - - /////////////////////////////////////// - // 2nd generation - /////////////////////////////////////// - // 1982 - //CPU_I286 // 16MB limit, 16-bit registers, added protected mode - CPU_I287, // CPU_I286 + math coprocessor - - /////////////////////////////////////// - // 3rd generation - /////////////////////////////////////// - // 1985 - CPU_I386, // 32-bit registers, 4GB memory limit - // 1988 - CPU_I387, // CPU_I386 + math coprocessor - - /////////////////////////////////////// - // 4th generation (1989) - /////////////////////////////////////// - CPU_I486, - - /////////////////////////////////////// - // 5th generation - /////////////////////////////////////// - // 1993 - CPU_PENTIUM, // superscalar architecture - // 1997 - //CPU_PENTIUM_MMX - - /////////////////////////////////////// - // 6th generation (1995) - /////////////////////////////////////// - CPU_PENTIUM_PRO, // P6 architecture, no MMX, out-of-order execution, speculative execution - //CPU_CYRIX_6X86, - //CPU_AMD_K5 // RISC processor - // 1997 - CPU_PENTIUM2, // Pentium Pro architecture + MMX - //CPU_AMD_K6, - //CPU_CYRIX_6X86MX, // Cyrix 6x86 + MMX - // 1998 - CPU_AMD_K6_2, // added 3DNow! (MMX) - // 1999 - // CPU_AMD_K6_3 // added SSE - - /////////////////////////////////////// - // 7th generation - /////////////////////////////////////// - // 1999 - CPU_PENTIUM3, // introduced SSE - // CPU_AMD_K7 // aka Athlon - // 2000 - CPU_PENTIUM4, // introduced SSE2 and hyperthreading - - // 2004? 2005? - CPU_PRESCOTT, // introduced SSE3 - - /////////////////////////////////////// - // 8th generation (X86-64) - // IA32 instruction set with 64-bit extensions, >4GB RAM - /////////////////////////////////////// - - // 2003 - CPU_AMD64, // includes Athlon 64 and Opteron aka X86-64 - - // 2004? - //CPU_EMD64 // Intel's version of AMD64 - CPU_IA64 // aka Itanium: new instruction set -- adds JMPE to IA32 mode to return to IA64 native code - -} CPU_TYPE; - -////////////////////////////////////////////////////////////////// -// Conditions (these can be OR'd) -////////////////////////////////////////////////////////////////// - -// Used for Flags.Preconditions -#define COND_O (1<<0) // overflow (signed) -#define COND_C (1<<1) // below (unsigned) -#define COND_Z (1<<2) // equal (unsigned) -#define COND_S (1<<3) // sign set (signed) -#define COND_P (1<<4) // parity even -#define COND_BE (1<<5) // CF or ZF is set (unsigned) -#define COND_L (1<<6) // (SF && !OF) || (OF && !SF) -#define COND_LE (1<<7) // ZF || (SF && !OF) || (OF && !SF) (signed) -#define COND_NO (1<<8) // !O -#define COND_NC (1<<9) // !C (not below, above or equal to) -#define COND_NZ (1<<10) // !Z (not equal) -#define COND_NS (1<<11) // !S -#define COND_NP (1<<12) // !P (parity odd) -#define COND_NL (1<<13) // (!SF && !OF) || (SF && OF) -#define COND_G (1<<14) // !ZF && ((!SF && !OF) || (SF && OF)) -#define COND_D (1<<15) // DF -#define COND_REG_xCX_BIG_Z (1<<16) // CX/ECX/RCX (depending on address size) == 0 -#define COND_REG_xCX_BIG_NZ (1<<17) // CX/ECX/RCX (depending on address size) != 0 -#define COND_OP1_EQ_OP2 (1<<18) -#define COND_OP1_EQ_OP3 (1<<19) -#define COND_B COND_C -#define COND_NAE COND_C -#define COND_E COND_Z -#define COND_NA COND_BE -#define COND_PE COND_P -#define COND_U COND_P -#define COND_NGE COND_L -#define COND_NG COND_LE -#define COND_PO COND_NP -#define COND_NU COND_NP -#define COND_NE COND_NZ -#define COND_NB COND_NC -#define COND_AE COND_NC -#define COND_NE COND_NZ -#define COND_A (COND_NC|COND_NZ) -#define COND_NBE COND_A -#define COND_GE COND_NL -#define COND_NLE COND_G - -// Used for Opcode.FlagsChanged -#define FLAG_CF_SET (1<<0) -#define FLAG_DF_SET (1<<1) -#define FLAG_IF_SET (1<<2) -#define FLAG_SET_MASK (FLAG_CF_SET|FLAG_DF_SET|FLAG_IF_SET) - -#define FLAG_SF_CLR (1<<3) -#define FLAG_ZF_CLR (1<<4) -#define FLAG_AF_CLR (1<<5) -#define FLAG_CF_CLR (1<<6) -#define FLAG_DF_CLR (1<<7) -#define FLAG_IF_CLR (1<<8) -#define FLAG_OF_CLR (1<<9) -#define FPU_C0_CLR (1<<19) -#define FPU_C1_CLR (1<<20) -#define FPU_C2_CLR (1<<21) -#define FPU_C3_CLR (1<<22) -#define FPU_ALL_CLR (FPU_C0_CLR|FPU_C1_CLR|FPU_C2_CLR|FPU_C3_CLR) -#define FLAG_CLR_MASK (FLAG_SF_CLR|FLAG_ZF_CLR|FLAG_AF_CLR|FLAG_CF_CLR|FLAG_DF_CLR|FLAG_IF_CLR|FLAG_OF_CLR|FPU_ALL_CLR) - -#define FLAG_OF_MOD (1<<10) -#define FLAG_SF_MOD (1<<11) -#define FLAG_ZF_MOD (1<<12) -#define FLAG_AF_MOD (1<<13) -#define FLAG_PF_MOD (1<<14) -#define FLAG_CF_MOD (1<<15) -#define FLAG_DF_MOD (1<<16) -#define FLAG_IF_MOD (1<<17) -#define FLAG_ALL_MOD (FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD|FLAG_CF_MOD|FLAG_DF_MOD|FLAG_IF_MOD) -#define FLAG_COMMON_MOD (FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD|FLAG_CF_MOD) -#define FPU_C0_MOD (1<<23) -#define FPU_C1_MOD (1<<24) -#define FPU_C2_MOD (1<<25) -#define FPU_C3_MOD (1<<26) -#define FPU_ALL_MOD (FPU_C0_MOD|FPU_C1_MOD|FPU_C2_MOD|FPU_C3_MOD) -#define FLAG_MOD_MASK (FLAG_ALL_MOD|FPU_ALL_MOD) - -#define FLAG_CF_TOG (1<<18) -#define FLAG_TOG_MASK FLAG_CF_TOG - -// Used for Opcode.ResultsIfTrue and Opcode.ResultsIfFalse -#define OP1_DST (1<<0) -#define OP2_DST (1<<1) -#define OP3_DST (1<<2) -#define OP1_SRC (1<<3) -#define OP2_SRC (1<<4) -#define OP3_SRC (1<<5) -#define FPU_STACK_INC (1<<6) -#define FPU_STACK_INC2 (1<<7) -#define FPU_STACK_DEC (1<<8) -#define SERIALIZE_WRITE (1<<9) -#define SERIALIZE_READ (1<<10) -#define xCX_DEC (1<<11) -#define xCX_REP_DEC (1<<12) -#define xDI_DEC (1<<13) -#define xDI_INC (1<<14) -#define xSI_DEC (1<<15) -#define xSI_INC (1<<16) -#define xDI_DECx (1<<17) -#define xDI_INCx (1<<18) -#define xSI_DECx (1<<19) -#define xSI_INCx (1<<20) -#define FPU_STACK_PUSH FPU_STACK_DEC -#define FPU_STACK_POP FPU_STACK_INC -#define FPU_STACK_POP2 FPU_STACK_INC2 -#define SERIALIZE_ALL (SERIALIZE_WRITE|SERIALIZE_READ) - -#define X86_SEGMENT_OFFSET 0x00 -#define X86_TEST_OFFSET 0x10 -#define X86_CONTROL_OFFSET 0x20 -#define X86_DEBUG_OFFSET 0x30 -#define X86_FPU_OFFSET 0x40 -#define X86_MMX_OFFSET 0x50 -#define X86_XMM_OFFSET 0x60 -#define X86_8BIT_OFFSET 0x70 -#define X86_16BIT_OFFSET 0x80 -#define X86_32BIT_OFFSET 0x90 -#define AMD64_8BIT_OFFSET 0xA0 -#define AMD64_16BIT_OFFSET 0xB0 -#define AMD64_32BIT_OFFSET 0xC0 -#define AMD64_64BIT_OFFSET 0xD0 - -typedef enum _X86_REGISTER -{ - // Segments - X86_SEG_ES = X86_SEGMENT_OFFSET, - X86_SEG_CS, - X86_SEG_SS, - X86_SEG_DS, - X86_SEG_FS, - X86_SEG_GS, - - // Miscellaneous - X86_REG_FLAGS, - X86_REG_EFLAGS, - AMD64_REG_RFLAGS, - X86_REG_IP, - X86_REG_EIP, - AMD64_REG_RIP, - - // Test registers - X86_REG_TR0 = X86_TEST_OFFSET, - X86_REG_TR1, - X86_REG_TR2, - X86_REG_TR3, - X86_REG_TR4, - X86_REG_TR5, - X86_REG_TR6, - X86_REG_TR7, - X86_REG_TR8, - X86_REG_TR9, - X86_REG_TR10, - X86_REG_TR11, - X86_REG_TR12, - X86_REG_TR13, - X86_REG_TR14, - X86_REG_TR15, - - // Control registers - X86_REG_CR0=X86_CONTROL_OFFSET, - X86_REG_CR1, - X86_REG_CR2, - X86_REG_CR3, - X86_REG_CR4, - X86_REG_CR5, - X86_REG_CR6, - X86_REG_CR7, - X86_REG_CR8, - X86_REG_CR9, - X86_REG_CR10, - X86_REG_CR11, - X86_REG_CR12, - X86_REG_CR13, - X86_REG_CR14, - X86_REG_CR15, - - // Debug registers - X86_REG_DR0=X86_DEBUG_OFFSET, - X86_REG_DR1, - X86_REG_DR2, - X86_REG_DR3, - X86_REG_DR4, - X86_REG_DR5, - X86_REG_DR6, - X86_REG_DR7, - X86_REG_DR8, - X86_REG_DR9, - X86_REG_DR10, - X86_REG_DR11, - X86_REG_DR12, - X86_REG_DR13, - X86_REG_DR14, - X86_REG_DR15, - - // FPU registers - X86_REG_ST0=X86_FPU_OFFSET, - X86_REG_ST1, - X86_REG_ST2, - X86_REG_ST3, - X86_REG_ST4, - X86_REG_ST5, - X86_REG_ST6, - X86_REG_ST7, - - // MMX registers - X86_REG_MM0=X86_MMX_OFFSET, - X86_REG_MM1, - X86_REG_MM2, - X86_REG_MM3, - X86_REG_MM4, - X86_REG_MM5, - X86_REG_MM6, - X86_REG_MM7, - - // XMM registers - X86_REG_XMM0=X86_XMM_OFFSET, - X86_REG_XMM1, - X86_REG_XMM2, - X86_REG_XMM3, - X86_REG_XMM4, - X86_REG_XMM5, - X86_REG_XMM6, - X86_REG_XMM7, - - // 8-bit registers - X86_REG_AL=X86_8BIT_OFFSET, - X86_REG_CL, - X86_REG_DL, - X86_REG_BL, - X86_REG_AH, - X86_REG_CH, - X86_REG_DH, - X86_REG_BH, - - // 16-bit registers - X86_REG_AX=X86_16BIT_OFFSET, - X86_REG_CX, - X86_REG_DX, - X86_REG_BX, - X86_REG_SP, - X86_REG_BP, - X86_REG_SI, - X86_REG_DI, - - // 32-bit registers - X86_REG_EAX=X86_32BIT_OFFSET, - X86_REG_ECX, - X86_REG_EDX, - X86_REG_EBX, - X86_REG_ESP, - X86_REG_EBP, - X86_REG_ESI, - X86_REG_EDI, - - // AMD64 8-bit registers - AMD64_REG_AL=AMD64_8BIT_OFFSET, - AMD64_REG_CL, - AMD64_REG_DL, - AMD64_REG_BL, - AMD64_REG_SPL, - AMD64_REG_BPL, - AMD64_REG_SIL, - AMD64_REG_DIL, - AMD64_REG_R8B, - AMD64_REG_R9B, - AMD64_REG_R10B, - AMD64_REG_R11B, - AMD64_REG_R12B, - AMD64_REG_R13B, - AMD64_REG_R14B, - AMD64_REG_R15B, - - // AMD64 16-bit registers - AMD64_REG_AX=AMD64_16BIT_OFFSET, - AMD64_REG_CX, - AMD64_REG_DX, - AMD64_REG_BX, - AMD64_REG_SP, - AMD64_REG_BP, - AMD64_REG_SI, - AMD64_REG_DI, - AMD64_REG_R8W, - AMD64_REG_R9W, - AMD64_REG_R10W, - AMD64_REG_R11W, - AMD64_REG_R12W, - AMD64_REG_R13W, - AMD64_REG_R14W, - AMD64_REG_R15W, - - // AMD64 32-bit registers - AMD64_REG_EAX=AMD64_32BIT_OFFSET, - AMD64_REG_ECX, - AMD64_REG_EDX, - AMD64_REG_EBX, - AMD64_REG_ESP, - AMD64_REG_EBP, - AMD64_REG_ESI, - AMD64_REG_EDI, - AMD64_REG_R8D, - AMD64_REG_R9D, - AMD64_REG_R10D, - AMD64_REG_R11D, - AMD64_REG_R12D, - AMD64_REG_R13D, - AMD64_REG_R14D, - AMD64_REG_R15D, - - // AMD64 64-bit registers - AMD64_REG_RAX=AMD64_64BIT_OFFSET, - AMD64_REG_RCX, - AMD64_REG_RDX, - AMD64_REG_RBX, - AMD64_REG_RSP, - AMD64_REG_RBP, - AMD64_REG_RSI, - AMD64_REG_RDI, - AMD64_REG_R8, - AMD64_REG_R9, - AMD64_REG_R10, - AMD64_REG_R11, - AMD64_REG_R12, - AMD64_REG_R13, - AMD64_REG_R14, - AMD64_REG_R15 -} X86_REGISTER; - -typedef enum _X86_TEST_REGISTER -{ - REG_TR0=0, - REG_TR1, - REG_TR2, - REG_TR3, - REG_TR4, - REG_TR5, - REG_TR6, - REG_TR7, - REG_TR8, - REG_TR9, - REG_TR10, - REG_TR11, - REG_TR12, - REG_TR13, - REG_TR14, - REG_TR15 -} X86_TEST_REGISTER; - -typedef enum _X86_CONTROL_REGISTER -{ - REG_CR0, - REG_CR1, - REG_CR2, - REG_CR3, - REG_CR4, - REG_CR5, - REG_CR6, - REG_CR7, - REG_CR8, - REG_CR9, - REG_CR10, - REG_CR11, - REG_CR12, - REG_CR13, - REG_CR14, - REG_CR15 -} X86_CONTROL_REGISTER; - -typedef enum _X86_DEBUG_REGISTER -{ - REG_DR0, - REG_DR1, - REG_DR2, - REG_DR3, - REG_DR4, - REG_DR5, - REG_DR6, - REG_DR7, - REG_DR8, - REG_DR9, - REG_DR10, - REG_DR11, - REG_DR12, - REG_DR13, - REG_DR14, - REG_DR15 -} X86_DEBUG_REGISTER; - -typedef enum _X86_MMX_REGISTER -{ - REG_MM0=0, - REG_MM1=1, - REG_MM2=2, - REG_MM3=3, - REG_MM4=4, - REG_MM5=5, - REG_MM6=6, - REG_MM7=7 -} X86_MMX_REGISTER; - -typedef enum _X86_SSE_REGISTER -{ - REG_XMM0=0, - REG_XMM1=1, - REG_XMM2=2, - REG_XMM3=3, - REG_XMM4=4, - REG_XMM5=5, - REG_XMM6=6, - REG_XMM7=7 -} X86_SSE_REGISTER; - -typedef enum _X86_FPU_REGISTER -{ - REG_ST0=0, - REG_ST1=1, - REG_ST2=2, - REG_ST3=3, - REG_ST4=4, - REG_ST5=5, - REG_ST6=6, - REG_ST7=7 -} X86_FPU_REGISTER; - -typedef enum _X86_8BIT_REGISTER -{ - REG_AL = 0, - REG_CL = 1, - REG_DL = 2, - REG_BL = 3, - REG_AH = 4, - REG_CH = 5, - REG_DH = 6, - REG_BH = 7 -} X86_8BIT_REGISTER; - -typedef enum _X86_16BIT_REGISTER -{ - REG_AX = 0, - REG_CX = 1, - REG_DX = 2, - REG_BX = 3, - REG_SP = 4, - REG_BP = 5, - REG_SI = 6, - REG_DI = 7 -} X86_16BIT_REGISTER; - -typedef enum _X86_32BIT_REGISTER -{ - REG_EAX = 0, - REG_ECX = 1, - REG_EDX = 2, - REG_EBX = 3, - REG_ESP = 4, - REG_EBP = 5, - REG_ESI = 6, - REG_EDI = 7 -} X86_32BIT_REGISTER; - -typedef enum _X86_SEGMENT -{ - SEG_ES = 0, - SEG_CS = 1, - SEG_SS = 2, - SEG_DS = 3, - SEG_FS = 4, - SEG_GS = 5, - SEG_MAX = 6 -} X86_SEGMENT; - -extern char *X86_Registers[]; - -#pragma pack(push,1) -typedef struct _MODRM -{ - U8 mod : 2; - U8 reg : 3; - U8 rm : 3; -} MODRM; -typedef struct _SIB -{ - U8 scale : 2; - U8 index : 3; - U8 base : 3; -} SIB; -typedef struct _REX -{ - U8 unused : 4; // bits 4,5,6,7 - U8 w : 1; // bit 3 - U8 r : 1; // bit 2 - U8 x : 1; // bit 1 - U8 b : 1; // bit 0 -} REX; -typedef struct _REX_MODRM -{ - U8 reg : 4; - U8 rm : 4; -} REX_MODRM; -typedef struct _REX_SIB -{ - U8 index : 4; - U8 base : 4; -} REX_SIB; -#pragma pack(pop) - -// -// Properties: -// If an operand is OP_COND_EXEC, it means that it is executed only if the pre-conditions are met. -// -// If if an instruction has one or more OP_COND_DST operands, then the actions are determined by -// whether the Opcode.Preconditions are met or not. If all the COND_* flags in Opcode.Preconditions -// are true, then the results are determined by ResultsIfTrue. If the preconditions are not met, then -// the results are determined by ResultsIfFalse. -// -// If Preconditions == NOCOND, then results in ResultsIfTrue are unconditional and ResultsIfFalse -// is ignored -// -typedef struct _X86_OPCODE -{ - struct _X86_OPCODE *Table; - CPU_TYPE CPU; // minimum CPU (starting with i386) - U32 MnemonicFlags; - char Mnemonic[X86_MAX_INSTRUCTION_LEN+1]; - U32 OperandFlags[X86_MAX_OPERANDS]; - U32 Preconditions; - U32 FlagsChanged; // changes in flags - U32 ResultsIfTrue; // results if Preconditions are met - U32 ResultsIfFalse; // results if Preconditions are not met -} X86_OPCODE; - -typedef struct _X86_INSTRUCTION -{ - struct _INSTRUCTION *Instruction; // the generic instruction format representing this instruction - - X86_OPCODE Opcode; - - U8 sib_b; - U8 modrm_b; - MODRM modrm; - SIB sib; - U8 rex_b; - REX rex; - REX_MODRM rex_modrm; - REX_SIB rex_sib; - - X86_SEGMENT DstSegment; - union - { - X86_SEGMENT Segment; - DWORD Selector; - }; - - // NOTE: these are for internal use, use Instruction->Operands[] - // - // If DstRegAddressing or SrcRegAddressing = TRUE then BaseRegister is the base register - // It is the operand represented by SIBOperand - // - // The operand indices of the destination operands is in DstOpIndex[0 to DstOpCount-1] - // The operand indices of the source operands is in SrcOpIndex[0 to SrcOpCount-1] - // - // These are used both for instructions like xadd/xchg (where both operands are source/destination) - // and to represent implicit registers (e.g., cmpxchg) - - U8 SrcOpIndex[3]; - U8 DstOpIndex[3]; - - // Addressing mode: - // If DstRegAddressing = TRUE, then these apply to DstReg - // If SrcRegAddressing = TRUE, then this applies to SrcReg[AddressIndex] - // If both are false, then SrcReg and DstReg are not addresses - X86_REGISTER BaseRegister; - X86_REGISTER IndexRegister; - - U8 Scale; - U8 HasDefault64Operand : 1; - U8 HasOperandSizePrefix : 1; - U8 HasAddressSizePrefix : 1; - U8 HasSegmentOverridePrefix : 1; - U8 HasLockPrefix : 1; - U8 HasRepeatWhileEqualPrefix : 1; - U8 HasRepeatWhileNotEqualPrefix : 1; - U8 HasBranchTakenPrefix : 1; - U8 HasBranchNotTakenPrefix : 1; - U8 HasDstAddressing : 1; - U8 HasSrcAddressing : 1; - U8 HasModRM : 1; - U8 HasBaseRegister : 1; - U8 HasIndexRegister : 1; - U8 HasFullDisplacement : 1; - U8 HasDstSegment : 1; // used for ins/cmps/scas/movs/etc which have 2 segments - U8 DstAddressIndex : 2; // DstOpIndex[DstAddressIndex] - U8 SrcAddressIndex : 2; // SrcOpIndex[SrcAddressIndex] - U8 DstOpCount : 2; - U8 SrcOpCount : 2; - U8 OperandSize : 4; - U8 AddressSize : 4; - U8 Relative : 1; - U8 HasSelector : 1; // segment is actually a selector - U8 Group : 5; - - S64 Displacement; - -} X86_INSTRUCTION; - -//////////////////////////////////////////////////////////////////////////////////// -// Exported functions -//////////////////////////////////////////////////////////////////////////////////// - -extern ARCHITECTURE_FORMAT_FUNCTIONS X86; - -// Instruction setup -BOOL X86_InitInstruction(struct _INSTRUCTION *Instruction); -void X86_CloseInstruction(struct _INSTRUCTION *Instruction); - -// Instruction translator -BOOL X86_TranslateInstruction(struct _INSTRUCTION *Instruction, BOOL Verbose); - -// Instruction decoder -BOOL X86_GetInstruction(struct _INSTRUCTION *Instruction, U8 *Address, DWORD Flags); - -// Function finding -U8 *X86_FindFunctionByPrologue(struct _INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, DWORD Flags); - -#ifdef __cplusplus -} -#endif -#endif // X86_DISASM_H - diff --git a/src/disasm-lib/disasm_x86_tables.h b/src/disasm-lib/disasm_x86_tables.h deleted file mode 100644 index 6c79d45c..00000000 --- a/src/disasm-lib/disasm_x86_tables.h +++ /dev/null @@ -1,3654 +0,0 @@ -// Copyright (C) 2004, Matt Conover (mconover@gmail.com) -// -// The opcode tables in this file are based off the Intel Instruction Set Reference -// and an assortment of disassemblers, primarily libdisasm (by mammon) - -#ifndef DISASM_X86_TABLES -#define DISASM_X86_TABLES - -#define X86_GET_REG(val) ((val) & 7) -#define X86_GET_REG64(val) ((GET_REX_B(X86Instruction->rex_b) << 3) | ((val) & 7)) - -#define GET_MODRM_MOD(a) (((a) >> 6) & 3) // bits 6, 7 -#define GET_MODRM_REG(a) (((a) >> 3) & 7) // bits 3, 4, 5 -#define GET_MODRM_EXT(a) (((a) >> 3) & 7) // bits 3, 4, 5 -#define GET_MODRM_RM(a) ((a) & 7) // bits 0, 1, 2 - -#define GET_SIB_SCALE(a) (((a) >> 6) & 3) // bits 6, 7 -#define GET_SIB_INDEX(a) (((a) >> 3) & 7) // bits 3, 4, 5 -#define GET_SIB_BASE(a) ((a) & 7) // bits 0, 1, 2 - -#define REX_PREFIX_START 0x40 -#define REX_PREFIX_END 0x4F -#define GET_REX_W(r) (((r) & 8) >> 3) // bit 3 -#define GET_REX_R(r) (((r) & 4) >> 2) // bit 2 -#define GET_REX_X(r) (((r) & 2) >> 1) // bit 1 -#define GET_REX_B(r) ((r) & 1) // bit 0 -#define REX_MASK(n) ((n >> 16) & 0x0F) // bits 0-3 - -// Groupings to make the opcode table more readible -#define NOARGS { 0, 0, 0 } -#define NOCOND 0 -#define NOGROUP NULL -#define NOACTION 0 -#define NOCHANGE 0 -#define IGNORED 0 -#define NOINSTR NOGROUP, CPU_UNKNOWN, 0, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED -#define GROUP CPU_UNKNOWN, 0, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED -#define PREFIX NOGROUP, CPU_UNKNOWN, ITYPE_EXT_PREFIX, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED -#define EXT_FPU CPU_UNKNOWN, ITYPE_EXT_FPU, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED -#define EXT_64 CPU_UNKNOWN, ITYPE_EXT_64, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED -#define EXT_SUFFIX(a, b, c) CPU_UNKNOWN, ITYPE_EXT_SUFFIX, "", { a, b, c }, NOCOND, NOCHANGE, NOACTION, IGNORED -#define EXT_MODRM CPU_UNKNOWN, ITYPE_EXT_MODRM, "", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED - -#define SET_MODRM(modrm, src) \ -{ \ - (modrm).mod = GET_MODRM_MOD(src); \ - (modrm).reg = GET_MODRM_REG(src); \ - (modrm).rm = GET_MODRM_RM(src); \ -} - -#define SET_REX_MODRM(rex_modrm, rex, modrm) \ -{ \ - (rex_modrm).rm = ((rex).b << 3) | (modrm).rm; \ - (rex_modrm).reg = ((rex).r << 3) | (modrm).reg; \ -} - -#define SET_SIB(sib, src) \ -{ \ - (sib).scale = GET_SIB_SCALE(src); \ - (sib).index = GET_SIB_INDEX(src); \ - (sib).base = GET_SIB_BASE(src); \ -} - -#define SET_REX_SIB(rex_sib, rex, sib) \ -{ \ - (rex_sib).index = ((rex).x << 3) | (sib).index; \ - (rex_sib).base = ((rex).b << 3) | (sib).base; \ -} - -#define SET_REX(rex, src) \ -{ \ - (rex).w = GET_REX_W(src); \ - (rex).r = GET_REX_R(src); \ - (rex).x = GET_REX_X(src); \ - (rex).b = GET_REX_B(src); \ -} - -// Addressing modes -#define AMODE_A 0x00010000 -#define AMODE_C 0x00020000 -#define AMODE_D 0x00030000 -#define AMODE_E 0x00040000 -#define AMODE_G 0x00050000 -#define AMODE_I 0x00060000 -#define AMODE_J 0x00070000 -#define AMODE_M 0x00080000 -#define AMODE_O 0x00090000 -#define AMODE_P 0x000A0000 -#define AMODE_Q 0x000B0000 -#define AMODE_R 0x000C0000 -#define AMODE_S 0x000D0000 -#define AMODE_T 0x000E0000 -#define AMODE_V 0x000F0000 -#define AMODE_W 0x00100000 -#define AMODE_X 0x00110000 -#define AMODE_Y 0x00120000 -#define AMODE_PR 0x00130000 -#define AMODE_VR 0x00140000 -#define AMODE_xlat 0x00150000 - -// Operand types -#define OPTYPE_a 0x01000000 -#define OPTYPE_b 0x02000000 -#define OPTYPE_d 0x03000000 -#define OPTYPE_p 0x04000000 -#define OPTYPE_q 0x05000000 -#define OPTYPE_dt 0x06000000 -#define OPTYPE_v 0x07000000 -#define OPTYPE_w 0x08000000 -#define OPTYPE_ps 0x09000000 // packed 128-bit single real -#define OPTYPE_pd 0x0A000000 // packed 128-bit double real -#define OPTYPE_pb 0x0B000000 // packed BCD (10 bytes, 18-bit precision) -#define OPTYPE_ss 0x0C000000 // scalar single real -#define OPTYPE_sd 0x0D000000 // scalar double real -#define OPTYPE_se 0x0E000000 // scalar extended real -#define OPTYPE_fev 0x0F000000 // FPU environment (28 bytes if 32-bit modes, 14 bytes in 16-bit mode) -#define OPTYPE_fst1 0x10000000 // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode) -#define OPTYPE_fst2 0x11000000 // FPU/MMX/XMM/MXCSR state (512 bytes) -#define OPTYPE_z 0x12000000 -#define OPTYPE_o 0x13000000 -#define OPTYPE_dq 0x14000000 // OPTYPE_d or OPTYPE_o -#define OPTYPE_mw 0x15000000 // word if memory, register size otherwise -#define OPTYPE_sso 0x16000000 // OPTYPE_ss or OPTYPE_o -#define OPTYPE_sdo 0x17000000 // OPTYPE_ss or OPTYPE_o -#define OPTYPE_cpu 0x18000000 // pointer to CPU state structure -#define OPTYPE_lea 0x19000000 // size set by other operand -// NOTE: if you change this, you must also update OptypeHandlers[] in disasm_x86.c -// Be sure to preserve the ordering - -////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Registers -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -static char *Addressing16[8] = {"bx+si","bx+di","bp+si","bp+di","si","di","bp","bx"}; -static char *MMX_Registers[8] = {"mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7"}; -static char *SSE_Registers[8] = {"xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"}; -static char *DR_Registers[8] = {"dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7"}; -static char *CR_Registers[8] = {"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7"}; -static char *TR_Registers[8] = {"tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7"}; -static char *FPU_Registers[8] = {"st(0)", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)"}; -static char *Segments[8] = {"es", "cs", "ss", "ds", "fs", "gs", "ERROR", "ERROR"}; -static char *Registers8[8] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" }; -static char *Registers16[8] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di" }; -static char *Registers32[8] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" }; -static char *REX_Registers8[16] = {"al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }; -static char *REX_Registers16[16] = {"ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }; -static char *REX_Registers32[16] = {"eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }; -static char *REX_Registers64[16] = {"rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }; -static char *DataSizes[8+1] = {"byte ptr", "word ptr", "dword ptr", "6_byte ptr", "qword ptr", "10_byte ptr", "INVALID PTR", "INVALID PTR", "oword ptr"}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// FPU constants -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -BYTE float_0[10] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -BYTE float_1[10] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x3F }; -BYTE float_l2t[10] = { 0xFE, 0x8A, 0x1B, 0xCD, 0x4B, 0x78, 0x9A, 0xD4, 0x00, 0x40 }; -BYTE float_l2e[10] = { 0xBC, 0xF0, 0x17, 0x5C, 0x29, 0x3B, 0xAA, 0xB8, 0xFF, 0x3F }; -BYTE float_pi[10] = { 0x35, 0xC2, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9, 0x00, 0x40 }; -BYTE float_lg2[10] = { 0x99, 0xF7, 0xCF, 0xFB, 0x84, 0x9A, 0x20, 0x9A, 0xFD, 0x3F }; -BYTE float_ln2[10] = { 0xAC, 0x79, 0xCF, 0xD1, 0xF7, 0x17, 0x72, 0xB1, 0xFE, 0x3F }; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Tables -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -extern X86_OPCODE X86_Opcodes_2[0x100]; -extern X86_OPCODE X86_Group_1_80[8], X86_Group_1_81[8], X86_Group_1_82[8], X86_Group_1_83[8], X86_Group_2_C0[8], X86_Group_2_C1[8], X86_Group_2_D0[8], X86_Group_2_D1[8], X86_Group_2_D2[8], X86_Group_2_D3[8], X86_Group_3_F6[8], X86_Group_3_F7[8], X86_Group_4[8], X86_Group_5[8], X86_Group_6[8], X86_Group_7[8], X86_Group_8[8], X86_Group_9[8], X86_Group_10[8], X86_Group_11[8], X86_Group_12_C6[8], X86_Group_12_C7[8], X86_Group_13[8], X86_Group_14[8], X86_Group_15[8], X86_Group_16[8], X86_Group_17[8], X86_Group_P[8]; -extern X86_OPCODE X86_SSE[0x300], X86_SSE2_Group_13[24], X86_SSE2_Group_14[24], X86_SSE2_Group_15[24]; -extern X86_OPCODE X86_ESC_0[0x48], X86_ESC_1[0x48], X86_ESC_2[0x48], X86_ESC_3[0x48], X86_ESC_3[0x48], X86_ESC_4[0x48], X86_ESC_5[0x48], X86_ESC_6[0x48], X86_ESC_7[0x48]; -extern X86_OPCODE X86_3DNOW_0F[0x100]; -extern X86_OPCODE X86_0F01_ModRM[0x100]; -extern X86_OPCODE X86_Opcode_63[2], X86_Opcode_0F05[2]; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Opcode tables -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -X86_OPCODE X86_Opcodes_1[0x100] = // 1 byte opcodes -{ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_ES | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_ES | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x08 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x09 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0A */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0B */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0C */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x0D */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_CS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x0E */ - { X86_Opcodes_2, GROUP }, /* 0x0F */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x10 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x11 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x12 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x13 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x14 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x15 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_SS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x16 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_SS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x17 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x18 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x19 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1A */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1B */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1C */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x1D */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_DS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x1E */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_DS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x1F */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x20 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x21 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x22 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x23 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x24 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x25 */ - { PREFIX }, /* 0x26 */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "daa", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_AF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x27 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x28 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x29 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2A */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2B */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2C */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x2D */ - { PREFIX }, /* 0x2E */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "das", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_AF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x2F */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x30 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x31 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x32 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x33 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x34 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x35 */ - { PREFIX }, /* 0x36 */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aaa", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_AF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x37 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x38 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x39 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_G | OPTYPE_b | OP_SRC, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3A */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3B */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { OPTYPE_REG_AL | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3C */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { OPTYPE_REG_xAX_BIG | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_z | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x3D */ - { PREFIX }, /* 0x3E */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aas", { OPTYPE_REG_AL | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_AF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x3F */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x40 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x41 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x42 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x43 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x44 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x45 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x46 */ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x47 */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x48 */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x49 */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4A */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4B */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4C */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4D */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4E */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x4F */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x50 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x51 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x52 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x53 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x54 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x55 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x56 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OP_REG | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x57 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x58 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x59 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5A */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5B */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5C */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5D */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5E */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OP_REG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5F */ - { NOGROUP, CPU_I386, ITYPE_PUSHA, "pushad", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x60 */ - { NOGROUP, CPU_I386, ITYPE_POPA, "popad", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x61 */ - { NOGROUP, CPU_I386, ITYPE_BOUNDS, "bound", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_M | OPTYPE_a | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x62 */ - { X86_Opcode_63, EXT_64 }, /* 0x63 */ - { PREFIX }, /* 0x64 */ - { PREFIX }, /* 0x65 */ - { PREFIX }, /* 0x66 */ - { PREFIX }, /* 0x67 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { AMODE_I | OPTYPE_z | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x68 */ - { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_z | OP_SIGNED | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x69 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6A */ - { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x6B */ - { NOGROUP, CPU_I386, ITYPE_IN, "insb", { AMODE_Y | OPTYPE_b | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DEC | xCX_REP_DEC, xDI_INC | xCX_REP_DEC }, /* 0x6C */ - { NOGROUP, CPU_I386, ITYPE_IN, "insd", { AMODE_Y | OPTYPE_z | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DECx | xCX_REP_DEC, xDI_INCx | xCX_REP_DEC }, /* 0x6D */ - { NOGROUP, CPU_I386, ITYPE_OUT, "outsb", { OPTYPE_REG_DX | OP_SYS | OP_DST, AMODE_X | OPTYPE_b | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DEC | xCX_REP_DEC, xSI_INC | xCX_REP_DEC }, /* 0x6E */ - { NOGROUP, CPU_I386, ITYPE_OUT, "outsd", { OPTYPE_REG_DX | OP_SYS | OP_DST, AMODE_X | OPTYPE_z | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DECx | xCX_REP_DEC, xSI_INCx | xCX_REP_DEC}, /* 0x6F */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jo", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_O, NOCHANGE, OP1_DST, NOACTION }, /* 0x70 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jno", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NO, NOCHANGE, OP1_DST, NOACTION }, /* 0x71 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jb", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_C, NOCHANGE, OP1_DST, NOACTION }, /* 0x72 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnb", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NC, NOCHANGE, OP1_DST, NOACTION }, /* 0x73 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_Z, NOCHANGE, OP1_DST, NOACTION }, /* 0x74 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NZ, NOCHANGE, OP1_DST, NOACTION }, /* 0x75 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jbe", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_BE, NOCHANGE, OP1_DST, NOACTION }, /* 0x76 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "ja", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_A, NOCHANGE, OP1_DST, NOACTION }, /* 0x77 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "js", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_S, NOCHANGE, OP1_DST, NOACTION }, /* 0x78 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jns", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NS, NOCHANGE, OP1_DST, NOACTION }, /* 0x79 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpe", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PE, NOCHANGE, OP1_DST, NOACTION }, /* 0x7A */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpo", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PO, NOCHANGE, OP1_DST, NOACTION }, /* 0x7B */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jl", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_L, NOCHANGE, OP1_DST, NOACTION }, /* 0x7C */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jge", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_GE, NOCHANGE, OP1_DST, NOACTION }, /* 0x7D */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jle", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_LE, NOCHANGE, OP1_DST, NOACTION }, /* 0x7E */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jg", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_G, NOCHANGE, OP1_DST, NOACTION }, /* 0x7F */ - { X86_Group_1_80, GROUP }, /* 0x80 Eb Ib */ - { X86_Group_1_81, GROUP }, /* 0x81 Ev Iz */ - { X86_Group_1_82, GROUP }, /* 0x82 Eb Ib */ - { X86_Group_1_83, GROUP }, /* 0x83 Ev Ib */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x84 */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x85 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, AMODE_G | OPTYPE_b | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x86 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_G | OPTYPE_v | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x87 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_b | OP_DST, AMODE_G | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x88 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x89 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_G | OPTYPE_b | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8A */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8B */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_mw | OP_DST, AMODE_S | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8C */ - { NOGROUP, CPU_I386, ITYPE_LEA, "lea", { AMODE_G | OPTYPE_v | OP_DST, AMODE_M | OPTYPE_lea | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8D */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_S | OPTYPE_w | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x8E */ - { X86_Group_10, GROUP }, /* 0x8F */ - { NOGROUP, CPU_I386, ITYPE_NOP, "nop", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x90 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x91 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x92 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x93 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x94 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x95 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x96 */ - { NOGROUP, CPU_I386, ITYPE_XCHG, "xchg", { OPTYPE_REG_xAX_BIG | OP_SRC | OP_DST, OP_REG | OP_SRC | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x97 */ - { NOGROUP, CPU_I386, ITYPE_SZCONV, "cwde", { OPTYPE_REG_xAX_BIG | OP_SIGNED | OP_DST, OPTYPE_REG_xAX_SMALL | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x98 */ - { NOGROUP, CPU_I386, ITYPE_SZCONV, "cdq", { OPTYPE_xDX_HI_xAX_LO | OP_SIGNED | OP_DST, OPTYPE_REG_xAX_BIG | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x99 */ - { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_A | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9A */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "wait", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9B */ - { NOGROUP, CPU_I386, ITYPE_PUSHF, "pushf", { OPTYPE_xFLAGS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9C */ - { NOGROUP, CPU_I386, ITYPE_POPF, "popf", { OPTYPE_xFLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_ALL_MOD, NOACTION, IGNORED }, /* 0x9D */ - { NOGROUP, CPU_I386, ITYPE_MOV, "sahf", { OPTYPE_FLAGS | OP_DST, OPTYPE_REG_AH | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_AF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x9E */ - { NOGROUP, CPU_I386, ITYPE_MOV, "lahf", { OPTYPE_REG_AH | OP_DST, OPTYPE_FLAGS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x9F */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG_AL | OP_DST, AMODE_O | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA0 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_O | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA1 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_O | OPTYPE_b | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA2 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_O | OPTYPE_v | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA3 */ - { NOGROUP, CPU_I386, ITYPE_STRMOV, "movsb", { AMODE_Y | OPTYPE_b | OP_DST, AMODE_X | OPTYPE_b | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DEC | xSI_DEC | xCX_REP_DEC, xDI_INC | xSI_INC | xCX_REP_DEC}, /* 0xA4 */ - { NOGROUP, CPU_I386, ITYPE_STRMOV, "movsd", { AMODE_Y | OPTYPE_z | OP_DST, AMODE_X | OPTYPE_z | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DECx | xSI_DECx| xCX_REP_DEC, xDI_INCx | xSI_INCx | xCX_REP_DEC }, /* 0xA5 */ - { NOGROUP, CPU_I386, ITYPE_STRCMP, "cmpsb", { AMODE_X | OPTYPE_b | OP_SRC, AMODE_Y | OPTYPE_b | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DEC | xSI_DEC | xCX_REP_DEC, xDI_INC | xSI_INC | xCX_REP_DEC }, /* 0xA6 */ - { NOGROUP, CPU_I386, ITYPE_STRCMP, "cmpsd", { AMODE_X | OPTYPE_z | OP_SRC, AMODE_Y | OPTYPE_z | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DECx | xSI_DECx | xCX_REP_DEC, xDI_INCx | xSI_INCx | xCX_REP_DEC}, /* 0xA7 */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { OPTYPE_REG_AL | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0xA8 */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { OPTYPE_REG_xAX_BIG | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0xA9 */ - { NOGROUP, CPU_I386, ITYPE_STRSTOR, "stosb", { AMODE_Y | OPTYPE_b | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DEC | xSI_DEC | xCX_REP_DEC, xDI_INC | xSI_INC | xCX_REP_DEC }, /* 0xAA */ - { NOGROUP, CPU_I386, ITYPE_STRSTOR, "stosd", { AMODE_Y | OPTYPE_z | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, COND_D, NOCHANGE, xDI_DECx | xSI_DECx | xCX_REP_DEC, xDI_INCx | xSI_INCx | xCX_REP_DEC }, /* 0xAB */ - { NOGROUP, CPU_I386, ITYPE_STRLOAD, "lodsb", { OPTYPE_REG_AL | OP_DST, AMODE_X | OPTYPE_b | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DEC | xCX_REP_DEC, xSI_INC | xCX_REP_DEC }, /* 0xAC */ - { NOGROUP, CPU_I386, ITYPE_STRLOAD, "lodsd", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_X | OPTYPE_z | OP_SRC, 0 }, COND_D, NOCHANGE, xSI_DECx | xCX_REP_DEC, xSI_INCx | xCX_REP_DEC }, /* 0xAD */ - { NOGROUP, CPU_I386, ITYPE_STRCMP, "scasb", { OPTYPE_REG_AL | OP_SRC, AMODE_Y | OPTYPE_b | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DEC | xCX_REP_DEC, xDI_INC | xCX_REP_DEC }, /* 0xAE */ - { NOGROUP, CPU_I386, ITYPE_STRCMP, "scasd", { OPTYPE_REG_xAX_BIG | OP_SRC, AMODE_Y | OPTYPE_z | OP_SRC, 0 }, COND_D, FLAG_COMMON_MOD, xDI_DECx, xDI_INCx }, /* 0xAF */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB0 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB1 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB2 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB3 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB4 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB5 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB6 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OPTYPE_REG8 | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB7 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB8 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB9 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBA */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBB */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBC */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBD */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBE */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { OP_REG | OP_DST, AMODE_I | OPTYPE_v | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBF */ - { X86_Group_2_C0, GROUP }, /* 0xC0 Eb Ib */ - { X86_Group_2_C1, GROUP }, /* 0xC1 Ev Ib */ - { NOGROUP, CPU_I386, ITYPE_RET, "ret", { AMODE_I | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC2 */ - { NOGROUP, CPU_I386, ITYPE_RET, "ret", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC3 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "les", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC4 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "lds", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC5 */ - { X86_Group_12_C6, GROUP }, /* 0xC6 Eb Ib */ - { X86_Group_12_C7, GROUP }, /* 0xC7 Ev Iz */ - { NOGROUP, CPU_I386, ITYPE_ENTER, "enter", { OPTYPE_REG_xBP | OP_SRC | OP_DST, AMODE_I | OPTYPE_w | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC8 */ - { NOGROUP, CPU_I386, ITYPE_LEAVE, "leave", { OPTYPE_REG_xBP | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC9 */ - { NOGROUP, CPU_I386, ITYPE_RET, "retf", { AMODE_I | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCA */ - { NOGROUP, CPU_I386, ITYPE_RET, "retf", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCB */ - { NOGROUP, CPU_I386, ITYPE_DEBUG, "int3", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCC */ - { NOGROUP, CPU_I386, ITYPE_TRAP, "int", { AMODE_I | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCD */ - { NOGROUP, CPU_I386, ITYPE_OFLOW, "into", NOARGS, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xCE */ - { NOGROUP, CPU_I386, ITYPE_TRAPRET, "iret", NOARGS, NOCOND, FLAG_ALL_MOD, NOACTION, IGNORED }, /* 0xCF */ - { X86_Group_2_D0, GROUP }, /* 0xD0 Eb, 1 */ - { X86_Group_2_D1, GROUP }, /* 0xD1 Ev, 1 */ - { X86_Group_2_D2, GROUP }, /* 0xD2 Eb, CL */ - { X86_Group_2_D3, GROUP }, /* 0xD3 Ev, CL */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aam", { OPTYPE_REG_AX | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD, NOACTION, IGNORED }, /* 0xD4 */ - { NOGROUP, CPU_I386, ITYPE_BCDCONV, "aad", { OPTYPE_REG_AX | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD, NOACTION, IGNORED }, /* 0xD5 */ - { NOGROUP, CPU_I386, ITYPE_ARITH, "salc", { OPTYPE_REG_AL | OP_DST, OPTYPE_FF | OP_SRC, OPTYPE_0 | OP_SRC }, COND_C, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0xD6 */ - { NOGROUP, CPU_I386, ITYPE_XLAT, "xlat", { OPTYPE_REG_AL | OP_DST, AMODE_xlat | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD7 */ - { X86_ESC_0, EXT_FPU }, /* 0xD8 */ - { X86_ESC_1, EXT_FPU }, /* 0xD9 */ - { X86_ESC_2, EXT_FPU }, /* 0xDA */ - { X86_ESC_3, EXT_FPU }, /* 0xDB */ - { X86_ESC_4, EXT_FPU }, /* 0xDC */ - { X86_ESC_5, EXT_FPU }, /* 0xDD */ - { X86_ESC_6, EXT_FPU }, /* 0xDE */ - { X86_ESC_7, EXT_FPU }, /* 0xDF */ - { NOGROUP, CPU_I386, ITYPE_LOOPCC, "loopnz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_NZ | COND_NZ, NOCHANGE, OP1_DST | xCX_DEC, NOACTION }, /* 0xE0 */ - { NOGROUP, CPU_I386, ITYPE_LOOPCC, "loopz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_NZ | COND_Z, NOCHANGE, OP1_DST | xCX_DEC, NOACTION }, /* 0xE1 */ - { NOGROUP, CPU_I386, ITYPE_LOOPCC, "loop", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_NZ, NOCHANGE, OP1_DST | xCX_DEC, NOACTION }, /* 0xE2 */ - { NOGROUP, CPU_I386, ITYPE_LOOPCC, "jecxz", { AMODE_J | OPTYPE_b | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_REG_xCX_BIG_Z, NOCHANGE, OP1_DST, NOACTION }, /* 0xE3 */ - { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_AL | OP_DST, AMODE_I | OPTYPE_b | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE4 */ - { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_xAX_BIG | OP_DST, AMODE_I | OPTYPE_b | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE5 */ - { NOGROUP, CPU_I386, ITYPE_OUT, "out", { AMODE_I | OPTYPE_b | OP_SYS | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE6 */ - { NOGROUP, CPU_I386, ITYPE_OUT, "out", { AMODE_I | OPTYPE_b | OP_SYS | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, NOACTION }, /* 0xE7 */ - { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_J | OPTYPE_z | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE8 */ - { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_J | OPTYPE_z | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE9 */ - { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_A | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEA */ - { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_J | OPTYPE_b | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEB */ - { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_AL | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEC */ - { NOGROUP, CPU_I386, ITYPE_IN, "in", { OPTYPE_REG_xAX_BIG | OP_DST, OPTYPE_REG_DX | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xED */ - { NOGROUP, CPU_I386, ITYPE_OUT, "out", { OPTYPE_REG_DX | OP_SYS | OP_DST, OPTYPE_REG_AL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEE */ - { NOGROUP, CPU_I386, ITYPE_OUT, "out", { OPTYPE_REG_DX | OP_SYS | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEF */ - { PREFIX }, /* 0xF0 */ - { NOGROUP, CPU_I386, ITYPE_DEBUG, "int1", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, // aka icebp /* 0xF1 */ - { PREFIX }, /* 0xF2 */ - { PREFIX }, /* 0xF3 */ - { NOGROUP, CPU_I386, ITYPE_HALT, "hlt", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF4 */ - { NOGROUP, CPU_I386, ITYPE_TOGCF, "cmc", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_CF_TOG, IGNORED }, /* 0xF5 */ - { X86_Group_3_F6, GROUP }, /* 0xF6 Eb */ - { X86_Group_3_F7, GROUP }, /* 0xF7 Ev */ - { NOGROUP, CPU_I386, ITYPE_CLEARCF, "clc", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_CF_CLR, NOACTION, IGNORED }, /* 0xF8 */ - { NOGROUP, CPU_I386, ITYPE_SETCF, "stc", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_CF_SET, NOACTION, IGNORED }, /* 0xF9 */ - { NOGROUP, CPU_I386, ITYPE_CLEARIF, "cli", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_IF_CLR, NOACTION, IGNORED }, /* 0xFA */ - { NOGROUP, CPU_I386, ITYPE_SETIF, "sti", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_IF_SET, NOACTION, IGNORED }, /* 0xFB */ - { NOGROUP, CPU_I386, ITYPE_CLEARDF, "cld", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_DF_CLR, NOACTION, IGNORED }, /* 0xFC */ - { NOGROUP, CPU_I386, ITYPE_SETDF, "std", { OPTYPE_FLAGS | OP_DST, 0, 0 }, NOCOND, FLAG_DF_SET, NOACTION, IGNORED }, /* 0xFD */ - { X86_Group_4, GROUP }, /* 0xFE */ - { X86_Group_5, GROUP }, /* 0xFF */ -}; - -X86_OPCODE X86_Opcodes_2[0x100] = // 2 byte opcodes -{ - { X86_Group_6, GROUP }, /* 0x00 */ - { X86_0F01_ModRM, EXT_MODRM }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lar", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lsl", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { X86_Opcode_0F05, EXT_64 }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "clts", { OPTYPE_CR0 | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_SYSCALLRET, "sysret", { OPTYPE_STAR_MSR | OP_MSR | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ - // 0F 07 could also be this undocumented instruction on older CPUs: - // { NOGROUP, CPU_I386, ITYPE_SYSTEM, "loadall", { AMODE_Y | OPTYPE_cpu | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ - { NOGROUP, CPU_I486, ITYPE_SYSTEM, "invd", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x08 */ - { NOGROUP, CPU_I486, ITYPE_SYSTEM, "wbinvd", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x09 */ - { NOINSTR }, /* 0x0A */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_INVALID, "undef" /* aka UD2 */, NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x0B */ - { NOINSTR }, /* 0x0C */ - { X86_Group_P, GROUP }, /* 0x0D */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "femms", { OPTYPE_FPU_TAG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x0E */ - { X86_3DNOW_0F, EXT_SUFFIX(AMODE_P | OPTYPE_q, AMODE_Q | OPTYPE_q, 0) }, /* 0x0F */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movups", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x10 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movups", { AMODE_W | OPTYPE_ps | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x11 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movlps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x12 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movlps", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x13 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "unpcklps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x14 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "unpckhps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x15 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movhps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x16 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movhps", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x17 */ - { X86_Group_17, GROUP }, /* 0x18 */ - { NOINSTR }, /* 0x19 */ - { NOINSTR }, /* 0x1A */ - { NOINSTR }, /* 0x1B */ - { NOINSTR }, /* 0x1C */ - { NOINSTR }, /* 0x1D */ - { NOINSTR }, /* 0x1E */ - { NOINSTR }, /* 0x1F */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_R | OPTYPE_dq | OP_DST, AMODE_C | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x20 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_R | OPTYPE_dq | OP_DST, AMODE_D | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x21 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_C | OPTYPE_dq | OP_DST, AMODE_R | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x22 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_D | OPTYPE_dq | OP_DST, AMODE_R | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x23 */ - { NOINSTR }, /* 0x24 */ - //{ NOGROUP, CPU_I486, ITYPE_MOV, "mov", { AMODE_R | OPTYPE_d | OP_DST, AMODE_T | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x24 */ - { NOINSTR }, /* 0x25 */ - { NOINSTR }, /* 0x26 */ - //{ NOGROUP, CPU_I486, ITYPE_MOV, "mov", { AMODE_T | OPTYPE_d | OP_DST, AMODE_R | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x26 */ - { NOINSTR }, /* 0x27 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movaps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x28 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movaps", { AMODE_W | OPTYPE_ps | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x29 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtpi2ps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2A */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movntps", { AMODE_M | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2B */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvttps2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2C */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtps2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x2D */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "ucomiss", { AMODE_V | OPTYPE_ss | OP_SRC, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, /* 0x2E */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "comiss", { AMODE_V | OPTYPE_ps | OP_SRC, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, /* 0x2F */ - { NOGROUP, CPU_PENTIUM, ITYPE_SYSTEM, "wrmsr", { OPTYPE_REG_ECX | OP_MSR | OP_DST, OPTYPE_EDX_HI_EAX_LO | OP_SRC, 0 } , NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x30 */ - { NOGROUP, CPU_PENTIUM, ITYPE_SYSTEM, "rdtsc", { OPTYPE_EDX_HI_EAX_LO | OP_DST, OPTYPE_TSC | OP_MSR | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x31 */ - { NOGROUP, CPU_PENTIUM, ITYPE_SYSTEM, "rdmsr", { OPTYPE_EDX_HI_EAX_LO | OP_DST, OPTYPE_REG_ECX | OP_MSR | OP_SRC, 0 } , NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x32 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_OTHER, "rdpmc", { OPTYPE_EDX_HI_EAX_LO | OP_DST, OPTYPE_REG_ECX | OP_SYS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x33 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSCALL, "sysenter", { OPTYPE_CS_MSR | OP_MSR | OP_SRC, OPTYPE_EIP_MSR | OP_MSR | OP_SRC, OPTYPE_ESP_MSR | OP_MSR | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x34 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSCALLRET, "sysexit", { OPTYPE_CS_MSR | OP_MSR | OP_SRC, OPTYPE_EIP_MSR | OP_MSR | OP_SRC, OPTYPE_ESP_MSR | OP_MSR | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x35 */ - { NOINSTR }, /* 0x36 */ - { NOINSTR }, /* 0x37 */ - { NOINSTR }, /* 0x38 */ - { NOINSTR }, /* 0x39 */ - { NOINSTR }, /* 0x3A */ - { NOINSTR }, /* 0x3B */ - { NOINSTR }, /* 0x3C */ - { NOINSTR }, /* 0x3D */ - { NOINSTR }, /* 0x3E */ - { NOINSTR }, /* 0x3F */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovo", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_O, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x40 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovno", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NO, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x41 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovc", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_C, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x42 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovnc", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NC, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x43 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovz", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_Z, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x44 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovnz", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NZ, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x45 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovbe", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_BE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x46 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmova", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_A, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x47 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovs", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_S, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x48 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovns", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_NS, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x49 */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovpe", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_PE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4A */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovpo", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_PO, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4B */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovl", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_L, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4C */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovge", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_GE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4D */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovle", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_LE, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4E */ - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_MOVCC, "cmovg", { AMODE_G | OPTYPE_v | OP_COND_DST, AMODE_E | OPTYPE_v | OP_COND_SRC, 0 }, COND_G, NOCHANGE, OP1_DST | OP2_SRC, NOACTION }, /* 0x4F */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "movmskps", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR | OPTYPE_ps| OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x50 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "sqrtps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x51 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "rsqrtps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x52 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "rcpps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x53 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_AND, "andps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x54 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_AND, "andnps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x55 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_OR, "orps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x56 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_XOR, "xorps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x57 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_ADD, "addps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x58 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MUL, "mulps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x59 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtps2pd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5A */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtdq2ps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5B */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_SUB, "subps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5C */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "minps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5D */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_DIV, "divps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5E */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "maxps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x5F */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpcklbw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x60 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpcklwd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x61 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckldq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x62 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "packsswb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x63 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpgtb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x64 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpgtw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x65 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpgtd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x66 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "packuswb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x67 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckhbw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x68 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckhwd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x69 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "punpckhdq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_d | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6A */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "packssdw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6B */ - { NOINSTR }, /* 0x6C */ - { NOINSTR }, /* 0x6D */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6E */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x6F */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pshufw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x70 */ - { X86_Group_13, GROUP }, /* 0x71 */ - { X86_Group_14, GROUP }, /* 0x72 */ - { X86_Group_15, GROUP }, /* 0x73 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpeqb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x74 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpeqw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x75 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_CMP, "pcmpeqd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x76 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "emms", { OPTYPE_FPU_TAG | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x77 */ - { NOINSTR }, /* 0x78 */ - { NOINSTR }, /* 0x79 */ - { NOINSTR }, /* 0x7A */ - { NOINSTR }, /* 0x7B */ - { NOINSTR }, /* 0x7C */ - { NOINSTR }, /* 0x7D */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movd", { AMODE_E | OPTYPE_dq | OP_DST, AMODE_P | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x7E */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MOV, "movq", { AMODE_Q | OPTYPE_q | OP_DST, AMODE_P | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x7F */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jo", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_O, NOCHANGE, OP1_DST, NOACTION }, /* 0x80 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jno", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NO, NOCHANGE, OP1_DST, NOACTION }, /* 0x81 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jb", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_C, NOCHANGE, OP1_DST, NOACTION }, /* 0x82 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnb", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NC, NOCHANGE, OP1_DST, NOACTION }, /* 0x83 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jz", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_Z, NOCHANGE, OP1_DST, NOACTION }, /* 0x84 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jnz", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NZ, NOCHANGE, OP1_DST, NOACTION }, /* 0x85 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jbe", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_BE, NOCHANGE, OP1_DST, NOACTION }, /* 0x86 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "ja", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_A, NOCHANGE, OP1_DST, NOACTION }, /* 0x87 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "js", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_S, NOCHANGE, OP1_DST, NOACTION }, /* 0x88 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jns", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_NS, NOCHANGE, OP1_DST, NOACTION }, /* 0x89 */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpe", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PE, NOCHANGE, OP1_DST, NOACTION }, /* 0x8A */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jpo", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_PO, NOCHANGE, OP1_DST, NOACTION }, /* 0x8B */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jl", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_L, NOCHANGE, OP1_DST, NOACTION }, /* 0x8C */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jge", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_GE, NOCHANGE, OP1_DST, NOACTION }, /* 0x8D */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jle", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_LE, NOCHANGE, OP1_DST, NOACTION }, /* 0x8E */ - { NOGROUP, CPU_I386, ITYPE_BRANCHCC, "jg", { AMODE_J | OPTYPE_z | OP_SRC | OP_COND_EXEC, 0, 0 }, COND_G, NOCHANGE, OP1_DST, NOACTION }, /* 0x8F */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "seto", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_O, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x90 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setno", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NO, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x91 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setb", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_C, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x92 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setnb", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NC, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x93 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "sete", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_Z, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x94 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setne", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NZ, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x95 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setbe", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_BE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x96 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "seta", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_A, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x97 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "sets", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_S, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x98 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setns", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_NS, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x99 */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setpe", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_PE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9A */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setpo", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_PO, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9B */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setl", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_L, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9C */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setge", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_GE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9D */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setle", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_LE, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9E */ - { NOGROUP, CPU_I386, ITYPE_MOVCC, "setg", { AMODE_E | OPTYPE_b | OP_COND_DST, OPTYPE_1 | OP_COND_SRC, OPTYPE_0 | OP_COND_SRC }, COND_G, NOCHANGE, OP1_DST | OP2_SRC, OP1_DST | OP3_SRC }, /* 0x9F */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_FS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA0 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_FS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA1 */ - { NOGROUP, CPU_PENTIUM, ITYPE_CPUID, "cpuid", { OPTYPE_EDX_ECX_EBX_EAX | OP_DST, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA2 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bt", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xA3 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shld", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xA4 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shld", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, OPTYPE_REG_CL | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xA5 */ - { NOINSTR }, /* 0xA6 */ - { NOINSTR }, /* 0xA7 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { OPTYPE_GS | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA8 */ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { OPTYPE_GS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xA9 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "rsm", NOARGS, NOCOND, FLAG_ALL_MOD, NOACTION, IGNORED }, /* 0xAA */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bts", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAB */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shrd", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAC */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shrd", { AMODE_E | OPTYPE_v | OP_DST, AMODE_G | OPTYPE_v | OP_SRC, OPTYPE_REG_CL | OP_SRC }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAD */ - { X86_Group_16, GROUP }, /* 0xAE */ - { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xAF */ - { NOGROUP, CPU_I486, ITYPE_XCHGCC, "cmpxchg", { AMODE_E | OPTYPE_b | OP_SRC | OP_COND_DST, OPTYPE_REG_AL | OP_SRC | OP_COND_DST, AMODE_G | OPTYPE_b | OP_COND_SRC }, COND_OP1_EQ_OP2, FLAG_COMMON_MOD, OP1_DST | OP3_SRC, OP2_DST | OP1_SRC }, /* 0xB0 */ - { NOGROUP, CPU_I486, ITYPE_XCHGCC, "cmpxchg", { AMODE_E | OPTYPE_v | OP_SRC | OP_COND_DST, OPTYPE_REG_xAX_BIG | OP_SRC | OP_COND_DST, AMODE_G | OPTYPE_v | OP_COND_SRC }, COND_OP1_EQ_OP2, FLAG_COMMON_MOD, OP1_DST | OP3_SRC, OP2_DST | OP1_SRC }, /* 0xB1 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "lss", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB2 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "btr", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xB3 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "lfs", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB4 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "lgs", { AMODE_G | OPTYPE_z | OP_DST, AMODE_M | OPTYPE_p | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB5 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "movzx", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB6 */ - { NOGROUP, CPU_I386, ITYPE_MOV, "movzx", { AMODE_G | OPTYPE_v | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xB7 */ - { NOINSTR }, /* 0xB8 */ - { X86_Group_11, GROUP }, /* 0xB9 */ - { X86_Group_8, GROUP }, /* 0xBA */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "btc", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_G | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0xBB */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bsf", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0xBC */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bsr", { AMODE_G | OPTYPE_v | OP_SRC, AMODE_E | OPTYPE_v | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0xBD */ - { NOGROUP, CPU_I386, ITYPE_MOV, "movsx", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBE */ - { NOGROUP, CPU_I386, ITYPE_MOV, "movsx", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xBF */ - { NOGROUP, CPU_I486, ITYPE_XCHGADD, "xadd", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, AMODE_G | OPTYPE_b | OP_SRC | OP_DST, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0xC0 */ - { NOGROUP, CPU_I486, ITYPE_XCHGADD, "xadd", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_G | OPTYPE_v | OP_SRC | OP_DST, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0xC1 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "cmpps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0xC2 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movnti", { AMODE_M | OPTYPE_dq | OP_DST, AMODE_G | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC3 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pinsrw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC4 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pextrw", { AMODE_G | OPTYPE_d | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC5 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "shufps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC6 */ - { X86_Group_9, GROUP }, /* 0xC7 */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC8 */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC9 */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCA */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCB */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCC */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCD */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCE */ - { NOGROUP, CPU_I486, ITYPE_XCHG, "bswap", { OP_REG | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xCF */ - { NOINSTR }, /* 0xD0 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD1 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrld", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD2 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD3 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_ADD, "paddq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD4 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MUL, "pmullw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD5 */ - { NOINSTR }, /* 0xD6 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pmovmskb", { AMODE_G | OPTYPE_d | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD7 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubusb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD8 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubusw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xD9 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pminub", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDA */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_AND, "pand", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDB */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddusb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDC */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddusw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDD */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pmaxub", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDE */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_AND, "pandn", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xDF */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pavgb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE0 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psraw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE1 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrad", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE2 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pavgw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE3 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MUL, "pmulhuw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE4 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_MUL, "pmulhw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE5 */ - { NOINSTR }, /* 0xE6 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MOV, "movntq", { AMODE_M | OPTYPE_q | OP_DST, AMODE_P | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE7 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubsb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE8 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xE9 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pminsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEA */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_OR, "por", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEB */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddsb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEC */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xED */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "pmaxsw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEE */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_XOR, "pxor", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xEF */ - { NOINSTR }, /* 0xF0 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF1 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pslld", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF2 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF3 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_MUL, "pmuludq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF4 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "pmaddwd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF5 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "psadbw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF6 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "maskmovq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF7 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF8 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xF9 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_SUB, "psubd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFA */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_SUB, "psubq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFB */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFC */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFD */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX_ADD, "paddd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xFE */ - { NOINSTR } /* 0xFF */, -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Groups -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -X86_OPCODE X86_Group_1_80[8] = // 80 -{ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_1_81[8] = // 81 -{ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_1_82[8] = // 82 -{ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_1_83[8] = // 83 -{ - { NOGROUP, CPU_I386, ITYPE_ADD, "add", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_OR, "or", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ADD, "adc", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sbb", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_AND, "and", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SUB, "sub", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_XOR, "xor", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_CMP, "cmp", { AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, AMODE_I | OPTYPE_b | OP_SIGNED | OP_SRC, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_C0[8] = // C0 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_C1[8] = // C1 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_D0[8] = // D0 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_D1[8] = // D1 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_1 | OP_SRC, 0 }, NOCOND, FLAG_OF_MOD | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_D2[8] = // D2 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_b | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_2_D3[8] = // D3 -{ - { NOGROUP, CPU_I386, ITYPE_ROL, "rol", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "ror", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_ROL, "rcl", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_ROR, "rcr", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "shl", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "shr", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SHL, "sal", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_SHR, "sar", { AMODE_E | OPTYPE_v | OP_DST, OPTYPE_REG_CL | OP_SRC, 0 }, NOCOND, FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_3_F6[8] = // F6 -{ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_b | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_NOT, "not", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_NEG, "neg", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_MUL, "mul", { OPTYPE_REG_AX | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, OPTYPE_REG_AL | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { OPTYPE_REG_AX | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_b | OP_SIGNED | OP_SRC, OPTYPE_REG_AL | OP_SIGNED | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_DIV, "div", { OPTYPE_REG_AX | OP_DST, AMODE_E | OPTYPE_b | OP_SRC, OPTYPE_REG_AX | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_DIV, "idiv", { OPTYPE_REG_AX | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_b | OP_SIGNED | OP_SRC, OPTYPE_REG_AX | OP_SIGNED | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED } /* 0x07 */, -}; - -X86_OPCODE X86_Group_3_F7[8] = // F7 -{ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_TEST, "test", { AMODE_E | OPTYPE_v | OP_SRC, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, FLAG_OF_CLR | FLAG_SF_MOD | FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_CLR, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_NOT, "not", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_NEG, "neg", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_MUL, "mul", { OPTYPE_xDX_HI_xAX_LO | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_MUL, "imul", { OPTYPE_xDX_HI_xAX_LO | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, FLAG_OF_MOD | FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_DIV, "div", { OPTYPE_xDX_HI_xAX_LO | OP_DST, AMODE_E | OPTYPE_v | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_DIV, "idiv", { OPTYPE_xDX_HI_xAX_LO | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_v | OP_SIGNED | OP_SRC, OPTYPE_REG_xAX_BIG | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_4[8] = // FE -{ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { AMODE_E | OPTYPE_b | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR } /* 0x07 */ -}; - -X86_OPCODE X86_Group_5[8] = // FF -{ - { NOGROUP, CPU_I386, ITYPE_INC, "inc", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_DEC, "dec", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, 0, 0 }, NOCOND, FLAG_OF_MOD|FLAG_SF_MOD|FLAG_ZF_MOD|FLAG_AF_MOD|FLAG_PF_MOD, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_E | OPTYPE_v | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_CALL, "call", { AMODE_E | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_E | OPTYPE_v | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_BRANCH, "jmp", { AMODE_E | OPTYPE_p | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_PUSH, "push", { AMODE_E | OPTYPE_v | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_6[8] = // 0F 00 -{ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "sldt", { AMODE_E | OPTYPE_mw | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "str", { AMODE_E | OPTYPE_mw | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lldt", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "ltr", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "verr", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "verw", { AMODE_E | OPTYPE_w | OP_SRC, 0, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_IA64, ITYPE_BRANCH, "jmpe", { AMODE_E | OPTYPE_v | OP_SRC | OP_EXEC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR } /* 0x07 */ -}; - -X86_OPCODE X86_Group_7[8] = // 0F 01 -{ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "sgdt", { AMODE_M | OPTYPE_dt | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "sidt", { AMODE_M | OPTYPE_dt | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lgdt", { AMODE_M | OPTYPE_dt | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lidt", { AMODE_M | OPTYPE_dt | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "smsw", { AMODE_E | OPTYPE_mw | OP_DST, OPTYPE_CR0 | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "lmsw", { OPTYPE_CR0 | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I486, ITYPE_SYSTEM, "invlpg", { AMODE_M | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_8[8] = // 0F BA -{ - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bt", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "bts", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "btr", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_BITTEST, "btc", { AMODE_E | OPTYPE_v | OP_SRC | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, FLAG_CF_MOD, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_9[8] = // 0F C7 -{ - { NOINSTR }, /* 0x00 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_XCHGCC, "cmpxchg8b", { AMODE_M | OPTYPE_q | OP_SRC | OP_COND_DST, OPTYPE_xDX_HI_xAX_LO | OP_SRC | OP_COND_DST, OPTYPE_xCX_HI_xBX_LO | OP_COND_SRC }, COND_OP1_EQ_OP2, FLAG_ZF_MOD, OP1_DST | OP3_SRC, OP2_DST | OP1_SRC }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_10[8] = // 8F (NOTE: AMD64 labels this Group 1A) -{ - { NOGROUP, CPU_I386, ITYPE_POP, "pop", { AMODE_E | OPTYPE_v | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_11[8] = // 0F B9 (NOTE: AMD64 labels this Group 10) -{ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_I386, ITYPE_INVALID, "undef", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED } /* 0x07 */ -}; - -X86_OPCODE X86_Group_12_C6[8] = // C6 (NOTE: AMD64 labels this Group 11) -{ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_b | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0xC6 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_12_C7[8] = // C7 (NOTE: AMD64 labels this Group 11) -{ - { NOGROUP, CPU_I386, ITYPE_MOV, "mov", { AMODE_E | OPTYPE_v | OP_DST, AMODE_I | OPTYPE_z | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -// NOTE: the X86_SSE2_* is only followed if it is a 3-byte opcode (e.g., prefix is 66, F2, or F3) -X86_OPCODE X86_Group_13[8] = // 0F 71 (NOTE: AMD64 labels this Group 12) -{ - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlw", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psraw", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllw", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_14[8] = // 0F 72 (NOTE: AMD64 labels this Group 13) -{ - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrld", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrad", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pslld", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_15[8] = // 0F 73 (NOTE: AMD64 labels this Group 14) -{ - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrlq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psrldq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "psllq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_MMX, "pslldq", { AMODE_PR | OPTYPE_q | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED } /* 0x07 */ -}; - -X86_OPCODE X86_Group_16[8] = // 0F AE (NOTE: AMD64 labels this Group 15) -{ - { NOGROUP, CPU_PENTIUM2, ITYPE_FPU, "fxsave", { AMODE_M | OPTYPE_fst2 | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_FPU, "fxrstor", { AMODE_M | OPTYPE_fst2 | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "ldmxcsr", { AMODE_M | OPTYPE_d | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "stmxcsr", { AMODE_M | OPTYPE_d | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "lfence", NOARGS, NOCOND, NOCHANGE, SERIALIZE_READ, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "mfence", NOARGS, NOCOND, NOCHANGE, SERIALIZE_ALL, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "sfence", NOARGS, NOCOND, NOCHANGE, SERIALIZE_WRITE, IGNORED } /* 0x07 */ -}; - -X86_OPCODE X86_Group_17[8] = // 0F 18 (NOTE: AMD64 labels this Group 16) -{ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetchnta", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x00 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetcht0", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetcht1", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "prefetcht2", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_PENTIUM2, ITYPE_SYSTEM, "hintnop", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ -}; - -X86_OPCODE X86_Group_P[8] = // 0F 0D -{ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "prefetch", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x01 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "prefetchw", { AMODE_E | OPTYPE_b | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// FPU (ESC) opcodes -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - - -X86_OPCODE X86_ESC_0[0x48] = // D8 -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x00 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { AMODE_M | OPTYPE_ss | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { AMODE_M | OPTYPE_ss | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x05 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_ss | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x07 - - // - // ModRM >= C0: ST(0) <- ST(0) + ST(i) - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // C8-CF - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - // D0-D7 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x7 - // D8-DF - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xF - // E0-E7 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // E8-EF - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF - // F0-F7 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // F8-FF - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED } // xF -}; - - -X86_OPCODE X86_ESC_1[0x48] = // D9 -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { AMODE_M | OPTYPE_ss | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x00 - { NOINSTR }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { AMODE_M | OPTYPE_ss | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { AMODE_M | OPTYPE_ss | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOGROUP, CPU_I287, ITYPE_FLOADENV, "fldenv", { AMODE_M | OPTYPE_fev | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldcw", { OPTYPE_FPU_CONTROL | OP_DST, AMODE_M | OPTYPE_w | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // 0x05 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstenv", { AMODE_M | OPTYPE_fev | OP_DST, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fnstcw", { AMODE_M | OPTYPE_w | OP_DST, OPTYPE_FPU_CONTROL | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // 0x07 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { OPTYPE_STx | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x7 - // C8-CF - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FEXCH, "fxch", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_STx | OP_SRC | OP_DST, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF - // D0-D7 - { NOGROUP, CPU_I287, ITYPE_FPU, "fnop", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // D8-DF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // E0-E7 - { NOGROUP, CPU_I287, ITYPE_FPU, "fchs", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FPU, "fabs", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOGROUP, CPU_I287, ITYPE_FPU, "ftst", { OPTYPE_ST0 | OP_SRC, OPTYPE_FLDZ | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FPU, "fxam", { OPTYPE_ST0 | OP_SRC, 0, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // E8-EF - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld1", { OPTYPE_FLD1 | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldl2t", { OPTYPE_FLDL2T | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldl2e", { OPTYPE_FLDL2E | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldpi", { OPTYPE_FLDPI | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldlg2", { OPTYPE_FLDLG2| OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldln2", { OPTYPE_FLDLN2 | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fldz", { OPTYPE_FLDZ | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // xE - { NOINSTR }, // xF - // F0-F7 - { NOGROUP, CPU_I287, ITYPE_FPU, "f2xm1", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FPU, "fyl2x", { OPTYPE_ST1 | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FPU, "fptan", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, FPU_STACK_PUSH, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FPU, "fpatan", { OPTYPE_ST1 | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC , 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FPU, "fxtract", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_DST, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x4 - { NOGROUP, CPU_I387, ITYPE_FPU, "fprem1", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FPU, "fdecstp", NOARGS, NOCOND, FPU_C1_MOD, FPU_STACK_DEC, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FPU, "fincstp", NOARGS, NOCOND, FPU_C1_MOD, FPU_STACK_INC, IGNORED }, // x7 - // F8-FF - { NOGROUP, CPU_I287, ITYPE_FPU, "fprem", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FPU, "fyl2xp1", { OPTYPE_ST1 | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FPU, "fsqrt", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FPU, "fsincos", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, FPU_STACK_PUSH, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FPU, "frndint", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FPU, "fscale", { OPTYPE_ST0 | OP_SRC | OP_DST, OPTYPE_ST1 | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FPU, "fsin", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FPU, "fcos", { OPTYPE_ST0 | OP_SRC | OP_DST, 0, 0 }, NOCOND, FPU_C1_MOD|FPU_C2_MOD, NOACTION, IGNORED } // xF -}; - - -X86_OPCODE X86_ESC_2[0x48] = // DA -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FADD, "fiadd", { OPTYPE_ST0 | OP_SIGNED | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fimul", { OPTYPE_ST0 | OP_SIGNED | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficom", { AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC | OP_DST, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficomp", { AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC | OP_DST, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fisub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fisubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fidiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fidivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_B, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7 - // C8-CF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmove", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_E, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF - // D0-D7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_BE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7 - // D8-DF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FMOVCC, "fcmovu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_COND_SRC, 0 }, COND_U, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF - // E0-E7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // E8-EF - { NOINSTR }, // x8 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucompp", { OPTYPE_ST1 | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP2, IGNORED }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // F0-F7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // F8-FF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR } // xF -}; - - - -X86_OPCODE X86_ESC_3[0x48] = // DB -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fild", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x00 - { NOGROUP, CPU_PENTIUM4, ITYPE_FSTORE, "fisttp", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fist", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fistp", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOINSTR }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { AMODE_M | OPTYPE_se | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x05 - { NOINSTR }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { AMODE_M | OPTYPE_se | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x07 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnb", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NB, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7 - // C8-CF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovne", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF - // D0-D7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnbe", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NBE, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x7 - // D8-DF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FPU, "fcmovnu", { OPTYPE_ST0 | OP_COND_DST, OPTYPE_STx | OP_SRC, 0 }, COND_NU, FPU_C1_MOD, OP1_DST | OP2_SRC, NOACTION }, // xF - // E0-E7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOGROUP, CPU_I287, ITYPE_FPU, "fnclex", { OPTYPE_FPU_STATUS | OP_DST, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FPU, "finit", { OPTYPE_FPU_STATUS | OP_DST, 0, 0 }, NOCOND, FPU_ALL_CLR, NOACTION, IGNORED }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // E8-EF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // xF - // F0-F7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomi", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, NOACTION, IGNORED }, // x7 - // F8-FF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR } // xF -}; - -X86_OPCODE X86_ESC_4[0x48] = // DC -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x00 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcom", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcomp", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x05 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x07 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FADD, "fadd", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // C8-CF - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmul", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF - // D0-D7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // D8-DF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // E0-E7 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // E8-EF - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsub", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xF - // F0-F7 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivr", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // F8-FF - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdiv", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED } // xF -}; - - -X86_OPCODE X86_ESC_5[0x48] = // DD -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - // - - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fld", { AMODE_M | OPTYPE_sd | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_FSTORE, "fisttp", { AMODE_M | OPTYPE_d | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { AMODE_M | OPTYPE_sd | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FRESTORE, "frstor", { AMODE_M | OPTYPE_fst1 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_I287, ITYPE_FSAVE, "fsave", { AMODE_M | OPTYPE_fst1 | OP_DST, 0 }, NOCOND, FPU_ALL_CLR, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fnstsw", { AMODE_M | OPTYPE_w | OP_DST, OPTYPE_FPU_STATUS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FPU, "ffree", { OPTYPE_FPU_TAG | OP_DST, OPTYPE_STx | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - // C8-CF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // D0-D7 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fst", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // x7 - // D8-DF - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fstp", { OPTYPE_STx | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xF - // E0-E7 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucom", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // x7 - // E8-EF - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I387, ITYPE_FCOMP, "fucomp", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xF - // F0-F7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // F8-FF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR } // xF -}; - - -X86_OPCODE X86_ESC_6[0x48] = // DE -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FADD, "fiadd", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x00 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fimul", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficom", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "ficomp", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fisub", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fisubr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x05 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fidiv", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fidivr", { OPTYPE_ST0 | OP_SRC | OP_DST, AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x07 - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - - // C0-C7 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FADD, "faddp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x7 - // C8-CF - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FMUL, "fmulp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xF - // D0-D7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // D8-DF - { NOINSTR }, // x8 - { NOGROUP, CPU_I287, ITYPE_FCOMP, "fcompp", { OPTYPE_ST1 | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_ALL_MOD, FPU_STACK_POP2, IGNORED }, // x9 - { NOINSTR }, // 0xA - { NOINSTR }, // 0xB - { NOINSTR }, // 0xC - { NOINSTR }, // 0xD - { NOINSTR }, // 0xE - { NOINSTR }, // 0xF - // E0-E7 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x7 - // E8-EF - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FSUB, "fsubp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xF - // F0-F7 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x0 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x1 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x2 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x4 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x5 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x6 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivrp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x7 - // F8-FF - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_I287, ITYPE_FDIV, "fdivp", { OPTYPE_STx | OP_SRC | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED } // xF -}; - - -X86_OPCODE X86_ESC_7[0x48] = // DF -{ - // - // ModRM < C0 - // Index 0x00-0x07 = opcode extension - // - - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fild", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_SRC, 0, 0}, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x00 - { NOGROUP, CPU_PENTIUM4, ITYPE_FSTORE, "fisttp", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x01 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fist", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, NOACTION, IGNORED }, // 0x02 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fistp", { AMODE_M | OPTYPE_w | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x03 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fbld", { AMODE_M | OPTYPE_pb | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x04 - { NOGROUP, CPU_I287, ITYPE_FLOAD, "fild", { AMODE_M | OPTYPE_q | OP_SIGNED | OP_SRC, 0, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_PUSH, IGNORED }, // 0x05 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fbstp", { AMODE_M | OPTYPE_pb | OP_DST, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x06 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fistp", { AMODE_M | OPTYPE_q | OP_SIGNED | OP_DST, OPTYPE_ST0 | OP_SRC, 0}, NOCOND, FPU_C1_MOD, FPU_STACK_POP, IGNORED }, // 0x07 - - // - // ModRM >= C0 - // Index 0x08-0x47 = ModRM 0xC0-0xFF - // - // C0-C7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // C8-CF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // D0-D7 - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // D8-DF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - // E0-E7 - { NOGROUP, CPU_I287, ITYPE_FSTORE, "fnstsw", { OPTYPE_REG_AX | OP_DST, OPTYPE_FPU_STATUS | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - // E8-EF - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fucomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // xF - // F0-F7 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM_PRO, ITYPE_FCOMP, "fcomip", { OPTYPE_STx | OP_SRC, OPTYPE_ST0 | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_PF_MOD | FLAG_CF_MOD | FPU_ALL_MOD, FPU_STACK_POP, IGNORED }, // x7 - // F8-FF - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR } // xF -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// SSE opcodes -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -X86_OPCODE X86_SSE[0x300] = -{ - // prefix 0x66 (operand size) - /* 0x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 1x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movupd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movupd", { AMODE_W | OPTYPE_pd | OP_DST, AMODE_V | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movlpd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_M | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movlpd", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "unpcklpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "unpckhpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movhpd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_M | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "mpvhpd", { AMODE_M | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 2x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movapd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movapd", { AMODE_W | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpi2pd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movntpd", { AMODE_M | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttpd2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpd2pi", { AMODE_P | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "ucomisd", { AMODE_V | OPTYPE_sd | OP_SRC, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "comisd", { AMODE_V | OPTYPE_pd | OP_SRC, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD | FLAG_CF_MOD | FLAG_PF_MOD | FLAG_OF_CLR | FLAG_SF_CLR | FLAG_AF_CLR, NOACTION, IGNORED }, // xF - - /* 3x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 4x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 5x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "movmskpd", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "sqrtpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "andpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "andnpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_OR, "orpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_XOR, "xorpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "addpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "mulpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpd2ps", { AMODE_V | OPTYPE_ps | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtps2dq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "subpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "minpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_DIV, "divpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maxpd", { AMODE_V | OPTYPE_pd | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 6x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpcklbw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpcklwd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckldq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "packsswb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pcmpgtb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pcmpgtw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pcmpgtd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "packuswb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhbw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhwd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhdq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "packssdw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpcklqdq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "punpckhqdq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqa", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 7x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pshufd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { X86_SSE2_Group_13, GROUP }, // x1 - { X86_SSE2_Group_14, GROUP }, // x2 - { X86_SSE2_Group_15, GROUP }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "pcmpeqb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "pcmpeqw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "pcmpeqd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_ADD, "haddpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_SUB, "hsubpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movd", { AMODE_E | OPTYPE_dq | OP_DST, AMODE_V | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqa", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 8x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 9x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Ax */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Bx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Cx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "cmppd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, // x2 - { NOINSTR }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pinsrw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_E | OPTYPE_w | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pextrw", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR| OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "shufpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Dx */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3, "addsubpd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrld", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmullw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movq", { AMODE_W | OPTYPE_q | OP_DST, AMODE_V | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pmovmskb", { AMODE_G | OPTYPE_d | OP_DST, AMODE_VR| OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubusb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubusw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pminub", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "pand", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddusb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddusw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pmaxub", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_AND, "pandn", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* Ex */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pavgb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psraw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrad", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pavgw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmulhuw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmulhw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttpd2dq", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movntdq", { AMODE_M | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubsb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubsw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pminsw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_OR, "por", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddsb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddsw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pmaxuw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_XOR, "pxor", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* Fx */ - { NOINSTR }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pslld", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "pmuludq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x4 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "pmaddwd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psadbw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maskmovdqu", { AMODE_V | OPTYPE_o | OP_DST, AMODE_VR| OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "psubq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddb", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddw", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "paddd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOINSTR }, // xF - - // prefix 0xf2 (repne) - /* 0x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 1x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movsd", { AMODE_V | OPTYPE_sdo | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movsd", { AMODE_W | OPTYPE_sd | OP_DST, AMODE_V | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_MOV, "movddup", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 2x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtsi2sd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOINSTR }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttsd2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtsd2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 3x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 4x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 5x */ - { NOINSTR }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "sqrtsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "addsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "mulsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtsd2ss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOINSTR }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "subsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "minsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_DIV, "divsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maxsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 6x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqa", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 7x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pshuflw", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_ADD, "haddps", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_SUB, "hsubps", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 8x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 9x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Ax */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Bx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Cx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_CMP, "cmpsd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_sd | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Dx */ - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE3, "addsubps", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdq2q", { AMODE_P | OPTYPE_q | OP_DST, AMODE_VR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Ex */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtpd2dq", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_pd | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Fx */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3, "lddqu", { AMODE_V | OPTYPE_o | OP_DST, AMODE_M | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - // prefix 0xf3 (rep) - /* 0x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 1x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movss", { AMODE_V | OPTYPE_sso | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movss", { AMODE_W | OPTYPE_ss | OP_DST, AMODE_V | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_MOV, "movsldup", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE3_MOV, "movshdup", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 2x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtsi2ss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_E | OPTYPE_dq | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOINSTR }, // xB - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvttss2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE, "cvtss2si", { AMODE_G | OPTYPE_dq | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 3x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 4x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 5x */ - { NOINSTR }, // x0 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "sqrtss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x1 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "rsqrtss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x2 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "rcpss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_ADD, "addss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MUL, "mulss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x9 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtss2sd", { AMODE_V | OPTYPE_sd | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xA - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvttps2dq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_ps | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xB - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_SUB, "subss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xC - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "minss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_DIV, "divss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "maxss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 6x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqu", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 7x */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pshufhw", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movq", { AMODE_V | OPTYPE_q | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xE - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movdqu", { AMODE_W | OPTYPE_o | OP_DST, AMODE_V | OPTYPE_o | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // xF - - /* 8x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* 9x */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Ax */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Bx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Cx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOGROUP, CPU_PENTIUM3, ITYPE_SSE_CMP, "cmpss", { AMODE_V | OPTYPE_ss | OP_DST, AMODE_W | OPTYPE_ss | OP_SRC, AMODE_I | OPTYPE_b | OP_SRC }, NOCOND, FLAG_COMMON_MOD, NOACTION, IGNORED }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Dx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2_MOV, "movq2dq", { AMODE_V | OPTYPE_o | OP_DST, AMODE_PR | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Ex */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "cvtdq2pd", { AMODE_V | OPTYPE_o | OP_DST, AMODE_W | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR }, // xF - - /* Fx */ - { NOINSTR }, // x0 - { NOINSTR }, // x1 - { NOINSTR }, // x2 - { NOINSTR }, // x3 - { NOINSTR }, // x4 - { NOINSTR }, // x5 - { NOINSTR }, // x6 - { NOINSTR }, // x7 - { NOINSTR }, // x8 - { NOINSTR }, // x9 - { NOINSTR }, // xA - { NOINSTR }, // xB - { NOINSTR }, // xC - { NOINSTR }, // xD - { NOINSTR }, // xE - { NOINSTR } // xF -}; - -X86_OPCODE X86_SSE2_Group_13[24] = // 66/F2/F3 0F 71 -{ - // prefix 0x66 (operand size) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlw", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psraw", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllw", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ - - // prefix 0xf2 (repne) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ - - // prefix 0xf3 (rep) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_SSE2_Group_14[24] = // 66/F2/F3 0F 72 -{ - // prefix 0x66 (operand size) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrld", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrad", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pslld", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ - - // prefix 0xf2 (repne) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ - - // prefix 0xf3 (rep) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -X86_OPCODE X86_SSE2_Group_15[24] = -{ - // prefix 0x66 (operand size) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrlq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x02 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psrldq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "psllq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x06 */ - { NOGROUP, CPU_PENTIUM4, ITYPE_SSE2, "pslldq", { AMODE_VR | OPTYPE_o | OP_DST, AMODE_I | OPTYPE_b | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0x07 */ - - // prefix 0xf2 (repne) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ - - // prefix 0xf3 (rep) - { NOINSTR }, /* 0x00 */ - { NOINSTR }, /* 0x01 */ - { NOINSTR }, /* 0x02 */ - { NOINSTR }, /* 0x03 */ - { NOINSTR }, /* 0x04 */ - { NOINSTR }, /* 0x05 */ - { NOINSTR }, /* 0x06 */ - { NOINSTR }, /* 0x07 */ -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// 3DNow opcodes -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -X86_OPCODE X86_3DNOW_0F[0x100] = -{ - { NOINSTR }, /* 00 */ - { NOINSTR }, /* 01 */ - { NOINSTR }, /* 02 */ - { NOINSTR }, /* 03 */ - { NOINSTR }, /* 04 */ - { NOINSTR }, /* 05 */ - { NOINSTR }, /* 06 */ - { NOINSTR }, /* 07 */ - { NOINSTR }, /* 08 */ - { NOINSTR }, /* 09 */ - { NOINSTR }, /* 0A */ - { NOINSTR }, /* 0B */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pi2fw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0C */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pi2fd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 0D */ - { NOINSTR }, /* 0E */ - { NOINSTR }, /* 0F */ - { NOINSTR }, /* 10 */ - { NOINSTR }, /* 11 */ - { NOINSTR }, /* 12 */ - { NOINSTR }, /* 13 */ - { NOINSTR }, /* 14 */ - { NOINSTR }, /* 15 */ - { NOINSTR }, /* 16 */ - { NOINSTR }, /* 17 */ - { NOINSTR }, /* 18 */ - { NOINSTR }, /* 19 */ - { NOINSTR }, /* 1A */ - { NOINSTR }, /* 1B */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pf2iw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 1C */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pf2id", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 1D */ - { NOINSTR }, /* 1E */ - { NOINSTR }, /* 1F */ - { NOINSTR }, /* 20 */ - { NOINSTR }, /* 21 */ - { NOINSTR }, /* 22 */ - { NOINSTR }, /* 23 */ - { NOINSTR }, /* 24 */ - { NOINSTR }, /* 25 */ - { NOINSTR }, /* 26 */ - { NOINSTR }, /* 27 */ - { NOINSTR }, /* 28 */ - { NOINSTR }, /* 29 */ - { NOINSTR }, /* 2A */ - { NOINSTR }, /* 2B */ - { NOINSTR }, /* 2C */ - { NOINSTR }, /* 2D */ - { NOINSTR }, /* 2E */ - { NOINSTR }, /* 2F */ - { NOINSTR }, /* 30 */ - { NOINSTR }, /* 31 */ - { NOINSTR }, /* 32 */ - { NOINSTR }, /* 33 */ - { NOINSTR }, /* 34 */ - { NOINSTR }, /* 35 */ - { NOINSTR }, /* 36 */ - { NOINSTR }, /* 37 */ - { NOINSTR }, /* 38 */ - { NOINSTR }, /* 39 */ - { NOINSTR }, /* 3A */ - { NOINSTR }, /* 3B */ - { NOINSTR }, /* 3C */ - { NOINSTR }, /* 3D */ - { NOINSTR }, /* 3E */ - { NOINSTR }, /* 3F */ - { NOINSTR }, /* 40 */ - { NOINSTR }, /* 41 */ - { NOINSTR }, /* 42 */ - { NOINSTR }, /* 43 */ - { NOINSTR }, /* 44 */ - { NOINSTR }, /* 45 */ - { NOINSTR }, /* 46 */ - { NOINSTR }, /* 47 */ - { NOINSTR }, /* 48 */ - { NOINSTR }, /* 49 */ - { NOINSTR }, /* 4A */ - { NOINSTR }, /* 4B */ - { NOINSTR }, /* 4C */ - { NOINSTR }, /* 4D */ - { NOINSTR }, /* 4E */ - { NOINSTR }, /* 4F */ - { NOINSTR }, /* 50 */ - { NOINSTR }, /* 51 */ - { NOINSTR }, /* 52 */ - { NOINSTR }, /* 53 */ - { NOINSTR }, /* 54 */ - { NOINSTR }, /* 55 */ - { NOINSTR }, /* 56 */ - { NOINSTR }, /* 57 */ - { NOINSTR }, /* 58 */ - { NOINSTR }, /* 59 */ - { NOINSTR }, /* 5A */ - { NOINSTR }, /* 5B */ - { NOINSTR }, /* 5C */ - { NOINSTR }, /* 5D */ - { NOINSTR }, /* 5E */ - { NOINSTR }, /* 5F */ - { NOINSTR }, /* 60 */ - { NOINSTR }, /* 61 */ - { NOINSTR }, /* 62 */ - { NOINSTR }, /* 63 */ - { NOINSTR }, /* 64 */ - { NOINSTR }, /* 65 */ - { NOINSTR }, /* 66 */ - { NOINSTR }, /* 67 */ - { NOINSTR }, /* 68 */ - { NOINSTR }, /* 69 */ - { NOINSTR }, /* 6A */ - { NOINSTR }, /* 6B */ - { NOINSTR }, /* 6C */ - { NOINSTR }, /* 6D */ - { NOINSTR }, /* 6E */ - { NOINSTR }, /* 6F */ - { NOINSTR }, /* 70 */ - { NOINSTR }, /* 71 */ - { NOINSTR }, /* 72 */ - { NOINSTR }, /* 73 */ - { NOINSTR }, /* 74 */ - { NOINSTR }, /* 75 */ - { NOINSTR }, /* 76 */ - { NOINSTR }, /* 77 */ - { NOINSTR }, /* 78 */ - { NOINSTR }, /* 79 */ - { NOINSTR }, /* 7A */ - { NOINSTR }, /* 7B */ - { NOINSTR }, /* 7C */ - { NOINSTR }, /* 7D */ - { NOINSTR }, /* 7E */ - { NOINSTR }, /* 7F */ - { NOINSTR }, /* 80 */ - { NOINSTR }, /* 81 */ - { NOINSTR }, /* 82 */ - { NOINSTR }, /* 83 */ - { NOINSTR }, /* 84 */ - { NOINSTR }, /* 85 */ - { NOINSTR }, /* 86 */ - { NOINSTR }, /* 87 */ - { NOINSTR }, /* 88 */ - { NOINSTR }, /* 89 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfnacc", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 8A */ - { NOINSTR }, /* 8B */ - { NOINSTR }, /* 8C */ - { NOINSTR }, /* 8D */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfpnacc", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 8E */ - { NOINSTR }, /* 8F */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_CMP, "pfcmpge", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 90 */ - { NOINSTR }, /* 91 */ - { NOINSTR }, /* 92 */ - { NOINSTR }, /* 93 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfmin", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 94 */ - { NOINSTR }, /* 95 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrcp", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 96 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrsqrt", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 97 */ - { NOINSTR }, /* 98 */ - { NOINSTR }, /* 99 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_SUB, "pfsub", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 9A */ - { NOINSTR }, /* 9B */ - { NOINSTR }, /* 9C */ - { NOINSTR }, /* 9D */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_ADD, "pfadd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* 9E */ - { NOINSTR }, /* 9F */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_CMP, "pfcmpgt", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A0 */ - { NOINSTR }, /* A1 */ - { NOINSTR }, /* A2 */ - { NOINSTR }, /* A3 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfmax", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A4 */ - { NOINSTR }, /* A5 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrcpit1", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A6 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrsqit1", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* A7 */ - { NOINSTR }, /* A8 */ - { NOINSTR }, /* A9 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_SUB, "pfsubr", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* AA */ - { NOINSTR }, /* AB */ - { NOINSTR }, /* AC */ - { NOINSTR }, /* AD */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfacc", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* AE */ - { NOINSTR }, /* AF */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_CMP, "pfcmpeq", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B0 */ - { NOINSTR }, /* B1 */ - { NOINSTR }, /* B2 */ - { NOINSTR }, /* B3 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_MUL, "pfmul", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B4 */ - { NOINSTR }, /* B5 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pfrcpit2", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B6 */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_MUL, "pmulhrw", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* B7 */ - { NOINSTR }, /* B8 */ - { NOINSTR }, /* B9 */ - { NOINSTR }, /* BA */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW_XCHG, "pswapd", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* BB */ - { NOINSTR }, /* BC */ - { NOINSTR }, /* BD */ - { NOINSTR }, /* BE */ - { NOGROUP, CPU_AMD_K6_2, ITYPE_3DNOW, "pavgb", { AMODE_P | OPTYPE_q | OP_DST, AMODE_Q | OPTYPE_q | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, /* BF */ - { NOINSTR }, /* C0 */ - { NOINSTR }, /* C1 */ - { NOINSTR }, /* C2 */ - { NOINSTR }, /* C3 */ - { NOINSTR }, /* C4 */ - { NOINSTR }, /* C5 */ - { NOINSTR }, /* C6 */ - { NOINSTR }, /* C7 */ - { NOINSTR }, /* C8 */ - { NOINSTR }, /* C9 */ - { NOINSTR }, /* CA */ - { NOINSTR }, /* CB */ - { NOINSTR }, /* CC */ - { NOINSTR }, /* CD */ - { NOINSTR }, /* CE */ - { NOINSTR }, /* CF */ - { NOINSTR }, /* D0 */ - { NOINSTR }, /* D1 */ - { NOINSTR }, /* D2 */ - { NOINSTR }, /* D3 */ - { NOINSTR }, /* D4 */ - { NOINSTR }, /* D5 */ - { NOINSTR }, /* D6 */ - { NOINSTR }, /* D7 */ - { NOINSTR }, /* D8 */ - { NOINSTR }, /* D9 */ - { NOINSTR }, /* DA */ - { NOINSTR }, /* DB */ - { NOINSTR }, /* DC */ - { NOINSTR }, /* DD */ - { NOINSTR }, /* DE */ - { NOINSTR }, /* DF */ - { NOINSTR }, /* E0 */ - { NOINSTR }, /* E1 */ - { NOINSTR }, /* E2 */ - { NOINSTR }, /* E3 */ - { NOINSTR }, /* E4 */ - { NOINSTR }, /* E5 */ - { NOINSTR }, /* E6 */ - { NOINSTR }, /* E7 */ - { NOINSTR }, /* E8 */ - { NOINSTR }, /* E9 */ - { NOINSTR }, /* EA */ - { NOINSTR }, /* EB */ - { NOINSTR }, /* EC */ - { NOINSTR }, /* ED */ - { NOINSTR }, /* EE */ - { NOINSTR }, /* EF */ - { NOINSTR }, /* F0 */ - { NOINSTR }, /* F1 */ - { NOINSTR }, /* F2 */ - { NOINSTR }, /* F3 */ - { NOINSTR }, /* F4 */ - { NOINSTR }, /* F5 */ - { NOINSTR }, /* F6 */ - { NOINSTR }, /* F7 */ - { NOINSTR }, /* F8 */ - { NOINSTR }, /* F9 */ - { NOINSTR }, /* FA */ - { NOINSTR }, /* FB */ - { NOINSTR }, /* FC */ - { NOINSTR }, /* FD */ - { NOINSTR }, /* FE */ - { NOINSTR } /* FF */ -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// 64-bit replacement opcodes -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -X86_OPCODE X86_Opcode_63[2] = -{ - { NOGROUP, CPU_I386, ITYPE_SYSTEM, "arpl", { AMODE_E | OPTYPE_w | OP_SRC, AMODE_G | OPTYPE_w | OP_SRC, 0 }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, // !ARCH_AMD64 - { NOGROUP, CPU_AMD64, ITYPE_MOV, "movsxd", { AMODE_G | OPTYPE_v | OP_SIGNED | OP_DST, AMODE_E | OPTYPE_d | OP_SIGNED | OP_SRC, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED } // ARCH_AMD64 -}; - -X86_OPCODE X86_Opcode_0F05[2] = -{ - { NOGROUP, CPU_AMD_K6_2, ITYPE_SYSCALL, "syscall", { OPTYPE_STAR_MSR | OP_MSR | OP_SRC, OPTYPE_CSTAR_MSR | OP_MSR | OP_SRC, OPTYPE_FMASK_MSR | OP_MSR | OP_SRC }, NOCOND, FLAG_ZF_MOD, NOACTION, IGNORED }, // !ARCH_AMD64 - { NOGROUP, CPU_AMD64, ITYPE_SYSCALL, "syscall", { OPTYPE_STAR_MSR | OP_MSR | OP_SRC, OPTYPE_LSTAR_MSR | OP_MSR | OP_SRC, OPTYPE_FMASK_MSR | OP_MSR | OP_SRC }, NOCOND, NOCHANGE, NOACTION, IGNORED } // ARCH_AMD64 -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Other 3 byte opcodes -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -// Three byte opcodes where the third opcode byte is ModRM -X86_OPCODE X86_0F01_ModRM[0x100] = -{ - /* 0x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 1x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 2x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 3x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 4x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 5x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 6x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 7x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 8x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* 9x */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Ax */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Bx */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Cx */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { NOGROUP, CPU_PRESCOTT, ITYPE_SYSTEM, "monitor", NOARGS, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { NOGROUP, CPU_PRESCOTT, ITYPE_SYSTEM, "mwait", NOARGS, NOCOND, NOCHANGE, SERIALIZE_ALL, IGNORED }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Dx */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Ex */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { X86_Group_7, GROUP }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP }, // xF - - /* Fx */ - { X86_Group_7, GROUP }, // x0 - { X86_Group_7, GROUP }, // x1 - { X86_Group_7, GROUP }, // x2 - { X86_Group_7, GROUP }, // x3 - { X86_Group_7, GROUP }, // x4 - { X86_Group_7, GROUP }, // x5 - { X86_Group_7, GROUP }, // x6 - { X86_Group_7, GROUP }, // x7 - { NOGROUP, CPU_AMD64, ITYPE_SYSTEM, "swapgs", { OPTYPE_KERNELBASE_MSR | OP_MSR | OP_SRC, 0, 0 }, NOCOND, NOCHANGE, NOACTION, IGNORED }, // x8 - { X86_Group_7, GROUP }, // x9 - { X86_Group_7, GROUP }, // xA - { X86_Group_7, GROUP }, // xB - { X86_Group_7, GROUP }, // xC - { X86_Group_7, GROUP }, // xD - { X86_Group_7, GROUP }, // xE - { X86_Group_7, GROUP } // xF -}; - -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Sanity checking tables -///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// - -#define S2 1 // SSE2 -#define S3 2 // SSE3 -BYTE X86_ModRM_1[0x100] = -{ - // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF - /* 0x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 1x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 2x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 3x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 6x */ 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 8x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Cx */ 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - /* Dx */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Fx */ 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 -}; -BYTE X86_ModRM_2[0x100] = -{ - // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF - /* 0x */ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, - /* 1x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, - /* 2x */ 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 4x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 5x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 6x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* 7x */ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 9x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* Ax */ 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, - /* Bx */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, - /* Cx */ 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - /* Dx */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* Ex */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - /* Fx */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 -}; - -BYTE X86_SSE_2[0x100] = -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 1x */ 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 5x */ 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, - /* 7x */ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Cx */ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Dx */ 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ex */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Fx */ 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -// Indicates if a LOCK prefix is allowed -// The following are allowed: -// add, adc, and, btc, btr, bts, cmpxchg, cmpxchg8, dec, inc, -// neg, not, or, sbb, sub, xor, xadd, xchg -#define GR 2 -BYTE X86_LockPrefix_1[0x100] = -{ - // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF - /* 0x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 1x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 2x */ 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - /* 3x */ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 8x */ GR, GR, GR, GR, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Fx */ 0, 0, 0, 0, 0, 0, GR, GR, 0, 0, 0, 0, 0, 0, GR, GR -}; - -BYTE X86_LockPrefix_2[0x100] = -{ - // x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - /* Bx */ 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, GR, 1, 0, 0, 0, 0, - /* Cx */ 1, 1, 0, 0, 0, 0, 0, GR, 0, 0, 0, 0, 0, 0, 0, 0, - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -BYTE X86_LockPrefix_Groups[17][8] = -{ -// x0 x1 x2 x3 x4 x5 x6 x7 - { 1, 1, 1, 1, 1, 1, 1, 0 }, // group 1 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 2 - { 0, 0, 1, 1, 0, 0, 0, 0 }, // group 3 - { 1, 1, 0, 0, 0, 0, 0, 0 }, // group 4 - { 1, 1, 0, 0, 0, 0, 0, 0 }, // group 5 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 6 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 7 - { 0, 0, 0, 0, 1, 1, 1, 1 }, // group 8 - { 0, 1, 0, 0, 0, 0, 0, 0 }, // group 9 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 10 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 11 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 12 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 13 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 14 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 15 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 16 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // group 17 -}; - -#define X86_MAX_GROUP 19 -BYTE X86_Groups_1[0x100] = // one-byte opcodes -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 2, 2, 0, 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */ - /* Dx */ 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 4, 5 /* Fx */ -}; - -// 19 = Group P -// 20 = 3DNow -BYTE X86_Groups_2[0x100] = // two-byte opcodes -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 19, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 8, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */ - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */ -}; - -// Indicate which 1-byte opcodes are invalid with a 16-bit operand size -BYTE X86_Invalid_Op16_1[0x100] = -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */ - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */ -}; - -// Indicate which 2-byte opcodes are invalid with a 16-bit operand size -BYTE X86_Invalid_Op16_2[0x100] = -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /* Cx */ - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */ -}; - -// Indicate which 1-byte opcodes are invalid with a 64-bit address size -BYTE X86_Invalid_Addr64_1[0x100] = -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, /* 2x */ - /* 3x */ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* Cx */ - /* Dx */ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */ -}; - -// Indicate which 2-byte opcodes are invalid with a 64-bit address size -BYTE X86_Invalid_Addr64_2[0x100] = -{ - /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ - /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ - /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ - /* 2x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ - /* 3x */ 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ - /* 4x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ - /* 5x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ - /* 6x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 6x */ - /* 7x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ - /* 8x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 8x */ - /* 9x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 9x */ - /* Ax */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ax */ - /* Bx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ - /* Cx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Cx */ - /* Dx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Dx */ - /* Ex */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Ex */ - /* Fx */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* Fx */ -}; - -#endif // DISASM_X86_TABLES diff --git a/src/disasm-lib/misc.h b/src/disasm-lib/misc.h deleted file mode 100644 index 63b3056e..00000000 --- a/src/disasm-lib/misc.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2002, Matt Conover (mconover@gmail.com) -#ifndef MISC_H -#define MISC_H -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - -// NOTE: start is inclusive, end is exclusive (as in start <= x < end) -#define IS_IN_RANGE(x, s, e) \ -( \ - ((ULONG_PTR)(x) == (ULONG_PTR)(s) && (ULONG_PTR)(x) == (ULONG_PTR)(e)) || \ - ((ULONG_PTR)(x) >= (ULONG_PTR)(s) && (ULONG_PTR)(x) < (ULONG_PTR)(e)) \ -) - -#if _MSC_VER >= 1400 -#pragma warning(disable:4996) -#endif - -#if defined(_WIN64) - #define VALID_ADDRESS_MAX 0x7FFEFFFFFFFFFFFF // Win64 specific - typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; -#else - #define VALID_ADDRESS_MAX 0x7FFEFFFF // Win32 specific - typedef unsigned long ULONG_PTR, *PULONG_PTR; -#endif - -#ifndef DECLSPEC_ALIGN - #if (_MSC_VER >= 1300) && !defined(MIDL_PASS) - #define DECLSPEC_ALIGN(x) __declspec(align(x)) - #else - #define DECLSPEC_ALIGN(x) - #endif -#endif - -#define VALID_ADDRESS_MIN 0x10000 // Win32 specific -#define IS_VALID_ADDRESS(a) IS_IN_RANGE(a, VALID_ADDRESS_MIN, VALID_ADDRESS_MAX+1) - -#ifdef __cplusplus -} -#endif -#endif // MISC_H diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 211e9ca9..a5b0d038 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -1,29 +1,73 @@ -// dllmain.cpp : Defines the entry point for the DLL application. -#include "stdafx.h" -#include "Modify.h" +#include "pch.h" -BOOL APIENTRY DllMain (HMODULE hModule, - DWORD ul_reason_for_call, LPVOID lpReserved) +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { - DisableThreadLibraryCalls (hModule); - std::wstring_view procname = GetCommandLine (); - // only Spotify process - this help avoid false positive - if (std::wstring_view::npos != procname.find (L"Spotify.exe")) { + DisableThreadLibraryCalls(hModule); + std::wstring_view procname = GetCommandLineW(); + if (std::wstring_view::npos != procname.find(L"Spotify.exe")) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: - if (std::wstring_view::npos == procname.find (L"--type=")) { - // Enable developer - main process - CreateThread (NULL, NULL, Developer, NULL, 0, NULL); - // block ads request - main process - CreateThread (NULL, NULL, KillAds, NULL, 0, NULL); - // block banner - main process - CreateThread(NULL, NULL, KillBanner, NULL, 0, NULL); + if (std::wstring_view::npos == procname.find(L"--type=")) { + try { + HANDLE hThread = nullptr; +#ifndef NDEBUG + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + if (AllocConsole()) { + if (_wfreopen(L"CONIN$", L"r", stdin) == nullptr) + MessageBoxW(0, L"Failed to redirect standard input", L"Error", 0); + if (_wfreopen(L"CONOUT$", L"w", stdout) == nullptr) + MessageBoxW(0, L"Failed to redirect standard output", L"Error", 0); + if (_wfreopen(L"CONOUT$", L"w", stderr) == nullptr) + MessageBoxW(0, L"Failed to redirect standard error", L"Error", 0); + } + hThread = CreateThread(NULL, 0, Debug, NULL, 0, NULL); + if (hThread != nullptr) { + CloseHandle(hThread); + } + //std::this_thread::sleep_for(std::chrono::milliseconds(1000)); +#endif + Utils::SetLocaleToUTF8(); + Utils::IniData data = { + { + L"Config", { + {L"Block_Ads", true}, + {L"Block_Banner", true}, + {L"Enable_Developer", true}, + {L"Enable_Log", false}, + } + } + }; + Utils::AppendIniFile(L"config.ini", data); + Logger::Init(L"_AdBlocker.log", data[L"Config"][L"Enable_Log"]); + + if (data[L"Config"][L"Enable_Developer"]) { + hThread = CreateThread(NULL, 0, EnableDeveloper, NULL, 0, NULL); + if (hThread != nullptr) { + CloseHandle(hThread); + } + } + + if (data[L"Config"][L"Block_Ads"]) { + hThread = CreateThread(NULL, 0, BlockAds, NULL, 0, NULL); + if (hThread != nullptr) { + CloseHandle(hThread); + } + } + + if (data[L"Config"][L"Block_Banner"]) { + hThread = CreateThread(NULL, 0, BlockBanner, NULL, 0, NULL); + if (hThread != nullptr) { + CloseHandle(hThread); + } + } + } + catch (const std::exception& e) { + Print({ Color::Red }, L"[{}] {}", L"ERROR", Utils::ToString(e.what())); + } } - break; } } return TRUE; } - diff --git a/src/framework.h b/src/framework.h new file mode 100644 index 00000000..2d62817b --- /dev/null +++ b/src/framework.h @@ -0,0 +1,21 @@ +#pragma once + +#define _CRT_SECURE_NO_WARNINGS + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#include +#include +#include + +#ifndef NDEBUG +#include +#endif + +#include "BasicUtils/Utils.h" +#include "BasicUtils/Logger.h" +#include "BasicUtils/PatternScanner.h" +#include "BasicUtils/Memory.h" +#include "BasicUtils/Hooking.h" +#include "BasicUtils/Console.h" + +using namespace Console; \ No newline at end of file diff --git a/src/mhook-lib/mhook.cpp b/src/mhook-lib/mhook.cpp deleted file mode 100644 index 419ff9d9..00000000 --- a/src/mhook-lib/mhook.cpp +++ /dev/null @@ -1,1528 +0,0 @@ -//Copyright (c) 2007-2008, Marton Anka -// -//Permission is hereby granted, free of charge, to any person obtaining a -//copy of this software and associated documentation files (the "Software"), -//to deal in the Software without restriction, including without limitation -//the rights to use, copy, modify, merge, publish, distribute, sublicense, -//and/or sell copies of the Software, and to permit persons to whom the -//Software is furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included -//in all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -//OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -//THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -//IN THE SOFTWARE. - -#include -#include -#include -#include "mhook.h" -#include "../disasm-lib/disasm.h" - -//========================================================================= -#ifndef GOOD_HANDLE -#define GOOD_HANDLE(a) ((a!=INVALID_HANDLE_VALUE)&&(a!=NULL)) -#endif - -//========================================================================= -#ifndef gle -#define gle GetLastError -#endif - -//========================================================================= -#ifndef ODPRINTF - -#ifdef _DEBUG -#define ODPRINTF(a) odprintf a -#else -#define ODPRINTF(a) -#endif - -inline void __cdecl odprintf(PCWSTR format, ...) -{ - va_list args; - va_start(args, format); - int len = _vscwprintf(format, args); - if (len > 0) - { - len += (1 + 2); - PWSTR buf = (PWSTR) malloc(sizeof(WCHAR)*len); - if (buf) - { - len = vswprintf_s(buf, len, format, args); - if (len > 0) - { - while (len && iswspace(buf[len-1])) len--; - buf[len++] = L'\r'; - buf[len++] = L'\n'; - buf[len] = 0; - OutputDebugStringW(buf); - } - free(buf); - } - va_end(args); - } -} - -#endif //#ifndef ODPRINTF - -//========================================================================= -#define MHOOKS_MAX_CODE_BYTES 32 -#define MHOOKS_MAX_RIPS 4 - -//========================================================================= -// The trampoline structure - stores every bit of info about a hook -struct MHOOKS_TRAMPOLINE -{ - PBYTE pSystemFunction; // the original system function - DWORD cbOverwrittenCode; // number of bytes overwritten by the jump - PBYTE pHookFunction; // the hook function that we provide - BYTE codeJumpToHookFunction[MHOOKS_MAX_CODE_BYTES]; // placeholder for code that jumps to the hook function - BYTE codeTrampoline[MHOOKS_MAX_CODE_BYTES]; // placeholder for code that holds the first few - // bytes from the system function and a jump to the remainder - // in the original location - BYTE codeUntouched[MHOOKS_MAX_CODE_BYTES]; // placeholder for unmodified original code - // (we patch IP-relative addressing) - MHOOKS_TRAMPOLINE* pPrevTrampoline; // When in the free list, thess are pointers to the prev and next entry. - MHOOKS_TRAMPOLINE* pNextTrampoline; // When not in the free list, this is a pointer to the prev and next trampoline in use. -}; - -//========================================================================= -// The patch data structures - store info about rip-relative instructions -// during hook placement -struct MHOOKS_RIPINFO -{ - DWORD dwOffset; - S64 nDisplacement; -}; - -struct MHOOKS_PATCHDATA -{ - S64 nLimitUp; - S64 nLimitDown; - DWORD nRipCnt; - MHOOKS_RIPINFO rips[MHOOKS_MAX_RIPS]; -}; - -//========================================================================= -// Hook context contains info about one hook -struct HOOK_CONTEXT -{ - PVOID pSystemFunction; - PVOID pHookFunction; - DWORD dwInstructionLength; - MHOOKS_TRAMPOLINE* pTrampoline; - - MHOOKS_PATCHDATA patchdata; - - bool needPatchJump; - bool needPatchCall; -}; - -//========================================================================= -// Global vars -static bool g_bVarsInitialized = false; -static CRITICAL_SECTION g_cs; -static MHOOKS_TRAMPOLINE* g_pHooks = NULL; -static MHOOKS_TRAMPOLINE* g_pFreeList = NULL; -static HANDLE* g_hThreadHandles = NULL; -static DWORD g_nThreadHandles = 0; -#define MHOOK_JMPSIZE 5 -#define MHOOK_MINALLOCSIZE 4096 - -//========================================================================= -// ntdll definitions - -typedef LONG NTSTATUS; - -typedef LONG KPRIORITY; - -typedef enum _SYSTEM_INFORMATION_CLASS -{ - SystemBasicInformation = 0, - SystemPerformanceInformation = 2, - SystemTimeOfDayInformation = 3, - SystemProcessInformation = 5, - SystemProcessorPerformanceInformation = 8, - SystemHandleInformation = 16, - SystemInterruptInformation = 23, - SystemExceptionInformation = 33, - SystemRegistryQuotaInformation = 37, - SystemLookasideInformation = 45, - SystemProcessIdInformation = 0x58 -} SYSTEM_INFORMATION_CLASS; - -typedef enum _KWAIT_REASON -{ - Executive, - FreePage, - PageIn, - PoolAllocation, - DelayExecution, - Suspended, - UserRequest, - WrExecutive, - WrFreePage, - WrPageIn, - WrPoolAllocation, - WrDelayExecution, - WrSuspended, - WrUserRequest, - WrEventPair, - WrQueue, - WrLpcReceive, - WrLpcReply, - WrVirtualMemory, - WrPageOut, - WrRendezvous, - Spare2, - Spare3, - Spare4, - Spare5, - Spare6, - WrKernel, - MaximumWaitReason -} KWAIT_REASON, *PKWAIT_REASON; - -typedef struct _CLIENT_ID -{ - HANDLE UniqueProcess; - HANDLE UniqueThread; -} CLIENT_ID, *PCLIENT_ID; - -typedef struct _SYSTEM_THREAD_INFORMATION -{ - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER CreateTime; - ULONG WaitTime; - PVOID StartAddress; - CLIENT_ID ClientId; - KPRIORITY Priority; - LONG BasePriority; - ULONG ContextSwitches; - ULONG ThreadState; - KWAIT_REASON WaitReason; -} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; - -typedef struct _UNICODE_STRING -{ - USHORT Length; - USHORT MaximumLength; - PWSTR Buffer; -} UNICODE_STRING; - -typedef struct _SYSTEM_PROCESS_INFORMATION -{ - ULONG uNext; - ULONG uThreadCount; - LARGE_INTEGER WorkingSetPrivateSize; // since VISTA - ULONG HardFaultCount; // since WIN7 - ULONG NumberOfThreadsHighWatermark; // since WIN7 - ULONGLONG CycleTime; // since WIN7 - LARGE_INTEGER CreateTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER KernelTime; - UNICODE_STRING ImageName; - KPRIORITY BasePriority; - HANDLE uUniqueProcessId; - HANDLE InheritedFromUniqueProcessId; - ULONG HandleCount; - ULONG SessionId; - ULONG_PTR UniqueProcessKey; // since VISTA (requires SystemExtendedProcessInformation) - SIZE_T PeakVirtualSize; - SIZE_T VirtualSize; - ULONG PageFaultCount; - SIZE_T PeakWorkingSetSize; - SIZE_T WorkingSetSize; - SIZE_T QuotaPeakPagedPoolUsage; - SIZE_T QuotaPagedPoolUsage; - SIZE_T QuotaPeakNonPagedPoolUsage; - SIZE_T QuotaNonPagedPoolUsage; - SIZE_T PagefileUsage; - SIZE_T PeakPagefileUsage; - SIZE_T PrivatePageCount; - LARGE_INTEGER ReadOperationCount; - LARGE_INTEGER WriteOperationCount; - LARGE_INTEGER OtherOperationCount; - LARGE_INTEGER ReadTransferCount; - LARGE_INTEGER WriteTransferCount; - LARGE_INTEGER OtherTransferCount; - SYSTEM_THREAD_INFORMATION Threads[1]; -} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; - -//========================================================================= -// ZwQuerySystemInformation definitions -typedef NTSTATUS(NTAPI* PZwQuerySystemInformation)( - __in SYSTEM_INFORMATION_CLASS SystemInformationClass, - __inout PVOID SystemInformation, - __in ULONG SystemInformationLength, - __out_opt PULONG ReturnLength - ); - -#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) -static PZwQuerySystemInformation fnZwQuerySystemInformation = reinterpret_cast(GetProcAddress(GetModuleHandle(L"ntdll.dll"), "ZwQuerySystemInformation")); - -//========================================================================= -// Internal function: -// -// Remove the trampoline from the specified list, updating the head pointer -// if necessary. -//========================================================================= -static VOID ListRemove(MHOOKS_TRAMPOLINE** pListHead, MHOOKS_TRAMPOLINE* pNode) -{ - if (pNode->pPrevTrampoline) - { - pNode->pPrevTrampoline->pNextTrampoline = pNode->pNextTrampoline; - } - - if (pNode->pNextTrampoline) - { - pNode->pNextTrampoline->pPrevTrampoline = pNode->pPrevTrampoline; - } - - if ((*pListHead) == pNode) - { - (*pListHead) = pNode->pNextTrampoline; - if (*pListHead != NULL) - { - assert((*pListHead)->pPrevTrampoline == NULL); - } - } - - pNode->pPrevTrampoline = NULL; - pNode->pNextTrampoline = NULL; -} - -//========================================================================= -// Internal function: -// -// Prepend the trampoline from the specified list and update the head pointer. -//========================================================================= -static VOID ListPrepend(MHOOKS_TRAMPOLINE** pListHead, MHOOKS_TRAMPOLINE* pNode) -{ - pNode->pPrevTrampoline = NULL; - pNode->pNextTrampoline = (*pListHead); - if ((*pListHead)) - { - (*pListHead)->pPrevTrampoline = pNode; - } - (*pListHead) = pNode; -} - -//========================================================================= -// Internal function: -// -// For iteration over the list -//========================================================================= -static MHOOKS_TRAMPOLINE* ListNext(MHOOKS_TRAMPOLINE* pNode) -{ - return pNode && pNode->pNextTrampoline ? pNode->pNextTrampoline : NULL; -} - -//========================================================================= -static VOID EnterCritSec() -{ - if (!g_bVarsInitialized) - { - InitializeCriticalSection(&g_cs); - g_bVarsInitialized = true; - } - EnterCriticalSection(&g_cs); -} - -//========================================================================= -static VOID LeaveCritSec() -{ - LeaveCriticalSection(&g_cs); -} - -//========================================================================= -// Internal function: -// -// Skip over jumps that lead to the real function. Gets around import -// jump tables, etc. -//========================================================================= -static PBYTE SkipJumps(PBYTE pbCode) -{ - PBYTE pbOrgCode = pbCode; -#ifdef _M_IX86_X64 -#ifdef _M_IX86 - //mov edi,edi: hot patch point - if (pbCode[0] == 0x8b && pbCode[1] == 0xff) - pbCode += 2; - // push ebp; mov ebp, esp; pop ebp; - // "collapsed" stackframe generated by MSVC - if (pbCode[0] == 0x55 && pbCode[1] == 0x8b && pbCode[2] == 0xec && pbCode[3] == 0x5d) - pbCode += 4; -#endif - if (pbCode[0] == 0xff && pbCode[1] == 0x25) - { -#ifdef _M_IX86 - // on x86 we have an absolute pointer... - PBYTE pbTarget = *(PBYTE *)&pbCode[2]; - // ... that shows us an absolute pointer. - return SkipJumps(*(PBYTE *)pbTarget); -#elif defined _M_X64 - // on x64 we have a 32-bit offset... - INT32 lOffset = *(INT32 *)&pbCode[2]; - // ... that shows us an absolute pointer - return SkipJumps(*(PBYTE*)(pbCode + 6 + lOffset)); - } - else if (pbCode[0] == 0x48 && pbCode[1] == 0xff && pbCode[2] == 0x25) - { - // or we can have the same with a REX prefix - INT32 lOffset = *(INT32 *)&pbCode[3]; - // ... that shows us an absolute pointer - return SkipJumps(*(PBYTE*)(pbCode + 7 + lOffset)); -#endif - } - else if (pbCode[0] == 0xe9) - { - // here the behavior is identical, we have... - // ...a 32-bit offset to the destination. - return SkipJumps(pbCode + 5 + *(INT32 *)&pbCode[1]); - } - else if (pbCode[0] == 0xeb) - { - // and finally an 8-bit offset to the destination - return SkipJumps(pbCode + 2 + *(CHAR *)&pbCode[1]); - } -#else -#error unsupported platform -#endif - return pbOrgCode; -} - -//========================================================================= -// Internal function: -// -// Writes code at pbCode that jumps to pbJumpTo. Will attempt to do this -// in as few bytes as possible. Important on x64 where the long jump -// (0xff 0x25 ....) can take up 14 bytes. -//========================================================================= -static PBYTE EmitJump(PBYTE pbCode, PBYTE pbJumpTo) -{ -#ifdef _M_IX86_X64 - PBYTE pbJumpFrom = pbCode + 5; - SIZE_T cbDiff = pbJumpFrom > pbJumpTo ? pbJumpFrom - pbJumpTo : pbJumpTo - pbJumpFrom; - ODPRINTF((L"mhooks: EmitJump: Jumping from %p to %p, diff is %p", pbJumpFrom, pbJumpTo, cbDiff)); - if (cbDiff <= 0x7fff0000) - { - pbCode[0] = 0xe9; - pbCode += 1; - *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbJumpTo - pbJumpFrom); - pbCode += sizeof(DWORD); - } - else - { - pbCode[0] = 0xff; - pbCode[1] = 0x25; - pbCode += 2; -#ifdef _M_IX86 - // on x86 we write an absolute address (just behind the instruction) - *((PDWORD)pbCode) = (DWORD)(DWORD_PTR)(pbCode + sizeof(DWORD)); -#elif defined _M_X64 - // on x64 we write the relative address of the same location - *((PDWORD)pbCode) = (DWORD)0; -#endif - pbCode += sizeof(DWORD); - *((PDWORD_PTR)pbCode) = (DWORD_PTR)(pbJumpTo); - pbCode += sizeof(DWORD_PTR); - } -#else -#error unsupported platform -#endif - return pbCode; -} - -//========================================================================= -// Internal function: -// -// Round down to the next multiple of rndDown -//========================================================================= -static size_t RoundDown(size_t addr, size_t rndDown) -{ - return (addr / rndDown) * rndDown; -} - -//========================================================================= -// Internal function: -// -// Will attempt allocate a block of memory within the specified range, as -// near as possible to the specified function. -//========================================================================= -static MHOOKS_TRAMPOLINE* BlockAlloc(PBYTE pSystemFunction, PBYTE pbLower, PBYTE pbUpper) -{ - SYSTEM_INFO sSysInfo = {0}; - ::GetSystemInfo(&sSysInfo); - - // Always allocate in bulk, in case the system actually has a smaller allocation granularity than MINALLOCSIZE. - const ptrdiff_t cAllocSize = MAX(sSysInfo.dwAllocationGranularity, MHOOK_MINALLOCSIZE); - - MHOOKS_TRAMPOLINE* pRetVal = NULL; - PBYTE pModuleGuess = (PBYTE) RoundDown((size_t)pSystemFunction, cAllocSize); - int loopCount = 0; - for (PBYTE pbAlloc = pModuleGuess; pbLower < pbAlloc && pbAlloc < pbUpper; ++loopCount) - { - // determine current state - MEMORY_BASIC_INFORMATION mbi; - ODPRINTF((L"mhooks: BlockAlloc: Looking at address %p", pbAlloc)); - if (!VirtualQuery(pbAlloc, &mbi, sizeof(mbi))) - break; - // free & large enough? - if (mbi.State == MEM_FREE && mbi.RegionSize >= (unsigned)cAllocSize) - { - // and then try to allocate it - pRetVal = (MHOOKS_TRAMPOLINE*)VirtualAlloc(pbAlloc, cAllocSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); - if (pRetVal) - { - size_t trampolineCount = cAllocSize / sizeof(MHOOKS_TRAMPOLINE); - ODPRINTF((L"mhooks: BlockAlloc: Allocated block at %p as %d trampolines", pRetVal, trampolineCount)); - - pRetVal[0].pPrevTrampoline = NULL; - pRetVal[0].pNextTrampoline = &pRetVal[1]; - - // prepare them by having them point down the line at the next entry. - for (size_t s = 1; s < trampolineCount; ++s) - { - pRetVal[s].pPrevTrampoline = &pRetVal[s - 1]; - pRetVal[s].pNextTrampoline = &pRetVal[s + 1]; - } - - // last entry points to the current head of the free list - pRetVal[trampolineCount - 1].pNextTrampoline = g_pFreeList; - if (g_pFreeList) - { - g_pFreeList->pPrevTrampoline = &pRetVal[trampolineCount - 1]; - } - break; - } - } - - // This is a spiral, should be -1, 1, -2, 2, -3, 3, etc. (* cAllocSize) - ptrdiff_t bytesToOffset = (cAllocSize * (loopCount + 1) * ((loopCount % 2 == 0) ? -1 : 1)); - pbAlloc = pbAlloc + bytesToOffset; - } - - return pRetVal; -} - -//========================================================================= -// Internal function: -// -// Will try to allocate a big block of memory inside the required range. -//========================================================================= -static MHOOKS_TRAMPOLINE* FindTrampolineInRange(PBYTE pLower, PBYTE pUpper) -{ - if (!g_pFreeList) - { - return NULL; - } - - // This is a standard free list, except we're doubly linked to deal with soem return shenanigans. - MHOOKS_TRAMPOLINE* curEntry = g_pFreeList; - while (curEntry) - { - if ((MHOOKS_TRAMPOLINE*) pLower < curEntry && curEntry < (MHOOKS_TRAMPOLINE*) pUpper) - { - ListRemove(&g_pFreeList, curEntry); - - return curEntry; - } - - curEntry = curEntry->pNextTrampoline; - } - - return NULL; -} - -//========================================================================= -// Internal function: -// -// Will try to allocate the trampoline structure within 2 gigabytes of -// the target function. -//========================================================================= -static MHOOKS_TRAMPOLINE* TrampolineAlloc(PBYTE pSystemFunction, S64 nLimitUp, S64 nLimitDown) -{ - - MHOOKS_TRAMPOLINE* pTrampoline = NULL; - - // determine lower and upper bounds for the allocation locations. - // in the basic scenario this is +/- 2GB but IP-relative instructions - // found in the original code may require a smaller window. - PBYTE pLower = pSystemFunction + nLimitUp; - pLower = pLower < (PBYTE)(DWORD_PTR)0x0000000080000000 ? - (PBYTE)(0x1) : (PBYTE)(pLower - (PBYTE)0x7fff0000); - PBYTE pUpper = pSystemFunction + nLimitDown; - pUpper = pUpper < (PBYTE)(DWORD_PTR)0xffffffff80000000 ? - (PBYTE)(pUpper + (DWORD_PTR)0x7ff80000) : (PBYTE)(DWORD_PTR)0xfffffffffff80000; - ODPRINTF((L"mhooks: TrampolineAlloc: Allocating for %p between %p and %p", pSystemFunction, pLower, pUpper)); - - // try to find a trampoline in the specified range - pTrampoline = FindTrampolineInRange(pLower, pUpper); - if (!pTrampoline) - { - // if it we can't find it, then we need to allocate a new block and - // try again. Just fail if that doesn't work - g_pFreeList = BlockAlloc(pSystemFunction, pLower, pUpper); - pTrampoline = FindTrampolineInRange(pLower, pUpper); - } - - // found and allocated a trampoline? - if (pTrampoline) - { - ListPrepend(&g_pHooks, pTrampoline); - } - - return pTrampoline; -} - -//========================================================================= -// Internal function: -// -// Return the internal trampoline structure that belongs to a hooked function. -//========================================================================= -static MHOOKS_TRAMPOLINE* TrampolineGet(PBYTE pHookedFunction) -{ - MHOOKS_TRAMPOLINE* pCurrent = g_pHooks; - - while (pCurrent) - { - if ((PBYTE)&(pCurrent->codeTrampoline) == pHookedFunction) - { - return pCurrent; - } - - pCurrent = pCurrent->pNextTrampoline; - } - - return NULL; -} - -//========================================================================= -// Internal function: -// -// Free a trampoline structure. -//========================================================================= -static VOID TrampolineFree(MHOOKS_TRAMPOLINE* pTrampoline, bool bNeverUsed) -{ - ListRemove(&g_pHooks, pTrampoline); - - // If a thread could feasinbly have some of our trampoline code - // on its stack and we yank the region from underneath it then it will - // surely crash upon returning. So instead of freeing the - // memory we just let it leak. Ugly, but safe. - if (bNeverUsed) - { - ListPrepend(&g_pFreeList, pTrampoline); - } -} - -static bool VerifyThreadContext(PBYTE pIp, HOOK_CONTEXT* hookCtx, int hookCount) -{ - for (int i = 0; i < hookCount; i++) - { - if (pIp >= (PBYTE)hookCtx[i].pSystemFunction && pIp < ((PBYTE)hookCtx[i].pSystemFunction + hookCtx[i].dwInstructionLength)) - { - return false; - } - } - - return true; -} - -//========================================================================= -// Internal function: -// -// Suspend a given thread and try to make sure that its instruction -// pointer is not in the given range. -//========================================================================= -//========================================================================= -static HANDLE SuspendOneThread(DWORD dwThreadId, HOOK_CONTEXT* hookCtx, int hookCount) -{ - // open the thread - HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, false, dwThreadId); - - if (GOOD_HANDLE(hThread)) - { - // attempt suspension - DWORD dwSuspendCount = SuspendThread(hThread); - if (dwSuspendCount != -1) - { - // see where the IP is - CONTEXT ctx; - ctx.ContextFlags = CONTEXT_CONTROL; - int nTries = 0; - while (GetThreadContext(hThread, &ctx)) - { -#ifdef _M_IX86 - PBYTE pIp = (PBYTE)(DWORD_PTR)ctx.Eip; -#elif defined _M_X64 - PBYTE pIp = (PBYTE)(DWORD_PTR)ctx.Rip; -#endif - if (!VerifyThreadContext(pIp, hookCtx, hookCount)) - { - if (nTries < 3) - { - // oops - we should try to get the instruction pointer out of here. - ODPRINTF((L"mhooks: SuspendOneThread: suspended thread %d - IP is at %p - IS COLLIDING WITH CODE", dwThreadId, pIp)); - ResumeThread(hThread); - Sleep(100); - SuspendThread(hThread); - nTries++; - } - else - { - // we gave it all we could. (this will probably never - // happen - unless the thread has already been suspended - // to begin with) - ODPRINTF((L"mhooks: SuspendOneThread: suspended thread %d - IP is at %p - IS COLLIDING WITH CODE - CAN'T FIX", dwThreadId, pIp)); - ResumeThread(hThread); - CloseHandle(hThread); - hThread = NULL; - break; - } - } - else - { - // success, the IP is not conflicting - ODPRINTF((L"mhooks: SuspendOneThread: Successfully suspended thread %d - IP is at %p", dwThreadId, pIp)); - break; - } - } - } - else - { - // couldn't suspend - CloseHandle(hThread); - hThread = NULL; - } - } - - return hThread; -} - -//========================================================================= -// Internal function: -// -// Free memory allocated for processes snapshot -//========================================================================= -static VOID CloseProcessSnapshot(VOID* snapshotContext) -{ - free(snapshotContext); -} - -//========================================================================= -// Internal function: -// -// Resumes all previously suspended threads in the current process. -//========================================================================= -static VOID ResumeOtherThreads() -{ - // make sure things go as fast as possible - INT nOriginalPriority = GetThreadPriority(GetCurrentThread()); - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - // go through our list - for (DWORD i=0; iuUniqueProcessId == (HANDLE)processId) - { - break; - } - - if (currentProcess->uNext == 0) - { - currentProcess = NULL; - } - else - { - currentProcess = (PSYSTEM_PROCESS_INFORMATION)(((LPBYTE)currentProcess) + currentProcess->uNext); - } - } - - return currentProcess; -} - -//========================================================================= -// Internal function: -// -// Get current process snapshot and process info -// -//========================================================================= -static bool GetCurrentProcessSnapshot(PVOID* snapshot, PSYSTEM_PROCESS_INFORMATION* procInfo) -{ - // get a view of the threads in the system - - if (!CreateProcessSnapshot(snapshot)) - { - ODPRINTF((L"mhooks: can't get process snapshot!")); - return false; - } - - DWORD pid = GetCurrentProcessId(); - - *procInfo = FindProcess(*snapshot, pid); - return true; -} - -//========================================================================= -// Internal function: -// -// Suspend all threads in this process while trying to make sure that their -// instruction pointer is not in the given range. -//========================================================================= -static bool SuspendOtherThreads(HOOK_CONTEXT* hookCtx, int hookCount, PSYSTEM_PROCESS_INFORMATION procInfo) -{ - bool bRet = false; - // make sure we're the most important thread in the process - INT nOriginalPriority = GetThreadPriority(GetCurrentThread()); - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); - - DWORD pid = GetCurrentProcessId(); - DWORD tid = GetCurrentThreadId(); - - // count threads in this process (except for ourselves) - DWORD nThreadsInProcess = 0; - - if (procInfo->uThreadCount != 0) - { - nThreadsInProcess = procInfo->uThreadCount - 1; - } - - ODPRINTF((L"mhooks: [%d:%d] SuspendOtherThreads: counted %d other threads", pid, tid, nThreadsInProcess)); - - if (nThreadsInProcess) - { - // alloc buffer for the handles we really suspended - g_hThreadHandles = (HANDLE*)malloc(nThreadsInProcess * sizeof(HANDLE)); - - if (g_hThreadHandles) - { - ZeroMemory(g_hThreadHandles, nThreadsInProcess * sizeof(HANDLE)); - DWORD nCurrentThread = 0; - bool bFailed = false; - - // go through every thread - for (ULONG threadIdx = 0; threadIdx < procInfo->uThreadCount; threadIdx++) - { - DWORD threadId = static_cast(reinterpret_cast(procInfo->Threads[threadIdx].ClientId.UniqueThread)); - - if (threadId != tid) - { - // attempt to suspend it - g_hThreadHandles[nCurrentThread] = SuspendOneThread(threadId, hookCtx, hookCount); - - if (GOOD_HANDLE(g_hThreadHandles[nCurrentThread])) - { - ODPRINTF((L"mhooks: [%d:%d] SuspendOtherThreads: successfully suspended %d", pid, tid, threadId)); - nCurrentThread++; - } - else - { - ODPRINTF((L"mhooks: [%d:%d] SuspendOtherThreads: error while suspending thread %d: %d", pid, tid, threadId, gle())); - // TODO: this might not be the wisest choice - // but we can choose to ignore failures on - // thread suspension. It's pretty unlikely that - // we'll fail - and even if we do, the chances - // of a thread's IP being in the wrong place - // is pretty small. - // bFailed = true; - } - } - } - - g_nThreadHandles = nCurrentThread; - bRet = !bFailed; - } - } - - //TODO: we might want to have another pass to make sure all threads - // in the current process (including those that might have been - // created since we took the original snapshot) have been - // suspended. - - if (!bRet && nThreadsInProcess != 0) - { - ODPRINTF((L"mhooks: [%d:%d] SuspendOtherThreads: Had a problem (or not running multithreaded), resuming all threads.", pid, tid)); - ResumeOtherThreads(); - } - - SetThreadPriority(GetCurrentThread(), nOriginalPriority); - - return bRet; -} - -//========================================================================= -// if IP-relative addressing has been detected, fix up the code so the -// offset points to the original location -static void FixupIPRelativeAddressing(PBYTE pbNew, PBYTE pbOriginal, MHOOKS_PATCHDATA* pdata) -{ -#if defined _M_X64 - S64 diff = pbNew - pbOriginal; - for (DWORD i = 0; i < pdata->nRipCnt; i++) - { - DWORD dwNewDisplacement = (DWORD)(pdata->rips[i].nDisplacement - diff); - ODPRINTF((L"mhooks: fixing up RIP instruction operand for code at 0x%p: " - L"old displacement: 0x%8.8x, new displacement: 0x%8.8x", - pbNew + pdata->rips[i].dwOffset, - (DWORD)pdata->rips[i].nDisplacement, - dwNewDisplacement)); - *(PDWORD)(pbNew + pdata->rips[i].dwOffset) = dwNewDisplacement; - } -#endif -} - -//========================================================================= -// Examine the machine code at the target function's entry point, and -// skip bytes in a way that we'll always end on an instruction boundary. -// We also detect branches and subroutine calls (as well as returns) -// at which point disassembly must stop. -// Finally, detect and collect information on IP-relative instructions -// that we can patch. -static DWORD DisassembleAndSkip(PVOID pFunction, DWORD dwMinLen, MHOOKS_PATCHDATA* pdata) -{ - DWORD dwRet = 0; - pdata->nLimitDown = 0; - pdata->nLimitUp = 0; - pdata->nRipCnt = 0; -#ifdef _M_IX86 - ARCHITECTURE_TYPE arch = ARCH_X86; -#elif defined _M_X64 - ARCHITECTURE_TYPE arch = ARCH_X64; -#else - #error unsupported platform -#endif - DISASSEMBLER dis; - if (InitDisassembler(&dis, arch)) - { - INSTRUCTION* pins = NULL; - U8* pLoc = (U8*)pFunction; - DWORD dwFlags = DISASM_DECODE | DISASM_DISASSEMBLE | DISASM_ALIGNOUTPUT; - - ODPRINTF((L"mhooks: DisassembleAndSkip: Disassembling %p", pLoc)); - while ( (dwRet < dwMinLen) && (pins = GetInstruction(&dis, (ULONG_PTR)pLoc, pLoc, dwFlags)) ) - { - ODPRINTF((L"mhooks: DisassembleAndSkip: %p:(0x%2.2x) %s", pLoc, pins->Length, pins->String)); - if (pins->Type == ITYPE_RET ) break; - if (pins->Type == ITYPE_BRANCHCC) break; - if (pins->Type == ITYPE_CALLCC) break; - - #if defined _M_X64 - bool bProcessRip = false; - // jmp to rip+imm32 - if ((pins->Type == ITYPE_BRANCH) && (pins->OperandCount == 1) && (pins->X86.Relative) && (pins->X86.BaseRegister == AMD64_REG_RIP) && (pins->Operands[0].Flags & OP_IPREL)) - { - // rip-addressing "jmp [rip+imm32]" - ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 1, pins->X86.Displacement, *(PDWORD)(pLoc + 3))); - bProcessRip = true; - } - - // mov or lea to register from rip+imm32 - else if ((pins->Type == ITYPE_MOV || pins->Type == ITYPE_LEA) && (pins->X86.Relative) && - (pins->X86.OperandSize == 8) && (pins->OperandCount == 2) && - (pins->Operands[1].Flags & OP_IPREL) && (pins->Operands[1].Register == AMD64_REG_RIP)) - { - // rip-addressing "mov reg, [rip+imm32]" - ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 1, pins->X86.Displacement, *(PDWORD)(pLoc+3))); - bProcessRip = true; - } - // mov or lea to rip+imm32 from register - else if ((pins->Type == ITYPE_MOV || pins->Type == ITYPE_LEA) && (pins->X86.Relative) && - (pins->X86.OperandSize == 8) && (pins->OperandCount == 2) && - (pins->Operands[0].Flags & OP_IPREL) && (pins->Operands[0].Register == AMD64_REG_RIP)) - { - // rip-addressing "mov [rip+imm32], reg" - ODPRINTF((L"mhooks: DisassembleAndSkip: found OP_IPREL on operand %d with displacement 0x%x (in memory: 0x%x)", 0, pins->X86.Displacement, *(PDWORD)(pLoc+3))); - bProcessRip = true; - } - else if ( (pins->OperandCount >= 1) && (pins->Operands[0].Flags & OP_IPREL) ) - { - // unsupported rip-addressing - ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 0)); - // dump instruction bytes to the debug output - for (DWORD i=0; iLength; i++) - { - ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i])); - } - break; - } - else if ( (pins->OperandCount >= 2) && (pins->Operands[1].Flags & OP_IPREL) ) - { - // unsupported rip-addressing - ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 1)); - // dump instruction bytes to the debug output - for (DWORD i=0; iLength; i++) - { - ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i])); - } - break; - } - else if ( (pins->OperandCount >= 3) && (pins->Operands[2].Flags & OP_IPREL) ) - { - // unsupported rip-addressing - ODPRINTF((L"mhooks: DisassembleAndSkip: found unsupported OP_IPREL on operand %d", 2)); - // dump instruction bytes to the debug output - for (DWORD i=0; iLength; i++) - { - ODPRINTF((L"mhooks: DisassembleAndSkip: instr byte %2.2d: 0x%2.2x", i, pLoc[i])); - } - break; - } - // follow through with RIP-processing if needed - if (bProcessRip) - { - // calculate displacement relative to function start - S64 nAdjustedDisplacement = pins->X86.Displacement + (pLoc - (U8*)pFunction); - // store displacement values furthest from zero (both positive and negative) - if (nAdjustedDisplacement < pdata->nLimitDown) - pdata->nLimitDown = nAdjustedDisplacement; - if (nAdjustedDisplacement > pdata->nLimitUp) - pdata->nLimitUp = nAdjustedDisplacement; - // store patch info - if (pdata->nRipCnt < MHOOKS_MAX_RIPS) - { - pdata->rips[pdata->nRipCnt].dwOffset = dwRet + 3; - pdata->rips[pdata->nRipCnt].nDisplacement = pins->X86.Displacement; - pdata->nRipCnt++; - } - else - { - // no room for patch info, stop disassembly - break; - } - } - #endif - - dwRet += pins->Length; - pLoc += pins->Length; - } - - CloseDisassembler(&dis); - } - - return dwRet; -} - -static bool IsInstructionPresentInFirstFiveByte(PVOID pFunction, INSTRUCTION_TYPE type) -{ - DWORD dwRet = 0; - -#ifdef _M_IX86 - ARCHITECTURE_TYPE arch = ARCH_X86; -#elif defined _M_X64 - ARCHITECTURE_TYPE arch = ARCH_X64; -#else -#error unsupported platform -#endif - DISASSEMBLER dis; - if (InitDisassembler(&dis, arch)) - { - INSTRUCTION* pins = NULL; - U8* pLoc = (U8*)pFunction; - DWORD dwFlags = DISASM_DECODE | DISASM_DISASSEMBLE | DISASM_ALIGNOUTPUT; - - while ((dwRet < MHOOK_JMPSIZE) && (pins = GetInstruction(&dis, (ULONG_PTR)pLoc, pLoc, dwFlags))) - { - if (pins->Type == type) - { - return true; - } - - dwRet += pins->Length; - pLoc += pins->Length; - } - - CloseDisassembler(&dis); - } - - return false; -} - -static PBYTE PatchRelative(PBYTE pCodeTrampoline, PVOID pSystemFunction) -{ - DWORD dwRet = 0; - -#ifdef _M_IX86 - ARCHITECTURE_TYPE arch = ARCH_X86; -#elif defined _M_X64 - ARCHITECTURE_TYPE arch = ARCH_X64; -#else -#error unsupported platform -#endif - DISASSEMBLER dis; - if (InitDisassembler(&dis, arch)) - { - INSTRUCTION* pins = NULL; - U8* pLoc = (U8*)pCodeTrampoline; - DWORD dwFlags = DISASM_DECODE | DISASM_DISASSEMBLE | DISASM_ALIGNOUTPUT; - - while ((dwRet < MHOOK_JMPSIZE) && (pins = GetInstruction(&dis, (ULONG_PTR)pLoc, pLoc, dwFlags))) - { - if (pins->Type == ITYPE_BRANCHCC) - { - // we will patch only near jump je/jz for now - if (pins->OpcodeLength == 1 && (pins->OpcodeBytes[0] == 0x74 || pins->OpcodeBytes[0] == 0x75)) - { - // save old offset from current position to jump destination - U8 oldOffset = *(pLoc + pins->OpcodeLength); - // write je opcode with rel32 address in codeTrampoline block - *pLoc = 0x0f; - *(pLoc + pins->OpcodeLength) = pins->OpcodeBytes[0] + 0x10; - - // Calculating offset from codeTrampoline to jump label in original function - - // get address of original jump destination - ULONG_PTR jumpDestinationAddress = reinterpret_cast(pSystemFunction); - // oldOffset is from the pLoc + pins->OpcodeLength address, so add it - jumpDestinationAddress += oldOffset + pins->OpcodeLength; - - // current address is from the pLoc + 2 (je rel32 opcode is 2-bytes length), so add it - const DWORD kJERel32OpcodeLength = 2; - ULONG_PTR currentAddress = reinterpret_cast(pLoc + kJERel32OpcodeLength); - - // take the offset that we should add to current address to reach original jump destination - LONG newOffset = static_cast(jumpDestinationAddress - currentAddress); - assert(currentAddress + newOffset == jumpDestinationAddress); - - memcpy(pLoc + kJERel32OpcodeLength, &newOffset, sizeof(newOffset)); - - return pLoc + kJERel32OpcodeLength + sizeof(newOffset); - } - } - - if (pins->Type == ITYPE_CALL) - { - // we will patch CALL relative32 - if (pins->OpcodeLength == 1 && pins->OpcodeBytes[0] == 0xE8) - { - // call rel32 address is relative to the next instruction start address - // reinterpret_cast(pSystemFunction) is the original function address - // (pLoc - pCodeTrampoline) for current offset of call from start of the function, - // pins->Length - full legth of instruction and operand address - ULONG_PTR oldStartAddress = (pLoc - pCodeTrampoline) + reinterpret_cast(pSystemFunction)+pins->Length; - // offset from the next instruction address - LONG oldOffset = *(reinterpret_cast(pins->Operands[0].BCD)); - // target function address - ULONG_PTR destination = oldStartAddress + oldOffset; - - // now calculate new start address and new offset - ULONG_PTR newStartAddress = reinterpret_cast(pins->Address) + pins->Length; - LONG newOffset = static_cast(destination - newStartAddress); - - // save new offset to the trampoline code - *reinterpret_cast(pLoc + pins->OpcodeLength) = newOffset; - - return pLoc + pins->OpcodeLength + sizeof(newOffset); - } - } - - dwRet += pins->Length; - pLoc += pins->Length; - } - - CloseDisassembler(&dis); - } - - return pCodeTrampoline; -} - -static bool FindSystemFunction(HOOK_CONTEXT* hookCtx, int fromIdx, int toIdx, PVOID pSystemFunction) -{ - for (int idx = fromIdx; idx < toIdx; idx++) - { - if (hookCtx[idx].pSystemFunction == pSystemFunction) - { - return true; - } - } - - return false; -} - -//========================================================================= -int Mhook_SetHookEx(HOOK_INFO* hooks, int hookCount) -{ - int hooksSet = 0; - - HOOK_CONTEXT* hookCtx = (HOOK_CONTEXT*)malloc(hookCount * sizeof(HOOK_CONTEXT)); - - if (hookCtx == NULL) - { - // return error status - ODPRINTF((L"mhooks: can't allocate buffer!")); - - return hooksSet; - } - - EnterCritSec(); - - for (int idx = 0; idx < hookCount; idx++) - { - hookCtx[idx].pSystemFunction = *hooks[idx].ppSystemFunction; - hookCtx[idx].pHookFunction = hooks[idx].pHookFunction; - hookCtx[idx].pTrampoline = NULL; - hookCtx[idx].dwInstructionLength = 0; - memset(&hookCtx[idx].patchdata, 0, sizeof(MHOOKS_PATCHDATA)); - hookCtx[idx].needPatchJump = false; - hookCtx[idx].needPatchCall = false; - - ODPRINTF((L"mhooks: Mhook_SetHook: Started on the job: %p / %p", hookCtx[idx].pSystemFunction, hookCtx[idx].pHookFunction)); - - // find the real functions (jump over jump tables, if any) - hookCtx[idx].pSystemFunction = SkipJumps((PBYTE)hookCtx[idx].pSystemFunction); - hookCtx[idx].pHookFunction = SkipJumps((PBYTE)hookCtx[idx].pHookFunction); - - if (FindSystemFunction(hookCtx, 0, idx, hookCtx[idx].pSystemFunction)) - { - // Same system function found. Skip it. - - // It is not an error. - // This case is possible when two system functions from different DLLs are stubs and they are redirected to the one internal implementation. - // We are going to hook first instance and skip other. - - ODPRINTF((L"mhooks: Mhook_SetHook: already hooked: %p", hookCtx[idx].pSystemFunction)); - - hookCtx[idx].pTrampoline = NULL; - } - else - { - ODPRINTF((L"mhooks: Mhook_SetHook: Started on the job: %p / %p", hookCtx[idx].pSystemFunction, hookCtx[idx].pHookFunction)); - - // figure out the length of the overwrite zone - hookCtx[idx].dwInstructionLength = DisassembleAndSkip(hookCtx[idx].pSystemFunction, MHOOK_JMPSIZE, &hookCtx[idx].patchdata); - - hookCtx[idx].needPatchJump = IsInstructionPresentInFirstFiveByte(hookCtx[idx].pSystemFunction, ITYPE_BRANCHCC); - hookCtx[idx].needPatchCall = IsInstructionPresentInFirstFiveByte(hookCtx[idx].pSystemFunction, ITYPE_CALL); - - if (hookCtx[idx].dwInstructionLength >= MHOOK_JMPSIZE && !(hookCtx[idx].needPatchJump && hookCtx[idx].needPatchCall)) - { - ODPRINTF((L"mhooks: Mhook_SetHook: disassembly signals %d bytes", hookCtx[idx].dwInstructionLength)); - - // allocate a trampoline structure (TODO: it is pretty wasteful to get - // VirtualAlloc to grab chunks of memory smaller than 100 bytes) - hookCtx[idx].pTrampoline = TrampolineAlloc((PBYTE)hookCtx[idx].pSystemFunction, hookCtx[idx].patchdata.nLimitUp, hookCtx[idx].patchdata.nLimitDown); - } - else - { - // error - skip hook - ODPRINTF((L"mhooks: error! disassembly signals %d bytes (unacceptable)", hookCtx[idx].dwInstructionLength)); - } - } - } - - VOID* procEnumerationCtx = NULL; - PSYSTEM_PROCESS_INFORMATION procInfo = NULL; - - if (GetCurrentProcessSnapshot(&procEnumerationCtx, &procInfo)) - { - // suspend threads - SuspendOtherThreads(hookCtx, hookCount, procInfo); - - // returns pseudo-handle, no need to CloseHandle() for it - HANDLE currentProcessHandle = GetCurrentProcess(); - - // the next code is same to the Mhook_SetHook. Differences are only in using hookCtx[i] - for (int i = 0; i < hookCount; i++) - { - if (hookCtx[i].pTrampoline) - { - ODPRINTF((L"mhooks: Mhook_SetHook: allocated structure at %p", hookCtx[i].pTrampoline)); - DWORD dwOldProtectSystemFunction = 0; - DWORD dwOldProtectTrampolineFunction = 0; - - // set the system function to PAGE_EXECUTE_READWRITE - if (VirtualProtect(hookCtx[i].pSystemFunction, hookCtx[i].dwInstructionLength, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) - { - ODPRINTF((L"mhooks: Mhook_SetHook: readwrite set on system function")); - - // mark our trampoline buffer to PAGE_EXECUTE_READWRITE - if (VirtualProtect(hookCtx[i].pTrampoline, sizeof(MHOOKS_TRAMPOLINE), PAGE_EXECUTE_READWRITE, &dwOldProtectTrampolineFunction)) - { - ODPRINTF((L"mhooks: Mhook_SetHook: readwrite set on trampoline structure")); - - // create our trampoline function - PBYTE pbCode = hookCtx[i].pTrampoline->codeTrampoline; - - // save original code.. - for (DWORD k = 0; k < hookCtx[i].dwInstructionLength; k++) - { - hookCtx[i].pTrampoline->codeUntouched[k] = pbCode[k] = ((PBYTE)hookCtx[i].pSystemFunction)[k]; - } - - if (hookCtx[i].needPatchJump || hookCtx[i].needPatchCall) - { - pbCode = PatchRelative(pbCode, hookCtx[i].pSystemFunction); - } - else - { - pbCode += hookCtx[i].dwInstructionLength; - } - - // plus a jump to the continuation in the original location - pbCode = EmitJump(pbCode, ((PBYTE)hookCtx[i].pSystemFunction) + hookCtx[i].dwInstructionLength); - ODPRINTF((L"mhooks: Mhook_SetHook: updated the trampoline")); - - // fix up any IP-relative addressing in the code - FixupIPRelativeAddressing(hookCtx[i].pTrampoline->codeTrampoline, (PBYTE)hookCtx[i].pSystemFunction, &hookCtx[i].patchdata); - - DWORD_PTR dwDistance = (PBYTE)hookCtx[i].pHookFunction < (PBYTE)hookCtx[i].pSystemFunction ? - (PBYTE)hookCtx[i].pSystemFunction - (PBYTE)hookCtx[i].pHookFunction : (PBYTE)hookCtx[i].pHookFunction - (PBYTE)hookCtx[i].pSystemFunction; - - if (dwDistance > 0x7fff0000) - { - // create a stub that jumps to the replacement function. - // we need this because jumping from the API to the hook directly - // will be a long jump, which is 14 bytes on x64, and we want to - // avoid that - the API may or may not have room for such stuff. - // (remember, we only have 5 bytes guaranteed in the API.) - // on the other hand we do have room, and the trampoline will always be - // within +/- 2GB of the API, so we do the long jump in there. - // the API will jump to the "reverse trampoline" which - // will jump to the user's hook code. - pbCode = hookCtx[i].pTrampoline->codeJumpToHookFunction; - pbCode = EmitJump(pbCode, (PBYTE)hookCtx[i].pHookFunction); - ODPRINTF((L"mhooks: Mhook_SetHook: created reverse trampoline")); - FlushInstructionCache(GetCurrentProcess(), hookCtx[i].pTrampoline->codeJumpToHookFunction, - pbCode - hookCtx[i].pTrampoline->codeJumpToHookFunction); - - // update the API itself - pbCode = (PBYTE)hookCtx[i].pSystemFunction; - pbCode = EmitJump(pbCode, hookCtx[i].pTrampoline->codeJumpToHookFunction); - } - else - { - // the jump will be at most 5 bytes so we can do it directly - // update the API itself - pbCode = (PBYTE)hookCtx[i].pSystemFunction; - pbCode = EmitJump(pbCode, (PBYTE)hookCtx[i].pHookFunction); - } - - // update data members - hookCtx[i].pTrampoline->cbOverwrittenCode = hookCtx[i].dwInstructionLength; - hookCtx[i].pTrampoline->pSystemFunction = (PBYTE)hookCtx[i].pSystemFunction; - hookCtx[i].pTrampoline->pHookFunction = (PBYTE)hookCtx[i].pHookFunction; - - // update pointer here for ability to hook system functions follows - if (hookCtx[i].pTrampoline->pSystemFunction) - { - // this is what the application will use as the entry point - // to the "original" unhooked function. - *hooks[i].ppSystemFunction = hookCtx[i].pTrampoline->codeTrampoline; - } - - // flush instruction cache and restore original protection - FlushInstructionCache(currentProcessHandle, hookCtx[i].pTrampoline->codeTrampoline, hookCtx[i].dwInstructionLength); - VirtualProtect(hookCtx[i].pTrampoline, sizeof(MHOOKS_TRAMPOLINE), dwOldProtectTrampolineFunction, &dwOldProtectTrampolineFunction); - } - else - { - ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtect 2: %d", gle())); - } - - // flush instruction cache and restore original protection - FlushInstructionCache(currentProcessHandle, hookCtx[i].pSystemFunction, hookCtx[i].dwInstructionLength); - VirtualProtect(hookCtx[i].pSystemFunction, hookCtx[i].dwInstructionLength, dwOldProtectSystemFunction, &dwOldProtectSystemFunction); - } - else - { - ODPRINTF((L"mhooks: Mhook_SetHook: failed VirtualProtect 1: %d", gle())); - } - - if (hookCtx[i].pTrampoline->pSystemFunction) - { - hooksSet++; - // setting the entry point is moved upper for ability to hook some internal system functions - ODPRINTF((L"mhooks: Mhook_SetHook: Hooked the function!")); - } - else - { - // if we failed discard the trampoline (forcing VirtualFree) - TrampolineFree(hookCtx[i].pTrampoline, true); - hookCtx[i].pTrampoline = NULL; - } - } - } - - // resume threads - ResumeOtherThreads(); - - CloseProcessSnapshot(procEnumerationCtx); - } - - free(hookCtx); - - LeaveCritSec(); - - return hooksSet; -} - -//========================================================================= -BOOL Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction) -{ - HOOK_INFO hook = { ppSystemFunction, pHookFunction }; - return Mhook_SetHookEx(&hook, 1) == 1; -} - -//========================================================================= -int Mhook_UnhookEx(PVOID** hooks, int hookCount) -{ - ODPRINTF((L"mhooks: Mhook_UnhookEx: %d hooks to unhook", hookCount)); - int result = 0; - - HOOK_CONTEXT* hookCtx = (HOOK_CONTEXT*)malloc(hookCount * sizeof(HOOK_CONTEXT)); - if (hookCtx == NULL) - { - // return error status - ODPRINTF((L"mhooks: Mhook_UnhookEx: can't allocate buffer!")); - - return result; - } - - EnterCritSec(); - - for (int idx = 0; idx < hookCount; idx++) - { - hookCtx[idx].pSystemFunction = *hooks[idx]; - // get the trampoline structure that corresponds to our function - hookCtx[idx].pTrampoline = TrampolineGet((PBYTE)hookCtx[idx].pSystemFunction); - - if (!hookCtx[idx].pTrampoline) - { - continue; - } - - ODPRINTF((L"mhooks: Mhook_UnhookEx: found struct at %p", hookCtx[idx].pTrampoline)); - - hookCtx[idx].dwInstructionLength = hookCtx[idx].pTrampoline->cbOverwrittenCode; - } - - VOID* procEnumerationCtx = NULL; - PSYSTEM_PROCESS_INFORMATION procInfo = NULL; - - if (GetCurrentProcessSnapshot(&procEnumerationCtx, &procInfo)) - { - // make sure nobody's executing code where we're about to overwrite a few bytes - SuspendOtherThreads(hookCtx, hookCount, procInfo); - - for (int idx = 0; idx < hookCount; idx++) - { - if (!hookCtx[idx].pTrampoline) - { - continue; - } - - DWORD dwOldProtectSystemFunction = 0; - // make memory writable - if (VirtualProtect(hookCtx[idx].pTrampoline->pSystemFunction, hookCtx[idx].pTrampoline->cbOverwrittenCode, PAGE_EXECUTE_READWRITE, &dwOldProtectSystemFunction)) - { - ODPRINTF((L"mhooks: Mhook_UnhookEx: readwrite set on system function")); - PBYTE pbCode = (PBYTE)hookCtx[idx].pTrampoline->pSystemFunction; - for (DWORD i = 0; i < hookCtx[idx].pTrampoline->cbOverwrittenCode; i++) - { - pbCode[i] = hookCtx[idx].pTrampoline->codeUntouched[i]; - } - - // flush instruction cache and make memory unwritable - FlushInstructionCache(GetCurrentProcess(), hookCtx[idx].pTrampoline->pSystemFunction, hookCtx[idx].pTrampoline->cbOverwrittenCode); - VirtualProtect(hookCtx[idx].pTrampoline->pSystemFunction, hookCtx[idx].pTrampoline->cbOverwrittenCode, dwOldProtectSystemFunction, &dwOldProtectSystemFunction); - - // return the original function pointer - *hooks[idx] = hookCtx[idx].pTrampoline->pSystemFunction; - result += 1; - - ODPRINTF((L"mhooks: Mhook_UnhookEx: sysfunc: %p", *hooks[idx])); - - // free the trampoline while not really discarding it from memory - TrampolineFree(hookCtx[idx].pTrampoline, false); - ODPRINTF((L"mhooks: Mhook_UnhookEx: unhook successful")); - } - else - { - ODPRINTF((L"mhooks: Mhook_UnhookEx: failed VirtualProtect 1: %d", gle())); - } - } - - // make the other guys runnable - ResumeOtherThreads(); - - CloseProcessSnapshot(procEnumerationCtx); - } - - free(hookCtx); - - LeaveCritSec(); - - return result; -} - -//========================================================================= -BOOL Mhook_Unhook(PVOID *ppHookedFunction) -{ - return Mhook_UnhookEx(&ppHookedFunction, 1) == 1; -} diff --git a/src/mhook-lib/mhook.h b/src/mhook-lib/mhook.h deleted file mode 100644 index 83f4fe82..00000000 --- a/src/mhook-lib/mhook.h +++ /dev/null @@ -1,37 +0,0 @@ -//Copyright (c) 2007-2008, Marton Anka -// -//Permission is hereby granted, free of charge, to any person obtaining a -//copy of this software and associated documentation files (the "Software"), -//to deal in the Software without restriction, including without limitation -//the rights to use, copy, modify, merge, publish, distribute, sublicense, -//and/or sell copies of the Software, and to permit persons to whom the -//Software is furnished to do so, subject to the following conditions: -// -//The above copyright notice and this permission notice shall be included -//in all copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -//OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -//THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -//FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -//IN THE SOFTWARE. - -#ifdef _M_IX86 -#define _M_IX86_X64 -#elif defined _M_X64 -#define _M_IX86_X64 -#endif - -struct HOOK_INFO -{ - PVOID *ppSystemFunction; // pointer to pointer to function to be hooked - PVOID pHookFunction; // hook function -}; - -// returns number of successfully set hooks -int Mhook_SetHookEx(HOOK_INFO* hooks, int hookCount); -BOOL Mhook_SetHook(PVOID *ppSystemFunction, PVOID pHookFunction); -int Mhook_UnhookEx(PVOID** hooks, int hookCount); -BOOL Mhook_Unhook(PVOID *ppHookedFunction); diff --git a/src/packages.config b/src/packages.config new file mode 100644 index 00000000..31cfc2d6 --- /dev/null +++ b/src/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/pch.h b/src/pch.h new file mode 100644 index 00000000..c6503f01 --- /dev/null +++ b/src/pch.h @@ -0,0 +1,15 @@ +// pch.h: This is a precompiled header file. +// Files listed below are compiled only once, improving build performance for future builds. +// This also affects IntelliSense performance, including code completion and many code browsing features. +// However, files listed here are ALL re-compiled if any one of them is updated between builds. +// Do not add files here that you will be updating frequently as this negates the performance advantage. + +#ifndef PCH_H +#define PCH_H + +// add headers that you want to pre-compile here +#include "framework.h" +#include "Debug.h" +#include "Modify.h" + +#endif //PCH_H diff --git a/src/stdafx.cpp b/src/stdafx.cpp deleted file mode 100644 index 02481531..00000000 --- a/src/stdafx.cpp +++ /dev/null @@ -1,8 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// SpotifyAdBlock.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file diff --git a/src/stdafx.h b/src/stdafx.h deleted file mode 100644 index 80ffa19b..00000000 --- a/src/stdafx.h +++ /dev/null @@ -1,19 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#pragma once - -#include "targetver.h" -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files: -#include -#include - -// TODO: reference additional headers your program requires here -#include -#include -#include -#include -#include "mhook-lib/mhook.h" diff --git a/src/targetver.h b/src/targetver.h deleted file mode 100644 index 87c0086d..00000000 --- a/src/targetver.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -// Including SDKDDKVer.h defines the highest available Windows platform. - -// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and -// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. - -#include