distorm64-1.7.30/0000755000175000017500000000000011673765455012434 5ustar enderenderdistorm64-1.7.30/CHANGES0000644000175000017500000000776711064272722013430 0ustar enderenderCopyright (C) 2003-2007 Gil Dabah, http://ragestorm.net/distorm/ History: -+------ FPU(387) parsing added Feb 2004. Prefixes parsing added July 2004. SIB parsing added Dec 2004. Rep/lock/xlat explicit-operand forms added Dec 2004. Wrapped in Python Jan 2005. Using static instructions tables Jan 2005. MMX parsing added Feb 2005. SSE parsing added Feb 2005. SSE2 parsing added March 2005. SSE3 parsing added March 2005. Pseudo Opcodes parsing added March 2005. 3DNow! parsing added March 2005. Global Optimization April 2005. AMD64 added July 2005. Linux Port November 2005. Strings Optimization November 2005. New API December 2005. LGPL December 2005. Doc + Sources uploaded Januar 2006. 64bit Offsets are now supported January 2006. diStorm is now licensed under the BSD license January 2006. 1.2.8 diStorm can be compiled for Big Endian systems May 2006. 1.3.9: SSE4 (later known as SSSE3) parsing added May 2006. 1.3.9: VMX instructions set is now supported. 1.4.10: Instructions' flags were changed, engine supports instsruction set class type. May 2006. 1.4.10: All comments are now C style, source code is now 64bits compiler compatible. 1.5.10: Operand size of Memory Indirection is now determined inside operands.c and not instructions.c. May 2006. 1.5.15 SVM Instructions set is added Aug 2006. Python2.5 is compiled too. Sep 2006. 1.5.17 Formerly unofficial SSE4 is now officially called SSSE3. diStorm has a sample code for Ring0 using the DDK. Jan 2007. 1.6.18 Instructions table are now more optimized for size. Feb 2007. 1.6.21 Added a new Mac makefile to compile diStorm on a Mac. Apr 2007. 1.7.22 Real SSE4 parsing added April 2007. 1.7.26 New AMD instructions, support of different compilers. Fixed bugs: -+--------- 2/11/05 1.0.1 Call instruction wasn't promoted to 64 bits automatically. 16/11/05 1.0.2 Mov MOFF instruction used RAX in 32 bits, and wasnt dropped in 16 bits. 17/01/06 1.1.3 Some special instructions were ignoring the REX.B flag. 27/01/06 1.1.4 Support for 64bit offsets was added. 03/02/06 1.1.5 PUSH, JMP and CMP instructions were slightly fixed. 18/03/06 1.1.6 MOVZX/MOVSX and RETF operands' types were changed. 20/03/06 1.1.7 A bug treating mandatory prefixes in 64bits was fixed. 18/04/06 1.1.8 LOOPxx instructions are now categorized as Natives. 18/05/06 1.2.9 A few FPU instructions weren't set correctly in IGEN. 28/05/06 1.4.10 Push/Pop instructions with ModR/M fields are now fixed. 02/06/06 1.5.11 Fixed a new bug in operands.c, where OT_IMM_FULL was broken in 64bits. 03/06/06 1.5.12 Invalid memory access occurred in 64bit environments only is now fixed. 09/06/06 1.5.13 SGDT, SIDT, LGDT, LIDT, JMP FAR, CALL FAR, SMSW, LMSW, LDS, LES, LFS, LGS, LSS and other instructions which have special memory operands' types were fully corrected. And a bug in locate_raw_inst when using mingw environment. 01/07/06 1.5.14 REX prefix with BASE bit isn't dropped always, and string instructions are now promoted to 64bits only with REX prefix. 08/07/06 1.5.14 The sample projects of both Linux and Windows have been updated. 02/10/06 1.5.16 MOVSXD wasn't decoded properly and it now supports MOVZXD. 08/01/07 1.5.17 Removed redundant #include's to standard libraries. 11/02/07 1.5.18 Fixed a bug in OT_RM32_64 decoding. 28/02/07 1.6.19 All string/IO instructions support both REP and REPNZ. 03/03/07 1.6.20 3DNow! instructions weren't decoded (produced in 1.6.19). 17/04/07 1.6.21 MOV-Offset instructions weren't decoded correctly in 64bits. 23/04/07 1.6.22 The mnemonic of MOVD/MOVQ wasn't changed according to operand size. 12/05/07 1.7.23 Added the instructions MOVSLDUP and INVLPGA and fixed SVM instructions. 03/07/07 1.7.24 Added multi-byte NOP instruction. 19/07/07 1.7.25 Fixed a memory leak in Python extension module. 07/12/07 1.7.27 Fixed various instructions. 09/02/08 1.7.28 NOP and XCHG are treated correctly in 64bits. 07/03/08 1.7.29 LEA now ignores segment override prefixes. 17/09/08 1.7.30 DLL project added to the Win32 solution and fixed DDK compilation. distorm64-1.7.30/config.h0000644000175000017500000000736511064272252014043 0ustar enderender/* config.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #ifndef CONFIG_H #define CONFIG_H /* diStorm version number. */ #define DISTORM_VER 0x01071e #include /* strlen, memset, memcpy - can be easily self implemented for libc independency. */ /* * 64 bit offsets support: * This macro should be defined from compiler command line flags, e.g: -DSUPPORT_64BIT_OFFSET * #define SUPPORT_64BIT_OFFSET * Note: make sure that the caller (library user) defines it too! */ /* * If you compile diStorm as a .DLL file, make sure you uncomment the next line. * So the interface functions will be exported, otherwise they are useable only as a library. * For example, the Python extension module defines this macro in its configuration. */ /* #define _DLL */ /* * diStorm now supports little/big endian CPU's. * It should detect the endianness according to predefined macro's of the compiler. * If you don't use GCC/MSVC you will have to define it on your own. */ /* These macros are used in order to make the code portable. */ #ifdef __GNUC__ #include #define _PACKED_ __attribute__((__packed__)) #define _DLLEXPORT_ #define _FASTCALL_ #define _INLINE_ static __inline__ /* GCC ignores this directive... */ /*#define _FASTCALL_ __attribute__((__fastcall__)) */ /* Set endianity (supposed to be LE though): */ #ifdef __BIG_ENDIAN__ #define BE_SYSTEM #endif /* End of __GCC__ */ #elif __WATCOMC__ #include #define _PACKED_ #define _DLLEXPORT_ #define _FASTCALL_ #define _INLINE_ __inline /* End of __WATCOMC__ */ #elif __DMC__ #include #define _PACKED_ #define _DLLEXPORT_ #define _FASTCALL_ #define _INLINE_ static __inline /* End of __DMC__ */ #elif __TINYC__ #include #define _PACKED_ #define _DLLEXPORT_ #define _FASTCALL_ #define _INLINE_ static /* End of __TINYC__ */ #elif _MSC_VER /* Since MSVC isn't shipped with stdint.h, we will have our own: */ typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; typedef signed __int32 int32_t; typedef unsigned __int32 uint32_t; typedef signed __int16 int16_t; typedef unsigned __int16 uint16_t; typedef signed __int8 int8_t; typedef unsigned __int8 uint8_t; #define _PACKED_ #define _DLLEXPORT_ __declspec(dllexport) #define _FASTCALL_ __fastcall #define _INLINE_ static __inline /* Set endianity (supposed to be LE though): */ #ifndef _M_IX86 #define BE_SYSTEM #endif #endif /* #elif _MSC_VER */ /* 32 or 64 bits integer for instruction offset. */ #ifdef SUPPORT_64BIT_OFFSET #define OFFSET_INTEGER uint64_t #else #define OFFSET_INTEGER uint32_t #endif #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif /* If the library isn't compiled as a .DLL don't export functions. */ #ifndef _DLL #undef _DLLEXPORT_ #define _DLLEXPORT_ #endif /* Define stream read functions for big endian systems. */ #ifdef BE_SYSTEM /* * These functions can read from the stream safely! * Swap endianity of input to little endian. */ _INLINE_ int16_t RSHORT(const uint8_t *s) { return s[0] | (s[1] << 8); } _INLINE_ uint16_t RUSHORT(const uint8_t *s) { return s[0] | (s[1] << 8); } _INLINE_ int32_t RLONG(const uint8_t *s) { return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); } _INLINE_ uint32_t RULONG(const uint8_t *s) { return s[0] | (s[1] << 8) | (s[2] << 16) | (s[3] << 24); } #else /* Little endian macro's will just make the cast. */ #define RSHORT(x) *(int16_t *)x #define RUSHORT(x) *(uint16_t *)x #define RLONG(x) *(int32_t *)x #define RULONG(x) *(uint32_t *)x #endif #endif /* CONFIG_H */ distorm64-1.7.30/COPYING0000644000175000017500000000303310753530262013446 0ustar enderender:[diStorm64}: The ultimate disassembler library. Copyright (c) 2003,2004,2005,2006,2007,2008, Gil Dabah All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the diStorm nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. distorm64-1.7.30/ddkproj/0000755000175000017500000000000011065513456014054 5ustar enderenderdistorm64-1.7.30/ddkproj/distorm.ini0000644000175000017500000000060510554325354016237 0ustar enderender\registry\machine\system\currentcontrolset\services\distorm ImagePath = system32\drivers\distorm.sys DisplayName = "distorm" Type = REG_DWORD 0x1 Start = REG_DWORD 0x3 Group = Extended base ErrorControl = REG_DWORD 0x1 \registry\machine\system\currentcontrolset\services\distorm\Parameters BreakOnEntry = REG_DWORD 0x0 DebugMask = REG_DWORD 0x0 LogEvents = REG_DWORD 0x0distorm64-1.7.30/ddkproj/dummy.c0000644000175000017500000000053211063061522015341 0ustar enderender// Since the DDK's nmake is limited with directories, we will bypass that with this simple hack. // Thanks to Razvan Hobeanu. // Sep 2009. #include "x86defs.c" #include "wstring.c" #include "textdefs.c" #include "prefix.c" #include "operands.c" #include "insts.c" #include "instructions.c" #include "distorm.c" #include "decoder.c" distorm64-1.7.30/ddkproj/main.c0000644000175000017500000000543111063015622015135 0ustar enderender/* * main.c * Sample kernel driver to show how diStorm can be easily compiled and used in Ring 0. * * /// Follow the README file in order to compile diStorm using the DDK. \\\ * * Izik, Gil Dabah * Jan 2007 * http://ragestorm.net/distorm/ */ #include #include "../distorm.h" // The number of the array of instructions the decoder function will use to return the disassembled instructions. // Play with this value for performance... #define MAX_INSTRUCTIONS (15) void DriverUnload(IN PDRIVER_OBJECT DriverObject) { } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { UNICODE_STRING pFcnName; // Holds the result of the decoding. _DecodeResult res; // Decoded instruction information. _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; // next is used for instruction's offset synchronization. // decodedInstructionsCount holds the count of filled instructions' array by the decoder. unsigned int decodedInstructionsCount = 0, i, next; // Default decoding mode is 32 bits, could be set by command line. _DecodeType dt = Decode32Bits; // Default offset for buffer is 0, could be set in command line. _OffsetType offset = 0; char* errch = NULL; // Buffer to disassemble. unsigned char *buf; int len = 100; // Register unload routine DriverObject->DriverUnload = DriverUnload; DbgPrint("diStorm Loaded!\n"); // Get address of KeBugCheck RtlInitUnicodeString(&pFcnName, L"KeBugCheck"); buf = (char *)MmGetSystemRoutineAddress(&pFcnName); offset = (unsigned) (_OffsetType)buf; DbgPrint("Resolving KeBugCheck @ 0x%08x\n", buf); // Decode the buffer at given offset (virtual address). while (1) { res = distorm_decode(offset, (const unsigned char*)buf, len, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); if (res == DECRES_INPUTERR) { DbgPrint(("NULL Buffer?!\n")); break; } for (i = 0; i < decodedInstructionsCount; i++) { // Note that we print the offset as a 64 bits variable!!! // It might be that you'll have to change it to %08X... DbgPrint("%08I64x (%02d) %s %s %s\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, (char*)decodedInstructions[i].operands.p); } if (res == DECRES_SUCCESS || decodedInstructionsCount == 0) { break; // All instructions were decoded. } // Synchronize: next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset); next += decodedInstructions[decodedInstructionsCount-1].size; // Advance ptr and recalc offset. buf += next; len -= next; offset += next; } DbgPrint(("Done!\n")); return STATUS_SUCCESS; } distorm64-1.7.30/ddkproj/makefile0000644000175000017500000000004210547606502015547 0ustar enderender!INCLUDE $(NTMAKEENV)\makefile.defdistorm64-1.7.30/ddkproj/README0000644000175000017500000000442311063061742014731 0ustar enderenderdiStorm64 for Ring 0 Gil Dabah Jan 2007 http://ragestorm.net/distorm/ Tested sample with DDK 3790.1830 using WinXPSP2. Steps of how to build the diStorm64 sample using the DDK. Warning - Make sure the path you extracted diStorm to does not include any spaces, otherwise you will get an error from the build. 1) Open the DDK's build environment, for example: "Win XP Free Build Environment", which readies the evnrionment variables for building a driver. 2) Launch "build". 3) If everything worked smoothly, you should see a new file named "distorm.sys" under objfre_wxp_x86\i386 (that's if you use WinXP and the Free Environment). - If you experienced any errors, try moving the whole distorm directory to c:\winddk\src\ (or any other directory tree which doesn't contain spaces in its name). 4) Now you will have to register the new driver: a. Copy the distorm.sys file to \windows\system32\drivers\. b. Use the DDK's regini.exe with the supplied distorm.ini. c. Restart Windows for the effect to take place. :( (this can be bypassed, if you register the driver directly in the SCM, there are other tools which do so). 5) Now open your favorite debug-strings monitor (mine is DebugView). Make sure you monitor kernel debug-strings. 6) Launching "net start distorm" from command line, will run the DriverEntry code in "main.c", which will disassemble a few instructions from the KeBugcheck routine and dump it using DbgPrint. 7) Later launch "net stop distorm" from command line to stop the test driver. NOTES: -+---- The sample uses the stack for storing the results from the decode function. If you have too many structures on the stack, you better allocate memory before calling the decode function, and later on free that memory. Don't use the NONPAGED pool if you don't really need it. _OffsetType is the type of the DecodedInstruction.Offset field, which defaults to 64bits, so make sure that when you print this variable you use %I64X, or when you use it anywhere else, you use the _OffsetType as well. If you want to change the _OffsetType into 32 bits, edit the "disconfig.h" file. diStorm can be really compiled for all IRQL, it doesn't use any resource or the standard C library at all. Although the sample uses diStorm at PASSIVE level. distorm64-1.7.30/ddkproj/sources0000644000175000017500000000031511063061512015446 0ustar enderenderTARGETNAME = distorm TARGETPATH = obj TARGETTYPE = DRIVER C_DEFINES = $(C_DEFINES) -DSUPPORT_64BIT_OFFSET INCLUDES = %BUILD%\inc;..\src; LIBS = %BUILD%\lib SOURCES = main.c dummy.c distorm64-1.7.30/distorm.h0000644000175000017500000001120411064272114014237 0ustar enderender/* diStorm64 1.7.30 */ /* distorm.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. This file is used in win32proj and linuxproj. */ #ifndef DISTORM_H #define DISTORM_H /* * 64 bit offsets support: * If the diStorm library you use was compiled with 64 bits offsets, * make sure you compile your own code with the following macro set: * SUPPORT_64BIT_OFFSET * Otherwise comment it out, or you will get a linker error of an unresolved symbol... */ /* TINYC has a problem with some 64bits library functions, so pass. */ #ifndef __TINYC__ /* Make sure it wasn't already defined by the compiler itself. */ #ifndef SUPPORT_64BIT_OFFSET #define SUPPORT_64BIT_OFFSET #endif #endif /* If your compiler doesn't support stdint.h, define your own 64 bits type. */ #ifdef SUPPORT_64BIT_OFFSET #ifdef _MSC_VER #define OFFSET_INTEGER unsigned __int64 #else #include #define OFFSET_INTEGER uint64_t #endif #else /* 32 bit offsets are used. */ #define OFFSET_INTEGER unsigned long #endif /* Support C++ compilers */ #ifdef __cplusplus extern "C" { #endif /* Decodes modes of the disassembler, 16 bits or 32 bits or 64 bits for AMD64, x86-64. */ typedef enum {Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2} _DecodeType; typedef OFFSET_INTEGER _OffsetType; /* Static size of strings. Do not change this value. */ #define MAX_TEXT_SIZE (60) typedef struct { unsigned int length; unsigned char p[MAX_TEXT_SIZE]; /* p is a null terminated string. */ } _WString; /* This structure holds all information the disassembler generates per instruction. */ typedef struct { _WString mnemonic; /* Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc. */ _WString operands; /* Operands of the decoded instruction, up to 3 operands, comma-seperated. */ _WString instructionHex; /* Hex dump - little endian, including prefixes. */ unsigned int size; /* Size of decoded instruction. */ _OffsetType offset; /* Start offset of the decoded instruction. */ } _DecodedInst; /* Return code of the decoding function. */ typedef enum {DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR} _DecodeResult; /* distorm_decode * Input: * offset - Origin of the given code (virtual address that is), NOT an offset in code. * code - Pointer to the code buffer to be disassembled. * length - Amount of bytes that should be decoded from the code buffer. * dt - Decoding mode, 16 bits (Decode16Bits), 32 bits (Decode32Bits) or AMD64 (Decode64Bits). * result - Array of type _DecodeInst which will be used by this function in order to return the disassembled instructions. * maxInstructions - The maximum number of entries in the result array that you pass to this function, so it won't exceed its bound. * usedInstructionsCount - Number of the instruction that successfully were disassembled and written to the result array. * Output: usedInstructionsCount will hold the number of entries used in the result array * and the result array itself will be filled with the disassembled instructions. * Return: DECRES_SUCCESS on success (no more to disassemble), DECRES_INPUTERR on input error (null code buffer, invalid decoding mode, etc...), * DECRES_MEMORYERR when there are not enough entries to use in the result array, BUT YOU STILL have to check for usedInstructionsCount! * Side-Effects: Even if the return code is DECRES_MEMORYERR, there might STILL be data in the * array you passed, this function will try to use as much entries as possible! * Notes: 1)The minimal size of maxInstructions is 15. * 2)You will have to synchronize the offset,code and length by yourself if you pass code fragments and not a complete code block! */ #ifdef SUPPORT_64BIT_OFFSET _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); #define distorm_decode distorm_decode64 #else _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount); #define distorm_decode distorm_decode32 #endif /* * distorm_version * Input: * none * * Output: unsigned int - version of compiler library. */ unsigned int distorm_version(); #ifdef __cplusplus } /* End Of Extern */ #endif #endif /* DISTORM_H */ distorm64-1.7.30/doc/0000755000175000017500000000000011065513456013164 5ustar enderenderdistorm64-1.7.30/doc/distorm.html0000644000175000017500000007155610433602652015544 0ustar enderender

/------------\
|Introduction|
\------------/
When I started this project, I told myself one thing
"How cool it would be to disassemble 80x86 instructions".
I started with disassmbling only integer instructions.
And soon enough later, I said to myself, "Woah, FPU is no less cool",
and FPU instructions were supported afterwards.
Then I got to a point where I said to myself, "You can't quit after this, it's getting hot in here",
and instruction prefixes and all other instruction sets were supported.
Eventually, not so long back ago, I had a serious piece of code, which was called a disassembler,
and I was thinking, "Hey, AMD64 is out, let's do it".
And here I am, one thought brought diStorm.
Today, I look forward into code analysis tools.
Guess my tomb stone would say "An assembly freak".

Of course, there are many disassemblers out there,
it's like there are much fish in the ocean, but not all of them are gold fish. :)
(warning- this applies on girls too, "Does she know 80x86? OMG" - J/K! honestly).
If you want to get convinced about why diStorm is a handy tool, read the next 'goals' part.

Anyways, I am a big fan of documentation, and that's why I wrote this whole document.
This document actually contains two parts:
80x86 instruction sets and major topics about diStorm.
I think that the first part is really interesting if you wish to learn about 80x86 bits and its low level
and therefore it was partly written as a tutorial, though for learning much more, you better read it all.

This document assumes you know something about programming and familiar with the 80x86 family and opcodes.
So some knowledge is required, but no worry, stay with me.

Before you keep on reading, I just wanted to write a few things about this all project.
diStorm was fully written from scratch, using the Intel and AMD documents.
To be honest, the AMD documents are much better, you should rely on them and use them more, and especially for AMD64.
In the first part of this tutorial I don't claim to be better than the documents,
I try to shed some light and how I interpret stuff. I thought it might be useful and helpful for beginners
and advanced assembly coders. I don't cover everything but very much of the important information you should
know about 80x86. I may have inaccuracies and mistakes, this applies to the second part as well,
so if you doubt anything, or just know that I am wrong, please let me know!

I tried to seperate the topics as much as possible, but because everything is related to each other,
it might be a little messy, so I guess sometimes you will have to keep on reading untill something will
get more clear later. As I stated earlier, even if I wanted, I couldn't cover here everything,
so if you are not sure about anything or wish to see how it was implemented, simply have a glance in the source code.

I really believe in documentation, that's why I put my efforts on it, instead of rushing and releasing the source code.
And I believe a good documentation is supposed to be used as a reference for upcoming changes or just for inspections.
In the hope this document will help people write their own disassembler and give them basics and ideas and of course,
learn about diStorm's internals, I found it an important task.

By this document I wish to contribute to the community,
if you are like me, please contact me for errors I have in this document or bugs I have in the source code,
so people could enjoy a better product!

BTW - I know the DOS style is kinda old and ugly,
but it's for keeping matters simple and maybe having a good nostalgia.

"A true (dis/)assembly guru respectes Debug.", me


Table of contents:
-+----------------
80x86 Machine Code
diStorm Internals

The rest of this file is general information about diStorm (API, Compilation, FAQ, etc...)

/-----\
|Goals|
\-----/
I had a few goals in mind while I was writing diStorm.
I wanted diStorm to be the best 80x86 disassembler out there, not less, not more.
diStorm became a product which stands a commercial standard.
This is the small list of goals I wanted to achieve, and managed to.
The major characteristics of diStorm are:
diStorm is really fast.
diStorm supports multi-threading.
diStorm supports AMD64, and all other 80x86 instruction sets.
diStorm supports up to date instruction sets, such as VMX and SSE4.
diStorm handles instruction prefixes in a serious manner.

diStorm is for free, as in open source, under the BSD license.
diStorm is easy to use, wrapped in Python too.
diStorm is portable.
diStorm is platform-independent.
diStorm is in a mature product status and bugfree.

I hope it will help the community and some people out there on our planet. Cheers.

/-----------\
|Added Value|
\-----------/
I decided it's important you will know what is so special about diStorm.
By now, if you followed the documentation you should know everything I'm talking about.
In addition to the most valued 'capabilities' (BSD License and AMD64 disassembler), there are a few low-level features that diStorm supports:

* Unused/extra prefixes are dropped (output as DB'ed).
* Lock prefix works only on lockable instructions if the first operand is in the form of memory indirection.
* REPn/z prefix works only on repeatable string instructions as well as I/O instructions.
* Segment Override prefixes are possible where memory indirection address is being used (and specially treated with string and I/O instructions).
* Some SSE2 instructions support pseudo opcodes (CMP family).
* "Native" instructions, those which have the same mnemonic in different decoding modes, unless there's an operand size prefix,
  which then a suffix letter is concatenated to the mnemonic in order to indicate the operation size (instructions like: PUSHA, IRET, etc.).
* XLAT instruction is treated specially when prefixed.
* Drops invalid instructions when their operands are invalid.
* Won't decode instructions which are longer than 15 bytes.
* CR8 register is now accessible using the Lock prefix in 32 bits decoding mode.
* In 64 bits decoding mode the Segment Override prefixes CS, DS, ES and SS are ignored.

I think that the above bullets were self explanatory.
It's time to focus on a few bullets here, that I haven't explained about before.

* Waitable instructions are supported (FINIT etc.) -
The FPU wait instruction is kinda tricky,
it can lead to a 3 bytes long instructions.
But as you all know, if the last byte of the 3 bytes opcode doesn't lead to the instruction so the whole instruction is dropped.
When that byte is the wait instruction, it is not dropped and specially output as a normal instruction.
According to the specs, the wait instruction can precede a limited set of instructions, if the instruction it precedes isn't out of those,
then the wait instruction should still be treated as a valid wait instruction.

* Some instructions which have two mnemonics according to the decoding modes are supported - 
Maybe you just read this and you say WTF is he talking about? then I will simply tell you, CWD, CDQ, etc...
Remember that when CWD is operand size prefixed (in 16 bits) then it becomes CDQ.
Or when you are in 32 bits there is CDQ from the beginning and only when it's operand size prefix it becomes CWD.
Then I am talking about these type instruction of instruction, which, by the way, support a third mnemonic for 64 bits...

* Truncates instructions when reaches end of stream -
This is another irritating subject we could argue about. And not because I want to start a flame war.
Some people would prefer to see at least the mnemonic of the instruction output instead of dropping the instruction.
This is only when you have enough info on the instruction that you can get its mnemonic, sometimes you don't even have that.
I decided that diStorm will drop the whole instruction and skip the first byte of that instruction, because in reality,
code sections aren't limited in size and can't just be ended.
Oh and give me a break about 'what if' questions (such as: if it were the end of the segment blah blah)...


/------------------\
|Library Interfaces|
\------------------/
As you already know diStorm supports two interfaces.
diStorm was originally written in C and later on was compiled as a module extension for Python.
I thought that most of the users would appreciate the Python version, but I was surprised to learn that
the C version got more downloads. As I see it, the Python version is there only for doing research
and other small tools. If I were to write a tool which uses diStorm I would use the C library, that's for speed only.

Both interfaces are implemented using the same function, internal_decode.
This was in order to avoid writing some code twice.

The first releases of diStorm came with the deprecated linked list mechanism for returning the results.
I think the linked list method was easier to use than the current interface, but when I optimized the code,
I understood that it is harder to use (side-effects, etc) and it is much slower!
That is the reason why I decided the user will pass an allocated in advance array of instructions
which will be filled by the disassembler, this way, the user doesn't have to make extra memcpy's from the linked list to his own
data structures, and pass right away an array of instructions, which is the most basic form of a disassembled instruction the
disassembler returns. Once that buffer is filled with data the user can do anything with it, unlike what used to be with the
linked list method.

C Library:
// Decodes modes of the disassembler, 16 bits or 32 bits or 64 bits for AMD64, x86-64.
typedef enum {Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2} _DecodeType;

// Static size of strings. Do not change this value.
#define MAX_TEXT_SIZE (60)
typedef struct {
	unsigned int length;
	unsigned char p[MAX_TEXT_SIZE]; // p is a null terminated string.
} _WString;

// This structure holds all information the disassembler generates per instruction.
typedef struct {
	_WString mnemonic; // Mnemonic of decoded instruction, prefixed if required by REP, LOCK etc.
	_WString operands; // Operands of the decoded instruction, up to 3 operands, comma-seperated.
	_WString instructionHex; // Hex dump - little endian, including prefixes.
	unsigned int size; // Size of decoded instruction.
	unsigned long offset; // Start offset of the decoded instruction.
} _DecodedInst;

// Return code of the decoding function.
typedef enum {DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR} _DecodeResult;

// distorm_decode //////////////////
// Input:
//         offset - Origin of the given code (virtual address that is), NOT an offset in code.
//         code - Pointer to the code buffer to be disassembled.
//         length - Amount of bytes that should be decoded from the code buffer.
//         dt - Decoding mode, 16 bits (Decode16Bits), 32 bits (Decode32Bits) or AMD64 (Decode64Bits).
//         result - Array of type _DecodeInst which will be used by this function in order to return the disassembled instructions.
//         maxInstructions - The maximum number of entries in the result array that you pass to this function, so it won't exceed its bound.
//         usedInstructionsCount - Number of the instruction that successfully were disassembled and written to the result array.
// Output: usedInstructionsCount will hold the number of entries used in the result array
//         and the result array itself will be filled with the disassembled instructions.
// Return: DECRES_SUCCESS on success (no more to disassemble), DECRES_INPUTERR on input error (null code buffer, invalid decoding mode, etc...),
//         DECRES_MEMORYERR when there are not enough entries to use in the result array, BUT YOU STILL have to check for usedInstructionsCount!
// Side-Effects: Even if the return code is DECRES_MEMORYERR, there might STILL be data in the
//               array you passed, this function will try to use as much entries as possible!
// Notes:  1)The minimal size of maxInstructions is 15.
//         2)You will have to synchronize the offset,code and length by yourself if you pass code fragments and not a complete code block!
///////////////////////////////////
_DecodeResult distorm_decode(unsigned long codeOffset, const unsigned char* code, long codeLen, _DecodeType dt,
                             _DecodedInst result[], unsigned long maxInstructions, unsigned long* usedInstructionsCount);

Python:
list Decode(long offset, string code, int mode)
Input:
offset - Offset of the code in memory(as of origin, virtual address)
code -   Buffer of the binary code
mode -      Decode16Bits - 80286 decoding
            Decode32Bits - IA-32 decoding
            Decode64Bits - AMD64 decoding
Return:
list - List of tuples with the disassembled instructions,
       each tuple consists of offset, size, mnemonic and hex strings per instruction

The main difference between the two interfaces is that the Python interface returns a complete textual instruction wheareas
the C library interface returns a mnemonic and an operands strings seperated.

Many people confuse with the 'offset' paramater. It is NOT the offset of where to start disassembling in the code block.
On the contrary it is the offset of the code in memory, that is the origin (ORG) command you tell the assembler above your actual code.
The same is here, you have to tell the disassembler where the code is found in memory, so all the addresses and relative
offsets will be calculated well.

One more thing about the C library interface, the reason the minimum size of array is 15 instructions, is because the way
diStorm disassembles code. More specifically, because of the way prefixes are decoded, it is possible to drop 15 prefixes at once.
That is because the maximum instruction size of an instruction is 15 bytes, now imagine to yourself that all 15 bytes are prefixes,
so they are supposed to be dropped according to how diStorm works. Now you are left with 15 instructions to fill in the result array.
If you allowed less than 15 instructions then it comes out that you are having two problems,
you have to decode some of the code twice or so (that's least problematic).
And it may happen that because you returned only part of the result (filled the whole result array already), you will start disassembling again,
from the next byte, but this time, you lost synchornization with the offset of that instruction, because you already returned some of its prefixes.
Now how do you know which prefix doesn't influence the instruction, because you still didn't disassemble the instruction itself.
So, to make it easier for all of us and prevent such extreme cases, I only ask for 15 instructions at least, which isn't much at all anyways.

/-------------\
|Licensing-BSD|
\-------------/
diStorm originally was released under the LGPL license.
After a while, listening to advice of a friend, I decided to change the license to BSD.
Looking at other disassemblers, most of them are GPL'ed, yet another GPL'ed disassembler isn't much of a help.
That is for a few reasons to say aloud:
I want the disassembler to be widely spread and used.
I wanted to contribute to the (both developers and reversers) community.
I want the community to contribute back by releasing patches/bug fixes or upgrades with source code.
I think that this community has much more to progress and get better, so this is my share.
I honestly believe that diStorm is far better than other disassemblers and can be used commercially.

I realized that the licensing isn't a matter for people,
if they won't want to publish their modification they won't do so no matter what.
That reason and the understanding that disassemblers aren't hot products,
after all, caused me to change the license to a more permissive one.
Anyways, the license is not going to hold people from releasing patches/modificiations.
I think I only deserve credit where due, so BSD it is.
I believe in 'open source'.
Eventually,
YOU can have diStorm for FREE, as in freedom!

/---------------\
|Modules Listing|
\---------------/
The brief of each module in the source code:

distorm - Where the API for C is implemented.
pydistorm - Where the API for Python is implemented.
decoder - The core of the disassembler, the engine which disassembles binary streams.
prefix - Responsible for the prefixes decoding algorithm.
instructions - Functionality to get an opcode from a binary stream.
insts - Defines the 80x86 instruction set talbes.
operands - Disassembling the operand types of a given instruction.

x86defs - All information regarding the 80x86 processor, registers, specific parameters and more.
textdefs - Optimized string conversions, numbers to (hex) strings.
wstring - Pascal style strings, to boost up performance when we know the strings' lengths in advance.

config.h - For porting, used in order to define compiler-specific macros, cross platform - endianity swapping, etc...
disconfig.h - Disassembler configuration parameters (64 bits offset support).

/-------\
|Porting|
\-------/
diStorm was originally written for Windows.
I wrote it in pure C, so it would compile on any platform, even embedded processors...
diStorm is also ported to Linux and available for download.

diStorm can be easily ported to other operating systems.
There is no code to touch at all, all you have to do is taking a look at the config.h file.
It defines a few compiler-specific macros, where compilers differ in their behavior.
After setting your compiler in config.h you are set to go.
That's it.

/--------------------\
|Platform-Independent|
\--------------------/
diStorm supports both little and big endian systems.
This means that you can run diStorm on big endian systems which
will decode 80x86's little endian binary stream and the output will be correct.
It was tested on PowerPC as well as on 80x86, of course.
In the config.h file, you will find a macro called BE_SYSTEM,
this macro should be set automatically when the compiler indicates that it's a big endian system,
otherwise it should be commented out. If the endianity 'auto-detection' won't work, simply define it manually.

/-----------\
|Compilation|
\-----------/
diStorm was originally written in C under Visual Studio 2003.
The solution file is bundled in the downloads.
There is no reason that diStorm couldn't be compiled under VC6 as well as VS03.
There is one solution and 2 projects: cdistorm and pydistorm.
In order to distinguish between C library compilation and Python compilation I seperated the projects to clib and py24/py23.
If you wish to compile for clib choose this solution configuration and vice versa for Python.

The different between the clib and Python compilations are minor,
for clib there is cdistorm.c which has the exported functions.
and for Python there are the pydistorm.c and pydistorm.h for the module extension functions.
Each configuration solution will use what files required to build its project, respectively.

The C library interface has only one function exported, that is distorm_decode.
The Python module extension interface requires you to export one function also,
but that function must be named init, therefore it's called initdistorm.
That initdistorm function initializes the distorm module in python and attaches the methods table to the module.
It also defines the distorm.info variable which holds version info of the latest build.
Eventually, the Python interface has only one vital function, distorm.Decode which does the work.
This function has to be Python-interface compliant, if you are not familiar with Embedded Python and how it works,
you can have a look at a tutorial I wrote back ago, here.
If you want to add more functions to the Python extension module, all you have to do is inserting an entry in
distormModulebMethods, defined in pydistorm.h.

Notes:
1)Maybe the Python compilation for Linux needs the '#include' directory changed in pydistorm.h.
2)Python compilation cannot be in Debug mode, because the Python project doesn't let you download a debug version of the python.lib.
but you can compile it on your own.
3)If you wish to debug the code in Debug mode using the C library interface, change that solution configuration to insert debugging info
(and remove optimizations).
4)When compiling the Python extension module in VS, you have a resource file defined in order to set the DLL file version info.

After compiling diStorm for Python, you have to copy the file into the Python\Lib\site-packages directory.
In fact, as long as the file is under the Python directory, Python is supposed to find it.
I would like to suggest you a tip, setting the command argument to a local Python script and the output directory of the .DLL to Python's,
lets you actually 'run' diStorm easily.

If you wish to use diStorm as in the C library interface you will have to use the distorm.h file,
but from the sample directory! This distorm.h file defines the distorm_decode's interface, you better follow the sample code.

-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~

Under Linux things get a little bit more complicated, but that's because there are several ways you can compile the library into.
The Linux version of diStorm comes with makefiles which will do the nasty job for you.
The makefile on default will compile diStorm both for C and Python.
If you wish to compile only the C library, simply use 'makefile clib',
and if you wish to compile the Python interface, use 'makefile py'.

As I mentioned before in the Porting part, the config.h as a big role in compiling diStorm for Linux,
although I already set some macros, maybe you will want to change something.

The Python module extension has to be compiled into a .SO (shared object) file and later installed using ldconfig.
There is an install script (instpython.sh) bundled with Linux build.

The C library for Python can be compiled in two ways,
a .SO as well as the Python project and a static library.
I prefer the static library to the shared object way, because you won't have to bundle that .SO with your project and install that file as well.
The problem with installing a shared object is that you have to be root, I guess that not all Linux users have root.
That's a real hit for the Python .SO too. The disasm project only shows how to use the static library way of diStorm.
In fact, when diStorm is compiled for C library, it creates both the .SO and the static library.
So you can change the makefile of the disasm project to use the .SO.

/------------\
|Benchmarking|
\------------/
As one of my goals in writing diStorm was speed, I wanted diStorm to disassemble instructions really quick.
In the beginning I wrote diStorm with no optimization at all, just wanted to see that it operates well.
After that I had a few optimization-sessions and got an immense boost in performance.
At last, on my lazy CPU, Athlon 1600xp+, diStorm disassembled (without output - printing to console)
a randomly generated chunk of 50 megs at (approximately) 10 secs. It makes a ratio of 5 megs to 1 secs on my CPU!

The first interface, using a linked list to return the disassembled instruction was really terrible.
I couldn't stand that slowness, that's why I came up with the amiable new interface, which is much more faster as well.

I benchmarked diStorm a few times against other public known disassemblers as well, so I would have some proportions
how fast diStorm operates.

The benchmarking was done in the following way:
Loading a randomly generated chunk of 50 megs into memory (one malloc, one ReadFile),
then using those disassemblers' interfaces I disassembled the whole 50 megs chunk.
I formatted each result into text in the form of: hex dump, instruction.
And pritned that string to stdout. Then using the OS pipe mechanism I directed the output to a file.
I started timing the operation immediately after loading the whole chunk into memory (before the first instruction was disassembled).
And stopped timing just after the last instruction was disassembled.

The results were pretty good (for diStorm, to put it right):
diStorm: 90 seconds.
disassembler #2: 129 seconds.
disassembler #3: 147 seconds.

I wish to not expose the names of the other disassemblers, but trust me you know them for sure.

The benchmarking was done quiet objectively, I know I can't really say that, because I did the bencharmking by myself, but stil...
The generated size of the file was around 1.1 GB!
Note that I didn't get down to a resolution of the length of the string of each disassembled instruction in every disassembler.
I merely wanted to have a gruff results, so the length couldn't make much a difference with the above timings.
And besides I assure you that the advantage of string's length per instruction wasn't to diStorm at all.

Anyways, I used one more tool to benchmark the performance of the code itself in function resolution using Linux's grpof.
I compiled the code with debug information and saw where the bottlenecks were and tried to eliminate them...

/-----\
|F.A.Q|
\-----/
I tried to answer a few questions that might come up:

Q.I want to use diStorm comercially
A.
To be honest, diStorm was first released under the LGP license, but now,
diStorm is licensed under the BSD license. It shouldn't stop you from using it comercially at all.
If you wish to have a proprietary license, please contact me.

Q.I have improvements to apply, will you accept them?
A.
If your improvements are useful and I find them appropriate to be included in diStorm, I will certainly apply them.

Q.I want to help you writing some code and tools, what now?
A.
If this is true, there is much more work to be done, please contact me.

Q.I have new ideas for diStorm and similar tools, do you want to help me writing them?
A.
Well, I would like to hear you ideas, but I don't promise I will help in coding them, in fact,
I have a sequential project to diStorm.

Q.What about tools for parsing PE, ELF, and a GUI?
A.
Because I am a Windows man after all, I will use or implement my own PE library.
As for ELF, I am not much interested in writing that too, so you are most welcome to help with this,
maybe in the far future the diStorm team will write that also.

I think that GUI is necessary for diStorm, but it's too early now, there are many GUIed disassemblers out there,
when diStorm will have some more features to offer (code analysis, ahm ahm), a GUI will be written.

Q.I need AT&T syntax, are you going to do that?
A.
The answer is easy, unforetunately, no.
I wish diStorm would support the AT&T syntax, but I don't have time for that as for now.

Q.diStorm doesn't disassemble prefixes as the processor does, are you going to change it?
A.
The current way diStorm analysis prefixes is fine with me so I don't see any reason to change it.
But if you still insist that it could be better treated,
please let me know how and I will probably change it if it makes more sense.

Q.What about code analysis?
A.
It is the future, not only for diStorm, but for all tools out there.
This is my next goal, 'coming soon'.

Q.Did you write it all alone?
A.
diStorm itself was 100% written by me from scratch.
Though, the sample project was sent to me by Stefan (who doesn't wish his email appears here) and I did a few touches.
I also got some help in porting diStorm to Linux, since I am not a Linux dude, Thanks to Izik for help in the 'build environment'.

Q.What do you plan for diStorm in the future?
A.
I already told you, code analysis.
Soon I am going to start working on diStorm3.
It is a big twist in the plot now, diStorm3 will create expression tree out of a disassembled instruction, no more text.
With expression trees you possess the power to do everything...code flow graphs, data flow anaylsis, etc...

Q.What is that diStorm team you mentioned earlier?
A.
After finished diStorm2, I found two serious partners who will write with me code analysis tools.
The work will be divided among us, and hopefully, we will have more products out there.

Q.You keep on mentioning code analysis tools, are they going to be open source?
A.
To be honest, some of them are going to be developed under Python, so I will plainly upload the scripts.
And the others are going to be written in a new framework using C++, which for the development phase will be closed source.
After that, maybe we will open the source for the public, I don't know yet.

/-------------\
|Closing Words|
\-------------/
3 years, was fun, I just begin.
diStorm3, anyone?

Je Je

Don't hesitate to write me regarding ANYthing, arkon@ragestorm.net.
Visit diStorm website for updates.

diStorm is copyrighted by Gil Dabah, 2006, http://ragestorm.net
distorm64-1.7.30/doc/qa.txt0000644000175000017500000002247610570250206014330 0ustar enderender/* qa.txt Copyright (C) 2003-2007 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ Beating the decoder?! or trying so :) This is for testing the disassembler with extreme cases of special manually crafted instructions and streams. Integer opcodes: -+-------------- 37 f1 80 17 80 ff 3f 0f 0b 0f d0 0f ba e0 05 0f c7 18 05 c3 one byte opcode: 37 (AAA) invalid one byte opcode: f0 one byte + reg bits opcode: 80 17 80 (ADC byte [BX], 0x80) invalid one byte + reg bits opcode: ff 3f (supposed to be CALL NEAR) two byte opcode: 0F 0B (UD2) invalid two byte opcode: 0f d0 two byte + reg bits opcode: 0F BA E0 05 (BT AX, 5) invalid two byte + reg bits opcode: 0f c7 18 (supposed to be CMPXCHG8B) not-enough bytes opcode (end of data): 05 C3 (ADD AX, ) --> DB 0x05;RET force general-purpose-register mod/rm when memory mode is a must: 0F 01 17 (LGDT [BX])--> 0F 01 c7 FPU opcodes: -+---------- escaped under C0: d8 07 escaped above C0: d8 c7 invalid escaped under C0: d9 08 invalid escaped above c0: d9 d1 five bits isolation: d9 c0 d9 c8 two bytes static fpu opcode: da e9 CREGS/SREGS parsing: -+------------------ invalid CR#: 0f 22 e9 (MOV CR5, ECX) invalid SREG#: 8e fa (MOV SREG7, DX) Prefixes: -+------ 0xF0,0xF2,0xF3 0x2E,0x36,0x3E,0x26,0x64,0x65 0x66,0x67 REP: -+- 16 bits: AD ~ LODSW 66 AD ~ LODSD F3 AC ~ REP LODSB F3 66 AD ~ REP LODSD F3 3E AC ~ REP LODS BYTE DS:[SI] F3 67 AD ~ REP LODS WORD [ESI] F3 65 AC ~ REP LODS BYTE GS:[SI] AD66ADF3ACF366ADF33EACF367ADF365AC XLAT: -+--- D7 ~ XLATB 67 D7 ~ XLAT BYTE [BX+AL] 26 D7 ~ XLAT BYTE ES:[EBX+AL] 64 D7 ~ XLAT BYTE FS:[RBX+AL] D767D726D764d7 Prefixes (32 bits decoding): -+-------------------------- f02e6667c3 simple prefixes 65662e no more bytes to decode after prefixes 2ef065662e no more bytes to decode after prefixes + extra prefixes 65666766c3 unused prefixes 656667b81111 partially unused 65672e66b81111 partially unused + extra prefixes 2ef06605 not enough bytes to decode instruction 662e0fc7c867c3 bad instruction operands 660f5800 mandatory prefix 2e67f02e660f5800 mandatory prefix + extra prefixes + partially unused 660f58 mandatory prefix + not enough bytes to decode instruction 2ef03e660f588411 partially unused + dropped prefixes + mandatory prefix + not enough bytes to decode instruction 660ff7b5 mandatory prefix + modrm doesn't decode well 6667406541424f33c0 extra rex's Prefixes (64 bits decoding): -+-------------------------- f20f5ac0 mandatory f2480f5ac0 mandatory + rex.w dropped f24f0f5ac0 mandatory + full rex f2420f5ac0 mandatory + rex.x dropped 660f6ec0 mandatory 66480f6ec0 mandatory + rex.w 2ef3664f0f6ec0 mandatory + full rex + dropped prefixes f065666747f02e6650 prefixes + rex + prefixes f06566674831c0 prefixes + rex 664833c0 opsize + rex.w Operand Types: -+------------ OT_IMM8, 80C155 add cl, 0x55 OT_IMM16, C8010012 enter 1, 12 OT_IMM_FULL, B801000000 mov eax, 1 OT_IMM32, OT_IMM_AADM, D550 AAD 0x50 d50a AAD D450 AAM 0x50 d40a AAM D550d50aD450d40a OT_SEIMM8, 83D8EE sbb eax, -12 OT_REG8, 32DA xor bl, dl OT_REG_FULL, 0FC1DA xadd edx, ebx OT_REG32, 0FBFC2 movsx eax, dx OT_REG32_RM, 0F23C8 mov dr1, eax 0F23F8 mov dr7, eax 0f2300 invalid OT_RM8, 80D512 adc ch, 0x12 OT_RM16, 8CD8 mov ax, ds 8C1F mov [bx], ds OT_RM_FULL, 0FA308 bt [eax], ecx OT_RM32, 0F6E38 movd MM7, [eax] OT_FPUM16, DE03 fiadd word ptr [ebx] OT_FPUM32, D803 fadd dword ptr [ebx] OT_FPUM64, DC3F fdivr qword ptr [edi] OT_FPUM80, DF21 fbld tbyte [ecx] OT_R32M16, * not clear, check data sheet 0FC40215 PINSRW MM0, [edx], 15 OT_CREG, 0F22CE mov cr1, esi (invalid) OT_DREG, 0F21DE mov esi, dr3 OT_SREG, 8C1B mov [ebx], ds OT_ACC8, 14AA adc al, 0xaa OT_ACC_FULL, 1578563412 adc eax, 0x12345678 OT_MEM1616, OT_MEM1632, OT_PTR1616, OT_RELCB, 7400 jz $+2 OT_RELC_FULL, 0x400073: 0F8287FFC0FF jc 0x10000 OT_MEM, 0FC70B cmpxchg8b [ebx] OT_MEM64, 0FE700 movntq [eax], MM0 OT_MEM128, OT_MOFFS, A034120000 mov al, [0x1234] OT_CONST1, D0E1 shl cl, 1 OT_REGCL, D3E3 shl ebx, cl OT_IB_RB, B155 mov cl, 0x55 OT_IB_R_FULL, 50 push eax OT_IB_RD, 0FC8 bswap eax OT_REGI_ESI, OT_REGI_EDI, OT_REGDX, OT_FPU_SI, D8D5 fcom st(5) OT_FPU_SSI, D8E2 fsub st, st(2) OT_FPU_SIS, DEFD fdivp st(5), st OT_MM, 0F6300 packsswb mm0, qword [eax] OT_MM_RM, 0FD7C7 PMOVMSKB eax, mm7 OT_MM32, 0F622A PUNPCKLDQ mm5, dword [edx] OT_MM64, 0F6F2B movq mm5, [ebx] OT_XMM, OT_XMM_RM, OT_XMM32, OT_XMM64, OT_XMM128, OT_DUMMY 004000AA: E8F1FFFFFF call 0x4000a0 Locate_instruction Engine: -+------------------------ Mmandatory Prefix OCST_1BYTE - c3 RET OCST_13BYTES - 80D155 adc cl, 55 OCST_1dBYTES - d9d0 fnop OCST_2BYTES - 0f08 invd OCST_23BYTES - 0F0013 lldt dword [ebx] OCST_2dBYTES - 0FAE06 FXSAVE [esi] OCST_3BYTES - f30f58ff ADDSS XMM7, XMM7 OCST_33BYTES - 660f73f055 PSLLQ XMM0, 0x55 3DNow! - 0f0fffa7 PFRSQIT1 MM7, MM7 Wait Instruction - 9b90 wait nop ; 9bDBE2 fclex ; DBE2 fnclex kill 3dnow instruction after modrm 0f0f db f db f 0f0fc3 db f db f ret 0f01e30f01f00f01c70f01080f01c80f01c90f0109 0faee80faef00faef80faef3ac0fae3f hexcode = "c3 FE07 DC00 D9C3 DBE3 0f06 0fba2055 0faee80faef00faef80faef3ac0fae3f 9bdbe3" 660f6800 ModR/M Options: -+------------- 16 bits: FF0C dec word [si] FF08 dec word [bx+si] FF0E3412 dec word [0x1234] FF4855 dec word [bx+si+0x55] FE8EAA00 dec byte [bp+0xaa] FE8D3412 dec byte [di+0x1234] ff0cff08FF0E3412FF4855FE8EAA00FE8D3412 32 bits: FF02 inc dword [edx] FF0578563412 inc dword [0x12345678] FF4755 inc dword [edi+0x55] FE8678563412 inc byte [esi+0x12345678] FF02FF0578563412FF4755FE8678563412 sib (src op =don't care) 0fc0042578563412 xadd [0x12345678], 0fc00401 xadd [eax + ecx], 0fc04ce1aa xadd [ecx + 0xaa], 0fc04ce555 xadd [ebp + 0x55], 0fc0b48278563412 xadd [eax*4 + edx + 0x12345678], 0fc0b4c478563412 xadd [eax*8 + esp + 0x12345678], 0fc00420 xadd [eax], al 0fc00425785634120fc004010fc04ce1aa0fc04ce5550fc0b482785634120fc0b4c4785634120fc00420 Block Instructions: -+----------------- bswap: 0fc8-0fcf dec: 48-4f inc: 40-47 pop: 58-5f push: 50-57 mov byte: b012-b712 mov word: b81234-bf1234 xchg: 91-97, 90 32 bits: 0fc80fcf 16 bits: 484f4047585f5057b012b712b81234bf1234919790 Seg2Text: -+------- 2efe07 inc byte cs:[bx] 65fe07 inc byte gs:[bx] 2efe0765fe07 Indirection2Text: -+--------------- 801712 adc byte [bx], 0x12 FF362341 push word [0x121312] UnusedPrefixes2Text: -+------------------ 66b055 mov al, 0x55 6740 inc ax 2e0e push cs f2ED in ax, dx f3E002 loopnz $+2 66b05567402e0ef2EDf3E002 Lock Prefix: -+---------- f0D3E0 shl eax, cl f0fe07 lock inc byte [bx] f0D3E0f0fe07 Double Mnemonics: -+--------------- 98 CBW, CWDE 99 CWD, CDQ (67) e3 JCXZ, JECXZ Natives: -+------ cf IRET 61 POPA 9d POPF 60 PUSHA 9c PUSHF cf619d609c 66cf6661669d6660669c Invalid Registers: -+---------------- 0F21E0 mov eax, dr4 0F21E8 mov eax, dr5 0F21F0 mov eax, dr6 8Cf8 mov ax, 0F20CB mov ebx, cr1 8EC8 mov cs, ax 0f21c0 mov eax, dr0 0f21bf Security: -+------- Misc: -+--- 67/66 jmp? 64 bit ------- FE4500 inc byte [rbp+0] fe01 inc byte [rcx] fe44bd05 inc byte [rdi*4+rbp+5] fe0501000000 inc byte [rip+1] 67fe0501000000 inc byte [rip+1] ff4704 inc dword [rdi+4] ff04c555000000 inc dword [rax*8+55] ff442501 inc dword [rbp+1] ffc7 inc edi 4fFE4500 inc byte [r13+0] 41fe01 inc byte [r9] 43fe44bd05 inc byte [r15*4+r13+5] 4ffe0501000000 db 0x4f; inc byte [rip+1] 41ff4704 inc dword [r15+4] 4aff04c555000000 inc qword [r8*8+55] 41ff442501 inc dword [r13+1] 41ffc7 inc r15d modrm ----- 4633C1 xor r8d, ecx 4933C1 xor rax, r9 8d01 lea eax, [rcx] 428d01 db 0x42; lea eax, [rcx] 418d01 lea eax, [r9] 4c8d01 lea r8, [rcx] 8d0cf8 lea ecx, [rax+rdi*8] 678d0cf8 lea ecx, [eax+edi*8] 418d0cf8 lea ecx, [r8+rdi*8] 67418d0cf8 lea ecx, [r8d+edi*8] 428d0cf8 lea ecx, [rax+r15*8] 448d0cf8 lea r9d, [rax+rdi*8] 4c8d0cf8 lea r9, [rax+rdi*8] 48 b8 0100000000000000 MOV RAX, 0x01 b8 01000000 MOV EAX, 0x01 8d0461 LEA EAX, [RCX] 428d0461 LEA EAX, [RCX + R12*2] 418D042500000000 db 0x41; LEA EAX, [0x0] 418D842500000000 LEA EAX, [R13+0x0] 8D0420 LEA EAX, [RAX] 428D0420 LEA EAX, [R12+RAX] 4d33c94533c9664733c9 4d33c9 XOR R9, R9 4533c9 XOR R9D, R9D 664733c9 XOR R9W, R9W 50 push rax 4e50 db 0x4e; push rax 6651 push cx 41b801010101 mov r8d, 0x01010101 65d7 XLAT BYTE GS:[RBX+AL] 6467d7 XLAT BYTE FS:[EBX+AL] 0FBE03 movsx eax, byte [rbx] 0FB707 movzx eax, word [rdi] 480FBE0424 movsx rax, byte [rsp] 480FBEC0 movsx rax, al 4c0fb6fe movzx r15, sil 66C1A04523010009 shl word [Rax+12345], 9 66C1A4C04523010055 shl word [Rax+Rax*8+12345], 55 C1A4C04523010009 shl dword [Rax+Rax*8+12345], 9 f20f2dc0 CVTSD2SI EAX, XMM0 f2480f2dc1 CVTSD2SI RAX, XMM1 CVTSD2SI CVTTSD2SI CVTSS2SI CVTTSS2SI CVTSI2SD CVTSI2SS OT_IB_R_FULL moffset64 OT_ACC_FULL 66 48 0f2dd9 66 is mandatory!! VMX -+- 0f01c10f01c20f01c30f01c4 VMCALL, VMLAUNCH, VMRESUME, VMXOFF 660fc7f0 // MEM can't use MOD=11 660fc730 VMCLEAR [EAX] 0fc730 VMPTRLD [EAX] 0fc7f0 // MEM again 0fc738 VMPTRST [RAX] f30fc737 VMXON [RDI] 0f78c1 VMREAD ECX, EAX 0f79c1 VMWRITE RAX, RCXdistorm64-1.7.30/doc/vol1.html0000644000175000017500000007634110547576442014756 0ustar enderender

80x86 Machine Code
-+----------------

This document is part of diStorm project
http://ragestorm.net/distorm

/--------------\
|Decoding Modes|
\--------------/
Decoding mode specifies the default size of an operation.
A code block is constructed from a sequence of instructions.
The decoding mode tells how that code(-the instructions) is being processed.
They can be processed in 16, 32 or 64 bits.
The number of bits is the operation size of each instruction.
DOS is known to be a 16 bits OS, thus the CPU executes its code in a 16 bits environment.
Windows and Linux are 32 bits, and even 64 bits nowadays...
Every piece of code or an instruction has to be disassembled in the corresponding size it was assembled/compiled to.
The disassembler disassembles the instructions according to this decoding mode only,
it makes much sense, because every decode mode supports different instruction sets or instructions and
can do different operations, so you have to know in advance the decoding mode of the stream you want to disassemble.

The 3 modes supported by diStorm are:
16 bits (Decode16Bits) - Instruction sets supported: 80186/80286
32 (Decode32Bits) - Instruction sets supported: 80x86 (Not including x64)
AMD64 (Decode64Bits) - Instruction sets supported: 80x86 + x64 (Not including prohibited instructions)

In addition to these instruction sets, there are more instruction sets that are supported no matter the mode,
these are the FPU, SSE, SSE2, SSE3, 3DNow!, 3DNow! extensions (and some P6 instructions), VMX and SSSE3 instructions.
Maybe the 16 bits decoding mode doesn't necessarily require all these sets,
but I found it useful, it can't harm nobody, anyways...

Every decode mode has a default operand size and address size, more on this later.

/-----------------\
|80x86 Instruction|
\-----------------/
A 80x86 instruction is divided to a number of elements:
1)Instruction prefixes, affects the behaviour of the instruction's operation.
2)Mandatory prefix used as an opcode byte for SSE instructions.
3)Opcode bytes, could be one or more bytes (up to 3 whole bytes).
4)ModR/M byte is optional and sometimes could contain a part of the opcode itself.
5)SIB byte is optional and represents complex memory indirection forms.
6)Displacement is optional and it is a value of a varying size of bytes(byte, word, long) and used as an offset.
7)Immediate is optional and it is used as a general number value built from a varying size of bytes(byte, word, long).

The format looks as follows:

/-------------------------------------------------------------------------------------------------------------------------------------------\
|*Prefixes | *Mandatory Prefix | *REX Prefix | Opcode Bytes | *ModR/M | *SIB | *Displacement (1,2 or 4 bytes) | *Immediate (1,2 or 4 bytes) |
\-------------------------------------------------------------------------------------------------------------------------------------------/
* means the element is optional.

/--------------------\
|Instruction Prefixes|
\--------------------/
The instruction prefixes are optional, they are used when the default behaviour of the instruction lacks functioning.
If you want to extend the behaviour of the instruction, or change its parameters, prefixes might achieve your goal.
There are 4 types of prefixes:
Lock and Repeat
Segment Override
Operand Size
Address Size

The following table shows the value in hex of the prefix and its mnemonic:
- Lock and Repeat:
	- 0xF0 — LOCK
	- 0xF2 — REPNE/REPNZ
	- 0xF3 - REP/REPE/REPZ
- Segment Override:
	- 0x2E - CS
	- 0x36 - SS
	- 0x3E - DS
	- 0x26 - ES
	- 0x64 - FS
	- 0x65 - GS
- Operand-Size Override: 0x66, switching to non-default size.
- Address-Size Override: 0x67, switching to non-default size.

Every instruction could have up to 4 prefixes and each prefix mustn't be used twice,
otherwise it could lead to undefined behaviour by the processor.

Lock prefix is used in order to lock the bus for writing.
It is used for spin locks and other techniques for the sake of code synchornization.
There is a small set of instructions which support the Lock prefix and that's also when the first operand is used as a memory indirection.
If this prefix is used for an instruction which doesn't support it or the first operand isn't a memory indirection form, an exception is
raised by the processor. In the case of the disassembler this prefix will be dropped (simply ignored).

There is a hack in the IA-32 processors to access CR8 register, using the Lock prefix for mov cr(n) instruction it acts
as the fourth (upper) bit of the REG field, this allows the processor reaching to the 8 upper CR registers.

The disassembler first makes sure the instruction is lockable and if so it validates that the destination operand is in the memory indirection form.
If these conditions aren't met, the prefix will be dropped.

Repeat prefixes are considered to be the same type of the Lock prefix, so an instruction could only have Lock or Repeat, not both at the same time.
Note that the disassembler is based on Intel's reference in this part of the code.
The AMD reference seperates the LOCK and the Repeat prefixes as two different types.
Repeat prefixes are used only with string instructions which support this prefix.
The disassembler ignores this prefix if used for other instructions, thus ending up with this prefix dropped.
There are two repeat prefixes, REPZ and REPNZ, repeat as long as the Zero flag (and rCX!=0) isn't set and vice versa.

Side note:
The meaning of rCX is a general-purpose register which can be one of the following: CX, ECX or RCX.
Notice the small letter 'r', which says it's one of the CX registers...The names of the register indicates its size,
which is defined according to the decoding mode.

Note that repeat prefix can be used as a mandatory prefix for SSE instructions.

The Repeat prefixes are treated specially with string instructions and when more prefixes are set.
It could change the textual representation of the instruction in some cases.
The way it's done in the disassembler is the same for all string instructions and is covered below.
One more thing to say about repeat prefixes is that IO string instructions also support this (such as: ins, outs).

Segment Override prefix is used in order to change the default segment for the instruction.
Every general-purpose register has its default segment. For example SS for ESP, DS for BX, etc...
If the instruction uses the memory indirection form and there is a segment override prefix set,
then it will be displayed in front of the operand. If the instruction doesn't support operands,
or in case the operands aren't in the memory indirection form, the prefix is dropped.
In 64 bits decoding mode the CS, SS, DS and ES segment overrides are ignored and ineffective.

Operand Size prefix is responsible for switching the operation size from the default size
(depends on the instruction and decoding mode) to the non-default mode.
It means that if the code is being run on a 32bits environment and the operand size prefix is used,
that specific prefixed instruction will be run as a 16bits instruction.

It is wrong to think that XOR EAX, EAX is different from XOR AX, AX - in their opcodes.
Both instructions have the same bytes. There are only two options for representing them these ways.
As stated earlier, most of the instructions are dependant on the decoding mode (16, 32).
So if you decode that XOR in 16 bits, you will end up with XOR AX, AX,
but if you decode that XOR in 32 bits, you will end up with XOR EAX, EAX.
The operand size prefix comes into play when you want to change the operation size of the instruction,
instead of the default size which is set by the decoding mode, to the non-default size.
If you decode the XOR instruction in 16 bits, but prefix it with operand size prefix, it will result in XOR EAX, EAX.

A known usage for operand size prefix in DOS (that is 16 bits code) was to fill the VGA screen using:
db 0x66
rep stosw
which actually run as:
rep stosd

Note that operand size prefix can be used as a mandatory prefix for SSE instructions.

Address Size prefix is quiet the same as Operand Size prefix, but acts on the memory indirection form of the operand.
It switches the memory indirection form to the non-default form.
Thus, if you read (in 16 bits) from [BP+DI], when prefixing it, the result is reading from [EBX].
(This is right, because 16 bits has a different memory indirections tables from 32 bits).

If you still ask yourself why you need both address and operand prefixes, the answer is right here.
Let's do some order in the mess:
You have to distinguish between the operand size and the address size.
The operand size acts on OPERATION size. The operation size is determined implicitly by the instruction.
For example (The default decoding mode is 16 bits):
MOV AX, BX --> we know the operation size is 16 bits, because we know that AX and BX are 16 bits registers.
MOV EAX, EBX --> 32 bits.
MOV EAX, [EBX] --> still easy, EAX is 32 bits, so we read 32 bits from the memory.
But what about this one:
MOV [EBX], 5 --> You see the problem, you don't know the operation size, it might be that we write only one byte, or maybe two or at last, four.
That's why in this case we have to explicitly tell the assembler, or display as the disassembler the operation size.

The confusion still exists.
MOV [BP+DI], DX --> 16 bits operation size.

MOV [EBX], DX
Now what!? No operand size is able to change BX into EBX in this case.
An operand size prefix won't affect the memory indirection form!
However, an address size prefix will affect it, thus changing BP+DI to EBX.
Even so, when the address size prefix is set, the operation size is untouched and stays the same one, the default one.

It is given that we decode in 16 bits in the following example:
MOV [BP+DI], AX --> Nothing special
MOV [EBX], AX --> This is done by Address Size prefix only.
MOV [BP+DI], EAX --> This is done by Operand Size prefix only.
MOV [EBX], EAX --> This is done by both address and operand size prefixes.

In the bottom line, the address size prefix affects the operand only if it's in the memory indirection form, otherwise it's ignored.
And the operand size affects the operation size, no matter in what form it is. It changes the amount of bytes the instruction is to work upon.
Of course, there are instructions which have a fixed operation size, thus the operand size prefix is ignored/dropped.

The behaviour of the operand/address size is defined in the following table (ignoring 64 bits!):

          /-------\
Default   |16 | 32|
          +-------+
Prefixed  |32 | 16|
          \-------/

Now that you know how all prefixes effects, I will describe how prefixes affect string instructions, using examples:
(Decoding mode is 16 bits)
AD ~ LODSW
66 AD ~ LODSD
F3 AC ~ REP LODSB
F3 66 AD ~ REP LODSD
F3 3E AC ~ REP LODS BYTE DS:[SI]
F3 67 AD ~ REP LODS WORD [ESI]

Notice that if the instruction is not required to be in the long form, it has a suffix letter which represents the operation size.
The long form of the string instructions are displayed when you change their address form or segment override them, which makes it explicit.

/----------------\
|Mandatory Prefix|
\----------------/
The mandatory prefixes are used as opcode bytes in special cases.
Their values can be one of: 0x66, 0xf2 or 0xf3.
The mandatory prefix byte must precede the first opcode byte, otherwise it is decoded just as a normal prefix.
When a prefix is detected as a mandatory prefix, its behaviour isn't taken into account as a normal prefix.
SSE instructions use the mandatory prefixes as part of the opcode itself,
it makes life a bit harder when fetching an instruction in the fetching phase.
This is covered thoroughly in the Decoding Phases!

/--------------------\
|REX Prefix - 64 Bits|
\--------------------/
REX stands for register extension.
One of the most important changes in 64 bits is that it permits access to 16 registers.
The REX prefix takes place only in 64 bits decoding mode.

'till now all you had is 8 general purpose registers.
Later on, I'm going to cover how the ModR/M is formatted and I will refer to the REX as well, so you see how it's related.

Anyways, the REX prefix must precede the first byte of the opcode itself, otherwise it is ignored.
I know I just wrote this same sentence about the mandatory prefix, but the REX prefix has a higher priority, calling it so.
So if there is a REX prefix set and a mandatory prefix is set as well, they won't interfere with each other!
It just comes out that the REX prefix has to be before the opcode itself, even if the mandatory prefix is set.
And the mandatory prefix should be set before the REX prefix if it's set, and before these two all other prefixes can precede, no matter their order.

The range of the REX prefix is 0x40 to 0x4f.
It means that in 64 bits it overrides the instructions INC and DEC, but these instructions have an alternative opcodes, so no worry.

So if we encounter a byte with the first (high) nibble with the value of 4, we know it's a REX prefix.
The REX is formatted as follows:

-7---4--3---2---1---0-- <-- Bits Index
| REX | W | R | X | B | <-- Field Name
----------------------- <-- End Line Marker

REX - 0x4, marks it is a REX prefix.
Width - 0, default operand size. 1, 64 bits operand size.
Here is how the REX.W flag affects the final operand size of the instruction:


-------------------------------------
|Default   |Default  |With   |With  |
|Operating-|Operand- |0x66   |REX.W |
|Mode      |Size     |Prefix |      |
|----------+------------------------|
|64 Bits   |  64     |IGNORED|  1   |
|-----------------------------------|
|64 Bits   |  32     |  16   |  0   |
|-----------------------------------|
|64 Bits   |  16     |  32   |  0   |
-------------------------------------

REX.W with a value of 0 causes no change to the operand size of the instruction.
But a value of 1 causes the operand size to be 64 bits.
Note that if a REX.W is 1 and an operand size prefix (0x66) is also set, then the 0x66 byte is fully ignored!
However, if an operand size prefix is set and the REX.W is clear, that operand size will affect the instruction as well.
REX.W won't affect byte operations as well as operand size prefix.

So you see, when you disassemble instruction in 64 bits and a REX.W is set, the effective operand size becomes 64 bits.
Now all instruction support 64 bits, that is their operands' types.
On the contrast, there are some instructions that in 64 bits decoding mode their effective operand size becomes 64 bits by default,
they are called promoted instructions. There is a limited list of promoted instructions,
for example when you push a register in 64 bits you don't need the REX prefix to tell the processor it's a 64 bits register...

Register field - 1 (high) bit extension of the ModR/M REG field.
indeX field - 1 (high) bit extension of the SIB Index field.
Base field - 1 (high) bit extension of the ModR/M or SIB Base field.

Later on, I will explain precisely how these bits affect the decoding of registers.
I just wanted to make sure you get familiar with them first.

It is not true to assume that a REX prefix with a value of 0x40 doesn't have any implications on the instruction it precedes!

/------\
|Opcode|
\------/
Opcode is the static portion of the instruction which leads to (defines) the instruction itself.
It is the bytes (and bits) you read from a stream in order to determine what instruction it is.
The opcode size can vary from 1 bytes to 4 bytes. And it may also include 3 more bits from the REG field of the ModR/M byte.
The instruction fetching mechanism in the disassembler is based on opcodes only
(there could be tables which convert from ModR/M value to a string...).
It is explained below how the fetch mechanism works with more info about the opcodes' varying sizes.
Most of the instructions belong to two types: 8 bits instructions, and 16/32 bits instructions (could be prefixed...).
The 16 or 32 bits operation size is set according to the decoding mode. I mentioned it earlier in the operand size prefix paragraph.
Instructions which operate on 8 bits ignore operand size prefix.
There are some instructions which are 5 bits long and the 3 other bits are used as the REG field,
but treated as a whole byte instruction (for example: 40, 41 disassmbles to: inc ax; inc cx).

The machine code of the opcodes is more complex than bytes granularity.
I found it easier to treat opcodes as whole bytes and if required using the REG field as well.
It simplifies stuff and makes the DB smaller, including its hierarchic structure (Trie data structure).

/------\
|ModR/M|
\------/
Some instructions require the ModR/M byte in order to specify the operands' forms.
And some other instructions have the operands' types known in advance by their opcode only and don't need the ModR/M byte in order to specify them.
The ModR/M byte is optional. The ModR/M could lead to a sequential SIB byte in 32 or 64 bits decoding modes.
The opcode of the instruction itself has info about the operands' types, but these types, still could be
extended in some ways, for instance, having an immediate number, or just a bit more complex effective-address.
The role of the ModR/M is to define whether a SIB byte, an immediate or a displacement are required.
And more than that, it defines the registers in use, according to the operands' types.
The ModR/M is built from 3 fields:

-7---6--543---210--
| MOD | REG | R/M |
-------------------

The MOD field is the two most significant bits, it defines whether a displacement is used, and if so, its size.
Well, and a few more things, keep on reading. Ah and MOD stands for Mode, how original.

------------------
|MOD       | Bin |
|----------+-----|
|No DISP   | 00  |
|DISP8     | 01  |
|DISP16/32 | 10  |
|REG       | 11  |
------------------

MOD
00 means no displacement is used.
01 requires a displacement of 8 bits.
10 requires a displacement of 16 or 32 bits, the size is set by the decoding mode, and could be altered by (operand size) prefix, of course.
11 means that only general-purpose registers are in use.

The famous REG field (3 bits).
The REG field is used in order to specify the register of one of the operands, if used, of course.
(The REG field defines the source or destination operand, it depends on the opcode itself).
However, the special thing about it, is that it could be used just as a part of the opcode.
This merely 3 bits are used many times in many instructions (0x80-0x83).
Later on, it is explained how it becomes a part of the instructions DB.

At last, but not least, the R/M field. The R/M field stands for Register or Memory.
It has a different meaning, and its meaning is chosen according to the MOD field.
It might be a general-purpose register when MOD is 11, or it might be a register for memory addressing when MOD is not 11.

Notice that the operation size of the instruction wasn't mentioned yet,
this is because for the ModR/M itself, the operation size isn't a matter.
It becomes usable when you know the operands' types of the instructions,
so with both parameters you will know what registers are used.

The REG field or R/M field could be one of the following:

-:Value to Register Table (32 bits):----
|0   |1   |2   |3   |4   |5   |6   |7  |
|EAX |ECX |EDX |EBX |ESP |EBP |ESI |EDI|
|AX  |CX  |DX  |BX  |SP  |BP  |SI  |DI |
|AL  |CL  |DL  |BL  |AH  |CH  |DH  |BH |
|SS0 |SS1 |SS2 |SS3 |SS4 |SS5 |SS6 |SS7|
|MM0 |MM1 |MM2 |MM3 |MM4 |MM5 |MM6 |MM7|
----------------------------------------

The only way to know which registers set you should use is by the operand type itself,
and of course by the corresponding field's value.

Let's decode some (in 32 bits) :)

88 1B MOV [EBX], BL

So 88 is a 8 bits operation size instruction.
According to the specs 88 is defined as: MOV r/m8,r8

In short, the first operand type: r/m means the operand could be a register or a memory addressing.
The number following the r/m means the size of the instruction's operation.
The other operand type, r8 or r32, means that the operand must be a register, its size is known too.

Now that we know what's going on with these two operands and what to expect let's examine some bits:

0x1B in binary is 00011011, making it ModR/M compatible: 00-011-011
Knowing in advance the operands' types and the ModR/M, let's disassemble the instruction:
88 is decoded as: MOV,
The MOD is 00, means only a register for memory addressing is used.
But how do we know which operand uses what field (REG or R/M), that's according to the operand type.
So the R/M field used in this case as the Destination (=first) operand and has the value of 011, which is (3) EBX,
and we know it's an R/M operand, thus it is a memory indirection form.
We are left with the REG field, which in this case is also used, its value is 011 and decodes to (3) BL,
it's BL and NOT EBX because the operand size is 8 bits, see that.

Ok, another one:
According to the specs:
F6 /3 NEG r/m8

Let's decode some more hex (in 32 bits) :
F6 19

Two things to note, the "/3" means it uses the REG field (as a part of the opcode!) with a value of 3 for indicating it's a NEG instruction.
And the second thing, that it is a simple one-operand instruction.

So encountering F6, we know it's a "NEG" instruction, alright.
NO, that was not right! Encountering F6, we still don't know it's a NEG instruction, it could be something else,
but we will know that we have to read the REG field in order to get the desired instruction, so after isolating the REG field,
and testing it, we know it's the "NEG" instruction - now it's alright, for real.
You see, reading F6 tells us that we have to read 3 more bits (REG),
and only then we'll know the instruction, maybe if we read the REG we reach to another instruction,
for example: F6 /6 is the DIV instruction.
It's can't be that reading F6 tells us to read another whole byte for constructing the opcode, because then we would have collisions...
Getting the instruction, we know its operands, in this case only one operand.
By now you should know that type of operand.

0x19 in binary ModR/M style is 00-011-001
Notice that this time the REG field is indeed 3, which is the missing bits (1 byte, 0xf6 isn't enough to determine the instruction),
which completes the opcode fetching.
So the REG field was already used and is ignored for operand decoding.
We know MOD of 00, so we look up the table and get [ECX] (because R/M=1).
Eventually the instruction is decoded as: NEG BYTE [ECX]
The "BYTE" is an addition to show the operation size explicitly,
otherwise you could keep on guessing the operation size of this instruction, without having any clue.

As you can see,
there are 3 ingredients to a good instruction :)
An opcode (which is a must, of course)
and is bundled with the operands' types (in fact, this is 2 in 1 :).
And ModR/M which is optional, but necessary most of the times.

There are a few quirks to the ModR/M decoding,
how to get from a ModR/M to SIB wasn't explained yet.
It varies from 16 to 32 bits, which have different tables for decoding the ModR/M,
but I will stick to the 32 bits version, as I have already done.
Note that 16 bits don't have a SIB byte, thus there are no complex memory addressings in 16 bits.

The ModR/M byte when decoded to specify the ESP as a memory addressing register, actually tells the processor to read the SIB byte!
This is because when the R/M field's value is 4 (ESP register) it means the instruction includes the SIB byte,
so in order to really specify an operand as ESP, we will have to use a SIB byte for that.

And there is another special case when MOD is 00 and R/M is 5 (EBP register) it means the EBP is NOT used at all,
and that a Displacement of 32 bits follows the ModR/M byte.
That's why using the EBP register as memory addressing register takes one more byte (using MOD=01, Disp8=0), making it [EBP+00].
I guess Intel chose the EBP register instead of the others, because EBP is intended as a stack frame pointer, and will have a disp8 offset.
So it's not big deal to pay one more byte for the instruction when we usually use that byte anyways...
The special R/M=5 case, allows the instructions to use an absolute memory address, for example:
MOV [0x1234567], EBX
Otherwise it wasn't possible using only ModR/M.

-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-64 bits decoding mode + ModR/M-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~

If that was the same case in 64 bits decoding mode, when the R/M is 5 then the result was:
MOV [RIP+0x1234567], EBX
So when R/M is 5, the RIP or Register-IP becomes the base register.
And if you still want an absolute addressing in 64 bits mode, you will have to use the SIB byte with a couple of tricks.
Yes, you actually can get the position of the currently being executed code with LEA RAX, [RIP+0] Genius!

Back to REX prefix now. This is the most hard part in 64 bits decoding, so pay extra attention:
so if the REX.R is set, the REG field of the ModR/M becomes a 4 bits variable which indicates a register index.
And if the REX.B is set, the R/M field of the ModR/M becomes a 4 bits variable...ditto.

All the above extreme cases of the EBP/ESP reigsters don't apply to this new variable,
it means that even if the REX.R is set, a RIP will be used, or a SIB will be read if the REX.R is set and REG is 4...
Sometimes the REX bits are ignored and the other times they are took into account, it depends what action is being done,
it is all covered in the AMD64 documentation really well, in the bottom line,
the REX is ignored when the fields tell the processor to read the SIB byte or in the extreme cases explained earlier.

A fourth bit in the REG or R/M field permits access to 16 registers.
There are new sets of registers for 64 bits.

These are the 64 bits registers:
-------------------------------------------------------------------------------
|RAX |RCX |RDX |RBX |RSP |RBP |RSI |RDI |R8 |R9 |R10 |R11 |R12 |R13 |R14 |R15 |
-------------------------------------------------------------------------------

Even 32 bits registers can be extended!
---------------------------------------------------------------------------------------
|EAX |ECX |EDX |EBX |ESP |EBP |ESI |EDI |R8D |R9D |R10D |R11D |R12D |R13D |R14D |R15D |
---------------------------------------------------------------------------------------

Further 16 bits registers can be extended using the suffix letter 'W' instead.

In 64 bits decoding mode, there is a new set of registers accessible, the low bytes of SI, DI, BP and SP!
I wonder how compilers will use these bytes in the future...
Anyways, there are two tables now:

8 bits registers without REX prefix (nothing special yet):
-------------------------------------------------------------------------------
|AL |CL |DL |BL |AH |CH |DH |BH |R8B |R9B |R10B |R11B |R12B |R13B |R14B |R15B |
-------------------------------------------------------------------------------

8 bits registers with REX prefix set (no matter its flags!):
-----------------------------------------------------------------------------------
|AL |CL |DL |BL |SPL |BPL |SIL |DIL |R8B |R9B |R10B |R11B |R12B |R13B |R14B |R15B |
-----------------------------------------------------------------------------------
This explains why a REX prefix with a value of 0x40 might affect the instruction, even with all bits cleared!

Note that the extended 32 bits registers could be used in memory addressing forms!
For example: INC DWORD [R8D + R15D * 8 + 0x1234].

One more comment about 64 bits -
the default addressing size is 64 bits, wheareas the default operand size is 32!
----------------------------------------
|Default   |Default  |With   |Effective|
|Operating-|Address- |0x67   |Address- |
|Mode      |Size     |Prefix |Size     |
|----------+---------------------------|
|64 Bits   |   64    |  No   |   64    |
|--------------------------------------|
|64 Bits   |   64    |  Yes  |   32    |
----------------------------------------

BTW - there are 16 XMM registers (SSE) as well in 64 bits.

/---\
|SIB|
\---/
SIB stands for Scale-Index-Base, it is a one byte which embodies these fields.
It is an optional byte and if used, it must be sequential to the ModR/M byte.
The SIB might be a part of the instruction only when the operand is in the addressing mode (MOD!=11).
The SIB makes the effective address more powerful, thus using less instructions in order to calculate complex addresses.

It formats as:

-7-----6-5-----3-2----0-
| SCALE | INDEX | BASE |
------------------------

And results in [INDEX * 2**SCALE + BASE].

The most significant two bits represent the SCALE field.
The scale field is used as a multiplication variant for the Index register.
The Index is multiplied by 2**Scale (powered), the Index register (3 bits long) could be any general-purpose register,
except the ESP register, makes sense, doesn't it?

The Base register is 3 bits long (less significant) and is used as a base address.
There is a special condition to this register, the base is ignored when it's the EBP register and MOD==00, recall it means
using a displacement of 32 bits.

In the bottom line, the special case comes to our call in 64 bits,
when we can't use an absolute memory address only (because then RIP is the base register automatically),
we are left with a special case:
If the MOD=00 and Base=EBP and Index=ESP, we end up with disp32 only.
Therefore even in 64 bits you can use absolute addresses!

So before we know which registers we are going to use,
we still have to decode the REX prefix, that is in 64 bits mode, and see how its flags affect the SIB.
REX.R is ignored when decoding SIB, because in order to read a SIB byte the REG field had to be 4.

So we are left with two more flags:
The REX.X flag is quiet easy to understand, it is only used as the high fourth bit of the Index field.
And the REX.B flag, which becomes the high fourth bit of the Base field.

If you are still confused, you should take a look at the AMD64 data sheets,
they have nice graphs describing these REX bits things...


/------------\
|Displacement|
\------------/
The displacement is optional, it might be used only if the R/M field defines so (recall the R/M table above).
The size of the displacement could vary from 1 byte, 2 bytes or 4 bytes, the MOD and R/M field define it too.
This field must follow the ModR/M byte or SIB byte if exists.
If this field is used, it will be used as part of the address.
The address size prefix affects the size of the displacement
(this is because it tells us to use the non-default addressing table, which has different definitions for the displacement).
In memory the displacement is stored in Little Endian.

/---------\
|Immediate|
\---------/
Instructions could load values into registers or use plain number in order to do other operations.
Instead of loading those values off the memory, they could be part of the instruction itself, hence their name.
The immediate could be treated as a signed number, and its size varies from 1 byte, 2 bytes or 4 bytes,
its size is dependant on the decoding mode and the (possibly set) prefixes.
The immediate is the last element in the instruction, and is stored in Little Endian.
distorm64-1.7.30/doc/vol2.html0000644000175000017500000012751310547576430014752 0ustar enderender

diStorm Internals
-+---------------

This document is part of diStorm project
http://ragestorm.net/distorm

/-------------------\
|Trie Data Structure|
\-------------------/
A decent technical explanation could be found at Wiki.
I decided to use the Trie data structure in order to find an instruction at O(1) instead of searching
it using a mask at O(n) where n is number of instructions in the data base.

The way it works is quiet easy to follow, there's the root instructions table, consists of 256 entries,
each entry holds a structure which tells you if you got the instruction or if you should keep on reading
more bytes or bits (in the 80x86 case).
The structure which defines a node (entry) in the table has to describe whether you got all bytes read
and thus, you got to the instruction itself, or whether you have to read some more bytes, using a type value
which indicates one of the two options. Or the third option, which says there is no instruction at this entry.
80x86 instructions have a varying length, that's why a Trie data structure fits in comfortably. Not mentioning,
the minimal fetching timing.

typedef struct InstNode {
	unsigned char type;
	union {
		_InstInfo* ii;
		struct InstNode* list;
	};
} _InstNode;

Reading a byte from a stream, you access to the root table with that byte as an index. You will end up reading an InstNode,
then examining the type, you know whether you found the instruction, or maybe you should read some more.
If you should read some more, then you read the next byte in the stream and then advance to the next table in the
Trie data structure, using the _InstInfo pointer, which leads to another table. Reading the next byte as an index within
this table, results in another read of InstNode structure, then you examine the type 'till you get an instruction
information structure. Or maybe the type says you got to the end of the road, so no instruction exists using the bytes
you read from the stream. In 3 hops at most you are supposed to find the instruction, if exists. Thus no loops are needed,
and the fetch timing is at O(1), which is huge advantage over other disassemblers. 3 hops is the maximum depth because 80x86
compatible instructions (to be accurate - opcodes that is) are 3 bytes long at most.

The 80x86 has a complex instruction sets, therefore reading a whole byte at a time isn't enough. Sometimes,
you have to read a whole byte and 3 more bits in order to get to the desired instruction. In the references it's called
Groups. The most familiar groups are 0x80-0x83. This makes the fetching code a bit more complicated. And some other instructions
have an opcode of a minimal 5 bits length, but because we seek the table with bytes granularity, we will have to treat these instructions
specially. FPU instructions are divided into two types, depending on their second opcode byte's value. This split is required in order to
distinguish between these types, one type is used for constant 2 bytes FPU instructions and the other for using the second FPU opcode byte
as a ModR/M byte. The type is determined according to the second byte's range. This gets more complicated when decoding some SSE instructions.

There are 6 types of InstNode:
typedef enum {
	INT_NOTEXISTS = -1,
	INT_NONE,
	INT_INFO,
	INT_LIST_GROUP,
	INT_LIST_FULL,
	INT_LIST_DIVIDED
} _InstNodeType;

INT_NOTEXISTS - no instruction information is found, this means we should drop the bytes we read.
INT_NONE - list or ii aren't set.
INT_INFO - an instruction was found, ii describes the instruction information for decoding.
INT_LIST_GROUP - list points to a group table (3 bits, REG field in the ModR/M),
so when you read the next byte, use only 3 bits as an index.
INT_LIST_FULL - list points to a full table (256 entries), so read another whole byte.
INT_LIST_DIVIDED - list points to a special table (72 entries), used for FPU instructions' complexity and some other sets.

The Trie data structure as used in this project is pre-built, statically initialized in the data segment.
The main advantages for this behaviour is that initalization time is spared and no memory should be consumed in run time.
The way instructions (as in the trie data structure described above) are formated in memory is for fetching speed's sake.
It appears to be a bit wasteful, although it could be more optimized in the memory form, making it slightly slower.
I'm going to cover the way it is used currently in this project, and the better memory way, in case anyone wishes to optimize it.
Well, to be honest I didn't manage to come up with anything better and I think the current mechanism is quiet alright.

Eventually, we have three types of tables: 256, 72 entries and 8 entries. Reading a whole byte or reading 3 bits (REG field)
from the next byte, respectively. It might be that some tables will be mostly empty, because not many instructions are
defined using these bytes. Thus, we end up having gaps in our tables, because not all entries are set to INT_INFO in the last table.
Let's say we have the root table, called Instructions, its size is 256, of course, because all 80x86 instructions are at least 1 byte long.
People might claim that I am not accurate, because for instance, push instruction is five bits long and the other 3 bits specify the register,
but it all depends how you represent and use your data, later on I will shed some light about those special cases.
All the entries in the root table are taken, except prefixes' values, which could lead nowhere. So the root table is quiet well used,
now if there are two bytes long instructions, we have to allocate another table. Say the instructions which start with 0x0F.
Getting Instructions at index 0x0F'th leads you to another table with 256 entries, because there are instructions of 2 bytes
and more using the first opcode byte as 0x0F. This 0x0F's table will be partly used, because the instructions defined for 0x0F don't use all entries.
And some of the instructions even require 3 more bits from the third byte in the stream, leading to another table of 8 entries.
Again, not all entries in that 8 entries' table are in use.
There are many entries which are not in use, but it saves us another byte fetch at the cost of O(1) in the fetching code of an instruction.
That's because we simply read the table at index X, where X is the byte (or 3 bits) read from the stream, this way avoiding bounds overflow.
The 72 entries table will be explained later, it's quiet confusing, so let's continue with the basics first.

An example of a Trie DB:
Where FULL = 4 entries and GROUP = 2, for the sake of example.
ROOT:
0 - INT_INFO
1 - INT_GROUP
2 - INT_INFO
3 - INT_NOTEXISTS

Group table for ROOT[1]:
1, 1 - INT_INFO
1, 2 - INT_NOTEXISTS

Reading one byte (in the range of 0-3...), you can retrieve the correct entry directly for that index.
Let's parse this stream according to the ROOT in the example:
0, 0, 1, 0, 1, 1

Offset 0: ROOT[0] results in INT_INFO, an instruction was found. So decode it and get to the next byte, restarting the whole process.
Offset 1: ROOT[0] ditto.
Offset 2: ROOT[1] results in INT_GROUP, thus in this table we know we have to read only 2 bits from the second byte of the instruction.
Offset 2,3: ROOT[1, 0] results in INT_INFO. Start all over.
Offset 4: ROOT[1] results in INT_GROUP. Get second byte...
Offset 4,5: ROOT[1,1] results in INT_NOTEXISTS, ah uh, no instruction defined.

As you can see there are two undefined instructions. In this table it's nothing special,
but when you have 80x86 tables, you will have many undefined instructions, thus wasting space.
In this project, I prefered to ignore the undefined instructions, which don't cost much space in memory and spares
some time in fetching instructions. If you really want to omit undefined instructions from your tables, I can only
suggest one technique. Every table will have an array of its size, using the above example, 4 cells in the ROOT table
and 2 cells in the GROUP table. Every cell in the node will be an index into the InstNode in that table, thus undefined
instructions take only 1 byte instead of a few for an empty InstNode.

So using this technique the new Trie DB appears like this:
ROOT:
[0,1,2,-1]
0 - INT_INFO
1 - INT_GROUP
2 - INT_INFO

Group table for ROOT[1]:
[0,-1]
1, 1 - INT_INFO

This way we eliminate INT_NOTEXISTS InstNodes using the -1 marker for "undefined".
You should say by now that -1 is a bit problematic. If you have 256 instructions and the index consists from 1 byte,
then it will simply direct you to the last entry, and you won't be able to tell the difference from Undefined to an index to the last entry.
So there are many ways to solve this problem, using a base and limit offsets for the indexing array, making it even smaller.
Or defining the indexing array as shorts, but then maybe you should make it DWORDs, because it will be read faster in Pentiums.
It's an endless story, the best way to know which technique and data type fit, is to test it all. I find the current algorithm good enough.

It might be that this technique, even saving memory space, but in the price of one more fetching (for the indexing-array) is still faster
than the current implemented mechanism, because of its small size it can be cached more easily. Though, I haven't tested it yet.
There are many ways to implement Trie data structure as you can see. I didn't put too much efforts on the Trie DB, my goal
was to find an instruction in 3 byte fetchings (at most) at O(1). The techniques in this documentation could be developed to more
optimized forms, if it's a memory space or a fetching time tradeoff.

2 bullets I think you should know:
1.The first version of diStorm used a dynamic allocated instruction tables.
Which I started to dislike with time. The true reason is that I hated calling the initialization and destruction routines
of the dynamic tables everytime I wanted to use the disassembler. Knowing that the dynamic tables are found in the resource
segment anyways, I found it easier and more comfortable to keep them static tables that way.
Which means you can just start using the ROOT of the Trie DB, without fretting for anything.

2.Another decision I had to make is to support all 80x86 instructions in my DB, with the exceptional of 3DNow!
and the WAIT instruction. In 'support' I mean that the code that fetches an instruction won't have to contain if statements
for searching/looking for a specific instructions or groups. Most of the disassemblers out there mix instruction tables
with code. I wanted that piece of code, which locates an instruction, to find that instruction according to the Trie DB only.
And yes, it makes matters a bit more complicated (divided instructions...), and I am not sure whether I gain timing here,
but I find it more reasonable and organized this way. The DB defines all instructions; and instructions shouldn't be
defined in the code itself.

/-----------------------\
|Instruction Information|
\-----------------------/
The instruction information has a major role in the disassembler.
We need the instruction information structure for two important reasons:
first of all, we know whether we reached an instruction in the Trie DB (from the given stream)
and we have to get the information about the instruction itself.

Information such as:
typedef struct _PACKED_ {
	unsigned char s, d;
	char* mnemonic;
	_iflags flags;
} _InstInfo;

This is the base structure, as you can see it defines a few things about an instruction,
its source and destination operand types, its mnemonic and flags describing the behaviour of the instruction.

There are more types of InstInfo structure, they are 'deriving' from the base _InstInfo above.
I needed more types in order to define some more attributes to instructions that require so,
because most of the instructions adequate with the _InstInfo, I decided to spare some space (not defining more variables).
This is the only place where I think C++ could be great in diStorm, but with a simple 'casting', it wasn't really necessary.

Some instructions require 3 operands defined, for example, the IMUL and other SSE instructions.
And there are other instructions which require 3 mnemonics (CWD, CBW, and JrCXZ).
There are special cases where the second and third mnemonics are used as the suffix letters for the mnemonic,
for example, the SSE pseudo compare instructions...blah

So how do you know which type of structure you hold after fetching that opcode?
In one word, flags.
They tell you essential info about the opcode and the operands.

There are many flags out there... I will name a few:
(Take a look at instructions.h for the full list.)
INST_INCLUDE_MODRM - A ModR/M byte follows the opcode byte, so read it and decode it as well.
INST_32BITS - The instruction can't be disassembled in 16 bits!
INST_PRE_LOCK - The instruction is lockable (means the lock prefix can precede it).
INST_PRE_REP - The (I/O) instruction is repeatable (means the rep prefix can precede it).
INST_3DNOW_FETCH - A 3DNow! instruction tells the disassembler to read one more byte to get its mnemonic...

Some of the instruction's flags are treated distinctively when different operand types are decoded,
you must make sure how that operand type acts upon that specific flag before you just clear it or set it.
This applies also to the extra mnemonics that a several instructions have.

/-----------------\
|Opcodes In The DB|
\-----------------/
Now that you know how the Trie DB is built, I am going to cover how the fetch of instructions is being done.
Starting with simplified instructions, then complex (FPU) instructions and at last, mandatory prefixes' mess.
In the 80x86 the length of instructions vary. As it all began as CISC processors, we have to suffer for back compability.
The Trie DB supports the following type of instructions:
typedef enum {
	OCST_1BYTE = 0
	OCST_13BYTES,
	OCST_1dBYTES,
	OCST_2BYTES,
	OCST_23BYTES,
	OCST_2dBYTES,
	OCST_3BYTES,
	OCST_33BYTES,
	OCST_4BYTES
} _OpcodeSize;

For every opcode size I will show a real instruction example, hope it will make it easier to follow.
The notation I use for instructions' sizes are:
1/2/3 byte(s) long instruction (kinda straight forward).
1.3 - A whole byte + 3 bits from the next byte, which represent the REG field from the ModR/M byte.
2.3 - Two whole bytes + 3 bits from the next byte...
3.3 - Three whole bytes + 3 bits from the next byte...You actually read it as "One Point Three bytes long instruction" and so on.
The ".3" means you read another byte, but uses only the REG field from the ModR/M according to the specs,
which means you read a whole byte in a 256 entries table and then you use 3 bits in a 8 entries table.
And last but not least, 4 bytes instruction, this is new for the SSSE3 instructions set.

1d, 2d - divided (range) instructions.
To be honest, it's a misleading name.
It's not the instructions theirselves that are divided, but the range of the second or third byte, respectively,
that defines which instruction it is.
Divided instructions are used for FPU instructions and are covered thoroughly below.

Fixed length instructions:
OCST_1BYTE - 0x9c: PUSHF
OCST_2BYTES - 0x0f, 0x06: CLTS
OCST_3BYTES - 0x9b, 0xdb, 0xe3: FINIT
OCST_4BYTES - 0x66, 0x0f, 0x3a, 0x0f;0xc0 (MODRM) 0x55 (IMM8) PALIGNR XMM0, XMM0, 0x55

The REG field from ModR/M byte comes into play:
OCST_13BYTES - 0xf6, (REG field)4: MUL
OCST_23BYTES - 0x0f, 0x00, (REG field)4: VERR
OCST_33BYTES - 0x66, 0x0f, 0x73, (REG field)7: PSLLDQ

Divided (range) instructions, according to ModR/M byte value:
OCST_1dBYTES - 0xd8, 0xd9: FCOMP
OCST_1dBYTES - 0xd9, (REG)0: FLD
OCST_2dBYTES - 0x0f, 0xae, (REG)1: FXRSTOR
OCST_2dBYTES - 0x0f, 0xae, 0xe8: LFENCE

As you can see, reading a byte and using it as an index in the ROOT table, then testing the type,
lets you know whether you are required to read another byte, or another byte for its 3 bits AKA the REG field.
In 80x86 the FPU instructions have are split to two ranges, from 0x0 to 0xbf and from 0xc0 to 0xff.
If the second or third byte (depends on the instruction's opcode) of the instruction lies within the first range,
then this instruction uses the second byte as a ModR/M byte, thus you will know what instruction it is,
using the REG field in the ModR/M as an index into a group table. If the second or third byte (depends
on the instruction's opcode) of the instruction lies within the second (high) range, then this instruction uses the
second byte as a whole, so it becomes a normal two bytes long instruction.

The reason the ranges are split on 0xc0 is because in ModR/M value the two upper bits (most significant) represent the MOD.
If the MOD is 11b, according to the specs, it means the operation of the instruction is being done on registers and not memory.
In the FPU instructions set it's not possible for an instruction to use a general-purpose register (that's why MOD=11 is not useful).
So MOD!=11 uses memory indirection and this range (0x0-0xbf) of the ModR/M is enough to define an instruction with its operands in this case.
This leaves the upper range (0xc0-0xff) for static instructions, makes them 2 bytes long instructions.

In practice, the way a divided table is stored goes like this, this is the 72 entries table story:
From the preceding paragraph we learnt that these divided instructions actually require Group table and a Full table.
But in practice, we know that we don't really need a full table, this is because the upper range only uses that full table,
and the upper range itself is from 0xc0 to 0xff. So we can merge both table and save some space. 72 is the sum of 8 entries for Group table
and 64 entries for the upper range. A table of 72 entries is allocated then, if the instruction is two bytes long and static (upper range), then
we use the entry which is read using the index of the second byte's value subtracted by 0xb8 (skipping the first 8 entries, but it's 0xc0 based).
So far so good, if it's the lower range, (remember that we know we are expecting a divided instruction) we isolate the 3 bits of the REG field,
shift them to the right (making them zero-based) and accessing that entry in the table, this way we get to the low range instructions.

* Note that in diStorm, unlike Intel's specifications, the nubmer of bytes (in OCS types) COUNTS the mandatory byte!

/-------------------\
|3DNow! Instructions|
\-------------------/
The 3DNow! instruction set is kinda tricky, when I saw them for the first time, I said "What the heck?!", that was after I calmed down...
The format of a 3DNow! instruction doesn't follow the normal 80x86 architecture, so they have to be treated specially.
Luckily, it's not magic after all, it goes like:

---------------------------------------------------------------
| 0x0F | 0x0F | ModR/M | *SIB | *DISPLACEMENT | 3DNow! Opcode |
---------------------------------------------------------------
* means the element is optional.

The first thing you should be asking yourself is "How the heck will I decode the operands if I don't know their types?".
Well, no worry, it was truely impossible if that was the problem. The matter is that they are fixed types.
The first operand type is: MMREG,
and the second operand type is: MMREG/MEM64.
As you may know, the 3DNow! instructions set operates on MMX registers (MM0-MM7).

The second operand says it could be defined to use another MMX register (recall MOD=11),
or it could be a memory indirection addressing (MOD!=11), loading a 64 bits value off memory as an MMX value.

After encountering two bytes in a row of 0x0F, you know you hit a 3DNow! instruction.
The next thing you do is telling the decoder you know the operands' types already and feed them in brutally.
Then when you are done messing with the ModR/M and the other optional elements you get the instruction's name
(its mnemonic) by the last byte in the instruction.
This happens using another function which will begin seeking the instruction from ROOT[0x0F][0x0F]->[3dNow Opcode Index].

The extended 3DNow! instruction set works (formatted) the same way, so it only has to be inserted into the DB.

/-------------\
|Operand Types|
\-------------/
Reading the opcode of an instruction gives us its operands' types, without them we couldn't disassemble the instruction further.
The following finite set is taken from the source code, it includes all possible types of the 80x86 instructions.

The legend goes like this:
OT_ = Operand Type, its real type by the specs and the size of the type.
It's kinda self explanatory.
One more thing, that 'FULL' suffix is a special size case, it means that the size of the type is either 16 or 32 bits (or 64...).
The default size of 'FULL' depends solely on the decoding mode (that is passed in the API), and prefixes such as Operand Size,
which switch the size to the non-default. It is all explained already in the Operand Size section, but this is how it's practically done.
Let's have a simple example:
PKUDA 
So if we disassemble that instruction (which is named PKUDA) in 16 bits (or prefixed with operand size in 32 bits),
we can only use the general purpose registers such as: AX, CX, DX, BX, SP, etc...
But if we disassemble that instruction in 32 bits, or prefix it with operand size in 16 bits,
the general purpose registers become: EAX, ECX, EDX, EBX, ESP, etc...

So 'FULL' tells the operand type decoder function to examine for set prefixes and the decoding mode itself, and decide its size on the fly.
The rationale for naming it 'FULL' isn't so clever, I will just leave it this way.

typedef enum OpType{
	/* No operand is set */
	OT_NONE = 0,

	/* Read a byte(8 bits) immediate */
	OT_IMM8,
	/* Force a read of a word(16 bits) immediate, used by ret only */
	OT_IMM16,
	/* Read a word/dword immediate */
	OT_IMM_FULL,
	/* Read a double-word(32 bits) immediate */
	OT_IMM32,

	/* Special immediate for two instructions, AAM, AAD which will output the byte only if it's not 0xa (base 10) */
	OT_IMM_AADM,

	/* Read a signed extended byte(8 bits) immediate */
	OT_SEIMM8,

	/* Use a 8bit register */
	OT_REG8,
	/* Use a 16bit register */
	OT_REG16,
	/* Use a 16/32/64bit register */
	OT_REG_FULL,
	/* Use a 32bit register */
	OT_REG32,
	/* MOVSXD uses 64 bits register */
	OT_REG64,
	/*
	 * If used with REX the reg operand size becomes 64 bits, otherwise 32 bits.
	 * VMX instructions are promoted automatically without a REX prefix.
	 */
	OT_REG32_64,
	/* Extract a 32bit register from the RM field, used for instructions with register operands only */
	OT_REG32_RM,
	/* Used only by MOV CR/DR(n). Promoted with REX onlly. */
	OT_FREG32_64_RM,

	/* Use or read (indirection) a 8bit register or immediate byte */
	OT_RM8,
	/* Some instructions force 16 bits (mov sreg, rm16) */
	OT_RM16,
	/* Use or read a 16/32/64bit register or immediate word/dword/qword */
	OT_RM_FULL,
	/* Use or read a 32bit register or immediate dword */
	OT_RM32,
	/*
	 * 32 or 64 bits (with REX) operand size indirection memory operand.
	 * Some instructions are promoted automatically without a REX prefix.
	 */
	OT_RM32_64,
	/* 16 or 32 bits RM. This is used only with MOVZXD instruction in 64bits. */
	OT_RM16_32,
	/* Same as OT_RMXX but POINTS to 16 bits [cannot use GENERAL-PURPOSE REG!] */
	OT_FPUM16,
	/* Same as OT_RMXX but POINTS to 32 bits (single precision) [cannot use GENERAL-PURPOSE REG!] */
	OT_FPUM32,
	/* Same as OT_RMXX but POINTS to 64 bits (double precision) [cannot use GENERAL-PURPOSE REG!] */
	OT_FPUM64,
	/* Same as OT_RMXX but POINTS to 80 bits (extended precision) [cannot use GENERAL-PURPOSE REG!] */
	OT_FPUM80,

	/*
	 * Special ModR/M for PINSRW, which need a 16 bits memory operand or 32 bits register.
	 * In 16 bits decoding mode R32 becomes R16, operand size cannot affect this.
	 */
	OT_R32M16,

	/*
	 * Special operand type for MOV reg16/32/64/mem16, segReg 8C /r. and SMSW.
	 * It supports all decoding modes, but if used as a memory indirection it's a 16 bit ModR/M indirection.
	 */
	OT_RFULL_M16,

	/* Use a control register */
	OT_CREG,
	/* Use a debug register */
	OT_DREG,
	/* Use a segment register */
	OT_SREG,
	/*
	 * SEG is encoded in the flags of the opcode itself!
	 * This is used for specific "push SS" where SS is a segment where
	 * each "push SS" has an absolutely different opcode byte.
	 * We need this to detect whether an operand size prefix is used.
	 */
	OT_SEG,
	
	/* Use AL */
	OT_ACC8,
	/* Use AX/EAX/RAX */
	OT_ACC_FULL,
	/* Use AX/EAX, no REX is possible for RAX, used only with IN/OUT which don't support 64 bit registers */
	OT_ACC_FULL_NOT64,

	/*
	 * Read one word (seg), and a word/dword/qword (depends on operand size) from memory.
	 * JMP FAR [EBX] means EBX point to 16:32 ptr.
	 */
	OT_MEM16_FULL,
	/* Read one word (seg) and a word/dword/qword (depends on operand size), usually SEG:OFF, JMP 1234:1234 */
	OT_PTR16_FULL,
	/* Read one word (limit) and a dword/qword (limit) (depends on operand size), used by SGDT, SIDT, LGDT, LIDT. */
	OT_MEM16_3264,

	/* Read a byte(8 bits) immediate and calculate it relatively to the current offset of the instruction being decoded */
	OT_RELCB,
	/* Read a word/dword immediate and calculate it relatively to the current offset of the instruction being decoded */
	OT_RELC_FULL,

	/* Use general memory indirection, with varying sizes: */
	OT_MEM,
	OT_MEM64,
	OT_MEM128,
	/* Used for cmpxchg8b/16b. */
	OT_MEM64_128,

	/* Read an immediate as an absolute address, size is known by instruction, used by MOV (offset) only */
	OT_MOFFS,
	/* Use an immediate of 1, as for SHR R/M, 1 */
	OT_CONST1,
	/* Use CL, as for SHR R/M, CL */
	OT_REGCL,

	/*
	 * Instruction-Block for one byte long instructions, used by INC/DEC/PUSH/POP/XCHG,
	 * REG is extracted from the value of opcode
	 * Use a 8bit register
	 */
	OT_IB_RB,
	/* Use a 32 or 64bit (with REX) register, used by BSWAP */
	OT_IB_R_DW_QW,
	/* Use a 16/32/64bit register */
	OT_IB_R_FULL,

	/* Use [(E)SI] as INDIRECTION, for repeatable instructions */
	OT_REGI_ESI,
	/* Use [(E)DI] as INDIRECTION, for repeatable instructions */
	OT_REGI_EDI,
	/* Use [(e)BX + AL] as INDIRECTIOM, used by XLAT only */
	OT_REGI_EBXAL,
	/* Use DX, as for OUTS DX, BYTE [SI] */
	OT_REGDX,

	/* FPU registers: */
	OT_FPU_SI, /* ST(i) */
	OT_FPU_SSI, /* ST(0), ST(i) */
	OT_FPU_SIS, /* ST(i), ST(0) */

	/* MMX registers: */
	OT_MM,
	/* Extract the MMX register from the RM bits this time (used when the REG bits are used for opcode extension) */
	OT_MM_RM,
	/* ModR/M points to 32 bits MMX variable */
	OT_MM32,
	/* ModR/M points to 32 bits MMX variable */
	OT_MM64,

	/* SSE registers: */
	OT_XMM,
	/* Extract the SSE register from the RM bits this time (used when the REG bits are used for opcode extension) */
	OT_XMM_RM,
	/* ModR/M points to 32 bits SSE variable */
	OT_XMM32,
	/* ModR/M points to 64 bits SSE variable */
	OT_XMM64,
	/* ModR/M points to 128 bits SSE variable */
	OT_XMM128,

	/*
	 * DUMMY for cases like CALL WORD [BX+DI], we would like to omit this "WORD". It's useless,
	 * because the DWORD/WORD/BYTE mechanism is being done automatically, we need some way to disable it in such cases...
	 */
	OT_DUMMY
} _OpType;

The suffix 'RM' means that instead of decoding the register field from the REG bits, it will read it from the R/M bits of the ModR/M byte.
This is crucial when the REG bits are already used as a part of the opcode itself.
Except OT_REG types, all types which are suffixed by a size means that they are part of a ModR/M byte.
For example:
OT_XMM64, means that XMM register is used as a real register, or that it is stored/loaded to/fro memory.
ADDPD OT_XMM, OT_XMM128 - ADDPD XMM0, [EBX]
The memory pointed by EBX is used as an XMM variable with the instruction ADDPD.

The Forced REG/RM types mean that the operand size is set according to the decoding mode and nothing else.
Even in 64bits the instruction doesn't care about REX prefix and it will be promoted to 64 bits nevertheless.
Let's see a practical example, same stream in both modes.
32 bits: 0x0f, 0x78, 0xc1 VMREAD ECX, EAX
64 bits: 0x0f, 0x79, 0xc1 VMWRITE RAX, RCX

On the contrary, there are few instructions which needs the REX prefix in order to be promoted to 64bits.
A good example might be the MOV REG, IMM32 which becomes MOV REG64, IMM64 ONLY when prefixed with a REX.W.

It's time to cover the special 5 bits instructions (OT_IB_xxx).
I decided to call them Instruction-Block because the REG field is extracted from the other 3 (LS) bits, but in the Trie DB they look as follow:
0x40-0x47: INC 
0x48-0x4f: DEC 
0x50-0x57: PUSH 
And so on...
Because the Trie DB works in a byte granularity, the trick I used was to define one instruction per a block which its operand size is OT_IB_xxx,
where xxx is the operand's size. So when we encounter a byte in the range of 0x40-0x47 for instance, we read from the corresponding instruction's
information structure an operand type of OT_IB_R_FULL, which is interpreted in the operand type decoder function as "read the REG field from
the lower 3 bits", and of course, because in this case the size is FULL, it means the decoding mode and the prefixes affect the actual register size.


/---------------\
|Decoding Phases|
\---------------/
There are a few basic steps that a disassembler have to do,
they definitely depend on the way an 80x86 instruction is formatted.

1) [Prefixes]
So the first thing the disassembler does when it gets a binary stream (a pointer and a length) is looking for prefixes.
You read the prefixes as long as there are bytes in the stream to read and basically, untill you hit another byte which isn't a prefix.
There is one extra condition, 80x86 instructions can't be longer than 15 bytes, this rule includes prefixes as well.
After reading the prefixes, we make sure that we didn't reach the end of the stream,
if this is the case, we will simply drop all prefixes and exit the main loop.
Extra prefixes will be dropped after examining the prefixes when they are being scanned.

2) [Fetch Opcode]
This is a quiet tricky routine, because if we read a mandatory prefix, we still don't know it is a mandatory prefix.
So we have to look for an instruction that begins with that prefix and only if an instruction was found we know that that prefix was a mandatory one,
and not a normal prefix.
To get matters clear, here's an example:
0x66, 0x0f, 0xc1 (this will get to the opcode XADD with the prefix(0x66) treated really as operand size).
So how do we know whether 0x66 should be treated as a normal operand size prefix or as a mandatory prefix?
This is done only by trying to fetch the instruction beginning with 0x66 in the Instructions (ROOT) table.
If we don't end up with an existing instruction-information structure, we know that the 0x66 prefix should be treated as a normal operand size prefix.
And the catch here, is to start fetching the instruction from the real non-prefix byte (in the example it's the byte 0x0f).

0x66, 0x0f, 0x58 will get to the ADDPD opcode (SS2E).
But you might ask, what about the stream 0x0f, 0x58, where this lead to?
Well, you can reach an opcode from this stream, ADDPS (SSE).
Here's how ADDPS is defined by the specs:
ADDPD OT_XMM, OT_XMM128
So you see, there is no need for an operand size prefix no matter what, it won't affect the instruction.
This means that even if you encounter a mandatory prefix you can be sure it's there for a reason and a collision can't really happen.

Eventually, the fethcing routine will return an instruction-information structure, which can be also NULL (means no instruction was found).

3) [Filter Opcode]
There are a few conditions we would like to make sure an opcode, we just got, meet.
If the decoding mode is 16 bits and the opcode we got is only 32 bits, then it means we read an invalid opcode (we should drop it).
Or maybe we read an opcode which is invalid in 64 bits decoding mode (there are a lot of invalid opcode in 64 bits).
We also make sure there is a ModR/M byte read or maybe we have to read it now,
this is because, as you know, the second byte of the FPU opcode is the ModR/M byte (yes - only if it's in the low range), so it means
we already read the ModR/M byte and don't have to read it.
But other opcodes don't contain the ModR/M byte as a part of the opcode itself, so in this step we will read it.
Another type of opcodes is the xxx.3 bytes long instructions (the ones which require the REG field...), therefore we ought to read already
ModR/M byte already, in order to locate that instruction using the extra 3 bits into a Group table.
For 3DNow! instructions, we have to see whether we read 0x0f, 0x0f (3DNow! opcode base) and change the pointer we got from the second step
to point into a special instruction information structure which describes the operands' types of a 3DNow! instruction
(remember we can't find the instruction because its reversed format?).

4) [Extract Operand(s)]
This is an important step,
we will call a function which will textually format the operand according to the bytes in the stream.
This function will use the ModR/M we read earlier in order to determine some vuage information about the operands.
It will then read a SIB byte if required and decode it also.

For each operand in the opcode we read, we will extract its operand.
Just to remind you that an 80x86 instruction could have up to 3 operands.

The extraction routines are the core of the disassembler, they will analysis the operands types
and act upon them. If required an immediate will be read, or a displacement will be read too.
Most of the meat in the disassembler lies within these functions, they also take care of the prefixes set.
Let's say someone input the disassembler with an operand prefix and a 8bits operation instruction (for instance: 0x66; inc al).
What I am actually trying to say is that only after extracting the operands we can know whether a prefix was used or not.

5) [Text Formatting]
This is another important step, from all the info we got from the above steps, they are enough to make the instruction representation itself,
but sometimes we still don't have all info required to build an instruction.
So if we fetched a 3DNow! opcode it's time to get its mnemonic, so we know we have to read another byte which will lead us to the complete opcode.
In addition, there are a group of SSE compare instructions which need a two-letters suffix to specify the flags they test, they are kinda similar to 3DNow!
instruction, because only after decoding the whole instruction, you have to read another byte which specifies the flags the instruction should test.

Anyways, in this step we concatenates all strings together to form the instruction string.
First, we get the instruction's mnemonic from the instruction information structure, taking care of operand size prefix.
There are special instructions, which I call them, Native instructions, that have the same mnemonic no matter of the decoding mode, unless they prefixed.
Such as: pusha, popa, iret. when they are operand size prefixed, they will be suffixed with a letter indicating their operation-size.
For example in 16 and 32 bits decoding: 0x60 is pusha in both cases, but (in 16 bits) 0x66, 0x60 will become pushad...

There is another exception to mnemonic selection, this happens with the instruction JrCX,
because an operand size prefix affects its offset's size, then an address size prefix affects its mnemonic (actually, its operation size)!
The mnemonic the address size prefix changes is from JCXZ to JECXZ to JRCXZ (depends on the decoding mode, of course).
Did I hear anyone says that he doesn't like hacks?

If the lock prefix were used and weren't filtered out we would have to prepend the mnemonic with a "LOCK" string.
Or if the rep's prefixes were used and weren't filtered out we would have to prepend the mnemonic with a "REP/REPNZ" string.

Most of the strings work is done here.
If an instruction weren't found then the first byte is dropped.
I guess that I used the verb 'drop' over and over this documentation already.
What I mean by this is that the first byte of that invalid instruction is output as: "DB 0x??", where ?? is the hex value of that byte,
and we skip only that byte and continue disassembling.

At last, if we got to an invalid instruction, or there are not enough bytes to read a whole instruction,
or an operand was invalid (for example, some operands require MOD not to be 11, but it read a MOD of 11, it will be an invalid instruction then),
in all these cases the instruction is dropped (DB'ed).

6) [Hex Dump]
Before we disassemble the instruction itself we try to read all prefixes that precede the instruction itself.
If there are no prefixes, we simply continue on to decode the opcode, etc...

There are three types of prefixes:
1)Superfluous prefixes -
These prefixes are dropped automatically.
The algorithm I used in order to decide which prefixes are categorized in this type is as follows:
Every prefix can be used once, no matter its order. If that prefix is used again
or another prefix from that same prefix's type is used then all prefixes up to that prefixes are
dropped and treated as extra prefixes.

Streams and result, by example:
0x66 0x66 0x50: will drop the first 0x66.
0x67 0x66 0x66 0x50: will drop 0x67 and 0x66, because the first 0x66 is canceled, so are the prefixes before.

0xf0 0xf2 0x50: will drop 0xf0, because 0xf0 and 0xf2 are from the same type.

0xf0 0xf0 0xf2 0x66 0x2e 0x66 0x67 0x36:
notice it doesn't matter what happens with the first bytes,
because the second segment override cancels the first segment override,
therefore we are left with 0x66 0x67 0x36.

This algorithm isn't so smart and to be honest, I think that the processor does NOT work the same.
But I thought it's supposed to be enough for a good disassembler.
In the documentation it's not written what happens if a prefix from the same type appears twice or more.
It seems the processor simply ignores most of the extra prefixes, except the lock prefix which renders the instruction invalid.

I decided on purpose to not drop a lock-prefixed instruction so the user could see it.
This algorithm could be easily changed to something better, but I don't find any reason to change it as for now.
Maybe one should take a look at the open source emulators and see what's going on...
This is the most not-clear subjects in disassemblers and I bet that in processors too, I am open to hear anything about it,
and if there's a good reason, I will change the code. So give it a thought ot two.

2)Valid prefixes - 
These are the prefixes which weren't categorized as extra prefixes.
They are left to be used by the disassembler for the instructions itself.

3)Unused prefixes - 
These are the valid prefixes which weren't used by the disassembler.
We only know which prefixes belong to this category only after we disassembled the instruction itself.
For example:
0x66 0xb0, 0x55 will result in db 0x66; mov al, 0x55
because mov al is a 8 bit operation the operand size prefix can't affect this instruction.
Notice that the prefix itself is valid, but couldn't affect the instruction's behaviour so it wasn't used.

Unused prefixes have to be sorted by their position before we drop them,
this is because we can't tell their order in advance, that's what the function get_unused_prefixes_list responsible for.
Because we want to drop prefixes according to their order we have to sort them out, because when a prefix is counted as valid,
we set a flag which indiciates so (and do some other book keeping), but nothing more. Now, when we know the prefix wasn't used,
we only know that, for instance, only the operand size and segment override prefixes weren't used, but we don't know which we should output first...

You should pay attention to the way prefixes are dropped, this happens according to their types:
The first type (Superfluous) of prefixes are dropped as a seperated instruction per se.
The second type (valid) prefixes are copied to the beginning of the hex dump buffer, before the instruction's hex itself, of course.
The last type (unused) prefixes are dropped as a seperated instruction, but share the SAME address of the instruction they precede.

7) [Decoded Instruction]

- Basic knowledge for this step is how the disassembler's interface is implemented (which can be found below).

If the instruction doesn't preceded by any prefixes, we use the next available entry in the result array and continue to next instruction.

On the contrast, if the instruction is prefixed, we use the next available entry in the result array.
(yes you read it alright), this time, if something went wrong we undo that entry insertion.
I gave a thought for this subject, and I understood that most of the prefixes aren't going to do problems,
because afterall a disassembler is there for disassembling code and not garbage/random streams.
Therefore, we give a chance to that instruction and use the next available entry, because we assume it will eventually use it.
But then, if something bad happens - the prefix is unused or dropped - we store that disassemmbled instruction to a temporary memory,
and remove it from the result array, then we insert the dropped prefixes and only then we restore the disassembled instruction back
to the result array.

This is the familiar do-fail-undo concept -
You know that 99% you should do X, but 1% of the times, you shouldn't,
so you prefer to do it anyways, but if you encounter that 1%, you will fold back and undo it.

Maybe for some of you it seems a plain concept, but it really boosted the performance of diStorm...

Another rule with strings is to use the final-destination memory.
That is, avoiding the copying of strings from one location to the other.
After all, the disassembler's sole purpose is to generate text, because we mess with loads of strings,
it is important to not do useless strcpy's when you can do it once, without temporary memory.
Therefore, after retrieving a free entry from the result array I pass that structure to the decoding routine to use.
It might sound unworthy note, but when the only thing you generate is strings and tons of them, it becomes a critical optimization.

/------------------\
|Program Flow Graph|
\------------------/
I thought this will give you a harsh overview of the disassembler's system and how it works
(I use herein the real functions' names for simplicity):
Unfortunately it's not a graphical layout.

distorm_decode - API - does parameters validations.
  internal_decode - Used by the C library API and by Python's extenstion module, implements Decode-Phase #7.
    is_prefix - Quick way to tell if the next byte in the stream is a prefix.
      decode_prefixes - Implements Decode-Phase #6 (the prefixes stuff only).
    decode_inst - The disassembler's kernel, disassemble a single instruction.
      locate_inst - Try to find an SSE instruction (checking for mandatory prefixes) or a normal instruction.
        locate_raw_inst - Finds an instruction(opcode) according to the binary stream itself (doesn't care of prefixes etc).
      extract_operand dest, source, op3 - Decode the instruction's operands, start with dest, then source and rarely a 3rd operand.
        extract_modrm - Decode the operand according to the ModR/M byte of the instruction.
          extract_sib - Decode the operand according to the SIB byte of the instruction.
      locate_3dnow_inst - 3DNow! instruction are completed only after the whole instruction was disassembled, time to get their mnemonic.
    get_unused_prefixes_list - Retrieve the unused prefixes, if any.
    ## start all over again, until end of stream

This is the core hierarchy of the kernel of diStorm, this is just so you can quickly start messing with the code,
and when you see it you won't panic. Kernel Panic.
For more information you have the code.
distorm64-1.7.30/linuxproj/0000755000175000017500000000000011065513456014451 5ustar enderenderdistorm64-1.7.30/linuxproj/main.c0000644000175000017500000001277310664141310015541 0ustar enderender// diStorm64 library sample // http://ragestorm.net/distorm/ // Arkon, Stefan, 2005 // Mikhail, 2006 // JvW, 2007 #include #include #include #include #include #include // For the compilers who don't have sysexits.h, which is not an ISO/ANSI include! #define EX_OK 0 #define EX_USAGE 64 #define EX_DATAERR 65 #define EX_NOINPUT 66 #define EX_NOUSER 67 #define EX_NOHOST 68 #define EX_UNAVAILABLE 69 #define EX_SOFTWARE 70 #define EX_OSERR 71 #define EX_OSFILE 72 #define EX_CANTCREAT 73 #define EX_IOERR 74 #define EX_TEMPFAIL 75 #define EX_PROTOCOL 76 #define EX_NOPERM 77 #define EX_CONFIG 78 #include "../distorm.h" // The number of the array of instructions the decoder function will use to return the disassembled instructions. // Play with this value for performance... #define MAX_INSTRUCTIONS (1000) int main(int argc, char **argv) { // Version of used compiled library. unsigned int dver = 0; // Holds the result of the decoding. _DecodeResult res; // Decoded instruction information. _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; // next is used for instruction's offset synchronization. // decodedInstructionsCount holds the count of filled instructions' array by the decoder. unsigned int decodedInstructionsCount = 0, i, next; // Default decoding mode is 32 bits, could be set by command line. _DecodeType dt = Decode32Bits; // Default offset for buffer is 0, could be set in command line. _OffsetType offset = 0; char* errch = NULL; // Index to file name in argv. int param = 1; // Handling file. FILE* f; unsigned long filesize = 0, bytesread = 0; struct stat st; // Buffer to disassemble. unsigned char *buf, *buf2; // Disassembler version. dver = distorm_version(); printf("diStorm version: %u.%u.%u\n", (dver >> 16), ((dver) >> 8) & 0xff, dver & 0xff); // Check params. if (argc < 2 || argc > 4) { printf("Usage: ./disasm [-b16] [-b64] filename [memory offset]\r\nRaw disassembler output.\r\nMemory offset is origin of binary file in memory (address in hex).\r\nDefault decoding mode is -b32.\r\nexample: disasm -b16 demo.com 789a\r\n"); return EX_USAGE; } if (strncmp(argv[param], "-b16", 4) == 0) { dt = Decode16Bits; param++; } else if (strncmp(argv[param], "-b64", 4) == 0) { dt = Decode64Bits; param++; } else if (*argv[param] == '-') { fputs("Decoding mode size isn't specified!\n", stderr); return EX_USAGE; } else if (argc == 4) { fputs("Too many parameters are set.\n", stderr); return EX_USAGE; } if (param >= argc) { fputs("Filename is missing.\n", stderr); return EX_USAGE; } if (param + 1 == argc-1) { // extra param? #ifdef SUPPORT_64BIT_OFFSET offset = strtoull(argv[param + 1], &errch, 16); #else offset = strtoul(argv[param + 1], &errch, 16); #endif if (*errch != '\0') { fprintf(stderr, "Offset `%s' couldn't be converted.\n", argv[param + 1]); return EX_USAGE; } } f = fopen(argv[param], "rb"); if (f == NULL) { perror(argv[param]); return EX_NOINPUT; } if (fstat(fileno(f), &st) != 0) { perror("fstat"); fclose(f); return EX_NOINPUT; } filesize = st.st_size; // We read the whole file into memory in order to make life easier, // otherwise we would have to synchronize the code buffer as well (so instructions won't be split). buf2 = buf = malloc(filesize); if (buf == NULL) { perror("File too large."); fclose(f); return EX_UNAVAILABLE; } bytesread = fread(buf, 1, filesize, f); if (bytesread != filesize) { perror("Can't read file into memory."); free(buf); fclose(f); return EX_IOERR; } fclose(f); printf("bits: %d\nfilename: %s\norigin: ", dt == Decode16Bits ? 16 : dt == Decode32Bits ? 32 : 64, argv[param]); #ifdef SUPPORT_64BIT_OFFSET if (dt != Decode64Bits) printf("%08llx\n", offset); else printf("%016llx\n", offset); #else printf("%08x\n", offset); #endif // Decode the buffer at given offset (virtual address). while (1) { // If you get an undefined reference linker error for the following line, // change the SUPPORT_64BIT_OFFSET in distorm.h. res = distorm_decode(offset, (const unsigned char*)buf, filesize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); if (res == DECRES_INPUTERR) { // Null buffer? Decode type not 16/32/64? fputs("Input error, halting!\n", stderr); free(buf2); return EX_SOFTWARE; } for (i = 0; i < decodedInstructionsCount; i++) #ifdef SUPPORT_64BIT_OFFSET printf("%0*llx (%02d) %-24s %s%s%s\r\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); #else printf("%08x (%02d) %-24s %s%s%s\r\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); #endif if (res == DECRES_SUCCESS) break; // All instructions were decoded. else if (decodedInstructionsCount == 0) break; // Synchronize: next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset); next += decodedInstructions[decodedInstructionsCount-1].size; // Advance ptr and recalc offset. buf += next; filesize -= next; offset += next; } // Release buffer free(buf2); return EX_OK; } distorm64-1.7.30/linuxproj/Makefile0000644000175000017500000000032610454043060016100 0ustar enderender# # diStorm (Linux Port) / Demo Application Makefile # TARGET = disasm CC = gcc CFLAGS = -Wall -O2 -I. -o all: disasm disasm: ${CC} ${CFLAGS} ${TARGET} main.c ../distorm64.a clean: /bin/rm -rf *.o ${TARGET} distorm64-1.7.30/python/0000755000175000017500000000000011065513456013740 5ustar enderenderdistorm64-1.7.30/python/pydistorm.py0000644000175000017500000000701211015164206016332 0ustar enderender""" :[diStorm64 1.7.29}: Copyright RageStorm (C) 2007, Gil Dabah diStorm is licensed under the BSD license. http://ragestorm.net/distorm/ --- Python binding for diStorm64 written by Victor Stinner """ import platform from ctypes import cdll, c_long, c_ulong, c_int, c_uint, c_char, c_char_p, POINTER, c_byte, Structure, addressof, byref, c_void_p, create_string_buffer, sizeof, cast # Define (u)int32_t and (u)int64_t types int32_t = c_int uint32_t = c_uint if sizeof(c_ulong) == 8: int64_t = c_long uint64_t = c_ulong else: from ctypes import c_longlong, c_ulonglong assert sizeof(c_longlong) == 8 assert sizeof(c_ulonglong) == 8 int64_t = c_longlong uint64_t = c_ulonglong SUPPORT_64BIT_OFFSET = True if SUPPORT_64BIT_OFFSET: _OffsetType = uint64_t else: _OffsetType = uint32_t osVer = platform.system() if osVer == "Windows": LIB_FILENAME = "distorm64.dll" else: LIB_FILENAME = 'libdistorm64.so' distorm = cdll.LoadLibrary(LIB_FILENAME) Decode16Bits = 0 Decode32Bits = 1 Decode64Bits = 2 DECODERS = (Decode16Bits, Decode32Bits, Decode64Bits) if osVer == "Windows": if SUPPORT_64BIT_OFFSET: decode_func = distorm.distorm_decode64 else: decode_func = distorm.distorm_decode32 else: decode_func = distorm.internal_decode DECRES_NONE = 0 DECRES_SUCCESS = 1 DECRES_MEMORYERR = 2 DECRES_INPUTERR = 3 MAX_INSTRUCTIONS = 100 MAX_TEXT_SIZE = 60 class _WString(Structure): _fields_ = ( ("pos", c_uint), # Unused. ("p", c_char * MAX_TEXT_SIZE), ) def __str__(self): return self.p class _DecodedInst(Structure): _fields_ = ( ("mnemonic", _WString), ("operands", _WString), ("instructionHex", _WString), ("size", c_uint), ("offset", _OffsetType), ) def __str__(self): return "%s %s" % (self.mnemonic, self.operands) decode_func.argtypes = (_OffsetType, c_void_p, c_int, c_int, c_void_p, c_uint, POINTER(c_uint)) def Decode(codeOffset, code, dt=Decode32Bits): """ Errors: TypeError, IndexError, MemoryError, ValueError """ # Check arguments if not isinstance(codeOffset, (int, long)): raise TypeError("codeOffset have to be an integer") if not isinstance(code, str): raise TypeError("code have to be a string") if dt not in DECODERS: raise IndexError("Decoding-type must be either Decode16Bits, Decode32Bits or Decode64Bits.") # Allocate memory for decoder code_buffer = create_string_buffer(code) decodedInstructionsCount = c_uint() result = create_string_buffer(sizeof(_DecodedInst)*MAX_INSTRUCTIONS) # Prepare arguments codeLen = len(code) code = addressof(code_buffer) while codeLen: # Call internal decoder res = decode_func(codeOffset, code, codeLen, dt, result, MAX_INSTRUCTIONS, byref(decodedInstructionsCount)) # Check for errors if res == DECRES_INPUTERR: raise ValueError("Invalid argument") count = decodedInstructionsCount.value if res == DECRES_MEMORYERR and not count: raise MemoryError() # No more instruction if not count: break # Yield instruction and compute decoded size size = 0 instr_array = cast(result, POINTER(_DecodedInst)) for index in xrange(count): instr = instr_array[index] size += instr.size yield instr # Update parameters to move to next instructions code += size codeOffset += size codeLen -= size distorm64-1.7.30/python/README0000644000175000017500000000101111015662574014612 0ustar enderenderThis is a sample code of how to use diStorm as a dynamic library using Python's ctypes module. Compile diStorm as a DLL under Windows or as a Shared Object under *nix. Make sure the output file can be found by Python. --------- from pydistorm import Decode, Decode16Bits, Decode32Bits, Decode64Bits for i in Decode(0x100, open("file.com", "rb").read(), Decode16Bits): print "0x%08x (%02x) %-20s %s" % (i.offset, i.size, i.instructionHex, str(i.mnemonic) + " " + str(i.operands)) Victor Stinner, Gil Dabah May 2008 distorm64-1.7.30/README0000644000175000017500000000533711064272376013311 0ustar enderender:[diStorm64}: (v1.7.30) The ultimate disassembler library (for AMD64, X86-64). diStorm is licensed under the BSD license. For documentation and MUCH MORE please refer to doc/distorm.html. Directory Listing: -+---------------- doc/ - Contains documentation files. build/win32/ - Solution file for VS03. build/linux/ - Make file and installation script for Python. build/mac/ - Make file and installation script for Python2.3 (works for Tiger). src/ - Full source code. linuxproj/ - Raw file disassembler, sample project, shows how to use the C Library. win32proj/ - Ditto, but for Win32. ddkproj/ - A Windows kernel driver source that disassembles the beginning of KeBugCheck as an example. distorm.h - Header file for diStorm's C library (Used by win32proj and linuxproj). config.h - Compiler specific macros definitions (Endianity support too). NOTE - See config.h and distorm.h for library configuration (such as exports, size of integers, etc). Win32 Compilation: -+---------------- The distorm.sln file contains two projects: cdistorm and pydistorm. There are three configurations: clib, py24 and py23. 'clib' configuration will create a distorm.lib file for win32proj used with the header file (distorm.h). 'py25/24/23' configuration will create distorm.pyd in the corresponding directory, which should be copied into the Python\Lib\site-packages. You might want to change the directories of the Python library/include directories which are set in the configurations. There is also a 'dyndistorm' project which will create a distorm.dll file which you can use along with 'distorm.h'. Linux Compilation: -+---------------- The makefile will compile diStorm for clib and py24. 'make clib' will create a static archive library named 'distorm64.a' which is used by linuxproj. 'make py' will create a shared object file, named 'libdistorm64.so' which is installed with the instpython.sh script (have to be root for that). Mac Compilation: -+-------------- The makefile will compile diStorm for clib and py23. You can easily edit it to compile diStorm for py2x. See the 'Linux Compilation' above for how to use the makefile. You can also use the same sample of linux project. DDK Compilation (Ring0): -+---------------------- diStorm can also be compiled as a kernel driver, there's a sample bundled under ddkproj. Follow accurately all the steps in the ddkproj/readme file to accomplish this task. For updates please visit http://ragestorm.net/distorm/ Note that there are currently not-known bugs. Please contact me for any bugs that are found in the source code by reporting to me, so people could enjoy a better product! If you wish to contact me, use this email: arkon@ragestorm.net Gil Dabah May 2007 distorm64-1.7.30/src/0000755000175000017500000000000011065513456013206 5ustar enderenderdistorm64-1.7.30/src/decoder.c0000644000175000017500000006724711013167370014770 0ustar enderender/* decoder.c Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #include "decoder.h" #include "prefix.h" #include "textdefs.h" #include "x86defs.h" #include "operands.h" /* Instruction Prefixes - Opcode - ModR/M - SIB - Displacement - Immediate */ _DecodeType ADDR_SIZE_AFFECT(_DecodeType dt, _iflags totalPrefixes) { /* Switch to non default mode if prefix exists, only for ADDRESS SIZE. */ if (totalPrefixes & INST_PRE_ADDR_SIZE) { switch (dt) { case Decode16Bits: dt = Decode32Bits; break; case Decode32Bits: dt = Decode16Bits; break; case Decode64Bits: dt = Decode32Bits; break; } } return dt; } _DecodeType OP_SIZE_AFFECT(_DecodeType dt, _iflags totalPrefixes, unsigned int rex, _iflags instFlags) { switch (dt) { case Decode16Bits: /* Toggle to 32 bits. */ if (totalPrefixes & INST_PRE_OP_SIZE) dt = Decode32Bits; break; case Decode32Bits: /* Toggle to 16 bits. */ if (totalPrefixes & INST_PRE_OP_SIZE) dt = Decode16Bits; break; case Decode64Bits: /* * REX Prefix toggles data size to 64 bits. * Operand size prefix toggles data size to 16. * Default data size is 32 bits. * Promoted instructions are 64 bits if they don't require a REX perfix. * Non promoted instructions are 64 bits if the REX prefix exists. */ if (totalPrefixes & INST_PRE_OP_SIZE) dt = Decode16Bits; /* Automatically promoted instructions have only INST_64BITS SET! */ else if (((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS) || /* Other instructions in 64 bits can be promoted only with a REX prefix. */ ((totalPrefixes & INST_PRE_REX) && (rex & PREFIX_REX_W))) dt = Decode64Bits; else dt = Decode32Bits; /* Default. */ break; } return dt; } static int decode_inst(const uint8_t* code, int codeLen, _OffsetType codeOffset, _PrefixState* ps, _DecodeType dt, _DecodedInst* di) { /* The ModR/M byte of the current instruction. */ unsigned int modrm = 0; /* The REX prefix byte value. */ unsigned int rex = 0; /* * Backup original input, so we can use it later if a problem occurs * (like not enough data for decoding, invalid opcode, etc). */ _OffsetType lastCodeOffset = codeOffset; const uint8_t* lastCode = code; /* Holds the info about the current found instruction. */ _InstInfo* ii = NULL; /* Used only for special CMP instructions which have pseudo opcodes suffix. */ unsigned int cmpType = 0; /* Return code from extract_operand. */ _ExOpRCType rc = EO_HALT; /* * Indicates whether it is right to LOCK the instruction by decoding its first operand. * Only then you know if it's ok to output the LOCK prefix's text... * Used for first operand only. */ int lockable = 0; /* * Dummy lockable...ExtractOperand writes the pointer no matter what. * We pass it so we won't have an exception, and because real lock can only work on first operand. */ int dummyLockable; /* Return code, TRUE for decoding success, FALSE for failure. */ int retCode = TRUE; /* Packed params to pass to extract_operand, used for optimizing. */ _CodeInfo ci; memset(di, 0, sizeof(_DecodedInst)); ii = locate_inst(&code, &codeLen, &codeOffset, &di->instructionHex, ps, dt); /* * In this point we know the instruction we are about to decode and its operands (unless, it's an invalid one!), * so it makes it the right time for decoding-type suitability testing. * Which practically means, don't allow 32 bits instructions in 16 bits decoding mode, but do allow * 16 bits instructions in 32 bits decoding mode, of course... * NOTE: Make sure the instruction set for 32 bits has explicitly this specfic flag set. * NOTE2: Make sure the instruction set for 64 bits has explicitly this specfic flag set. * If this is the case, drop what we've got and restart all over after DB'ing that byte. * Though, don't drop an instruction which is also supported in 16 and 32 bits. */ /* ! ! ! (V1.4.10) DISABLED UNTIL FURTHER NOTICE ! ! ! Decode16Bits CAN NOW DECODE 32 BITS INSTRUCTIONS ! ! !*/ /* if (ii && (dt == Decode16Bits) && (ii->flags & INST_32BITS) && (~ii->flags & INST_16BITS)) ii = NULL; */ /* Drop instructions which are invalid in 64 bits. */ if (ii && (dt == Decode64Bits) && (ii->flags & INST_INVALID_64BITS)) ii = NULL; /* If it's only a 64 bits instruction drop it in other decoding modes. */ if (ii && (dt != Decode64Bits) && (ii->flags & INST_64BITS_FETCH)) ii = NULL; /* code points to the last instruction-byte read, so if the instruction needs the ModR/M byte, we'll just read it. */ if (ii && (ii->d != OT_NONE) && (ii->d != OT_DUMMY) && (ii->flags & INST_INCLUDE_MODRM)) { modrm = *code; str_hex_b(&di->instructionHex, modrm); if (--codeLen < 0) ii = NULL; code++; codeOffset++; /* If the instruction uses only register operands, mod=11 is a must! */ if (ii && (ii->flags & INST_MODRR) && (modrm < INST_DIVIDED_MODRM)) ii = NULL; } /* Store REX value for further tests. */ if (ps->isREXPrefixValid) rex = *ps->rexpos; /* * V 1.7.28 - Treat NOP/XCHG specially. * If we're not in 64bits restore XCHG to NOP, since in the DB it's XCHG. * Else if we're in 64bits examine REX, if exists, and decide which instruction should should go to output. * 48 90 XCHG RAX, RAX is a true NOP (eat REX in this case because it's valid). * 90 XCHG EAX, EAX is a true NOP (and not high dword of RAX = 0 because it should be a 32 bits operation). */ if (ii == &II_90) { if ((dt != Decode64Bits) || (~rex & PREFIX_REX_B)) ii = &II_nop; if (rex & PREFIX_REX_W) ps->usedPrefixes |= INST_PRE_REX; } /* V 1.7.29 - Ignore segment override prefixes for LEA instruction. */ if (ii == &II_8D) ps->totalPrefixes &= ~(INST_PRE_SEGOVRD_MASK); ci.code = code; ci.codeLen = codeLen; ci.codeOffset = codeOffset; if (ii && (ii->d != OT_NONE) && (ii->d != OT_DUMMY)) { rc = extract_operand(&ci, &di->instructionHex, &di->operands, (_OpType)ii->d, (_OpType)ii->s, ONT_1, ii->flags, modrm, ps, dt, &lockable); if (rc == EO_HALT) ii = NULL; } if (ii && (ii->s != OT_NONE) && (ii->s != OT_DUMMY)) { strcat_WSN(&di->operands, SEP_STR); rc = extract_operand(&ci, &di->instructionHex, &di->operands, (_OpType)ii->s, (_OpType)ii->d, ONT_2, ii->flags, modrm, ps, dt, &dummyLockable); if (rc == EO_HALT) ii = NULL; } /* Use third operand, only if the flags says this InstInfo requires it. */ if (ii && (ii->flags & INST_USE_OP3) && (((_InstInfoEx*)ii)->op3 != OT_NONE) && (((_InstInfoEx*)ii)->op3 != OT_DUMMY)) { strcat_WSN(&di->operands, SEP_STR); rc = extract_operand(&ci, &di->instructionHex, &di->operands, (_OpType)((_InstInfoEx*)ii)->op3, OT_NONE, ONT_3, ii->flags, modrm, ps, dt, &dummyLockable); if (rc == EO_HALT) ii = NULL; } /* V 1.7.26 Support for a fourth operand is added for INSERTQ instruction. */ if (ii && (ii->flags & INST_USE_OP4)) { strcat_WSN(&di->operands, SEP_STR); rc = extract_operand(&ci, &di->instructionHex, &di->operands, (_OpType)((_InstInfoEx*)ii)->op4, OT_NONE, ONT_4, ii->flags, modrm, ps, dt, &dummyLockable); if (rc == EO_HALT) ii = NULL; } /* * Remove extra space in operands text buffer if required. * V1.5.12 - The pos test was added to avoid memory access exceeding bounds. */ if ((di->operands.pos >= 2) && (di->operands.p[di->operands.pos-2] == SEP_CHR)) { di->operands.p[di->operands.pos-2] = '\0'; di->operands.pos -= 2; } /* If it were a 3DNow! instruction, we will have to find the instruction itself now that we got its operands extracted. */ if (ii && ii->flags & INST_3DNOW_FETCH) ii = locate_3dnow_inst(&ci, &di->instructionHex); code = ci.code; codeLen = ci.codeLen; codeOffset = ci.codeOffset; /* * There's a limit of 15 bytes on instruction length. The only way to violate * this limit is by putting redundant prefixes before an instruction. * start points to first prefix if any, otherwise it points to instruction first byte. */ if ((code - ps->start) > INST_MAXIMUM_SIZE) ii = NULL; /* Drop instruction. */ /* Check whether pseudo opcode is needed, only for CMP instructions: */ if (ii && (ii->flags & INST_PSEUDO_OPCODE)) { cmpType = *code; /* Comparison type must be between 0 to 8, otherwise Reserved. */ if (cmpType >= INST_CMP_MAX_RANGE) ii = NULL; else str_hex_b(&di->instructionHex, cmpType); if (--codeLen < 0) ii = NULL; code++; codeOffset++; } /* * If ii is valid, we located the instruction in the DB and extracted operands. * Otherwise, some problem occurred while decoding it. */ if (ii) { /* * Use the correct mnemonic according to the DT. * If we are in 32 bits decoding mode it doesn't necessarily mean we will choose mnemonic2, alas, * it means that if there is a mnemonic2, it will be used. */ strclear_WS(&di->mnemonic); /* It's time for adding prefixes' texts if needed. */ /* Start with prefix LOCK. */ if ((lockable == 1) && (ii->flags & INST_PRE_LOCK)) { ps->usedPrefixes |= INST_PRE_LOCK; strcpy_WSN(&di->mnemonic, PREFIX_LOCK_TEXT); } else if ((ii->flags & INST_PRE_REPNZ) && (ps->totalPrefixes & INST_PRE_REPNZ)) { ps->usedPrefixes |= INST_PRE_REPNZ; strcpy_WS(&di->mnemonic, PREFIX_REPNZ_TEXT); } else if ((ii->flags & INST_PRE_REP) && (ps->totalPrefixes & INST_PRE_REP)) { ps->usedPrefixes |= INST_PRE_REP; strcpy_WSN(&di->mnemonic, PREFIX_REP_TEXT); } /* If it's JeCXZ the ADDR_SIZE prefix affects them. */ if ((ii->flags & (INST_PRE_ADDR_SIZE | INST_USE_EXMNEMONIC)) == (INST_PRE_ADDR_SIZE | INST_USE_EXMNEMONIC)) { ps->usedPrefixes |= (ps->totalPrefixes & INST_PRE_ADDR_SIZE); if (ADDR_SIZE_AFFECT(dt, ps->totalPrefixes) == Decode16Bits) strcatlen_WS(&di->mnemonic, &ii->mnemonic[1], ii->mnemonic[0]); else if (ADDR_SIZE_AFFECT(dt, ps->totalPrefixes) == Decode32Bits) strcatlen_WS(&di->mnemonic, &((_InstInfoEx*)ii)->mnemonic2[1], ((_InstInfoEx*)ii)->mnemonic2[0]); /* Ignore REX.W in 64bits, JECXZ is promoted. */ else /* Decode64Bits */ strcatlen_WS(&di->mnemonic, &((_InstInfoEx*)ii)->mnemonic3[1], ((_InstInfoEx*)ii)->mnemonic3[0]); } /* V1.1.8 LOOPxx instructions are also native instruction, but they are special case ones, ADDR_SIZE prefix affects them. */ else if ((ii->flags & (INST_PRE_ADDR_SIZE | INST_NATIVE)) == (INST_PRE_ADDR_SIZE | INST_NATIVE)) { strcpylen_WS(&di->mnemonic, &ii->mnemonic[1], ii->mnemonic[0]); /* We only enter the next if statement if the addr-size prefix is set, this behaviour is Native's. */ /* Ignore REX.W in 64bits, LOOPxx is promoted. */ if (ps->totalPrefixes & INST_PRE_ADDR_SIZE) { ps->usedPrefixes |= (ps->totalPrefixes & INST_PRE_ADDR_SIZE); if (ADDR_SIZE_AFFECT(dt, ps->totalPrefixes) == Decode16Bits) chrcat_WS(&di->mnemonic, SUFFIX_SIZE_WORD); else if (ADDR_SIZE_AFFECT(dt, ps->totalPrefixes) == Decode32Bits) chrcat_WS(&di->mnemonic, SUFFIX_SIZE_DWORD); else /* Decode64Bits */ chrcat_WS(&di->mnemonic, SUFFIX_SIZE_QWORD); } } /* * Note: * If the instruction is prefixed by operand size we will format it in the non-default decoding mode! * So there might be a situation that an instruction of 32 bit gets formatted in 16 bits decoding mode. * Both ways should end up with a corrected and expected formatting of the text. */ else if (OP_SIZE_AFFECT(dt, ps->totalPrefixes, rex, ii->flags) == Decode16Bits) { /* Decode16Bits */ /* * If it's a special instruction which has two mnemonics, then use the 16 bits one + update usedPrefixes. * Note: use 16 bits mnemonic if that instruction supports 32 bit or 64 bit explicitly. */ if ((ii->flags & INST_USE_EXMNEMONIC) && ((ii->flags & (INST_32BITS | INST_64BITS)) == 0)) ps->usedPrefixes |= (ps->totalPrefixes & INST_PRE_OP_SIZE); strcatlen_WS(&di->mnemonic, &ii->mnemonic[1], ii->mnemonic[0]); /* Add a suffix letter for repeatable/xlat instructions only. */ if (rc == EO_SUFFIX) { /* Is it a 16 bits operation? */ if (ii->flags & INST_16BITS) chrcat_WS(&di->mnemonic, SUFFIX_SIZE_WORD); else chrcat_WS(&di->mnemonic, SUFFIX_SIZE_BYTE); /* It's 8 bits operation then. */ } /* Add a suffix, if it's a native instruction (making it 16 bits). */ if ((ii->flags & INST_NATIVE) && (ps->totalPrefixes & INST_PRE_OP_SIZE)) { ps->usedPrefixes |= INST_PRE_OP_SIZE; chrcat_WS(&di->mnemonic, SUFFIX_SIZE_WORD); } } else if (OP_SIZE_AFFECT(dt, ps->totalPrefixes, rex, ii->flags) == Decode32Bits) { /* Decode32Bits */ /* Give a chance for special mnemonic instruction in 32 bits decoding. */ if (ii->flags & INST_USE_EXMNEMONIC) { ps->usedPrefixes |= (ps->totalPrefixes & INST_PRE_OP_SIZE); /* Is it a special instruction which has another mnemonic for mod=11 ? */ if (ii->flags & INST_MODRM_BASED) { if (modrm >= INST_DIVIDED_MODRM) strcatlen_WS(&di->mnemonic, &ii->mnemonic[1], ii->mnemonic[0]); else strcatlen_WS(&di->mnemonic, &((_InstInfoEx*)ii)->mnemonic2[1], ((_InstInfoEx*)ii)->mnemonic2[0]); } /* Or is it a special CMP instruction which needs a pseudo opcode suffix ? */ else if (ii->flags & INST_PSEUDO_OPCODE) { /* So we have to read the imm8 which tells us which comparison type it is. */ strcpylen_WS(&di->mnemonic, &ii->mnemonic[1], ii->mnemonic[0]); str_x86def(&di->mnemonic, &_CONDITIONS_PSEUDO[cmpType]); strcatlen_WS(&di->mnemonic, &((_InstInfoEx*)ii)->mnemonic2[1], ((_InstInfoEx*)ii)->mnemonic2[0]); } else strcatlen_WS(&di->mnemonic, &((_InstInfoEx*)ii)->mnemonic2[1], ((_InstInfoEx*)ii)->mnemonic2[0]); /* Two-mnemonics instructions. */ } else strcatlen_WS(&di->mnemonic, &ii->mnemonic[1], ii->mnemonic[0]); /* Add a suffix letter for repeatable(/xlat) instructions only. */ if (rc == EO_SUFFIX) { /* Is it a 16 bits operation (means 32 bits in 32 bit decoding mode)? */ if (ii->flags & INST_16BITS) chrcat_WS(&di->mnemonic, SUFFIX_SIZE_DWORD); else chrcat_WS(&di->mnemonic, SUFFIX_SIZE_BYTE); /* It's 8 bits operation then. */ } /* Add a suffix, if it's a native instruction (making it 32 bits). */ if ((ii->flags & INST_NATIVE) && (ps->totalPrefixes & INST_PRE_OP_SIZE)) { ps->usedPrefixes |= INST_PRE_OP_SIZE; chrcat_WS(&di->mnemonic, SUFFIX_SIZE_DWORD); } } else { /* Decode64Bits */ /* /////////////////////////////////////////////////////////////////////////////////////////// */ if (ii->flags & (INST_USE_EXMNEMONIC | INST_USE_EXMNEMONIC2)) { /* Is it a special instruction which has another mnemonic for mod=11 ? */ if (ii->flags & INST_MODRM_BASED) { if (modrm >= INST_DIVIDED_MODRM) strcatlen_WS(&di->mnemonic, &ii->mnemonic[1], ii->mnemonic[0]); else strcatlen_WS(&di->mnemonic, &((_InstInfoEx*)ii)->mnemonic2[1], ((_InstInfoEx*)ii)->mnemonic2[0]); } /* Or is it a special CMP instruction which needs a pseudo opcode suffix ? */ else if (ii->flags & INST_PSEUDO_OPCODE) { /* So we have to read the imm8 which tells us which comparison type it is. */ strcpylen_WS(&di->mnemonic, &ii->mnemonic[1], ii->mnemonic[0]); str_x86def(&di->mnemonic, &_CONDITIONS_PSEUDO[cmpType]); strcatlen_WS(&di->mnemonic, &((_InstInfoEx*)ii)->mnemonic2[1], ((_InstInfoEx*)ii)->mnemonic2[0]); } else /* Use third mnemonic, for 64 bits. */ if ((ii->flags & INST_USE_EXMNEMONIC2) && (ps->isREXPrefixValid) && (rex & PREFIX_REX_W)) { ps->usedPrefixes |= INST_PRE_REX; strcatlen_WS(&di->mnemonic, &((_InstInfoEx*)ii)->mnemonic3[1], ((_InstInfoEx*)ii)->mnemonic3[0]); } else strcatlen_WS(&di->mnemonic, &((_InstInfoEx*)ii)->mnemonic2[1], ((_InstInfoEx*)ii)->mnemonic2[0]); /* Use second mnemonic. */ } else strcatlen_WS(&di->mnemonic, &ii->mnemonic[1], ii->mnemonic[0]); /* /////////////////////////////////////////////////////////////////////////////////////////// */ /* Add a suffix letter for repeatable(/xlat) instructions only. */ if (rc == EO_SUFFIX) { /* Is it a 16 bits operation (means 64 bits in 64 bit decoding mode)? */ if (ii->flags & INST_16BITS) { if (ii->flags & INST_64BITS) { ps->usedPrefixes |= INST_PRE_REX; chrcat_WS(&di->mnemonic, SUFFIX_SIZE_QWORD); } else chrcat_WS(&di->mnemonic, SUFFIX_SIZE_DWORD); } else chrcat_WS(&di->mnemonic, SUFFIX_SIZE_BYTE); /* It's 8 bits operation then. */ } /* Add a suffix, if it's a native instruction (making it 64 bits). */ if (ii->flags & INST_NATIVE) { if (ps->totalPrefixes & INST_PRE_OP_SIZE) { /* Operand size. */ ps->usedPrefixes |= INST_PRE_OP_SIZE; chrcat_WS(&di->mnemonic, SUFFIX_SIZE_WORD); /* 16 Bits. */ } /* See if a REX prefix is required, otherwise ignore it. */ else if ((ps->totalPrefixes & INST_PRE_REX) && (rex & PREFIX_REX_W) && ((ii->flags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX))) { /* REX.W is set, mark it. */ ps->usedPrefixes |= INST_PRE_REX; chrcat_WS(&di->mnemonic, SUFFIX_SIZE_QWORD); /* 64 Bits. */ } } } } else { strclear_WS(&di->operands); /* Special case for WAIT instruction: If it's dropped, you have to return a valid instruction! */ if (*lastCode == WAIT_INSTRUCTION_CODE) { codeOffset = lastCodeOffset + 1; strcpy_WS(&di->instructionHex, get_hex_b(WAIT_INSTRUCTION_CODE)); strcpy_WSN(&di->mnemonic, WAIT_INSTRUCTION_MNEMONIC); ps->usedPrefixes = 0; } else { /* * Exclude the first byte, couldn't decode that instruction. * So just DB(define byte) it and skip it. * Fix codeOffset, because we've lost track of them (code, codeOffset, codeLen)! * The caller calculates them again every instruction according to the size we return which is based on codeOffset. * A fix for codeOffset is necessary because below the decoded-instruction size depends on it. */ codeOffset = lastCodeOffset + 1; /* + 1 for what we are DB'ing. */ strcpy_WS(&di->instructionHex, get_hex_b(*lastCode)); strcpy_WSN(&di->mnemonic, BYTE_UNDEFINED); str_code_sp_hb(&di->mnemonic, *lastCode); /* Clean operands just in case... */ ps->usedPrefixes = 0; /* Drop'em all. */ /* Mark that we didn't manage to decode the instruction well. */ retCode = FALSE; } } /* Calculate the size of the instruction we've just decoded. */ di->size = (unsigned int)(codeOffset - lastCodeOffset); return retCode; } _DecodeResult internal_decode(_OffsetType codeOffset, const uint8_t* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxResultCount, unsigned int* usedInstructionsCount) { _PrefixState ps; unsigned int prefixSize; /* * This is used for printing only, it is the real offset of where the whole instruction begins. * We need this variable in addition to codeOffset, because prefixes might change the real offset an instruction begins at. * So we keep track of both. */ _OffsetType startCodeOffset = 0; _WString hex; int isInstructionPopped = FALSE; uint8_t unusedPrefixesList[MAX_PREFIXES]; const uint8_t* p; unsigned int i; /* Current working decoded instruction. */ unsigned int nextPos = 0; /* in result. */ _DecodedInst *pdi = NULL, di; /* No entries are used yet. */ *usedInstructionsCount = 0; /* Decode instructions as long as we have what to decode/enough room in entries. */ while (codeLen > 0) { /* startCodeOffset holds the displayed offset of current instruction. */ startCodeOffset = codeOffset; /* Decode prefixes: */ strclear_WS(&hex); memset(&ps, 0, sizeof(_PrefixState)); ps.start = code; ps.last = code; prefixSize = 0; if (is_prefix(*code, dt)) { /* Most chances there are no prefixes at all, so give it a try. */ decode_prefixes(code, codeLen, &ps, dt); /* Count prefixes, start points to first valid prefix. */ prefixSize = (int)(ps.last - ps.start); /* Drop extra prefixes if any. */ if (ps.start != code) { /* Make sure there is enough room. */ if (nextPos + (ps.start - code) > maxResultCount) return DECRES_MEMORYERR; /* Not enough then. */ for (p = code; p < ps.start; p++, codeOffset++, codeLen--, code++) { /* Use next entry. */ pdi = &result[nextPos++]; strcpy_WSN(&pdi->mnemonic, BYTE_UNDEFINED); str_code_sp_hb(&pdi->mnemonic, *p); strclear_WS(&pdi->operands); strcpy_WS(&pdi->instructionHex, get_hex_b(*p)); pdi->size = 1; pdi->offset = codeOffset; } *usedInstructionsCount = nextPos; /* So far so good. */ /* These prefixes were really dropped, so update the displayable offset as well. */ startCodeOffset = codeOffset; } /* Update variables to take effect of the prefixes existence. */ codeLen -= prefixSize; /* * It might be that we will just notice that we ran out of bytes, * so we will have to drop all prefixes and halt. */ if (codeLen <= 0) { /* Make sure there is enough room. */ if (nextPos + (ps.last - code) > maxResultCount) return DECRES_MEMORYERR; for (p = code; p < ps.last; p++, startCodeOffset++) { /* Use next entry. */ pdi = &result[nextPos++]; strcpy_WSN(&pdi->mnemonic, BYTE_UNDEFINED); str_code_sp_hb(&pdi->mnemonic, *p); strclear_WS(&pdi->operands); strcpy_WS(&pdi->instructionHex, get_hex_b(*p)); pdi->size = 1; pdi->offset = startCodeOffset; } *usedInstructionsCount = nextPos; /* Include them all. */ break; /* Bye bye, out of bytes. */ } code += prefixSize; codeOffset += prefixSize; /*usedInstructionsCount = nextPos; */ /* Take them into account. */ } /* * Now we decode the instruction and only then we do further prefixes handling. * This is because the instruction could not be decoded at all, or an instruction requires * a mandatory prefix, or some of the prefixes were useless, etc... * Even if there were a mandatory prefix, we already took into account its size as a normal prefix. * so prefixSize includes that, and the returned size in di is simply the size of the real(=without prefixes) instruction. * If the instruction were decoded successfully, we will have to build a prefix hex string and drop unused prefixes. * Otherwise drop all instructions. * In 64 bits, we have to validate that the REX prefix precedes immediately the first opcode byte. * If so, remove it, and take into account we disabled it, in the unused prefixes! */ if (dt == Decode64Bits) { if (ps.totalPrefixes & INST_PRE_REX) { if (ps.rexpos != (code-1)) ps.totalPrefixes &= ~INST_PRE_REX; else { ps.isREXPrefixValid = 1; /* * Now check out if Operand Size is still valid, because REX has precedence over Operand Size prefix. * So if this is the case, we will simply disable Operand Size prefix. * Note that it happens only if REX.W is set ! */ if (*ps.rexpos & PREFIX_REX_W) ps.totalPrefixes &= ~INST_PRE_OP_SIZE; /* Could be mandatory prefix later. */ } } /* In 64 bits, segment overrides of CS, DS, ES and SS are ignored. So don't take'em into account. */ ps.totalPrefixes &= ~(INST_PRE_CS | INST_PRE_SS | INST_PRE_DS | INST_PRE_ES); } /* * Make sure there is at least one more entry to fill, for the upcoming instruction. * Though in practice it could be used for an ignored prefix... */ if (nextPos + 1 > maxResultCount) return DECRES_MEMORYERR; if (prefixSize > 0) { /* * Assume: if instruction is prefixed, it won't ignore the prefixes. * This is because we rely on the fact that the disassembler will decode 99% of the times real code. * Thus, it will be faster to treat the prefixes as correct, in case the assumption is wrong, * we will have to fold back, and pay twice for this assumption, because we will have to backup pdi and restore it later. * For example: we assume c is 0 in most of the times (if it's 1 we subtract b): a += b; if (c) a -= 2 * b; */ pdi = &result[nextPos++]; isInstructionPopped = FALSE; if (decode_inst(code, codeLen, codeOffset, &ps, dt, pdi)) { /* * Build a prefix string including all VALID prefixes. Maximum 5 prefixes. * Note that we don't care whether or not we turned the last prefix into a mandatory one, * ps.last is changed if required to affect this. */ for (p = ps.start; p < ps.last; p++) { str_hex_b(&hex, *p); chrcat_WS(&hex, SP_CHR); } /* List the prefixes which weren't used at all, although they are treated as valid. */ get_unused_prefixes_list(unusedPrefixesList, &ps); if (ps.unusedCount > 0) { if (nextPos + ps.unusedCount > maxResultCount) return DECRES_MEMORYERR; /* Pop the instruction from the array. */ memcpy(&di, pdi, sizeof(_DecodedInst)); isInstructionPopped = TRUE; nextPos--; /* Insert the dropped prefixes in their place. */ for (i = 0; i < ps.unusedCount; i++) { /* Use next entry. */ pdi = &result[nextPos++]; strcpy_WSN(&pdi->mnemonic, BYTE_UNDEFINED); str_code_sp_hb(&pdi->mnemonic, unusedPrefixesList[i]); strclear_WS(&pdi->operands); strcpy_WS(&pdi->instructionHex, get_hex_b(unusedPrefixesList[i])); pdi->size = 1; pdi->offset = startCodeOffset; } } /* * Intentionally usedInstructionsCount is not updated here, * simply because if we run out of entries, we won't be able to synchronize the decoding again from this point. * This is true, because unused prefixes can't be skipped (we don't know their exact order). */ } else { /* No success in decoding. */ /* * Drop all prefixes, because the instruction wasn't successfully decoded. * After we tried to decode an instruction, it could be that we have a mandatory prefix * that we would like to drop too (along with REX). */ ps.last += ps.specialPrefixesSize; if (ps.last - ps.start > 0) { if (nextPos + (ps.last - ps.start) > maxResultCount) return DECRES_MEMORYERR; /* Pop the instruction from the array. */ memcpy(&di, pdi, sizeof(_DecodedInst)); isInstructionPopped = TRUE; nextPos--; for (p = ps.start; p < ps.last; p++, startCodeOffset++) { /* Use next entry. */ pdi = &result[nextPos++]; strcpy_WSN(&pdi->mnemonic, BYTE_UNDEFINED); str_code_sp_hb(&pdi->mnemonic, *p); strclear_WS(&pdi->operands); strcpy_WS(&pdi->instructionHex, get_hex_b(*p)); pdi->size = 1; pdi->offset = startCodeOffset; } prefixSize = 0; *usedInstructionsCount = nextPos; } } if (isInstructionPopped) { /* Restore instruction. */ pdi = &result[nextPos++]; memcpy(pdi, &di, sizeof(_DecodedInst)); } /* else pdi already points to the instruction. */ /* Advance to next instruction. */ codeLen -= pdi->size; codeOffset += pdi->size; code += pdi->size; pdi->size += prefixSize; pdi->offset = startCodeOffset; /* Concat the instruction's hex to the prefixes' hex. */ strcatlen_WS(&hex, (const int8_t*)pdi->instructionHex.p, pdi->instructionHex.pos); memcpy(&pdi->instructionHex.p, &hex.p, hex.pos + 1); } else { /* No prefixes! Only instruction. */ /* Use the next available entry without doubt. */ pdi = &result[nextPos++]; decode_inst(code, codeLen, codeOffset, &ps, dt, pdi); pdi->offset = startCodeOffset; /* Advance to next instruction. */ codeLen -= pdi->size; codeOffset += pdi->size; code += pdi->size; } /* Alright, the caller can read, at least, up to this one. */ *usedInstructionsCount = nextPos; } return DECRES_SUCCESS; } distorm64-1.7.30/src/decoder.h0000644000175000017500000000224111013167270014753 0ustar enderender/* decoder.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #ifndef DECODER_H #define DECODER_H #include "../config.h" #include "wstring.h" typedef unsigned int _iflags; /* DEFAULT instructions decoding mode. */ typedef enum {Decode16Bits = 0, Decode32Bits = 1, Decode64Bits = 2} _DecodeType; typedef OFFSET_INTEGER _OffsetType; typedef struct { _WString mnemonic; _WString operands; _WString instructionHex; unsigned int size; _OffsetType offset; } _DecodedInst; typedef struct { const uint8_t* code; int codeLen; _OffsetType codeOffset; } _CodeInfo; typedef enum {DECRES_NONE, DECRES_SUCCESS, DECRES_MEMORYERR, DECRES_INPUTERR} _DecodeResult; _DecodeResult internal_decode(_OffsetType codeOffset, const uint8_t* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxResultCount, unsigned int* usedEntriesCount); _DecodeType ADDR_SIZE_AFFECT(_DecodeType dt, _iflags totalPrefixes); _DecodeType OP_SIZE_AFFECT(_DecodeType dt, _iflags totalPrefixes, unsigned int rex, _iflags instFlags); #endif /* DECODER_H */ distorm64-1.7.30/src/distorm.c0000644000175000017500000000315011013167314015021 0ustar enderender/* distorm.c :[diStorm64}: C Library Interface The ultimate disassembler library (80x86, AMD64) Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #include "../config.h" #include "decoder.h" #include "x86defs.h" /* C LIBRARY EXPORTS */ #ifdef SUPPORT_64BIT_OFFSET _DLLEXPORT_ _DecodeResult distorm_decode64(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) #else _DLLEXPORT_ _DecodeResult distorm_decode32(_OffsetType codeOffset, const unsigned char* code, int codeLen, _DecodeType dt, _DecodedInst result[], unsigned int maxInstructions, unsigned int* usedInstructionsCount) #endif { *usedInstructionsCount = 0; /* I use codeLen as a signed variable in order to ease detection of underflow... and besides - */ if (codeLen < 0) { return DECRES_INPUTERR; } if ((dt != Decode16Bits) && (dt != Decode32Bits) && (dt != Decode64Bits)) { return DECRES_INPUTERR; } if (code == NULL || result == NULL) { return DECRES_INPUTERR; } /* Assume length=0 is success. */ if (codeLen == 0) { return DECRES_SUCCESS; } /* We need to supply at least 15 entries so the internal_decoder could return anything possible. */ if (maxInstructions < INST_MAXIMUM_SIZE) { return DECRES_MEMORYERR; } return internal_decode(codeOffset, code, codeLen, dt, result, maxInstructions, usedInstructionsCount); } _DLLEXPORT_ unsigned int distorm_version() { return DISTORM_VER; } distorm64-1.7.30/src/instructions.c0000644000175000017500000004336710753530316016130 0ustar enderender/* instructions.c Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #include "instructions.h" #include "insts.h" #include "prefix.h" #include "textdefs.h" #include "x86defs.h" #include "wstring.h" /* I use the trie data structure as I found it most fitting to a disassembler mechanism. When you read a byte and have to decide if it's enough or you should read more bytes, 'till you get to the instruction information. It's really fast because you POP the instruction info in top 3 iterates on the DB, because an instruction can be formed from two bytes + 3 bits reg from the ModR/M byte. For a simple explanation, check this out: http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/Trie/ Futher reading: http://en.wikipedia.org/wiki/Trie The first GATE (array you read off a trie data structure), as I call them, is statically allocated by the compiler. The second and third gates if used are being allocated dynamically by the instructions-insertion functionality. How would such a thing look in memory, say we support 4 instructions with 3 bytes top (means 2 dynamically allocated gates). -> |-------| 0, |0| -------------------------------> |-------| |1|RET | 1, |0|AND | |2| -----> |-------| |1|XOR | |3|INT3 | |0|PUSH | |2|OR | 0,3, |-------| |1|POP | |3| --------->|-------| |2|PUSHF| |-------| |0|ROR | |3|POPF | |1|ROL | |-------| |2|SHR | |3|SHL | |-------| Of course, this is NOT how Intel instructions set looks!!! but I just wanted to give a small demonstration. Now the instructions you get from such a trie DB goes like this: 0, 0 - AND 0, 1 - XOR 0, 2 - OR 0, 3, 0, ROR 0, 3, 1, ROL 0, 3, 2, SHR 0, 3, 3, SHL 1 - RET 2, 0 - PUSH 2, 1 - POP 2, 2 - PUSHF 2, 3 - POPF 3 - INT3 I guess it's clear by now. So now, if you read 0, you know that you have to enter the second gate(list) with the second byte specifying the index. But if you read 1, you know that you go to an instruction (in this case, a RET). That's why there's an Instruction-Node structure, it tells you whether you got to an instruction or another list so you should keep on reading byte). In Intel, you could go through 4 gates at top, because there're instructions which are built from 2 bytes and another smaller list for the REG part, or newest SSE4 instructions which use 4 bytes for opcode. Therefore, Intel's first gate is 256 long, and other gates are 256 (/72) or 8 long, yes, it costs pretty much alot of memory for non-used defined instructions, but I think that it still rocks. */ /* * This function is reponsible to return the instruction information of the first found in code. * It returns the _InstInfo of the found instruction, otherwise NULL. * code should point to the ModR/M byte upon exit (if used), or after the instruction binary code itself. * This function is NOT decoding-type dependant, it is up to the caller to see whether the instruction is valid. * Get the instruction info, using a Trie data structure. * I call it "raw", because it simply locates an instruction, it doesn't care what bytes it's using, such as prefixes. */ static _InstInfo* locate_raw_inst(const uint8_t** code0, int* codeLen0, _OffsetType* codeOffset0, _WString* instructionHex, int isREXPrefixValid, _DecodeType dt) { const uint8_t* code = *code0; int codeLen = *codeLen0; _OffsetType codeOffset = *codeOffset0; unsigned int tmpIndex0 = 0, tmpIndex1 = 0, tmpIndex2 = 0, tmpIndex3 = 0; _InstNode* in = NULL; _InstInfo* ii = NULL; /* Precaution. */ if (codeLen <= 0) return NULL; tmpIndex0 = *code; /* Check for NULL node for index 0. */ in = (_InstNode*)Instructions.list[Instructions.ids[tmpIndex0]]; if (in == NULL) return NULL; /* Single byte instruction (OCST_1BYTE). */ if (in->type == INT_INFO) { str_hex_b(instructionHex, tmpIndex0); codeLen -= 1; if (codeLen < 0) return NULL; code += 1; codeOffset += 1; *code0 = code; *codeLen0 = codeLen; *codeOffset0 = codeOffset; /* * ARPL/MOVSXD share the same instruction number, and both have different operands and mnemonics, of course. * Practically, I couldn't come up with a comfortable way to merge the operands' types of ARPL/MOVSXD. * And since the DB can't be patched dynamically, because the DB has to be multi-threaded compliant, * I have no choice but to check for ARPL/MOVSXD right here - "right about now, the funk soul brother, check it out now, the funk soul brother...", fatboy slim */ if (tmpIndex0 == INST_ARPL_INDEX) return dt == Decode64Bits ? (_InstInfo*)&II_movsxd : &II_arpl; return (_InstInfo*)in; } /* Single byte instruction + reg bits (OCST_13BYTES). */ if (in->type == INT_LIST_GROUP) { str_hex_b(instructionHex, tmpIndex0); codeLen -= 1; if (codeLen <= 0) return NULL; code += 1; codeOffset += 1; *code0 = code; *codeLen0 = codeLen; *codeOffset0 = codeOffset; return (_InstInfo*)in->list[in->ids[(*code >> 3) & 7]]; } /* Single byte instruction + reg byte OR one whole byte (OCST_1dBYTES). */ if (in->type == INT_LIST_DIVIDED) { str_hex_b(instructionHex, tmpIndex0); codeLen -= 1; if (codeLen <= 0) return NULL; code += 1; codeOffset += 1; tmpIndex1 = *code; /* OCST_1dBYTES is relatively simple to OCST_2dBYTES, since it's really divided at 0xc0. */ if (tmpIndex1 < INST_DIVIDED_MODRM) { /* An instruction which requires a ModR/M byte. Thus it's 1.3 bytes long instruction. */ tmpIndex1 = (tmpIndex1 >> 3) & 7; /* Isolate the 3 REG/OPCODE bits. */ } else { /* Normal 2 bytes instruction. */ str_hex_b(instructionHex, tmpIndex1); codeLen -= 1; if (codeLen < 0) return NULL; code += 1; codeOffset += 1; /* * Divided instructions can't be in the range of 0x8-0xc0. * That's because 0-8 are used for 3 bits group. * And 0xc0-0xff are used for not-divided instruction. * So the inbetween range is omitted, thus saving some more place in the tables. */ tmpIndex1 -= INST_DIVIDED_MODRM - 8; } *code0 = code; *codeLen0 = codeLen; *codeOffset0 = codeOffset; return (_InstInfo*)in->list[in->ids[tmpIndex1]]; } /* At least 2 bytes long instruction. */ if (in->type == INT_LIST_FULL) { str_hex_b(instructionHex, tmpIndex0); if (isREXPrefixValid) { /* Skip REX prefix byte. */ codeLen -= 1; if (codeLen <= 0) return NULL; code += 1; codeOffset += 1; str_hex_sp_b(instructionHex, *code); chrcat_WS(instructionHex, SP_CHR); } codeLen -= 1; if (codeLen <= 0) return NULL; code += 1; codeOffset += 1; tmpIndex1 = *code; in = (_InstNode*)in->list[in->ids[tmpIndex1]]; /* Check for NULL node for index 1. */ if (in == NULL) return NULL; /* This is where we check if we just read two escape bytes in a row, which means it is a 3DNow! instruction. */ if ((tmpIndex0 == _3DNOW_ESCAPE_BYTE) && (tmpIndex1 == _3DNOW_ESCAPE_BYTE)) { str_hex_b(instructionHex, tmpIndex1); chrcat_WS(instructionHex, SP_CHR); codeLen -= 1; if (codeLen < 0) return NULL; code += 1; codeOffset += 1; *code0 = code; *codeLen0 = codeLen; *codeOffset0 = codeOffset; return &II_3dnow; } /* 2 bytes instruction (OCST_2BYTES). */ if (in->type == INT_INFO) { str_hex_b(instructionHex, tmpIndex1); codeLen -= 1; if (codeLen < 0) return NULL; code += 1; codeOffset += 1; *code0 = code; *codeLen0 = codeLen; *codeOffset0 = codeOffset; return (_InstInfo*)in; } /* 2 bytes + reg instruction (OCST_23BYTES). */ if (in->type == INT_LIST_GROUP) { str_hex_b(instructionHex, tmpIndex1); codeLen -= 1; if (codeLen <= 0) return NULL; code += 1; codeOffset += 1; *code0 = code; *codeLen0 = codeLen; *codeOffset0 = codeOffset; return (_InstInfo*)in->list[in->ids[(*code >> 3) & 7]]; } /* 2 bytes + divided range (OCST_2dBYTES). */ if (in->type == INT_LIST_DIVIDED) { str_hex_b(instructionHex, tmpIndex1); codeLen -= 1; if (codeLen <= 0) return NULL; code += 1; codeOffset += 1; tmpIndex2 = *code; ii = (_InstInfo*)in->list[in->ids[(tmpIndex2 >> 3) & 7]]; /* * OCST_2dBYTES is complex, because there are a few instruction which are not divided in special cases, etc... * If the instruction wasn't divided (but still it must be a 2.3) or it was an official 2.3 (because its index was less than 0xc0) * Then it means the instruction should be using the REG bits, otherwise give a chance to range 0xc0-0xff. */ if ((ii != NULL) && ((ii->flags & INST_NOT_DIVIDED) || (tmpIndex2 < INST_DIVIDED_MODRM))) ii = (_InstInfo*)in->list[in->ids[(tmpIndex2 >> 3) & 7]]; else if (tmpIndex2 >= INST_DIVIDED_MODRM) ii = (_InstInfo*)in->list[in->ids[tmpIndex2 - INST_DIVIDED_MODRM + 8]]; /* Divided tables are smaller, range 0x8-0xc0 is omitted. */ /* V 1.5.13 - It might be that we got here without touching ii in the above if statements, then it becomes invalid instruction prolly. */ if ((ii != NULL) && ((ii->flags & INST_INCLUDE_MODRM) == 0)) { /* Read 3 whole bytes, for divided instructions which have no ModR/M byte. */ str_hex_b(instructionHex, tmpIndex2); codeLen -= 1; if (codeLen < 0) return NULL; code += 1; codeOffset += 1; } *code0 = code; *codeLen0 = codeLen; *codeOffset0 = codeOffset; return ii; } /* At least 3 bytes (OCST_3BYTES). */ if (in->type == INT_LIST_FULL) { str_hex_b(instructionHex, tmpIndex1); codeLen -= 1; if (codeLen < 0) return NULL; code += 1; codeOffset += 1; tmpIndex2 = *code; /* OCST_3BYTES. */ in = (_InstNode*)in->list[in->ids[tmpIndex2]]; /* Check for NULL node for index 2. */ if (in == NULL) return NULL; if (in->type == INT_INFO) { str_hex_b(instructionHex, tmpIndex2); codeLen -= 1; if (codeLen < 0) return NULL; code += 1; codeOffset += 1; *code0 = code; *codeLen0 = codeLen; *codeOffset0 = codeOffset; return (_InstInfo*)in; } /* 3.3 bytes (OCST_33BYTES). */ if (in->type == INT_LIST_GROUP) { str_hex_b(instructionHex, tmpIndex2); codeLen -= 1; if (codeLen <= 0) return NULL; code += 1; codeOffset += 1; *code0 = code; *codeLen0 = codeLen; *codeOffset0 = codeOffset; return (_InstInfo*)in->list[in->ids[(*code >> 3) & 7]]; } /* If we reached here, it's at least 4 bytes opcode. */ if (in->type == INT_LIST_FULL) { str_hex_b(instructionHex, tmpIndex2); codeLen -= 1; if (codeLen < 0) return NULL; code += 1; codeOffset += 1; tmpIndex3 = *code; /* OCST_4BYTES */ in = (_InstNode*)in->list[in->ids[tmpIndex3]]; /* Check for NULL node for index 3. */ if (in == NULL) return NULL; if (in->type == INT_INFO) { str_hex_b(instructionHex, tmpIndex3); codeLen -= 1; if (codeLen < 0) return NULL; code += 1; codeOffset += 1; *code0 = code; *codeLen0 = codeLen; *codeOffset0 = codeOffset; return (_InstInfo*)in; } } } } /* Kahtchinggg, damn. */ return NULL; } /* Locate an instruction, give chance to S/SSE/2/3 instructions which need the prefix as a nomral byte instruction! */ _InstInfo* locate_inst(const uint8_t** code, int* codeLen, _OffsetType* codeOffset, _WString* instructionHex, _PrefixState* ps, _DecodeType dt) { _InstInfo* ii = NULL; unsigned int lastCodeLen = *codeLen; _OffsetType lastCodeOffset = *codeOffset; const uint8_t* lastCode = *code; unsigned int lastBC = 0; /* byte code. */ /* Keep last byte code (a prefix), read from ps->last only if we skipped prefixes. */ if (ps->start < ps->last) { /* * V1.1.7 - read the byte code only if exists! - FIXED * If REX prefixes the opcode, it won't necessarily mean another prefix precedes the REX... */ if (ps->isREXPrefixValid && (ps->start <= ps->last - 2)) lastBC = *(ps->last - 2); /* Skip REX prefix byte. */ else lastBC = *(ps->last-1); /* This might read a REX, but we don't care then. */ } /* * Sometimes normal prefixes become mandatory prefixes, which means they are now part of the instruction opcode bytes. * This is a bit tricky now, * if the first byte is a REP (F3) prefix, we will have to give a chance to an SSE instruction. * If an instruction doesn't exist, we will make it as a prefix and re-locateinst. * A case such that a REP prefix is being changed into an instruction byte and also an SSE instruction will not be found can't happen, * simply because there are no collisions between string instruction and SSE instructions (they are escaped). * As for S/SSE2/3, check for F2 and 66 as well. * In 64 bits, we have to make sure that we will skip the REX prefix, if it exists. * There's a specific case, where a 66 is mandatory but it was dropped because REG.W was used, * but it doesn't behave as an operand size prefix but as a mandatory, so we will have to take it into account. * For example (64 bits decoding mode): * 66 98 CBW * 48 98 CDQE * 66 48 98: db 0x66; CDQE * Shows that operand size is dropped. * Now, it's a mandatory prefix and NOT an operand size one. * 66480f2dc0 db 0x48; CVTPD2PI XMM0, XMM0 * Although this instruction doesn't require a REX.W, it just shows, that even if it did - it doesn't matter. * REX.W is dropped because it's not requried, but the decode function disabled the operand size even so. */ if ((lastBC == PREFIX_REP) || (lastBC == PREFIX_REPNZ) || (lastBC == PREFIX_OP_SIZE)) { /* Take the prefix into account, making it an instruction byte. */ if (ps->isREXPrefixValid) { (*code) -= 2; (*codeLen) += 2; (*codeOffset) -= 2; } else { (*code)--; (*codeLen)++; (*codeOffset)--; } ii = locate_raw_inst(code, codeLen, codeOffset, instructionHex, ps->isREXPrefixValid, dt); if (ii) { /* * An S/SSE/2/3 instruction was found, * so remove the last prefix. It is now a mandatory prefix and skip REX as usual. * Let the decode function know that we turned a prefix into mandatory one. * So if some problem occurs later, we will know to handle it specially because of this end case. */ if (ps->isREXPrefixValid) { ps->last -= 2; ps->specialPrefixesSize = 2; /* REX + SSE. */ } else { ps->last--; ps->specialPrefixesSize = 1; /* SSE only. */ } /* Remove that flag specifically. */ switch (lastBC) { case PREFIX_REP: ps->totalPrefixes &= ~INST_PRE_LOKREP_MASK; ps->lokrepPos = NULL; break; case PREFIX_REPNZ: ps->totalPrefixes &= ~INST_PRE_LOKREP_MASK; ps->lokrepPos = NULL; break; case PREFIX_OP_SIZE: ps->totalPrefixes &= ~INST_PRE_OP_SIZE; ps->opsizePos = NULL; break; } } else { /* Undo: */ strclear_WS(instructionHex); /* Remove output prefix. */ *code = lastCode; *codeLen = lastCodeLen; *codeOffset = lastCodeOffset; } } /* No instruction was found before, so it's a "simple" one: */ if (ii == NULL) ii = locate_raw_inst(code, codeLen, codeOffset, instructionHex, 0, dt); return ii; } /* * 3DNow! instruction handling: * This is used when we encounter a 3DNow! instruction. * We can't really locate a 3DNow! instruction before we see two escaped bytes, * 0x0f, 0x0f. Then we have to extract operands which are, dest=mmx register, src=mmx register or quadword indirection. * When we are finished with the extraction of operands we can resume to locate the instruction by reading another byte * which tells us which 3DNow instruction we really tracked down... * So in order to tell the extract operands function which operands the 3DNow! instruction require, we need to set up some * generic instruction info for 3DNow! instructions. * In the locate_inst itself, when we read an OCST_3BYTES which the two first bytes are 0x0f and 0x0f. * we will return this special generic II for the specific operands we are interested in (MM, MM64). * Then after extracting the operand, we'll call a completion routine for locating the instruction * which will be called only for 3DNow! instructions, distinguished by a flag, and it will read the last byte of the 3 bytes. */ _InstInfo II_3dnow = {INT_INFO, ISCT_3DNOW, OT_MM64, OT_MM, (int8_t*) "\x0a" "_3DNow! II", INST_32BITS | INST_INCLUDE_MODRM | INST_3DNOW_FETCH}; _InstInfo* locate_3dnow_inst(_CodeInfo* ci, _WString* instructionHex) { unsigned int tmpIndex2 = *ci->code; /* Start off from the two escape bytes gates... which is 3DNow! table.*/ _InstNode* in = &Table_0F_0F; /* V1.6.20 - the following expression is fixed, so instructions can be fetched. */ in = (_InstNode*)in->list[in->ids[tmpIndex2]]; if ((in != NULL) && (in->type == INT_INFO)) { str_hex_sp_b(instructionHex, tmpIndex2); ci->codeLen -= 1; if (ci->codeLen < 0) return NULL; ci->code += 1; ci->codeOffset += 1; return (_InstInfo*)in; } return NULL; } void str_indirection_text(_WString* s, _OperandSizeType opSize) { switch (opSize) { case OPERAND_SIZE_NONE: break; case OPERAND_SIZE8: strcat_WSN(s, TEXT_8_BITS); break; case OPERAND_SIZE16: strcat_WSN(s, TEXT_16_BITS); break; case OPERAND_SIZE32: strcat_WSN(s, TEXT_32_BITS); break; case OPERAND_SIZE64: strcat_WSN(s, TEXT_64_BITS); break; case OPERAND_SIZE80: strcat_WSN(s, TEXT_80_BITS); break; case OPERAND_SIZE128: strcat_WSN(s, TEXT_128_BITS); break; } } distorm64-1.7.30/src/instructions.h0000644000175000017500000003643211014441532016120 0ustar enderender/* instructions.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #ifndef INSTRUCTIONS_H #define INSTRUCTIONS_H #include "../config.h" #include "decoder.h" #include "prefix.h" /* * Operand type possibilities: * Note "_FULL" suffix indicates to decode the operand as 16 bits or 32 bits depends on DecodeType - * actually, it depends on the decoding mode, unless there's an operand/address size prefix. * For example, the code: 33 c0 could be decoded/executed as XOR AX, AX or XOR EAX, EAX. */ typedef enum OpType { /* No operand is set */ OT_NONE = 0, /* Read a byte(8 bits) immediate */ OT_IMM8, /* Force a read of a word(16 bits) immediate, used by ret only */ OT_IMM16, /* Read a word/dword immediate */ OT_IMM_FULL, /* Read a double-word(32 bits) immediate */ OT_IMM32, /* Special immediate for two instructions, AAM, AAD which will output the byte only if it's not 0xa (base 10) */ OT_IMM_AADM, /* Read a signed extended byte(8 bits) immediate */ OT_SEIMM8, /* Use a 8bit register */ OT_REG8, /* Use a 16bit register */ OT_REG16, /* Use a 16/32/64bit register */ OT_REG_FULL, /* Use a 32bit register */ OT_REG32, /* MOVSXD uses 64 bits register */ OT_REG64, /* * If used with REX the reg operand size becomes 64 bits, otherwise 32 bits. * VMX instructions are promoted automatically without a REX prefix. */ OT_REG32_64, /* Extract a 32bit register from the RM field, used for instructions with register operands only */ OT_REG32_RM, /* Used only by MOV CR/DR(n). Promoted with REX onlly. */ OT_FREG32_64_RM, /* Use or read (indirection) a 8bit register or immediate byte */ OT_RM8, /* Some instructions force 16 bits (mov sreg, rm16) */ OT_RM16, /* Use or read a 16/32/64bit register or immediate word/dword/qword */ OT_RM_FULL, /* Use or read a 32bit register or immediate dword */ OT_RM32, /* * 32 or 64 bits (with REX) operand size indirection memory operand. * Some instructions are promoted automatically without a REX prefix. */ OT_RM32_64, /* 16 or 32 bits RM. This is used only with MOVZXD instruction in 64bits. */ OT_RM16_32, /* Same as OT_RMXX but POINTS to 16 bits [cannot use GENERAL-PURPOSE REG!] */ OT_FPUM16, /* Same as OT_RMXX but POINTS to 32 bits (single precision) [cannot use GENERAL-PURPOSE REG!] */ OT_FPUM32, /* Same as OT_RMXX but POINTS to 64 bits (double precision) [cannot use GENERAL-PURPOSE REG!] */ OT_FPUM64, /* Same as OT_RMXX but POINTS to 80 bits (extended precision) [cannot use GENERAL-PURPOSE REG!] */ OT_FPUM80, /* * Special operand type for SSE4 where the ModR/M might * be a 32 bits register or 8 bits memory indirection operand. */ OT_R32_M8, /* * Special ModR/M for PINSRW, which need a 16 bits memory operand or 32 bits register. * In 16 bits decoding mode R32 becomes R16, operand size cannot affect this. */ OT_R32_M16, /* * Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or * a 8 bits memory indirection operand. */ OT_R32_64_M8, /* * Special type for SSE4, ModR/M might be a 32 bits or 64 bits (with REX) register or * a 16 bits memory indirection operand. */ OT_R32_64_M16, /* * Special operand type for MOV reg16/32/64/mem16, segReg 8C /r. and SMSW. * It supports all decoding modes, but if used as a memory indirection it's a 16 bit ModR/M indirection. */ OT_RFULL_M16, /* Use a control register */ OT_CREG, /* Use a debug register */ OT_DREG, /* Use a segment register */ OT_SREG, /* * SEG is encoded in the flags of the opcode itself! * This is used for specific "push SS" where SS is a segment where * each "push SS" has an absolutely different opcode byte. * We need this to detect whether an operand size prefix is used. */ OT_SEG, /* Use AL */ OT_ACC8, /* Use AX (FSTSW) */ OT_ACC16, /* Use AX/EAX/RAX */ OT_ACC_FULL, /* Use AX/EAX, no REX is possible for RAX, used only with IN/OUT which don't support 64 bit registers */ OT_ACC_FULL_NOT64, /* * Read one word (seg), and a word/dword/qword (depends on operand size) from memory. * JMP FAR [EBX] means EBX point to 16:32 ptr. */ OT_MEM16_FULL, /* Read one word (seg) and a word/dword/qword (depends on operand size), usually SEG:OFF, JMP 1234:1234 */ OT_PTR16_FULL, /* Read one word (limit) and a dword/qword (limit) (depends on operand size), used by SGDT, SIDT, LGDT, LIDT. */ OT_MEM16_3264, /* Read a byte(8 bits) immediate and calculate it relatively to the current offset of the instruction being decoded */ OT_RELCB, /* Read a word/dword immediate and calculate it relatively to the current offset of the instruction being decoded */ OT_RELC_FULL, /* Use general memory indirection, with varying sizes: */ OT_MEM, OT_MEM32, /* Memory dereference for MOVNTI, either 32 or 64 bits (with REX). */ OT_MEM32_64, OT_MEM64, OT_MEM128, /* Used for cmpxchg8b/16b. */ OT_MEM64_128, /* Read an immediate as an absolute address, size is known by instruction, used by MOV (offset) only */ OT_MOFFS, /* Use an immediate of 1, as for SHR R/M, 1 */ OT_CONST1, /* Use CL, as for SHR R/M, CL */ OT_REGCL, /* * Instruction-Block for one byte long instructions, used by INC/DEC/PUSH/POP/XCHG, * REG is extracted from the value of opcode * Use a 8bit register */ OT_IB_RB, /* Use a 32 or 64bit (with REX) register, used by BSWAP */ OT_IB_R_DW_QW, /* Use a 16/32/64bit register */ OT_IB_R_FULL, /* Use [(r)SI] as INDIRECTION, for repeatable instructions */ OT_REGI_ESI, /* Use [(r)DI] as INDIRECTION, for repeatable instructions */ OT_REGI_EDI, /* Use [(r)BX + AL] as INDIRECTIOM, used by XLAT only */ OT_REGI_EBXAL, /* Use [(r)AX] as INDIRECTION, used by AMD's SVM instructions */ OT_REGI_EAX, /* Use DX, as for OUTS DX, BYTE [SI] */ OT_REGDX, /* Use ECX in INVLPGA instruction */ OT_REGECX, /* FPU registers: */ OT_FPU_SI, /* ST(i) */ OT_FPU_SSI, /* ST(0), ST(i) */ OT_FPU_SIS, /* ST(i), ST(0) */ /* MMX registers: */ OT_MM, /* Extract the MMX register from the RM bits this time (used when the REG bits are used for opcode extension) */ OT_MM_RM, /* ModR/M points to 32 bits MMX variable */ OT_MM32, /* ModR/M points to 32 bits MMX variable */ OT_MM64, /* SSE registers: */ OT_XMM, /* Extract the SSE register from the RM bits this time (used when the REG bits are used for opcode extension) */ OT_XMM_RM, /* ModR/M points to 16 bits SSE variable */ OT_XMM16, /* ModR/M points to 32 bits SSE variable */ OT_XMM32, /* ModR/M points to 64 bits SSE variable */ OT_XMM64, /* ModR/M points to 128 bits SSE variable */ OT_XMM128, /* Implied XMM0 register as operand, used in SSE4. */ OT_REGXMM0, /* * DUMMY for cases like CALL WORD [BX+DI], we would like to omit this "WORD". It's useless, * because the DWORD/WORD/BYTE mechanism is being done automatically, we need some way to disable it in such cases... */ OT_DUMMY } _OpType; /* Flags for instruction: */ /* Empty flags indicator: */ #define INST_FLAGS_NONE ((_iflags)-1) /* * Explicitly define that the instruction doesn't require a ModRM byte. * NOTE its value is 0! you can't do much with it, it is used for instructions that for sure don't use the ModR/M byte. */ #define INST_EXCLUDE_MODRM (0) /* The instruction we are going to decode has a ModR/M byte. */ #define INST_INCLUDE_MODRM (1) /* Special treatment for instructions which are in the divided-category but still needs the whole byte for ModR/M... */ #define INST_NOT_DIVIDED (1 << 1) /* * Used explicitly in repeatable instructions, * which needs a suffix letter in their mnemonic to specify operation-size (depend on operands). */ #define INST_16BITS (1 << 2) /* If the opcode is supported by 80286 and upper models (16/32 bits). */ #define INST_32BITS (1 << 3) /* * Prefix flags (4 types: lock/rep, seg override, addr-size, oper-size) * There are several specific instructions that can follow LOCK prefix, * note that they must be using a memory operand form, otherwise they generate an exception. */ #define INST_PRE_LOCK (1 << 4) /* REPNZ prefix for string instructions only - means an instruction can follow it. */ #define INST_PRE_REPNZ (1 << 5) /* REP prefix for string instructions only - means an instruction can follow it. */ #define INST_PRE_REP (1 << 6) /* CS override prefix. */ #define INST_PRE_CS (1 << 7) /* SS override prefix. */ #define INST_PRE_SS (1 << 8) /* DS override prefix. */ #define INST_PRE_DS (1 << 9) /* ES override prefix. */ #define INST_PRE_ES (1 << 10) /* FS override prefix. Funky Segment :) */ #define INST_PRE_FS (1 << 11) /* GS override prefix. Groovy Segment, of course not, duh ! */ #define INST_PRE_GS (1 << 12) /* Switch operand size from 32 to 16 and vice versa. */ #define INST_PRE_OP_SIZE (1 << 13) /* Switch address size from 32 to 16 and vice versa. */ #define INST_PRE_ADDR_SIZE (1 << 14) /* Native instructions which needs suffix letter to indicate their operation-size (and don't depend on operands). */ #define INST_NATIVE (1 << 15) /* Use extended mnemonic, means it's an _InstInfoEx structure, which contains another mnemonic for 32 bits specifically. */ #define INST_USE_EXMNEMONIC (1 << 16) /* Use third operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */ #define INST_USE_OP3 (1 << 17) /* Use fourth operand, means it's an _InstInfoEx structure, which contains another operand for special instructions. */ #define INST_USE_OP4 (1 << 18) /* The instruction's mnemonic depends on the mod value of the ModR/M byte (mod=11, mod!=11). */ #define INST_MODRM_BASED (1 << 19) /* The instruction uses a ModR/M byte which the MOD must be 11 (for registers operands only). */ #define INST_MODRR (1 << 20) /* The way of 3DNow! instructions are built, we have to handle their locating specially. Suffix imm8 tells which instruction it is. */ #define INST_3DNOW_FETCH (1 << 21) /* The instruction needs two suffixes, one for the comparison type (imm8) and the second for its operation size indication (second mnemonic). */ #define INST_PSEUDO_OPCODE (1 << 22) /* Invalid instruction at 64 bits decoding mode. */ #define INST_INVALID_64BITS (1 << 23) /* Specific instruction is can be promoted to 64 bits (without REX it is promoted automatically). */ #define INST_64BITS (1 << 24) /* Indicates the instruction must be REX prefixed in order to use 64 bits operands. */ #define INST_PRE_REX (1 << 25) /* Third mnemonic is set. */ #define INST_USE_EXMNEMONIC2 (1 << 26) /* Instruction is only valid in 64 bits decoding mode. */ #define INST_64BITS_FETCH (1 << 27) #define INST_PRE_REPS (INST_PRE_REPNZ | INST_PRE_REP) #define INST_PRE_LOKREP_MASK (INST_PRE_LOCK | INST_PRE_REPNZ | INST_PRE_REP) #define INST_PRE_SEGOVRD_MASK (INST_PRE_CS | INST_PRE_SS | INST_PRE_DS | INST_PRE_ES | INST_PRE_FS | INST_PRE_GS) /* Instructions Set classes: */ /* Indicates the instruction belongs to the General Integer set. */ #define ISCT_INTEGER 1 /* Indicates the instruction belongs to the 387 FPU set. */ #define ISCT_FPU 2 /* Indicates the instruction belongs to the P6 set. */ #define ISCT_P6 3 /* Indicates the instruction belongs to the MMX set. */ #define ISCT_MMX 4 /* Indicates the instruction belongs to the SSE set. */ #define ISCT_SSE 5 /* Indicates the instruction belongs to the SSE2 set. */ #define ISCT_SSE2 6 /* Indicates the instruction belongs to the SSE3 set. */ #define ISCT_SSE3 7 /* Indicates the instruction belongs to the SSSE3 set. */ #define ISCT_SSSE3 8 /* Indicates the instruction belongs to the SSE4.1 set. */ #define ISCT_SSE4_1 9 /* Indicates the instruction belongs to the SSE4.2 set. */ #define ISCT_SSE4_2 10 /* Indicates the instruction belongs to the AMD's SSE4.A set. */ #define ISCT_SSE4_A 11 /* Indicates the instruction belongs to the 3DNow! set. */ #define ISCT_3DNOW 12 /* Indicates the instruction belongs to the 3DNow! Extensions set. */ #define ISCT_3DNOWEXT 13 /* Indicates the instruction belongs to the VMX (Intel) set. */ #define ISCT_VMX 14 /* Indicates the instruction belongs to the SVM (AMD) set. */ #define ISCT_SVM 15 /* * Indicates which operand is being decoded. * Destination (1st), Source (2nd), op3 (3rd), op4 (4th). * Its main purpose to help the decode-operands function know whether its the first operand (+ it's indirection + there's a lock prefix). */ typedef enum {ONT_NONE = -1, ONT_1, ONT_2, ONT_3, ONT_4} _OperandNumberType; #define MAX_MNEMONIC_LENGTH (32) #ifdef _MSC_VER #pragma pack(push, 1) #endif /* * Info about the instruction, source/dest types, its name in text and flags. * This structure is used for the instructions DB and NOT for the disassembled result code! * This is the BASE structure, there are extentions to this structure below. */ typedef struct _PACKED_ { uint8_t type; uint8_t isc; uint8_t s, d; /* OpType */ int8_t* mnemonic; _iflags flags; } _InstInfo; /* * There are merely few instructions which need a second mnemonic for 32 bits. * Or a third for 64 bits. Therefore sometimes the second mnemonic is empty but not the third. * In all decoding modes the first mnemonic is the default. * A flag will indicate it uses another mnemonic. * * There are a couple of (SSE4) instructions in the whole DB which need both op3 and 3rd mnemonic for 64bits, * therefore, I decided to make the extended structure contain all extra info in the same structure. * There are a few instructions (SHLD/SHRD/IMUL and SSE too) which use third operand (or a fourth). * A flag will indicate it uses a third/fourth operand. * */ typedef struct _PACKED_ { uint8_t type; uint8_t isc; uint8_t s, d; /* OpType */ int8_t* mnemonic; _iflags flags; uint8_t op3, op4; /* OpType */ int8_t* mnemonic2; int8_t* mnemonic3; } _InstInfoEx; /* Trie data structure node type: */ typedef enum { INT_NOTEXISTS = -1, /* Not exists (this is used for a return code only). */ INT_NONE, /* No instruction info or list set. */ INT_INFO, /* It's an instruction info. */ INT_LIST_GROUP, INT_LIST_FULL, INT_LIST_DIVIDED } _InstNodeType; /* * A node in the instructions DB; * Can be both a node or an info, depends on type. */ typedef struct _PACKED_ InstNode{ uint8_t type; uint8_t* ids; _InstInfo** list; /* The second level might point to _InstNode, this is determined by type in runtime. */ } _InstNode; #ifdef _MSC_VER #pragma pack(pop) #endif typedef enum {OPERAND_SIZE_NONE = 0, OPERAND_SIZE8, OPERAND_SIZE16, OPERAND_SIZE32, OPERAND_SIZE64, OPERAND_SIZE80, OPERAND_SIZE128} _OperandSizeType; /* * Used for letting the extract operand know the type of operands without knowing the * instruction itself yet, because of the way those instructions work. */ extern _InstInfo II_3dnow; _InstInfo* locate_inst(const uint8_t** code, int* codeLen, _OffsetType* codeOffset, _WString* instructionHex, _PrefixState* ps, _DecodeType dt); _InstInfo* locate_3dnow_inst(_CodeInfo* ci, _WString* instructionHex); /* Concatenates a text describing the size used for indirections form. (MOV *WORD* [BX], 0x12) when it's not cleared from operands. */ void str_indirection_text(_WString* s, _OperandSizeType opSize); #endif /* INSTRUCTIONS_H */ distorm64-1.7.30/src/insts.c0000644000175000017500000036140511014441732014512 0ustar enderender/* insts.c Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #include "../config.h" #include "insts.h" /* * GENERATED BY disOps at Mon May 19 20:16:59 2008 */ #define _I8P (int8_t*) /* Fix signedness warning. */ _InstInfo II_00 = {1, 1, 7, 15, _I8P "\x03" "ADD", 17}; _InstInfo II_01 = {1, 1, 9, 17, _I8P "\x03" "ADD", 17}; _InstInfo II_02 = {1, 1, 15, 7, _I8P "\x03" "ADD", 17}; _InstInfo II_03 = {1, 1, 17, 9, _I8P "\x03" "ADD", 17}; _InstInfo II_04 = {1, 1, 1, 34, _I8P "\x03" "ADD", 0}; _InstInfo II_05 = {1, 1, 3, 36, _I8P "\x03" "ADD", 0}; _InstInfo II_06 = {1, 1, 0, 33, _I8P "\x04" "PUSH", 8389632}; _InstInfo II_07 = {1, 1, 0, 33, _I8P "\x03" "POP", 8389632}; _InstInfo II_08 = {1, 1, 7, 15, _I8P "\x02" "OR", 17}; _InstInfo II_09 = {1, 1, 9, 17, _I8P "\x02" "OR", 17}; _InstInfo II_0A = {1, 1, 15, 7, _I8P "\x02" "OR", 17}; _InstInfo II_0B = {1, 1, 17, 9, _I8P "\x02" "OR", 17}; _InstInfo II_0C = {1, 1, 1, 34, _I8P "\x02" "OR", 0}; _InstInfo II_0D = {1, 1, 3, 36, _I8P "\x02" "OR", 0}; _InstInfo II_0E = {1, 1, 0, 33, _I8P "\x04" "PUSH", 8388736}; _InstInfo II_0F_00_00 = {1, 1, 0, 17, _I8P "\x04" "SLDT", 1}; _InstInfo II_0F_00_01 = {1, 1, 0, 16, _I8P "\x03" "STR", 1}; _InstInfo II_0F_00_02 = {1, 1, 0, 16, _I8P "\x04" "LLDT", 1}; _InstInfo II_0F_00_03 = {1, 1, 0, 16, _I8P "\x03" "LTR", 9}; _InstInfo II_0F_00_04 = {1, 1, 0, 16, _I8P "\x04" "VERR", 1}; _InstInfo II_0F_00_05 = {1, 1, 0, 16, _I8P "\x04" "VERW", 1}; _InstInfo II_0F_01_00 = {1, 1, 0, 40, _I8P "\x04" "SGDT", 16777217}; _InstInfo II_0F_01_01 = {1, 1, 0, 40, _I8P "\x04" "SIDT", 16777217}; _InstInfo II_0F_01_02 = {1, 1, 0, 40, _I8P "\x04" "LGDT", 16777217}; _InstInfo II_0F_01_03 = {1, 1, 0, 40, _I8P "\x04" "LIDT", 16777217}; _InstInfo II_0F_01_04 = {1, 1, 0, 29, _I8P "\x04" "SMSW", 3}; _InstInfo II_0F_01_06 = {1, 1, 0, 16, _I8P "\x04" "LMSW", 3}; _InstInfo II_0F_01_07 = {1, 1, 0, 43, _I8P "\x06" "INVLPG", 9}; _InstInfo II_0F_01_C1 = {1, 14, 0, 0, _I8P "\x06" "VMCALL", 8}; _InstInfo II_0F_01_C2 = {1, 14, 0, 0, _I8P "\x08" "VMLAUNCH", 8}; _InstInfo II_0F_01_C3 = {1, 14, 0, 0, _I8P "\x08" "VMRESUME", 8}; _InstInfo II_0F_01_C4 = {1, 14, 0, 0, _I8P "\x06" "VMXOFF", 8}; _InstInfo II_0F_01_C8 = {1, 1, 0, 0, _I8P "\x07" "MONITOR", 8}; _InstInfo II_0F_01_C9 = {1, 1, 0, 0, _I8P "\x05" "MWAIT", 8}; _InstInfo II_0F_01_D8 = {1, 15, 0, 58, _I8P "\x05" "VMRUN", 9}; _InstInfo II_0F_01_D9 = {1, 15, 0, 0, _I8P "\x07" "VMMCALL", 8}; _InstInfo II_0F_01_DA = {1, 15, 0, 58, _I8P "\x06" "VMLOAD", 8}; _InstInfo II_0F_01_DB = {1, 15, 0, 58, _I8P "\x06" "VMSAVE", 8}; _InstInfo II_0F_01_DC = {1, 15, 0, 0, _I8P "\x04" "STGI", 8}; _InstInfo II_0F_01_DD = {1, 15, 0, 0, _I8P "\x04" "CLGI", 8}; _InstInfo II_0F_01_DE = {1, 15, 0, 58, _I8P "\x06" "SKINIT", 8}; _InstInfo II_0F_01_DF = {1, 15, 60, 58, _I8P "\x07" "INVLPGA", 8}; _InstInfo II_0F_01_F8 = {1, 1, 0, 0, _I8P "\x06" "SWAPGS", 134217728}; _InstInfo II_0F_01_F9 = {1, 1, 0, 0, _I8P "\x06" "RDTSCP", 134217728}; _InstInfo II_0F_02 = {1, 1, 16, 9, _I8P "\x03" "LAR", 1}; _InstInfo II_0F_03 = {1, 1, 16, 9, _I8P "\x03" "LSL", 1}; _InstInfo II_0F_05 = {1, 3, 0, 0, _I8P "\x07" "SYSCALL", 8}; _InstInfo II_0F_06 = {1, 1, 0, 0, _I8P "\x04" "CLTS", 8}; _InstInfo II_0F_07 = {1, 3, 0, 0, _I8P "\x06" "SYSRET", 8}; _InstInfo II_0F_08 = {1, 1, 0, 0, _I8P "\x04" "INVD", 8}; _InstInfo II_0F_09 = {1, 1, 0, 0, _I8P "\x06" "WBINVD", 8}; _InstInfo II_0F_0B = {1, 1, 0, 0, _I8P "\x03" "UD2", 8}; _InstInfo II_0F_0D_00 = {1, 12, 0, 43, _I8P "\x08" "PREFETCH", 9}; _InstInfo II_0F_0D_01 = {1, 12, 0, 43, _I8P "\x09" "PREFETCHW", 9}; _InstInfo II_0F_0E = {1, 12, 0, 0, _I8P "\x05" "FEMMS", 0}; _InstInfo II_0F_0F_0C = {1, 13, 67, 64, _I8P "\x05" "PI2FW", 2097161}; _InstInfo II_0F_0F_0D = {1, 12, 67, 64, _I8P "\x05" "PI2FD", 2097161}; _InstInfo II_0F_0F_1C = {1, 13, 67, 64, _I8P "\x05" "PF2IW", 2097161}; _InstInfo II_0F_0F_1D = {1, 12, 67, 64, _I8P "\x05" "PF2ID", 2097161}; _InstInfo II_0F_0F_8A = {1, 13, 67, 64, _I8P "\x06" "PFNACC", 2097161}; _InstInfo II_0F_0F_8E = {1, 13, 67, 64, _I8P "\x07" "PFPNACC", 2097161}; _InstInfo II_0F_0F_90 = {1, 12, 67, 64, _I8P "\x07" "PFCMPGE", 2097161}; _InstInfo II_0F_0F_94 = {1, 12, 67, 64, _I8P "\x05" "PFMIN", 2097161}; _InstInfo II_0F_0F_96 = {1, 12, 67, 64, _I8P "\x05" "PFRCP", 2097161}; _InstInfo II_0F_0F_97 = {1, 12, 67, 64, _I8P "\x07" "PFRSQRT", 2097161}; _InstInfo II_0F_0F_9A = {1, 12, 67, 64, _I8P "\x05" "PFSUB", 2097161}; _InstInfo II_0F_0F_9E = {1, 12, 67, 64, _I8P "\x05" "PFADD", 2097161}; _InstInfo II_0F_0F_A0 = {1, 12, 67, 64, _I8P "\x07" "PFCMPGT", 2097161}; _InstInfo II_0F_0F_A4 = {1, 12, 67, 64, _I8P "\x05" "PFMAX", 2097161}; _InstInfo II_0F_0F_A6 = {1, 12, 67, 64, _I8P "\x08" "PFRCPIT1", 2097161}; _InstInfo II_0F_0F_A7 = {1, 12, 67, 64, _I8P "\x08" "PFRSQIT1", 2097161}; _InstInfo II_0F_0F_AA = {1, 12, 67, 64, _I8P "\x06" "PFSUBR", 2097161}; _InstInfo II_0F_0F_AE = {1, 12, 67, 64, _I8P "\x05" "PFACC", 2097161}; _InstInfo II_0F_0F_B0 = {1, 12, 67, 64, _I8P "\x07" "PFCMPEQ", 2097161}; _InstInfo II_0F_0F_B4 = {1, 12, 67, 64, _I8P "\x05" "PFMUL", 2097161}; _InstInfo II_0F_0F_B6 = {1, 12, 67, 64, _I8P "\x08" "PFRCPIT2", 2097161}; _InstInfo II_0F_0F_B7 = {1, 12, 67, 64, _I8P "\x07" "PMULHRW", 2097161}; _InstInfo II_0F_0F_BB = {1, 13, 67, 64, _I8P "\x06" "PSWAPD", 2097161}; _InstInfo II_0F_0F_BF = {1, 12, 67, 64, _I8P "\x07" "PAVGUSB", 2097161}; _InstInfo II_0F_10 = {1, 5, 73, 68, _I8P "\x06" "MOVUPS", 9}; _InstInfo II_0F_11 = {1, 5, 68, 73, _I8P "\x06" "MOVUPS", 9}; _InstInfoEx II_0F_12 = {1, 5, 72, 68, _I8P "\x07" "MOVHLPS", 589833, 0, 0, _I8P "\x06" "MOVLPS", _I8P "\x00" ""}; _InstInfo II_0F_13 = {1, 5, 68, 46, _I8P "\x06" "MOVLPS", 9}; _InstInfo II_0F_14 = {1, 5, 73, 68, _I8P "\x08" "UNPCKLPS", 9}; _InstInfo II_0F_15 = {1, 5, 73, 68, _I8P "\x08" "UNPCKHPS", 9}; _InstInfoEx II_0F_16 = {1, 5, 72, 68, _I8P "\x07" "MOVLHPS", 589833, 0, 0, _I8P "\x06" "MOVHPS", _I8P "\x00" ""}; _InstInfo II_0F_17 = {1, 5, 68, 46, _I8P "\x06" "MOVHPS", 9}; _InstInfo II_0F_18_00 = {1, 5, 0, 43, _I8P "\x0b" "PREFETCHNTA", 9}; _InstInfo II_0F_18_01 = {1, 5, 0, 43, _I8P "\x0a" "PREFETCHT0", 9}; _InstInfo II_0F_18_02 = {1, 5, 0, 43, _I8P "\x0a" "PREFETCHT1", 9}; _InstInfo II_0F_18_03 = {1, 5, 0, 43, _I8P "\x0a" "PREFETCHT2", 9}; _InstInfo II_0F_1F_00 = {1, 1, 0, 17, _I8P "\x03" "NOP", 1}; _InstInfo II_0F_20 = {1, 1, 30, 14, _I8P "\x03" "MOV", 17825801}; _InstInfo II_0F_21 = {1, 1, 31, 14, _I8P "\x03" "MOV", 17825801}; _InstInfo II_0F_22 = {1, 1, 14, 30, _I8P "\x03" "MOV", 17825801}; _InstInfo II_0F_23 = {1, 1, 14, 31, _I8P "\x03" "MOV", 17825801}; _InstInfo II_0F_28 = {1, 5, 73, 68, _I8P "\x06" "MOVAPS", 9}; _InstInfo II_0F_29 = {1, 5, 68, 73, _I8P "\x06" "MOVAPS", 9}; _InstInfo II_0F_2A = {1, 5, 67, 68, _I8P "\x08" "CVTPI2PS", 9}; _InstInfo II_0F_2B = {1, 5, 68, 47, _I8P "\x07" "MOVNTPS", 9}; _InstInfo II_0F_2C = {1, 5, 72, 64, _I8P "\x09" "CVTTPS2PI", 9}; _InstInfo II_0F_2D = {1, 5, 72, 64, _I8P "\x08" "CVTPS2PI", 9}; _InstInfo II_0F_2E = {1, 5, 71, 68, _I8P "\x07" "UCOMISS", 9}; _InstInfo II_0F_2F = {1, 5, 71, 68, _I8P "\x06" "COMISS", 9}; _InstInfo II_0F_30 = {1, 1, 0, 0, _I8P "\x05" "WRMSR", 8}; _InstInfo II_0F_31 = {1, 1, 0, 0, _I8P "\x05" "RDTSC", 8}; _InstInfo II_0F_32 = {1, 1, 0, 0, _I8P "\x05" "RDMSR", 8}; _InstInfo II_0F_33 = {1, 1, 0, 0, _I8P "\x05" "RDPMC", 8}; _InstInfo II_0F_34 = {1, 3, 0, 0, _I8P "\x08" "SYSENTER", 8388616}; _InstInfo II_0F_35 = {1, 3, 0, 0, _I8P "\x07" "SYSEXIT", 8388616}; _InstInfo II_0F_38_00 = {1, 8, 67, 64, _I8P "\x06" "PSHUFB", 9}; _InstInfo II_0F_38_01 = {1, 8, 67, 64, _I8P "\x06" "PHADDW", 9}; _InstInfo II_0F_38_02 = {1, 8, 67, 64, _I8P "\x06" "PHADDD", 9}; _InstInfo II_0F_38_03 = {1, 8, 67, 64, _I8P "\x07" "PHADDSW", 9}; _InstInfo II_0F_38_04 = {1, 8, 67, 64, _I8P "\x09" "PMADDUBSW", 9}; _InstInfo II_0F_38_05 = {1, 8, 67, 64, _I8P "\x06" "PHSUBW", 9}; _InstInfo II_0F_38_06 = {1, 8, 67, 64, _I8P "\x06" "PHSUBD", 9}; _InstInfo II_0F_38_07 = {1, 8, 67, 64, _I8P "\x07" "PHSUBSW", 9}; _InstInfo II_0F_38_08 = {1, 8, 67, 64, _I8P "\x06" "PSIGNB", 9}; _InstInfo II_0F_38_09 = {1, 8, 67, 64, _I8P "\x06" "PSIGNW", 9}; _InstInfo II_0F_38_0A = {1, 8, 67, 64, _I8P "\x06" "PSIGND", 9}; _InstInfo II_0F_38_0B = {1, 8, 67, 64, _I8P "\x08" "PMULHRSW", 9}; _InstInfo II_0F_38_1C = {1, 8, 67, 64, _I8P "\x05" "PABSB", 9}; _InstInfo II_0F_38_1D = {1, 8, 67, 64, _I8P "\x05" "PABSW", 9}; _InstInfo II_0F_38_1E = {1, 8, 67, 64, _I8P "\x05" "PABSD", 9}; _InstInfoEx II_0F_3A_0F = {1, 8, 67, 64, _I8P "\x07" "PALIGNR", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_0F_40 = {1, 3, 17, 9, _I8P "\x05" "CMOVO", 9}; _InstInfo II_0F_41 = {1, 3, 17, 9, _I8P "\x06" "CMOVNO", 9}; _InstInfo II_0F_42 = {1, 3, 17, 9, _I8P "\x05" "CMOVB", 9}; _InstInfo II_0F_43 = {1, 3, 17, 9, _I8P "\x06" "CMOVAE", 9}; _InstInfo II_0F_44 = {1, 3, 17, 9, _I8P "\x05" "CMOVZ", 9}; _InstInfo II_0F_45 = {1, 3, 17, 9, _I8P "\x06" "CMOVNZ", 9}; _InstInfo II_0F_46 = {1, 3, 17, 9, _I8P "\x06" "CMOVBE", 9}; _InstInfo II_0F_47 = {1, 3, 17, 9, _I8P "\x05" "CMOVA", 9}; _InstInfo II_0F_48 = {1, 3, 17, 9, _I8P "\x05" "CMOVS", 9}; _InstInfo II_0F_49 = {1, 3, 17, 9, _I8P "\x06" "CMOVNS", 9}; _InstInfo II_0F_4A = {1, 3, 17, 9, _I8P "\x05" "CMOVP", 9}; _InstInfo II_0F_4B = {1, 3, 17, 9, _I8P "\x06" "CMOVNP", 9}; _InstInfo II_0F_4C = {1, 3, 17, 9, _I8P "\x05" "CMOVL", 9}; _InstInfo II_0F_4D = {1, 3, 17, 9, _I8P "\x06" "CMOVGE", 9}; _InstInfo II_0F_4E = {1, 3, 17, 9, _I8P "\x06" "CMOVLE", 9}; _InstInfo II_0F_4F = {1, 3, 17, 9, _I8P "\x05" "CMOVG", 9}; _InstInfo II_0F_50 = {1, 5, 69, 10, _I8P "\x08" "MOVMSKPS", 1048585}; _InstInfo II_0F_51 = {1, 5, 73, 68, _I8P "\x06" "SQRTPS", 9}; _InstInfo II_0F_52 = {1, 5, 73, 68, _I8P "\x07" "RSQRTPS", 9}; _InstInfo II_0F_53 = {1, 5, 73, 68, _I8P "\x05" "RCPPS", 9}; _InstInfo II_0F_54 = {1, 5, 73, 68, _I8P "\x05" "ANDPS", 9}; _InstInfo II_0F_55 = {1, 5, 73, 68, _I8P "\x06" "ANDNPS", 9}; _InstInfo II_0F_56 = {1, 5, 73, 68, _I8P "\x04" "ORPS", 9}; _InstInfo II_0F_57 = {1, 5, 73, 68, _I8P "\x05" "XORPS", 9}; _InstInfo II_0F_58 = {1, 5, 73, 68, _I8P "\x05" "ADDPS", 9}; _InstInfo II_0F_59 = {1, 5, 73, 68, _I8P "\x05" "MULPS", 9}; _InstInfo II_0F_5A = {1, 6, 72, 68, _I8P "\x08" "CVTPS2PD", 9}; _InstInfo II_0F_5B = {1, 6, 73, 68, _I8P "\x08" "CVTDQ2PS", 9}; _InstInfo II_0F_5C = {1, 5, 73, 68, _I8P "\x05" "SUBPS", 9}; _InstInfo II_0F_5D = {1, 5, 73, 68, _I8P "\x05" "MINPS", 9}; _InstInfo II_0F_5E = {1, 5, 73, 68, _I8P "\x05" "DIVPS", 9}; _InstInfo II_0F_5F = {1, 5, 73, 68, _I8P "\x05" "MAXPS", 9}; _InstInfo II_0F_60 = {1, 4, 66, 64, _I8P "\x09" "PUNPCKLBW", 9}; _InstInfo II_0F_61 = {1, 4, 66, 64, _I8P "\x09" "PUNPCKLWD", 9}; _InstInfo II_0F_62 = {1, 4, 66, 64, _I8P "\x09" "PUNPCKLDQ", 9}; _InstInfo II_0F_63 = {1, 4, 67, 64, _I8P "\x08" "PACKSSWB", 9}; _InstInfo II_0F_64 = {1, 4, 67, 64, _I8P "\x07" "PCMPGTB", 9}; _InstInfo II_0F_65 = {1, 4, 67, 64, _I8P "\x07" "PCMPGTW", 9}; _InstInfo II_0F_66 = {1, 4, 67, 64, _I8P "\x07" "PCMPGTD", 9}; _InstInfo II_0F_67 = {1, 4, 67, 64, _I8P "\x08" "PACKUSWB", 9}; _InstInfo II_0F_68 = {1, 4, 67, 64, _I8P "\x09" "PUNPCKHBW", 9}; _InstInfo II_0F_69 = {1, 4, 67, 64, _I8P "\x09" "PUNPCKHWD", 9}; _InstInfo II_0F_6A = {1, 4, 67, 64, _I8P "\x09" "PUNPCKHDQ", 9}; _InstInfo II_0F_6B = {1, 4, 67, 64, _I8P "\x08" "PACKSSDW", 9}; _InstInfoEx II_0F_6E = {1, 4, 19, 64, _I8P "\x04" "MOVD", 117440521, 0, 0, _I8P "\x00" "", _I8P "\x04" "MOVQ"}; _InstInfo II_0F_6F = {1, 4, 67, 64, _I8P "\x04" "MOVQ", 9}; _InstInfoEx II_0F_70 = {1, 5, 67, 64, _I8P "\x06" "PSHUFW", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_0F_71_02 = {1, 4, 1, 65, _I8P "\x05" "PSRLW", 1048585}; _InstInfo II_0F_71_04 = {1, 4, 1, 65, _I8P "\x05" "PSRAW", 1048585}; _InstInfo II_0F_71_06 = {1, 4, 1, 65, _I8P "\x05" "PSLLW", 1048585}; _InstInfo II_0F_72_02 = {1, 4, 1, 65, _I8P "\x05" "PSRLD", 1048585}; _InstInfo II_0F_72_04 = {1, 4, 1, 65, _I8P "\x05" "PSRAD", 1048585}; _InstInfo II_0F_72_06 = {1, 4, 1, 65, _I8P "\x05" "PSLLD", 1048585}; _InstInfo II_0F_73_02 = {1, 4, 1, 65, _I8P "\x05" "PSRLQ", 1048585}; _InstInfo II_0F_73_06 = {1, 4, 1, 65, _I8P "\x05" "PSLLQ", 1048585}; _InstInfo II_0F_74 = {1, 4, 67, 64, _I8P "\x07" "PCMPEQB", 9}; _InstInfo II_0F_75 = {1, 4, 67, 64, _I8P "\x07" "PCMPEQW", 9}; _InstInfo II_0F_76 = {1, 4, 67, 64, _I8P "\x07" "PCMPEQD", 9}; _InstInfo II_0F_77 = {1, 4, 0, 0, _I8P "\x04" "EMMS", 8}; _InstInfo II_0F_78 = {1, 14, 12, 19, _I8P "\x06" "VMREAD", 16777225}; _InstInfo II_0F_79 = {1, 14, 19, 12, _I8P "\x07" "VMWRITE", 16777225}; _InstInfoEx II_0F_7E = {1, 4, 64, 19, _I8P "\x04" "MOVD", 117440521, 0, 0, _I8P "\x00" "", _I8P "\x04" "MOVQ"}; _InstInfo II_0F_7F = {1, 4, 64, 67, _I8P "\x04" "MOVQ", 9}; _InstInfo II_0F_80 = {1, 1, 0, 42, _I8P "\x02" "JO", 8}; _InstInfo II_0F_81 = {1, 1, 0, 42, _I8P "\x03" "JNO", 8}; _InstInfo II_0F_82 = {1, 1, 0, 42, _I8P "\x02" "JB", 8}; _InstInfo II_0F_83 = {1, 1, 0, 42, _I8P "\x03" "JAE", 8}; _InstInfo II_0F_84 = {1, 1, 0, 42, _I8P "\x02" "JZ", 8}; _InstInfo II_0F_85 = {1, 1, 0, 42, _I8P "\x03" "JNZ", 8}; _InstInfo II_0F_86 = {1, 1, 0, 42, _I8P "\x03" "JBE", 8}; _InstInfo II_0F_87 = {1, 1, 0, 42, _I8P "\x02" "JA", 8}; _InstInfo II_0F_88 = {1, 1, 0, 42, _I8P "\x02" "JS", 8}; _InstInfo II_0F_89 = {1, 1, 0, 42, _I8P "\x03" "JNS", 8}; _InstInfo II_0F_8A = {1, 1, 0, 42, _I8P "\x02" "JP", 8}; _InstInfo II_0F_8B = {1, 1, 0, 42, _I8P "\x03" "JNP", 8}; _InstInfo II_0F_8C = {1, 1, 0, 42, _I8P "\x02" "JL", 8}; _InstInfo II_0F_8D = {1, 1, 0, 42, _I8P "\x03" "JGE", 8}; _InstInfo II_0F_8E = {1, 1, 0, 42, _I8P "\x03" "JLE", 8}; _InstInfo II_0F_8F = {1, 1, 0, 42, _I8P "\x02" "JG", 8}; _InstInfo II_0F_90 = {1, 1, 0, 15, _I8P "\x04" "SETO", 9}; _InstInfo II_0F_91 = {1, 1, 0, 15, _I8P "\x05" "SETNO", 9}; _InstInfo II_0F_92 = {1, 1, 0, 15, _I8P "\x04" "SETB", 9}; _InstInfo II_0F_93 = {1, 1, 0, 15, _I8P "\x05" "SETAE", 9}; _InstInfo II_0F_94 = {1, 1, 0, 15, _I8P "\x04" "SETZ", 9}; _InstInfo II_0F_95 = {1, 1, 0, 15, _I8P "\x05" "SETNZ", 9}; _InstInfo II_0F_96 = {1, 1, 0, 15, _I8P "\x05" "SETBE", 9}; _InstInfo II_0F_97 = {1, 1, 0, 15, _I8P "\x04" "SETA", 9}; _InstInfo II_0F_98 = {1, 1, 0, 15, _I8P "\x04" "SETS", 9}; _InstInfo II_0F_99 = {1, 1, 0, 15, _I8P "\x05" "SETNS", 9}; _InstInfo II_0F_9A = {1, 1, 0, 15, _I8P "\x04" "SETP", 9}; _InstInfo II_0F_9B = {1, 1, 0, 15, _I8P "\x05" "SETNP", 9}; _InstInfo II_0F_9C = {1, 1, 0, 15, _I8P "\x04" "SETL", 9}; _InstInfo II_0F_9D = {1, 1, 0, 15, _I8P "\x05" "SETGE", 9}; _InstInfo II_0F_9E = {1, 1, 0, 15, _I8P "\x05" "SETLE", 9}; _InstInfo II_0F_9F = {1, 1, 0, 15, _I8P "\x04" "SETG", 9}; _InstInfo II_0F_A0 = {1, 1, 0, 33, _I8P "\x04" "PUSH", 16779272}; _InstInfo II_0F_A1 = {1, 1, 0, 33, _I8P "\x03" "POP", 2056}; _InstInfo II_0F_A2 = {1, 1, 0, 0, _I8P "\x05" "CPUID", 8}; _InstInfo II_0F_A3 = {1, 1, 9, 17, _I8P "\x02" "BT", 9}; _InstInfoEx II_0F_A4 = {1, 1, 9, 17, _I8P "\x04" "SHLD", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_0F_A5 = {1, 1, 9, 17, _I8P "\x04" "SHLD", 131081, 51, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_0F_A8 = {1, 1, 0, 33, _I8P "\x04" "PUSH", 16781320}; _InstInfo II_0F_A9 = {1, 1, 0, 33, _I8P "\x03" "POP", 4104}; _InstInfo II_0F_AA = {1, 1, 0, 0, _I8P "\x03" "RSM", 8}; _InstInfo II_0F_AB = {1, 1, 9, 17, _I8P "\x03" "BTS", 25}; _InstInfoEx II_0F_AC = {1, 1, 9, 17, _I8P "\x04" "SHRD", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_0F_AD = {1, 1, 9, 17, _I8P "\x04" "SHRD", 131081, 51, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_0F_AE_00 = {1, 1, 0, 43, _I8P "\x06" "FXSAVE", 9}; _InstInfo II_0F_AE_01 = {1, 1, 0, 43, _I8P "\x07" "FXRSTOR", 9}; _InstInfo II_0F_AE_02 = {1, 1, 0, 43, _I8P "\x07" "LDMXCSR", 9}; _InstInfo II_0F_AE_03 = {1, 1, 0, 43, _I8P "\x07" "STMXCSR", 9}; _InstInfo II_0F_AE_07 = {1, 1, 0, 43, _I8P "\x07" "CLFLUSH", 9}; _InstInfo II_0F_AE_E8 = {1, 1, 0, 0, _I8P "\x06" "LFENCE", 8}; _InstInfo II_0F_AE_F0 = {1, 1, 0, 0, _I8P "\x06" "MFENCE", 8}; _InstInfo II_0F_AE_F8 = {1, 1, 0, 0, _I8P "\x06" "SFENCE", 8}; _InstInfo II_0F_AF = {1, 1, 17, 9, _I8P "\x04" "IMUL", 9}; _InstInfo II_0F_B0 = {1, 1, 7, 15, _I8P "\x07" "CMPXCHG", 25}; _InstInfo II_0F_B1 = {1, 1, 9, 17, _I8P "\x07" "CMPXCHG", 25}; _InstInfo II_0F_B2 = {1, 1, 38, 9, _I8P "\x03" "LSS", 50331657}; _InstInfo II_0F_B3 = {1, 1, 9, 17, _I8P "\x03" "BTR", 25}; _InstInfo II_0F_B4 = {1, 1, 38, 9, _I8P "\x03" "LFS", 50331657}; _InstInfo II_0F_B5 = {1, 1, 38, 9, _I8P "\x03" "LGS", 50331657}; _InstInfo II_0F_B6 = {1, 1, 15, 9, _I8P "\x05" "MOVZX", 9}; _InstInfo II_0F_B7 = {1, 1, 16, 9, _I8P "\x05" "MOVZX", 50331657}; _InstInfo II_0F_B9 = {1, 1, 0, 0, _I8P "\x03" "UD2", 8}; _InstInfo II_0F_BA_04 = {1, 1, 1, 17, _I8P "\x02" "BT", 9}; _InstInfo II_0F_BA_05 = {1, 1, 1, 17, _I8P "\x03" "BTS", 25}; _InstInfo II_0F_BA_06 = {1, 1, 1, 17, _I8P "\x03" "BTR", 25}; _InstInfo II_0F_BA_07 = {1, 1, 1, 17, _I8P "\x03" "BTC", 25}; _InstInfo II_0F_BB = {1, 1, 9, 17, _I8P "\x03" "BTC", 25}; _InstInfo II_0F_BC = {1, 1, 17, 9, _I8P "\x03" "BSF", 9}; _InstInfo II_0F_BD = {1, 1, 17, 9, _I8P "\x03" "BSR", 9}; _InstInfo II_0F_BE = {1, 1, 15, 9, _I8P "\x05" "MOVSX", 9}; _InstInfo II_0F_BF = {1, 1, 16, 9, _I8P "\x05" "MOVSX", 50331657}; _InstInfo II_0F_C0 = {1, 1, 7, 15, _I8P "\x04" "XADD", 25}; _InstInfo II_0F_C1 = {1, 1, 9, 17, _I8P "\x04" "XADD", 25}; _InstInfoEx II_0F_C2 = {1, 5, 73, 68, _I8P "\x03" "CMP", 4259849, 0, 0, _I8P "\x02" "PS", _I8P "\x00" ""}; _InstInfo II_0F_C3 = {1, 6, 12, 45, _I8P "\x06" "MOVNTI", 50331657}; _InstInfoEx II_0F_C4 = {1, 5, 26, 64, _I8P "\x06" "PINSRW", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_0F_C5 = {1, 5, 65, 10, _I8P "\x06" "PEXTRW", 1179657, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_0F_C6 = {1, 5, 73, 68, _I8P "\x06" "SHUFPS", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_0F_C7_01 = {1, 1, 0, 48, _I8P "\x09" "CMPXCHG8B", 117440537, 0, 0, _I8P "\x00" "", _I8P "\x0a" "CMPXCHG16B"}; _InstInfo II_0F_C7_06 = {1, 14, 0, 46, _I8P "\x07" "VMPTRLD", 9}; _InstInfo II_0F_C7_07 = {1, 14, 0, 46, _I8P "\x07" "VMPTRST", 9}; _InstInfo II_0F_C8 = {1, 1, 0, 53, _I8P "\x05" "BSWAP", 50331656}; _InstInfo II_0F_D1 = {1, 4, 67, 64, _I8P "\x05" "PSRLW", 9}; _InstInfo II_0F_D2 = {1, 4, 67, 64, _I8P "\x05" "PSRLD", 9}; _InstInfo II_0F_D3 = {1, 4, 67, 64, _I8P "\x05" "PSRLQ", 9}; _InstInfo II_0F_D4 = {1, 6, 72, 68, _I8P "\x05" "PADDQ", 9}; _InstInfo II_0F_D5 = {1, 4, 67, 64, _I8P "\x06" "PMULLW", 9}; _InstInfo II_0F_D7 = {1, 5, 65, 10, _I8P "\x08" "PMOVMSKB", 1048585}; _InstInfo II_0F_D8 = {1, 4, 67, 64, _I8P "\x07" "PSUBUSB", 9}; _InstInfo II_0F_D9 = {1, 4, 67, 64, _I8P "\x07" "PSUBUSW", 9}; _InstInfo II_0F_DA = {1, 5, 67, 64, _I8P "\x06" "PMINUB", 9}; _InstInfo II_0F_DB = {1, 4, 67, 64, _I8P "\x04" "PAND", 9}; _InstInfo II_0F_DC = {1, 4, 67, 64, _I8P "\x07" "PADDUSB", 9}; _InstInfo II_0F_DD = {1, 4, 67, 64, _I8P "\x07" "PADDUSW", 9}; _InstInfo II_0F_DE = {1, 5, 67, 64, _I8P "\x06" "PMAXUB", 9}; _InstInfo II_0F_DF = {1, 4, 67, 64, _I8P "\x05" "PANDN", 9}; _InstInfo II_0F_E0 = {1, 5, 67, 64, _I8P "\x05" "PAVGB", 9}; _InstInfo II_0F_E1 = {1, 4, 67, 64, _I8P "\x05" "PSRAW", 9}; _InstInfo II_0F_E2 = {1, 4, 67, 64, _I8P "\x05" "PSRAD", 9}; _InstInfo II_0F_E3 = {1, 5, 67, 64, _I8P "\x05" "PAVGW", 9}; _InstInfo II_0F_E4 = {1, 5, 67, 64, _I8P "\x07" "PMULHUW", 9}; _InstInfo II_0F_E5 = {1, 4, 67, 64, _I8P "\x06" "PMULHW", 9}; _InstInfo II_0F_E7 = {1, 5, 64, 46, _I8P "\x06" "MOVNTQ", 9}; _InstInfo II_0F_E8 = {1, 4, 67, 64, _I8P "\x06" "PSUBSB", 9}; _InstInfo II_0F_E9 = {1, 4, 67, 64, _I8P "\x06" "PSUBSW", 9}; _InstInfo II_0F_EA = {1, 5, 67, 64, _I8P "\x06" "PMINSW", 9}; _InstInfo II_0F_EB = {1, 4, 67, 64, _I8P "\x03" "POR", 9}; _InstInfo II_0F_EC = {1, 4, 67, 64, _I8P "\x06" "PADDSB", 9}; _InstInfo II_0F_ED = {1, 4, 67, 64, _I8P "\x06" "PADDSW", 9}; _InstInfo II_0F_EE = {1, 5, 67, 64, _I8P "\x06" "PMAXSW", 9}; _InstInfo II_0F_EF = {1, 4, 67, 64, _I8P "\x04" "PXOR", 9}; _InstInfo II_0F_F1 = {1, 4, 67, 64, _I8P "\x05" "PSLLW", 9}; _InstInfo II_0F_F2 = {1, 4, 67, 64, _I8P "\x05" "PSLLD", 9}; _InstInfo II_0F_F3 = {1, 4, 67, 64, _I8P "\x05" "PSLLQ", 9}; _InstInfo II_0F_F4 = {1, 6, 67, 64, _I8P "\x07" "PMULUDQ", 9}; _InstInfo II_0F_F5 = {1, 4, 67, 64, _I8P "\x07" "PMADDWD", 9}; _InstInfo II_0F_F6 = {1, 5, 67, 64, _I8P "\x06" "PSADBW", 9}; _InstInfo II_0F_F7 = {1, 5, 65, 64, _I8P "\x08" "MASKMOVQ", 1048585}; _InstInfo II_0F_F8 = {1, 4, 67, 64, _I8P "\x05" "PSUBB", 9}; _InstInfo II_0F_F9 = {1, 4, 67, 64, _I8P "\x05" "PSUBW", 9}; _InstInfo II_0F_FA = {1, 4, 67, 64, _I8P "\x05" "PSUBD", 9}; _InstInfo II_0F_FB = {1, 6, 67, 64, _I8P "\x05" "PSUBQ", 9}; _InstInfo II_0F_FC = {1, 4, 67, 64, _I8P "\x05" "PADDB", 9}; _InstInfo II_0F_FD = {1, 4, 67, 64, _I8P "\x05" "PADDW", 9}; _InstInfo II_0F_FE = {1, 4, 67, 64, _I8P "\x05" "PADDD", 9}; _InstInfo II_10 = {1, 1, 7, 15, _I8P "\x03" "ADC", 17}; _InstInfo II_11 = {1, 1, 9, 17, _I8P "\x03" "ADC", 17}; _InstInfo II_12 = {1, 1, 15, 7, _I8P "\x03" "ADC", 17}; _InstInfo II_13 = {1, 1, 17, 9, _I8P "\x03" "ADC", 17}; _InstInfo II_14 = {1, 1, 1, 34, _I8P "\x03" "ADC", 0}; _InstInfo II_15 = {1, 1, 3, 36, _I8P "\x03" "ADC", 0}; _InstInfo II_16 = {1, 1, 0, 33, _I8P "\x04" "PUSH", 8388864}; _InstInfo II_17 = {1, 1, 0, 33, _I8P "\x03" "POP", 8388864}; _InstInfo II_18 = {1, 1, 7, 15, _I8P "\x03" "SBB", 17}; _InstInfo II_19 = {1, 1, 9, 17, _I8P "\x03" "SBB", 17}; _InstInfo II_1A = {1, 1, 15, 7, _I8P "\x03" "SBB", 17}; _InstInfo II_1B = {1, 1, 17, 9, _I8P "\x03" "SBB", 17}; _InstInfo II_1C = {1, 1, 1, 34, _I8P "\x03" "SBB", 0}; _InstInfo II_1D = {1, 1, 3, 36, _I8P "\x03" "SBB", 0}; _InstInfo II_1E = {1, 1, 0, 33, _I8P "\x04" "PUSH", 8389120}; _InstInfo II_1F = {1, 1, 0, 33, _I8P "\x03" "POP", 8389120}; _InstInfo II_20 = {1, 1, 7, 15, _I8P "\x03" "AND", 17}; _InstInfo II_21 = {1, 1, 9, 17, _I8P "\x03" "AND", 17}; _InstInfo II_22 = {1, 1, 15, 7, _I8P "\x03" "AND", 17}; _InstInfo II_23 = {1, 1, 17, 9, _I8P "\x03" "AND", 17}; _InstInfo II_24 = {1, 1, 1, 34, _I8P "\x03" "AND", 0}; _InstInfo II_25 = {1, 1, 3, 36, _I8P "\x03" "AND", 0}; _InstInfo II_27 = {1, 1, 0, 0, _I8P "\x03" "DAA", 8388608}; _InstInfo II_28 = {1, 1, 7, 15, _I8P "\x03" "SUB", 17}; _InstInfo II_29 = {1, 1, 9, 17, _I8P "\x03" "SUB", 17}; _InstInfo II_2A = {1, 1, 15, 7, _I8P "\x03" "SUB", 17}; _InstInfo II_2B = {1, 1, 17, 9, _I8P "\x03" "SUB", 17}; _InstInfo II_2C = {1, 1, 1, 34, _I8P "\x03" "SUB", 0}; _InstInfo II_2D = {1, 1, 3, 36, _I8P "\x03" "SUB", 0}; _InstInfo II_2F = {1, 1, 0, 0, _I8P "\x03" "DAS", 8388608}; _InstInfo II_30 = {1, 1, 7, 15, _I8P "\x03" "XOR", 17}; _InstInfo II_31 = {1, 1, 9, 17, _I8P "\x03" "XOR", 17}; _InstInfo II_32 = {1, 1, 15, 7, _I8P "\x03" "XOR", 17}; _InstInfo II_33 = {1, 1, 17, 9, _I8P "\x03" "XOR", 17}; _InstInfo II_34 = {1, 1, 1, 34, _I8P "\x03" "XOR", 0}; _InstInfo II_35 = {1, 1, 3, 36, _I8P "\x03" "XOR", 0}; _InstInfo II_37 = {1, 1, 0, 0, _I8P "\x03" "AAA", 8388608}; _InstInfo II_38 = {1, 1, 7, 15, _I8P "\x03" "CMP", 1}; _InstInfo II_39 = {1, 1, 9, 17, _I8P "\x03" "CMP", 1}; _InstInfo II_3A = {1, 1, 15, 7, _I8P "\x03" "CMP", 1}; _InstInfo II_3B = {1, 1, 17, 9, _I8P "\x03" "CMP", 1}; _InstInfo II_3C = {1, 1, 1, 34, _I8P "\x03" "CMP", 0}; _InstInfo II_3D = {1, 1, 3, 36, _I8P "\x03" "CMP", 0}; _InstInfo II_3F = {1, 1, 0, 0, _I8P "\x03" "AAS", 8388608}; _InstInfo II_40 = {1, 1, 0, 54, _I8P "\x03" "INC", 8388608}; _InstInfo II_48 = {1, 1, 0, 54, _I8P "\x03" "DEC", 8388608}; _InstInfo II_50 = {1, 1, 0, 54, _I8P "\x04" "PUSH", 16777216}; _InstInfo II_58 = {1, 1, 0, 54, _I8P "\x03" "POP", 16777216}; _InstInfo II_60 = {1, 1, 0, 0, _I8P "\x05" "PUSHA", 8421376}; _InstInfo II_61 = {1, 1, 0, 0, _I8P "\x04" "POPA", 8421376}; _InstInfo II_62 = {1, 1, 43, 9, _I8P "\x05" "BOUND", 8388609}; _InstInfo II_63 = {1, 1, 8, 16, _I8P "\x04" "ARPL", 16777217}; _InstInfo II_66_0F_10 = {1, 6, 73, 68, _I8P "\x06" "MOVUPD", 9}; _InstInfo II_66_0F_11 = {1, 6, 68, 73, _I8P "\x06" "MOVUPD", 9}; _InstInfo II_66_0F_12 = {1, 6, 46, 68, _I8P "\x06" "MOVLPD", 9}; _InstInfo II_66_0F_13 = {1, 6, 68, 46, _I8P "\x06" "MOVLPD", 9}; _InstInfo II_66_0F_14 = {1, 6, 73, 68, _I8P "\x08" "UNPCKLPD", 9}; _InstInfo II_66_0F_15 = {1, 6, 73, 68, _I8P "\x08" "UNPCKHPD", 9}; _InstInfo II_66_0F_16 = {1, 6, 46, 68, _I8P "\x06" "MOVHPD", 9}; _InstInfo II_66_0F_17 = {1, 6, 68, 46, _I8P "\x06" "MOVHPD", 9}; _InstInfo II_66_0F_28 = {1, 6, 73, 68, _I8P "\x06" "MOVAPD", 9}; _InstInfo II_66_0F_29 = {1, 6, 68, 73, _I8P "\x06" "MOVAPD", 9}; _InstInfo II_66_0F_2A = {1, 6, 67, 68, _I8P "\x08" "CVTPI2PD", 9}; _InstInfo II_66_0F_2B = {1, 6, 68, 47, _I8P "\x07" "MOVNTPD", 9}; _InstInfo II_66_0F_2C = {1, 6, 73, 64, _I8P "\x09" "CVTTPD2PI", 9}; _InstInfo II_66_0F_2D = {1, 6, 73, 68, _I8P "\x08" "CVTPD2PI", 9}; _InstInfo II_66_0F_2E = {1, 6, 72, 68, _I8P "\x07" "UCOMISD", 9}; _InstInfo II_66_0F_2F = {1, 6, 72, 68, _I8P "\x06" "COMISD", 9}; _InstInfo II_66_0F_38_00 = {1, 8, 73, 68, _I8P "\x06" "PSHUFB", 9}; _InstInfo II_66_0F_38_01 = {1, 8, 73, 68, _I8P "\x06" "PHADDW", 9}; _InstInfo II_66_0F_38_02 = {1, 8, 73, 68, _I8P "\x06" "PHADDD", 9}; _InstInfo II_66_0F_38_03 = {1, 8, 73, 68, _I8P "\x07" "PHADDSW", 9}; _InstInfo II_66_0F_38_04 = {1, 8, 73, 68, _I8P "\x09" "PMADDUBSW", 9}; _InstInfo II_66_0F_38_05 = {1, 8, 73, 68, _I8P "\x06" "PHSUBW", 9}; _InstInfo II_66_0F_38_06 = {1, 8, 73, 68, _I8P "\x06" "PHSUBD", 9}; _InstInfo II_66_0F_38_07 = {1, 8, 73, 68, _I8P "\x07" "PHSUBSW", 9}; _InstInfo II_66_0F_38_08 = {1, 8, 73, 68, _I8P "\x06" "PSIGNB", 9}; _InstInfo II_66_0F_38_09 = {1, 8, 73, 68, _I8P "\x06" "PSIGNW", 9}; _InstInfo II_66_0F_38_0A = {1, 8, 73, 68, _I8P "\x06" "PSIGND", 9}; _InstInfo II_66_0F_38_0B = {1, 8, 73, 68, _I8P "\x08" "PMULHRSW", 9}; _InstInfoEx II_66_0F_38_10 = {1, 9, 73, 68, _I8P "\x08" "PBLENDVB", 131081, 74, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_38_14 = {1, 9, 73, 68, _I8P "\x08" "BLENDVPS", 131081, 74, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_38_15 = {1, 9, 73, 68, _I8P "\x08" "BLENDVPD", 131081, 74, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_66_0F_38_17 = {1, 10, 73, 68, _I8P "\x05" "PTEST", 9}; _InstInfo II_66_0F_38_1C = {1, 8, 73, 68, _I8P "\x05" "PABSB", 9}; _InstInfo II_66_0F_38_1D = {1, 8, 73, 68, _I8P "\x05" "PABSW", 9}; _InstInfo II_66_0F_38_1E = {1, 8, 73, 68, _I8P "\x05" "PABSD", 9}; _InstInfo II_66_0F_38_20 = {1, 9, 72, 68, _I8P "\x08" "PMOVSXBW", 9}; _InstInfo II_66_0F_38_21 = {1, 9, 71, 68, _I8P "\x08" "PMOVSXBD", 9}; _InstInfo II_66_0F_38_22 = {1, 9, 70, 68, _I8P "\x08" "PMOVSXBQ", 9}; _InstInfo II_66_0F_38_23 = {1, 9, 72, 68, _I8P "\x08" "PMOVSXWD", 9}; _InstInfo II_66_0F_38_24 = {1, 9, 71, 68, _I8P "\x08" "PMOVSXWQ", 9}; _InstInfo II_66_0F_38_25 = {1, 9, 72, 68, _I8P "\x08" "PMOVSXDQ", 9}; _InstInfo II_66_0F_38_28 = {1, 9, 73, 68, _I8P "\x06" "PMULDQ", 9}; _InstInfo II_66_0F_38_29 = {1, 9, 73, 68, _I8P "\x07" "PCMPEQQ", 9}; _InstInfo II_66_0F_38_2A = {1, 9, 47, 68, _I8P "\x08" "MOVNTDQA", 9}; _InstInfo II_66_0F_38_2B = {1, 9, 73, 68, _I8P "\x08" "PACKUSDW", 9}; _InstInfo II_66_0F_38_30 = {1, 9, 72, 68, _I8P "\x08" "PMOVZXBW", 9}; _InstInfo II_66_0F_38_31 = {1, 9, 71, 68, _I8P "\x08" "PMOVZXBD", 9}; _InstInfo II_66_0F_38_32 = {1, 9, 70, 68, _I8P "\x08" "PMOVZXBQ", 9}; _InstInfo II_66_0F_38_33 = {1, 9, 72, 68, _I8P "\x08" "PMOVZXWD", 9}; _InstInfo II_66_0F_38_34 = {1, 9, 71, 68, _I8P "\x08" "PMOVZXWQ", 9}; _InstInfo II_66_0F_38_35 = {1, 9, 72, 68, _I8P "\x08" "PMOVZXDQ", 9}; _InstInfo II_66_0F_38_37 = {1, 10, 73, 68, _I8P "\x07" "PCMPGTQ", 9}; _InstInfo II_66_0F_38_38 = {1, 9, 73, 68, _I8P "\x06" "PMINSB", 9}; _InstInfo II_66_0F_38_39 = {1, 9, 73, 68, _I8P "\x06" "PMINSD", 9}; _InstInfo II_66_0F_38_3A = {1, 9, 73, 68, _I8P "\x06" "PMINUW", 9}; _InstInfo II_66_0F_38_3B = {1, 9, 73, 68, _I8P "\x06" "PMINUD", 9}; _InstInfo II_66_0F_38_3C = {1, 9, 73, 68, _I8P "\x06" "PMAXSB", 9}; _InstInfo II_66_0F_38_3D = {1, 9, 73, 68, _I8P "\x06" "PMAXSD", 9}; _InstInfo II_66_0F_38_3E = {1, 9, 73, 68, _I8P "\x06" "PMAXUW", 9}; _InstInfo II_66_0F_38_3F = {1, 9, 73, 68, _I8P "\x06" "PMAXUD", 9}; _InstInfo II_66_0F_38_40 = {1, 9, 73, 68, _I8P "\x06" "PMULLD", 9}; _InstInfo II_66_0F_38_41 = {1, 9, 73, 68, _I8P "\x0a" "PHMINPOSUW", 9}; _InstInfoEx II_66_0F_3A_08 = {1, 9, 73, 68, _I8P "\x07" "ROUNDPS", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_09 = {1, 9, 73, 68, _I8P "\x07" "ROUNDPD", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_0A = {1, 9, 71, 68, _I8P "\x07" "ROUNDSS", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_0B = {1, 9, 72, 68, _I8P "\x07" "ROUNDSD", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_0C = {1, 9, 73, 68, _I8P "\x07" "BLENDPS", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_0D = {1, 9, 73, 68, _I8P "\x07" "BLENDPD", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_0E = {1, 9, 73, 68, _I8P "\x07" "PBLENDW", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_0F = {1, 8, 73, 68, _I8P "\x07" "PALIGNR", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_14 = {1, 9, 68, 27, _I8P "\x06" "PEXTRB", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_15 = {1, 9, 68, 28, _I8P "\x06" "PEXTRW", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_16 = {1, 9, 68, 19, _I8P "\x06" "PEXTRD", 67239945, 1, 0, _I8P "\x00" "", _I8P "\x06" "PEXTRQ"}; _InstInfoEx II_66_0F_3A_17 = {1, 9, 68, 19, _I8P "\x09" "EXTRACTPS", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_20 = {1, 9, 25, 68, _I8P "\x06" "PINSRB", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_21 = {1, 9, 71, 68, _I8P "\x08" "INSERTPS", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_22 = {1, 9, 19, 68, _I8P "\x06" "PINSRD", 67239945, 1, 0, _I8P "\x00" "", _I8P "\x06" "PINSRQ"}; _InstInfoEx II_66_0F_3A_40 = {1, 9, 73, 68, _I8P "\x04" "DPPS", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_41 = {1, 9, 73, 68, _I8P "\x04" "DPPD", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_42 = {1, 9, 73, 68, _I8P "\x07" "MPSADBW", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_60 = {1, 10, 73, 68, _I8P "\x09" "PCMPESTRM", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_61 = {1, 10, 73, 68, _I8P "\x09" "PCMPESTRI", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_62 = {1, 10, 73, 68, _I8P "\x09" "PCMPISTRM", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_3A_63 = {1, 10, 73, 68, _I8P "\x09" "PCMPISTRI", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_66_0F_50 = {1, 6, 69, 10, _I8P "\x08" "MOVMSKPD", 1048585}; _InstInfo II_66_0F_51 = {1, 6, 73, 68, _I8P "\x06" "SQRTPD", 9}; _InstInfo II_66_0F_54 = {1, 6, 73, 68, _I8P "\x05" "ANDPD", 9}; _InstInfo II_66_0F_55 = {1, 6, 73, 68, _I8P "\x06" "ANDNPD", 9}; _InstInfo II_66_0F_56 = {1, 6, 73, 68, _I8P "\x04" "ORPD", 9}; _InstInfo II_66_0F_57 = {1, 6, 73, 68, _I8P "\x05" "XORPD", 9}; _InstInfo II_66_0F_58 = {1, 6, 73, 68, _I8P "\x05" "ADDPD", 9}; _InstInfo II_66_0F_59 = {1, 6, 73, 68, _I8P "\x05" "MULPD", 9}; _InstInfo II_66_0F_5A = {1, 6, 73, 68, _I8P "\x08" "CVTPD2PS", 9}; _InstInfo II_66_0F_5B = {1, 6, 73, 68, _I8P "\x08" "CVTPS2DQ", 9}; _InstInfo II_66_0F_5C = {1, 6, 73, 68, _I8P "\x05" "SUBPD", 9}; _InstInfo II_66_0F_5D = {1, 6, 73, 68, _I8P "\x05" "MINPD", 9}; _InstInfo II_66_0F_5E = {1, 6, 73, 68, _I8P "\x05" "DIVPD", 9}; _InstInfo II_66_0F_5F = {1, 6, 73, 68, _I8P "\x05" "MAXPD", 9}; _InstInfo II_66_0F_60 = {1, 6, 73, 68, _I8P "\x09" "PUNPCKLBW", 9}; _InstInfo II_66_0F_61 = {1, 6, 73, 68, _I8P "\x09" "PUNPCKLWD", 9}; _InstInfo II_66_0F_62 = {1, 6, 73, 68, _I8P "\x09" "PUNPCKLDQ", 9}; _InstInfo II_66_0F_63 = {1, 6, 73, 68, _I8P "\x08" "PACKSSWB", 9}; _InstInfo II_66_0F_64 = {1, 6, 73, 68, _I8P "\x07" "PCMPGTB", 9}; _InstInfo II_66_0F_65 = {1, 6, 73, 68, _I8P "\x07" "PCMPGTW", 9}; _InstInfo II_66_0F_66 = {1, 6, 73, 68, _I8P "\x07" "PCMPGTD", 9}; _InstInfo II_66_0F_67 = {1, 6, 73, 68, _I8P "\x08" "PACKUSWB", 9}; _InstInfo II_66_0F_68 = {1, 6, 73, 68, _I8P "\x09" "PUNPCKHBW", 9}; _InstInfo II_66_0F_69 = {1, 6, 73, 68, _I8P "\x09" "PUNPCKHWD", 9}; _InstInfo II_66_0F_6A = {1, 6, 73, 68, _I8P "\x09" "PUNPCKHDQ", 9}; _InstInfo II_66_0F_6B = {1, 6, 73, 68, _I8P "\x08" "PACKSSDW", 9}; _InstInfo II_66_0F_6C = {1, 6, 73, 68, _I8P "\x0a" "PUNPCKLQDQ", 9}; _InstInfo II_66_0F_6D = {1, 6, 73, 68, _I8P "\x0a" "PUNPCKHQDQ", 9}; _InstInfoEx II_66_0F_6E = {1, 6, 19, 68, _I8P "\x04" "MOVD", 117440521, 0, 0, _I8P "\x00" "", _I8P "\x04" "MOVQ"}; _InstInfo II_66_0F_6F = {1, 6, 73, 68, _I8P "\x06" "MOVDQA", 9}; _InstInfoEx II_66_0F_70 = {1, 6, 73, 68, _I8P "\x06" "PSHUFD", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_66_0F_71_02 = {1, 6, 1, 69, _I8P "\x05" "PSRLW", 9}; _InstInfo II_66_0F_71_04 = {1, 6, 1, 69, _I8P "\x05" "PSRAW", 9}; _InstInfo II_66_0F_71_06 = {1, 6, 1, 69, _I8P "\x05" "PSLLW", 9}; _InstInfo II_66_0F_72_02 = {1, 6, 1, 69, _I8P "\x05" "PSRLD", 9}; _InstInfo II_66_0F_72_04 = {1, 6, 1, 69, _I8P "\x05" "PSRAD", 9}; _InstInfo II_66_0F_72_06 = {1, 6, 1, 69, _I8P "\x05" "PSLLD", 9}; _InstInfo II_66_0F_73_02 = {1, 6, 1, 69, _I8P "\x05" "PSRLQ", 9}; _InstInfo II_66_0F_73_03 = {1, 6, 1, 69, _I8P "\x06" "PSRLDQ", 9}; _InstInfo II_66_0F_73_06 = {1, 6, 1, 69, _I8P "\x05" "PSLLQ", 9}; _InstInfo II_66_0F_73_07 = {1, 6, 1, 69, _I8P "\x06" "PSLLDQ", 9}; _InstInfo II_66_0F_74 = {1, 6, 73, 68, _I8P "\x07" "PCMPEQB", 9}; _InstInfo II_66_0F_75 = {1, 6, 73, 68, _I8P "\x07" "PCMPEQW", 9}; _InstInfo II_66_0F_76 = {1, 6, 73, 68, _I8P "\x07" "PCMPEQD", 9}; _InstInfoEx II_66_0F_78_00 = {1, 11, 1, 69, _I8P "\x05" "EXTRQ", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_66_0F_79 = {1, 11, 69, 68, _I8P "\x05" "EXTRQ", 9}; _InstInfo II_66_0F_7C = {1, 7, 73, 68, _I8P "\x06" "HADDPD", 9}; _InstInfo II_66_0F_7D = {1, 7, 73, 68, _I8P "\x06" "HSUBPD", 9}; _InstInfoEx II_66_0F_7E = {1, 6, 68, 19, _I8P "\x04" "MOVD", 117440521, 0, 0, _I8P "\x00" "", _I8P "\x04" "MOVQ"}; _InstInfo II_66_0F_7F = {1, 6, 68, 73, _I8P "\x06" "MOVDQA", 9}; _InstInfoEx II_66_0F_C2 = {1, 6, 73, 68, _I8P "\x03" "CMP", 4259849, 0, 0, _I8P "\x02" "PD", _I8P "\x00" ""}; _InstInfoEx II_66_0F_C4 = {1, 6, 26, 68, _I8P "\x06" "PINSRW", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_C5 = {1, 6, 69, 10, _I8P "\x06" "PEXTRW", 1179657, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_66_0F_C6 = {1, 6, 73, 68, _I8P "\x06" "SHUFPD", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_66_0F_C7_06 = {1, 14, 0, 46, _I8P "\x07" "VMCLEAR", 9}; _InstInfo II_66_0F_D0 = {1, 7, 73, 68, _I8P "\x08" "ADDSUBPD", 9}; _InstInfo II_66_0F_D1 = {1, 6, 73, 68, _I8P "\x05" "PSRLW", 9}; _InstInfo II_66_0F_D2 = {1, 6, 73, 68, _I8P "\x05" "PSRLD", 9}; _InstInfo II_66_0F_D3 = {1, 6, 73, 68, _I8P "\x05" "PSRLQ", 9}; _InstInfo II_66_0F_D4 = {1, 6, 73, 68, _I8P "\x05" "PADDQ", 9}; _InstInfo II_66_0F_D5 = {1, 6, 73, 68, _I8P "\x06" "PMULLW", 9}; _InstInfo II_66_0F_D6 = {1, 6, 68, 72, _I8P "\x04" "MOVQ", 9}; _InstInfo II_66_0F_D7 = {1, 6, 69, 10, _I8P "\x08" "PMOVMSKB", 1048585}; _InstInfo II_66_0F_D8 = {1, 6, 73, 68, _I8P "\x07" "PSUBUSB", 9}; _InstInfo II_66_0F_D9 = {1, 6, 73, 68, _I8P "\x07" "PSUBUSW", 9}; _InstInfo II_66_0F_DA = {1, 6, 73, 68, _I8P "\x06" "PMINUB", 9}; _InstInfo II_66_0F_DB = {1, 6, 73, 68, _I8P "\x04" "PAND", 9}; _InstInfo II_66_0F_DC = {1, 6, 73, 68, _I8P "\x07" "PADDUSB", 9}; _InstInfo II_66_0F_DD = {1, 6, 73, 68, _I8P "\x07" "PADDUSW", 9}; _InstInfo II_66_0F_DE = {1, 6, 73, 68, _I8P "\x06" "PMAXUB", 9}; _InstInfo II_66_0F_DF = {1, 6, 73, 68, _I8P "\x05" "PANDN", 9}; _InstInfo II_66_0F_E0 = {1, 6, 73, 68, _I8P "\x05" "PAVGB", 9}; _InstInfo II_66_0F_E1 = {1, 6, 73, 68, _I8P "\x05" "PSRAW", 9}; _InstInfo II_66_0F_E2 = {1, 6, 73, 68, _I8P "\x05" "PSRAD", 9}; _InstInfo II_66_0F_E3 = {1, 6, 73, 68, _I8P "\x05" "PAVGW", 9}; _InstInfo II_66_0F_E4 = {1, 6, 73, 68, _I8P "\x07" "PMULHUW", 9}; _InstInfo II_66_0F_E5 = {1, 6, 73, 68, _I8P "\x06" "PMULHW", 9}; _InstInfo II_66_0F_E6 = {1, 6, 73, 68, _I8P "\x09" "CVTTPD2DQ", 9}; _InstInfo II_66_0F_E7 = {1, 6, 68, 47, _I8P "\x07" "MOVNTDQ", 9}; _InstInfo II_66_0F_E8 = {1, 6, 73, 68, _I8P "\x06" "PSUBSB", 9}; _InstInfo II_66_0F_E9 = {1, 6, 73, 68, _I8P "\x06" "PSUBSW", 9}; _InstInfo II_66_0F_EA = {1, 6, 73, 68, _I8P "\x06" "PMINSW", 9}; _InstInfo II_66_0F_EB = {1, 6, 73, 68, _I8P "\x03" "POR", 9}; _InstInfo II_66_0F_EC = {1, 6, 73, 68, _I8P "\x06" "PADDSB", 9}; _InstInfo II_66_0F_ED = {1, 6, 73, 68, _I8P "\x06" "PADDSW", 9}; _InstInfo II_66_0F_EE = {1, 6, 73, 68, _I8P "\x06" "PMAXSW", 9}; _InstInfo II_66_0F_EF = {1, 6, 73, 68, _I8P "\x04" "PXOR", 9}; _InstInfo II_66_0F_F1 = {1, 6, 73, 68, _I8P "\x05" "PSLLW", 9}; _InstInfo II_66_0F_F2 = {1, 6, 73, 68, _I8P "\x05" "PSLLD", 9}; _InstInfo II_66_0F_F3 = {1, 6, 73, 68, _I8P "\x05" "PSLLQ", 9}; _InstInfo II_66_0F_F4 = {1, 6, 73, 68, _I8P "\x07" "PMULUDQ", 9}; _InstInfo II_66_0F_F5 = {1, 6, 73, 68, _I8P "\x07" "PMADDWD", 9}; _InstInfo II_66_0F_F6 = {1, 6, 73, 68, _I8P "\x06" "PSADBW", 9}; _InstInfo II_66_0F_F7 = {1, 6, 69, 68, _I8P "\x0a" "MASKMOVDQU", 1048585}; _InstInfo II_66_0F_F8 = {1, 6, 73, 68, _I8P "\x05" "PSUBB", 9}; _InstInfo II_66_0F_F9 = {1, 6, 73, 68, _I8P "\x05" "PSUBW", 9}; _InstInfo II_66_0F_FA = {1, 6, 73, 68, _I8P "\x05" "PSUBD", 9}; _InstInfo II_66_0F_FB = {1, 6, 73, 68, _I8P "\x05" "PSUBQ", 9}; _InstInfo II_66_0F_FC = {1, 6, 73, 68, _I8P "\x05" "PADDB", 9}; _InstInfo II_66_0F_FD = {1, 6, 73, 68, _I8P "\x05" "PADDW", 9}; _InstInfo II_66_0F_FE = {1, 6, 73, 68, _I8P "\x05" "PADDD", 9}; _InstInfo II_68 = {1, 1, 0, 3, _I8P "\x04" "PUSH", 0}; _InstInfoEx II_69 = {1, 1, 17, 9, _I8P "\x04" "IMUL", 131073, 3, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_6A = {1, 1, 0, 6, _I8P "\x04" "PUSH", 8192}; _InstInfoEx II_6B = {1, 1, 17, 9, _I8P "\x04" "IMUL", 131073, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_6C = {1, 1, 59, 56, _I8P "\x03" "INS", 1120}; _InstInfo II_6D = {1, 1, 59, 56, _I8P "\x03" "INS", 1124}; _InstInfo II_6E = {1, 1, 55, 59, _I8P "\x04" "OUTS", 608}; _InstInfo II_6F = {1, 1, 55, 59, _I8P "\x04" "OUTS", 612}; _InstInfo II_70 = {1, 1, 0, 41, _I8P "\x02" "JO", 0}; _InstInfo II_71 = {1, 1, 0, 41, _I8P "\x03" "JNO", 0}; _InstInfo II_72 = {1, 1, 0, 41, _I8P "\x02" "JB", 0}; _InstInfo II_73 = {1, 1, 0, 41, _I8P "\x03" "JAE", 0}; _InstInfo II_74 = {1, 1, 0, 41, _I8P "\x02" "JZ", 0}; _InstInfo II_75 = {1, 1, 0, 41, _I8P "\x03" "JNZ", 0}; _InstInfo II_76 = {1, 1, 0, 41, _I8P "\x03" "JBE", 0}; _InstInfo II_77 = {1, 1, 0, 41, _I8P "\x02" "JA", 0}; _InstInfo II_78 = {1, 1, 0, 41, _I8P "\x02" "JS", 0}; _InstInfo II_79 = {1, 1, 0, 41, _I8P "\x03" "JNS", 0}; _InstInfo II_7A = {1, 1, 0, 41, _I8P "\x02" "JP", 0}; _InstInfo II_7B = {1, 1, 0, 41, _I8P "\x03" "JNP", 0}; _InstInfo II_7C = {1, 1, 0, 41, _I8P "\x02" "JL", 0}; _InstInfo II_7D = {1, 1, 0, 41, _I8P "\x03" "JGE", 0}; _InstInfo II_7E = {1, 1, 0, 41, _I8P "\x03" "JLE", 0}; _InstInfo II_7F = {1, 1, 0, 41, _I8P "\x02" "JG", 0}; _InstInfo II_80_00 = {1, 1, 1, 15, _I8P "\x03" "ADD", 17}; _InstInfo II_80_01 = {1, 1, 1, 15, _I8P "\x02" "OR", 17}; _InstInfo II_80_02 = {1, 1, 1, 15, _I8P "\x03" "ADC", 17}; _InstInfo II_80_03 = {1, 1, 1, 15, _I8P "\x03" "SBB", 17}; _InstInfo II_80_04 = {1, 1, 1, 15, _I8P "\x03" "AND", 17}; _InstInfo II_80_05 = {1, 1, 1, 15, _I8P "\x03" "SUB", 17}; _InstInfo II_80_06 = {1, 1, 1, 15, _I8P "\x03" "XOR", 17}; _InstInfo II_80_07 = {1, 1, 1, 15, _I8P "\x03" "CMP", 1}; _InstInfo II_81_00 = {1, 1, 3, 17, _I8P "\x03" "ADD", 17}; _InstInfo II_81_01 = {1, 1, 3, 17, _I8P "\x02" "OR", 17}; _InstInfo II_81_02 = {1, 1, 3, 17, _I8P "\x03" "ADC", 17}; _InstInfo II_81_03 = {1, 1, 3, 17, _I8P "\x03" "SBB", 17}; _InstInfo II_81_04 = {1, 1, 3, 17, _I8P "\x03" "AND", 17}; _InstInfo II_81_05 = {1, 1, 3, 17, _I8P "\x03" "SUB", 17}; _InstInfo II_81_06 = {1, 1, 3, 17, _I8P "\x03" "XOR", 17}; _InstInfo II_81_07 = {1, 1, 3, 17, _I8P "\x03" "CMP", 1}; _InstInfo II_82_00 = {1, 1, 6, 15, _I8P "\x03" "ADD", 8388625}; _InstInfo II_82_01 = {1, 1, 6, 15, _I8P "\x02" "OR", 8388625}; _InstInfo II_82_02 = {1, 1, 6, 15, _I8P "\x03" "ADC", 8388625}; _InstInfo II_82_03 = {1, 1, 6, 15, _I8P "\x03" "SBB", 8388625}; _InstInfo II_82_04 = {1, 1, 6, 15, _I8P "\x03" "AND", 8388625}; _InstInfo II_82_05 = {1, 1, 6, 15, _I8P "\x03" "SUB", 8388625}; _InstInfo II_82_06 = {1, 1, 6, 15, _I8P "\x03" "XOR", 8388625}; _InstInfo II_82_07 = {1, 1, 6, 15, _I8P "\x03" "CMP", 8388609}; _InstInfo II_83_00 = {1, 1, 6, 17, _I8P "\x03" "ADD", 17}; _InstInfo II_83_01 = {1, 1, 6, 17, _I8P "\x02" "OR", 25}; _InstInfo II_83_02 = {1, 1, 6, 17, _I8P "\x03" "ADC", 17}; _InstInfo II_83_03 = {1, 1, 6, 17, _I8P "\x03" "SBB", 17}; _InstInfo II_83_04 = {1, 1, 6, 17, _I8P "\x03" "AND", 25}; _InstInfo II_83_05 = {1, 1, 6, 17, _I8P "\x03" "SUB", 17}; _InstInfo II_83_06 = {1, 1, 6, 17, _I8P "\x03" "XOR", 25}; _InstInfo II_83_07 = {1, 1, 6, 17, _I8P "\x03" "CMP", 1}; _InstInfo II_84 = {1, 1, 7, 15, _I8P "\x04" "TEST", 1}; _InstInfo II_85 = {1, 1, 9, 17, _I8P "\x04" "TEST", 1}; _InstInfo II_86 = {1, 1, 7, 15, _I8P "\x04" "XCHG", 17}; _InstInfo II_87 = {1, 1, 9, 17, _I8P "\x04" "XCHG", 17}; _InstInfo II_88 = {1, 1, 7, 15, _I8P "\x03" "MOV", 1}; _InstInfo II_89 = {1, 1, 9, 17, _I8P "\x03" "MOV", 1}; _InstInfo II_8A = {1, 1, 15, 7, _I8P "\x03" "MOV", 1}; _InstInfo II_8B = {1, 1, 17, 9, _I8P "\x03" "MOV", 1}; _InstInfo II_8C = {1, 1, 32, 29, _I8P "\x03" "MOV", 1}; _InstInfo II_8D = {1, 1, 43, 9, _I8P "\x03" "LEA", 1}; _InstInfo II_8E = {1, 1, 16, 32, _I8P "\x03" "MOV", 1}; _InstInfo II_8F_00 = {1, 1, 0, 17, _I8P "\x03" "POP", 16777217}; _InstInfo II_90 = {1, 1, 36, 54, _I8P "\x04" "XCHG", 0}; _InstInfo II_91 = {1, 1, 36, 54, _I8P "\x04" "XCHG", 0}; _InstInfo II_92 = {1, 1, 36, 54, _I8P "\x04" "XCHG", 0}; _InstInfo II_93 = {1, 1, 36, 54, _I8P "\x04" "XCHG", 0}; _InstInfo II_94 = {1, 1, 36, 54, _I8P "\x04" "XCHG", 0}; _InstInfo II_95 = {1, 1, 36, 54, _I8P "\x04" "XCHG", 0}; _InstInfo II_96 = {1, 1, 36, 54, _I8P "\x04" "XCHG", 0}; _InstInfo II_97 = {1, 1, 36, 54, _I8P "\x04" "XCHG", 0}; _InstInfoEx II_98 = {1, 1, 0, 0, _I8P "\x03" "CBW", 67174400, 0, 0, _I8P "\x04" "CWDE", _I8P "\x04" "CDQE"}; _InstInfoEx II_99 = {1, 1, 0, 0, _I8P "\x03" "CWD", 67174400, 0, 0, _I8P "\x03" "CDQ", _I8P "\x03" "CQO"}; _InstInfo II_9A = {1, 1, 0, 39, _I8P "\x08" "CALL FAR", 8388608}; _InstInfo II_9B_D9_06 = {1, 2, 0, 43, _I8P "\x06" "FSTENV", 9}; _InstInfo II_9B_D9_07 = {1, 2, 0, 43, _I8P "\x05" "FSTCW", 9}; _InstInfo II_9B_DB_E2 = {1, 2, 0, 0, _I8P "\x05" "FCLEX", 8}; _InstInfo II_9B_DB_E3 = {1, 2, 0, 0, _I8P "\x05" "FINIT", 8}; _InstInfo II_9B_DD_06 = {1, 2, 0, 43, _I8P "\x05" "FSAVE", 9}; _InstInfo II_9B_DD_07 = {1, 2, 0, 43, _I8P "\x05" "FSTSW", 9}; _InstInfo II_9B_DF_E0 = {1, 2, 0, 35, _I8P "\x05" "FSTSW", 8}; _InstInfo II_9C = {1, 1, 0, 0, _I8P "\x05" "PUSHF", 16809984}; _InstInfo II_9D = {1, 1, 0, 0, _I8P "\x04" "POPF", 16809984}; _InstInfo II_9E = {1, 1, 0, 0, _I8P "\x04" "SAHF", 0}; _InstInfo II_9F = {1, 1, 0, 0, _I8P "\x04" "LAHF", 0}; _InstInfo II_A0 = {1, 1, 49, 34, _I8P "\x03" "MOV", 0}; _InstInfo II_A1 = {1, 1, 49, 36, _I8P "\x03" "MOV", 0}; _InstInfo II_A2 = {1, 1, 34, 49, _I8P "\x03" "MOV", 0}; _InstInfo II_A3 = {1, 1, 36, 49, _I8P "\x03" "MOV", 0}; _InstInfo II_A4 = {1, 1, 0, 56, _I8P "\x04" "MOVS", 1120}; _InstInfo II_A5 = {1, 1, 0, 56, _I8P "\x04" "MOVS", 50332772}; _InstInfo II_A6 = {1, 1, 0, 55, _I8P "\x04" "CMPS", 1120}; _InstInfo II_A7 = {1, 1, 0, 55, _I8P "\x04" "CMPS", 50332772}; _InstInfo II_A8 = {1, 1, 1, 34, _I8P "\x04" "TEST", 0}; _InstInfo II_A9 = {1, 1, 3, 36, _I8P "\x04" "TEST", 0}; _InstInfo II_AA = {1, 1, 0, 56, _I8P "\x04" "STOS", 1120}; _InstInfo II_AB = {1, 1, 0, 56, _I8P "\x04" "STOS", 50332772}; _InstInfo II_AC = {1, 1, 0, 55, _I8P "\x04" "LODS", 608}; _InstInfo II_AD = {1, 1, 0, 55, _I8P "\x04" "LODS", 50332260}; _InstInfo II_AE = {1, 1, 0, 56, _I8P "\x04" "SCAS", 1120}; _InstInfo II_AF = {1, 1, 0, 56, _I8P "\x04" "SCAS", 50332772}; _InstInfo II_B0 = {1, 1, 1, 52, _I8P "\x03" "MOV", 0}; _InstInfo II_B8 = {1, 1, 3, 54, _I8P "\x03" "MOV", 50331648}; _InstInfo II_C0_00 = {1, 1, 1, 15, _I8P "\x03" "ROL", 1}; _InstInfo II_C0_01 = {1, 1, 1, 15, _I8P "\x03" "ROR", 1}; _InstInfo II_C0_02 = {1, 1, 1, 15, _I8P "\x03" "RCL", 1}; _InstInfo II_C0_03 = {1, 1, 1, 15, _I8P "\x03" "RCR", 1}; _InstInfo II_C0_04 = {1, 1, 1, 15, _I8P "\x03" "SHL", 1}; _InstInfo II_C0_05 = {1, 1, 1, 15, _I8P "\x03" "SHR", 1}; _InstInfo II_C0_06 = {1, 1, 1, 15, _I8P "\x03" "SAL", 1}; _InstInfo II_C0_07 = {1, 1, 1, 15, _I8P "\x03" "SAR", 1}; _InstInfo II_C1_00 = {1, 1, 1, 17, _I8P "\x03" "ROL", 1}; _InstInfo II_C1_01 = {1, 1, 1, 17, _I8P "\x03" "ROR", 1}; _InstInfo II_C1_02 = {1, 1, 1, 17, _I8P "\x03" "RCL", 1}; _InstInfo II_C1_03 = {1, 1, 1, 17, _I8P "\x03" "RCR", 1}; _InstInfo II_C1_04 = {1, 1, 1, 17, _I8P "\x03" "SHL", 1}; _InstInfo II_C1_05 = {1, 1, 1, 17, _I8P "\x03" "SHR", 1}; _InstInfo II_C1_06 = {1, 1, 1, 17, _I8P "\x03" "SAL", 1}; _InstInfo II_C1_07 = {1, 1, 1, 17, _I8P "\x03" "SAR", 1}; _InstInfo II_C2 = {1, 1, 0, 2, _I8P "\x03" "RET", 0}; _InstInfo II_C3 = {1, 1, 0, 0, _I8P "\x03" "RET", 0}; _InstInfo II_C4 = {1, 1, 38, 9, _I8P "\x03" "LES", 8388609}; _InstInfo II_C5 = {1, 1, 38, 9, _I8P "\x03" "LDS", 8388609}; _InstInfo II_C6_00 = {1, 1, 1, 15, _I8P "\x03" "MOV", 1}; _InstInfo II_C7_00 = {1, 1, 3, 17, _I8P "\x03" "MOV", 1}; _InstInfo II_C8 = {1, 1, 1, 2, _I8P "\x05" "ENTER", 0}; _InstInfo II_C9 = {1, 1, 0, 0, _I8P "\x05" "LEAVE", 0}; _InstInfo II_CA = {1, 1, 0, 2, _I8P "\x04" "RETF", 50364416}; _InstInfo II_CB = {1, 1, 0, 0, _I8P "\x04" "RETF", 50364416}; _InstInfo II_CC = {1, 1, 0, 0, _I8P "\x05" "INT 3", 0}; _InstInfo II_CD = {1, 1, 0, 1, _I8P "\x03" "INT", 0}; _InstInfo II_CE = {1, 1, 0, 0, _I8P "\x04" "INTO", 8388608}; _InstInfo II_CF = {1, 1, 0, 0, _I8P "\x04" "IRET", 50364416}; _InstInfo II_D0_00 = {1, 1, 50, 15, _I8P "\x03" "ROL", 1}; _InstInfo II_D0_01 = {1, 1, 50, 15, _I8P "\x03" "ROR", 1}; _InstInfo II_D0_02 = {1, 1, 50, 15, _I8P "\x03" "RCL", 1}; _InstInfo II_D0_03 = {1, 1, 50, 15, _I8P "\x03" "RCR", 1}; _InstInfo II_D0_04 = {1, 1, 50, 15, _I8P "\x03" "SHL", 1}; _InstInfo II_D0_05 = {1, 1, 50, 15, _I8P "\x03" "SHR", 1}; _InstInfo II_D0_06 = {1, 1, 50, 15, _I8P "\x03" "SAL", 1}; _InstInfo II_D0_07 = {1, 1, 50, 15, _I8P "\x03" "SAR", 1}; _InstInfo II_D1_00 = {1, 1, 50, 17, _I8P "\x03" "ROL", 1}; _InstInfo II_D1_01 = {1, 1, 50, 17, _I8P "\x03" "ROR", 1}; _InstInfo II_D1_02 = {1, 1, 50, 17, _I8P "\x03" "RCL", 1}; _InstInfo II_D1_03 = {1, 1, 50, 17, _I8P "\x03" "RCR", 1}; _InstInfo II_D1_04 = {1, 1, 50, 17, _I8P "\x03" "SHL", 1}; _InstInfo II_D1_05 = {1, 1, 50, 17, _I8P "\x03" "SHR", 1}; _InstInfo II_D1_06 = {1, 1, 50, 17, _I8P "\x03" "SAL", 1}; _InstInfo II_D1_07 = {1, 1, 50, 17, _I8P "\x03" "SAR", 1}; _InstInfo II_D2_00 = {1, 1, 51, 15, _I8P "\x03" "ROL", 1}; _InstInfo II_D2_01 = {1, 1, 51, 15, _I8P "\x03" "ROR", 1}; _InstInfo II_D2_02 = {1, 1, 51, 15, _I8P "\x03" "RCL", 1}; _InstInfo II_D2_03 = {1, 1, 51, 15, _I8P "\x03" "RCR", 1}; _InstInfo II_D2_04 = {1, 1, 51, 15, _I8P "\x03" "SHL", 1}; _InstInfo II_D2_05 = {1, 1, 51, 15, _I8P "\x03" "SHR", 1}; _InstInfo II_D2_06 = {1, 1, 51, 15, _I8P "\x03" "SAL", 1}; _InstInfo II_D2_07 = {1, 1, 51, 15, _I8P "\x03" "SAR", 1}; _InstInfo II_D3_00 = {1, 1, 51, 17, _I8P "\x03" "ROL", 1}; _InstInfo II_D3_01 = {1, 1, 51, 17, _I8P "\x03" "ROR", 1}; _InstInfo II_D3_02 = {1, 1, 51, 17, _I8P "\x03" "RCL", 1}; _InstInfo II_D3_03 = {1, 1, 51, 17, _I8P "\x03" "RCR", 1}; _InstInfo II_D3_04 = {1, 1, 51, 17, _I8P "\x03" "SHL", 1}; _InstInfo II_D3_05 = {1, 1, 51, 17, _I8P "\x03" "SHR", 1}; _InstInfo II_D3_06 = {1, 1, 51, 17, _I8P "\x03" "SAL", 1}; _InstInfo II_D3_07 = {1, 1, 51, 17, _I8P "\x03" "SAR", 1}; _InstInfo II_D4 = {1, 1, 0, 5, _I8P "\x03" "AAM", 8388608}; _InstInfo II_D5 = {1, 1, 0, 5, _I8P "\x03" "AAD", 8388608}; _InstInfo II_D6 = {1, 1, 0, 0, _I8P "\x04" "SALC", 8388608}; _InstInfo II_D7 = {1, 1, 0, 57, _I8P "\x04" "XLAT", 512}; _InstInfo II_D8_00 = {1, 2, 0, 22, _I8P "\x04" "FADD", 1}; _InstInfo II_D8_01 = {1, 2, 0, 22, _I8P "\x04" "FMUL", 1}; _InstInfo II_D8_02 = {1, 2, 0, 22, _I8P "\x04" "FCOM", 1}; _InstInfo II_D8_03 = {1, 2, 0, 22, _I8P "\x05" "FCOMP", 1}; _InstInfo II_D8_04 = {1, 2, 0, 22, _I8P "\x04" "FSUB", 1}; _InstInfo II_D8_05 = {1, 2, 0, 22, _I8P "\x05" "FSUBR", 1}; _InstInfo II_D8_06 = {1, 2, 0, 22, _I8P "\x04" "FDIV", 1}; _InstInfo II_D8_07 = {1, 2, 0, 22, _I8P "\x05" "FDIVR", 1}; _InstInfo II_D8_C0 = {1, 2, 0, 62, _I8P "\x04" "FADD", 0}; _InstInfo II_D8_C8 = {1, 2, 0, 62, _I8P "\x04" "FMUL", 0}; _InstInfo II_D8_D0 = {1, 2, 0, 61, _I8P "\x04" "FCOM", 0}; _InstInfo II_D8_D8 = {1, 2, 0, 61, _I8P "\x05" "FCOMP", 0}; _InstInfo II_D8_D9 = {1, 2, 0, 0, _I8P "\x05" "FCOMP", 0}; _InstInfo II_D8_E0 = {1, 2, 0, 62, _I8P "\x04" "FSUB", 0}; _InstInfo II_D8_E8 = {1, 2, 0, 62, _I8P "\x05" "FSUBR", 0}; _InstInfo II_D8_F0 = {1, 2, 0, 62, _I8P "\x04" "FDIV", 0}; _InstInfo II_D8_F8 = {1, 2, 0, 62, _I8P "\x05" "FDIVR", 0}; _InstInfo II_D9_00 = {1, 2, 0, 22, _I8P "\x03" "FLD", 1}; _InstInfo II_D9_02 = {1, 2, 0, 22, _I8P "\x03" "FST", 1}; _InstInfo II_D9_03 = {1, 2, 0, 22, _I8P "\x04" "FSTP", 1}; _InstInfo II_D9_04 = {1, 2, 0, 43, _I8P "\x06" "FLDENV", 1}; _InstInfo II_D9_05 = {1, 2, 0, 43, _I8P "\x05" "FLDCW", 1}; _InstInfo II_D9_06 = {1, 2, 0, 43, _I8P "\x07" "FNSTENV", 1}; _InstInfo II_D9_07 = {1, 2, 0, 43, _I8P "\x06" "FNSTCW", 1}; _InstInfo II_D9_C0 = {1, 2, 0, 61, _I8P "\x03" "FLD", 0}; _InstInfo II_D9_C8 = {1, 2, 0, 61, _I8P "\x04" "FXCH", 0}; _InstInfo II_D9_C9 = {1, 2, 0, 0, _I8P "\x04" "FXCH", 0}; _InstInfo II_D9_D0 = {1, 2, 0, 0, _I8P "\x04" "FNOP", 0}; _InstInfo II_D9_E0 = {1, 2, 0, 0, _I8P "\x04" "FCHS", 0}; _InstInfo II_D9_E1 = {1, 2, 0, 0, _I8P "\x04" "FABS", 0}; _InstInfo II_D9_E4 = {1, 2, 0, 0, _I8P "\x04" "FTST", 0}; _InstInfo II_D9_E5 = {1, 2, 0, 0, _I8P "\x04" "FXAM", 0}; _InstInfo II_D9_E8 = {1, 2, 0, 0, _I8P "\x04" "FLD1", 0}; _InstInfo II_D9_E9 = {1, 2, 0, 0, _I8P "\x06" "FLDL2T", 0}; _InstInfo II_D9_EA = {1, 2, 0, 0, _I8P "\x06" "FLDL2E", 0}; _InstInfo II_D9_EB = {1, 2, 0, 0, _I8P "\x05" "FLDPI", 0}; _InstInfo II_D9_EC = {1, 2, 0, 0, _I8P "\x06" "FLDLG2", 0}; _InstInfo II_D9_ED = {1, 2, 0, 0, _I8P "\x06" "FLDLN2", 0}; _InstInfo II_D9_EE = {1, 2, 0, 0, _I8P "\x04" "FLDZ", 0}; _InstInfo II_D9_F0 = {1, 2, 0, 0, _I8P "\x05" "F2XM1", 0}; _InstInfo II_D9_F1 = {1, 2, 0, 0, _I8P "\x05" "FYL2X", 0}; _InstInfo II_D9_F2 = {1, 2, 0, 0, _I8P "\x05" "FPTAN", 0}; _InstInfo II_D9_F3 = {1, 2, 0, 0, _I8P "\x06" "FPATAN", 0}; _InstInfo II_D9_F4 = {1, 2, 0, 0, _I8P "\x07" "FXTRACT", 0}; _InstInfo II_D9_F5 = {1, 2, 0, 0, _I8P "\x06" "FPREM1", 0}; _InstInfo II_D9_F6 = {1, 2, 0, 0, _I8P "\x07" "FDECSTP", 0}; _InstInfo II_D9_F7 = {1, 2, 0, 0, _I8P "\x07" "FINCSTP", 0}; _InstInfo II_D9_F8 = {1, 2, 0, 0, _I8P "\x05" "FPREM", 0}; _InstInfo II_D9_F9 = {1, 2, 0, 0, _I8P "\x07" "FYL2XP1", 0}; _InstInfo II_D9_FA = {1, 2, 0, 0, _I8P "\x05" "FSQRT", 0}; _InstInfo II_D9_FB = {1, 2, 0, 0, _I8P "\x07" "FSINCOS", 0}; _InstInfo II_D9_FC = {1, 2, 0, 0, _I8P "\x07" "FRNDINT", 0}; _InstInfo II_D9_FD = {1, 2, 0, 0, _I8P "\x06" "FSCALE", 0}; _InstInfo II_D9_FE = {1, 2, 0, 0, _I8P "\x04" "FSIN", 0}; _InstInfo II_D9_FF = {1, 2, 0, 0, _I8P "\x04" "FCOS", 0}; _InstInfo II_DA_00 = {1, 2, 0, 22, _I8P "\x05" "FIADD", 1}; _InstInfo II_DA_01 = {1, 2, 0, 22, _I8P "\x05" "FIMUL", 1}; _InstInfo II_DA_02 = {1, 2, 0, 22, _I8P "\x05" "FICOM", 1}; _InstInfo II_DA_03 = {1, 2, 0, 22, _I8P "\x06" "FICOMP", 1}; _InstInfo II_DA_04 = {1, 2, 0, 22, _I8P "\x05" "FISUB", 1}; _InstInfo II_DA_05 = {1, 2, 0, 22, _I8P "\x06" "FISUBR", 1}; _InstInfo II_DA_06 = {1, 2, 0, 22, _I8P "\x05" "FIDIV", 1}; _InstInfo II_DA_07 = {1, 2, 0, 22, _I8P "\x06" "FIDIVR", 1}; _InstInfo II_DA_C0 = {1, 3, 0, 62, _I8P "\x06" "FCMOVB", 8}; _InstInfo II_DA_C8 = {1, 3, 0, 62, _I8P "\x06" "FCMOVE", 8}; _InstInfo II_DA_D0 = {1, 3, 0, 62, _I8P "\x07" "FCMOVBE", 8}; _InstInfo II_DA_D8 = {1, 3, 0, 62, _I8P "\x06" "FCMOVU", 8}; _InstInfo II_DA_E9 = {1, 2, 0, 0, _I8P "\x07" "FUCOMPP", 0}; _InstInfo II_DB_00 = {1, 2, 0, 22, _I8P "\x04" "FILD", 1}; _InstInfo II_DB_01 = {1, 7, 0, 22, _I8P "\x06" "FISTTP", 9}; _InstInfo II_DB_02 = {1, 2, 0, 22, _I8P "\x04" "FIST", 1}; _InstInfo II_DB_03 = {1, 2, 0, 22, _I8P "\x05" "FISTP", 1}; _InstInfo II_DB_05 = {1, 2, 0, 24, _I8P "\x03" "FLD", 1}; _InstInfo II_DB_07 = {1, 2, 0, 24, _I8P "\x04" "FSTP", 1}; _InstInfo II_DB_C0 = {1, 3, 0, 62, _I8P "\x07" "FCMOVNB", 8}; _InstInfo II_DB_C8 = {1, 3, 0, 62, _I8P "\x07" "FCMOVNE", 8}; _InstInfo II_DB_D0 = {1, 3, 0, 62, _I8P "\x08" "FCMOVNBE", 8}; _InstInfo II_DB_D8 = {1, 3, 0, 62, _I8P "\x07" "FCMOVNU", 8}; _InstInfo II_DB_E0 = {1, 2, 0, 0, _I8P "\x04" "FENI", 0}; _InstInfo II_DB_E1 = {1, 2, 0, 0, _I8P "\x06" "FEDISI", 0}; _InstInfo II_DB_E2 = {1, 2, 0, 0, _I8P "\x06" "FNCLEX", 0}; _InstInfo II_DB_E3 = {1, 2, 0, 0, _I8P "\x06" "FNINIT", 0}; _InstInfo II_DB_E4 = {1, 2, 0, 0, _I8P "\x06" "FSETPM", 0}; _InstInfo II_DB_E8 = {1, 2, 0, 62, _I8P "\x06" "FUCOMI", 8}; _InstInfo II_DB_F0 = {1, 3, 0, 62, _I8P "\x05" "FCOMI", 8}; _InstInfo II_DC_00 = {1, 2, 0, 23, _I8P "\x04" "FADD", 1}; _InstInfo II_DC_01 = {1, 2, 0, 23, _I8P "\x04" "FMUL", 1}; _InstInfo II_DC_02 = {1, 2, 0, 23, _I8P "\x04" "FCOM", 1}; _InstInfo II_DC_03 = {1, 2, 0, 23, _I8P "\x05" "FCOMP", 1}; _InstInfo II_DC_04 = {1, 2, 0, 23, _I8P "\x04" "FSUB", 1}; _InstInfo II_DC_05 = {1, 2, 0, 23, _I8P "\x05" "FSUBR", 1}; _InstInfo II_DC_06 = {1, 2, 0, 23, _I8P "\x04" "FDIV", 1}; _InstInfo II_DC_07 = {1, 2, 0, 23, _I8P "\x05" "FDIVR", 1}; _InstInfo II_DC_C0 = {1, 2, 0, 63, _I8P "\x04" "FADD", 0}; _InstInfo II_DC_C8 = {1, 2, 0, 63, _I8P "\x04" "FMUL", 0}; _InstInfo II_DC_E0 = {1, 2, 0, 63, _I8P "\x05" "FSUBR", 0}; _InstInfo II_DC_E8 = {1, 2, 0, 63, _I8P "\x04" "FSUB", 0}; _InstInfo II_DC_F0 = {1, 2, 0, 63, _I8P "\x05" "FDIVR", 0}; _InstInfo II_DC_F8 = {1, 2, 0, 63, _I8P "\x04" "FDIV", 0}; _InstInfo II_DD_00 = {1, 2, 0, 23, _I8P "\x03" "FLD", 1}; _InstInfo II_DD_01 = {1, 7, 0, 23, _I8P "\x06" "FISTTP", 9}; _InstInfo II_DD_02 = {1, 2, 0, 23, _I8P "\x03" "FST", 1}; _InstInfo II_DD_03 = {1, 2, 0, 23, _I8P "\x04" "FSTP", 1}; _InstInfo II_DD_04 = {1, 2, 0, 43, _I8P "\x06" "FRSTOR", 1}; _InstInfo II_DD_06 = {1, 2, 0, 43, _I8P "\x06" "FNSAVE", 1}; _InstInfo II_DD_07 = {1, 2, 0, 43, _I8P "\x06" "FNSTSW", 1}; _InstInfo II_DD_C0 = {1, 2, 0, 61, _I8P "\x05" "FFREE", 0}; _InstInfo II_DD_D0 = {1, 2, 0, 61, _I8P "\x03" "FST", 0}; _InstInfo II_DD_D8 = {1, 2, 0, 61, _I8P "\x04" "FSTP", 0}; _InstInfo II_DD_E0 = {1, 2, 0, 63, _I8P "\x05" "FUCOM", 0}; _InstInfo II_DD_E1 = {1, 2, 0, 0, _I8P "\x05" "FUCOM", 0}; _InstInfo II_DD_E8 = {1, 2, 0, 61, _I8P "\x06" "FUCOMP", 0}; _InstInfo II_DD_E9 = {1, 2, 0, 0, _I8P "\x06" "FUCOMP", 0}; _InstInfo II_DE_00 = {1, 2, 0, 21, _I8P "\x05" "FIADD", 1}; _InstInfo II_DE_01 = {1, 2, 0, 21, _I8P "\x05" "FIMUL", 1}; _InstInfo II_DE_02 = {1, 2, 0, 21, _I8P "\x05" "FICOM", 1}; _InstInfo II_DE_03 = {1, 2, 0, 21, _I8P "\x06" "FICOMP", 1}; _InstInfo II_DE_04 = {1, 2, 0, 21, _I8P "\x05" "FISUB", 1}; _InstInfo II_DE_05 = {1, 2, 0, 21, _I8P "\x06" "FISUBR", 1}; _InstInfo II_DE_06 = {1, 2, 0, 21, _I8P "\x05" "FIDIV", 1}; _InstInfo II_DE_07 = {1, 2, 0, 21, _I8P "\x06" "FIDIVR", 1}; _InstInfo II_DE_C0 = {1, 2, 0, 63, _I8P "\x05" "FADDP", 0}; _InstInfo II_DE_C1 = {1, 2, 0, 0, _I8P "\x05" "FADDP", 0}; _InstInfo II_DE_C8 = {1, 2, 0, 63, _I8P "\x05" "FMULP", 0}; _InstInfo II_DE_C9 = {1, 2, 0, 0, _I8P "\x05" "FMULP", 0}; _InstInfo II_DE_D9 = {1, 2, 0, 0, _I8P "\x06" "FCOMPP", 0}; _InstInfo II_DE_E0 = {1, 2, 0, 63, _I8P "\x06" "FSUBRP", 0}; _InstInfo II_DE_E1 = {1, 2, 0, 0, _I8P "\x06" "FSUBRP", 0}; _InstInfo II_DE_E8 = {1, 2, 0, 63, _I8P "\x05" "FSUBP", 0}; _InstInfo II_DE_E9 = {1, 2, 0, 0, _I8P "\x05" "FSUBP", 0}; _InstInfo II_DE_F0 = {1, 2, 0, 63, _I8P "\x06" "FDIVRP", 0}; _InstInfo II_DE_F1 = {1, 2, 0, 0, _I8P "\x06" "FDIVRP", 0}; _InstInfo II_DE_F8 = {1, 2, 0, 63, _I8P "\x05" "FDIVP", 0}; _InstInfo II_DE_F9 = {1, 2, 0, 0, _I8P "\x05" "FDIVP", 0}; _InstInfo II_DF_00 = {1, 2, 0, 21, _I8P "\x04" "FILD", 1}; _InstInfo II_DF_01 = {1, 7, 0, 21, _I8P "\x06" "FISTTP", 9}; _InstInfo II_DF_02 = {1, 2, 0, 21, _I8P "\x04" "FIST", 1}; _InstInfo II_DF_03 = {1, 2, 0, 21, _I8P "\x05" "FISTP", 1}; _InstInfo II_DF_04 = {1, 2, 0, 24, _I8P "\x04" "FBLD", 1}; _InstInfo II_DF_05 = {1, 2, 0, 23, _I8P "\x04" "FILD", 1}; _InstInfo II_DF_06 = {1, 2, 0, 24, _I8P "\x05" "FBSTP", 1}; _InstInfo II_DF_07 = {1, 2, 0, 23, _I8P "\x05" "FISTP", 1}; _InstInfo II_DF_E0 = {1, 2, 0, 35, _I8P "\x06" "FNSTSW", 0}; _InstInfo II_DF_E8 = {1, 2, 0, 62, _I8P "\x07" "FUCOMIP", 8}; _InstInfo II_DF_F0 = {1, 2, 0, 62, _I8P "\x06" "FCOMIP", 8}; _InstInfo II_E0 = {1, 1, 0, 41, _I8P "\x06" "LOOPNZ", 49152}; _InstInfo II_E1 = {1, 1, 0, 41, _I8P "\x05" "LOOPZ", 49152}; _InstInfo II_E2 = {1, 1, 0, 41, _I8P "\x04" "LOOP", 49152}; _InstInfoEx II_E3 = {1, 1, 0, 41, _I8P "\x04" "JCXZ", 67190784, 0, 0, _I8P "\x05" "JECXZ", _I8P "\x05" "JRCXZ"}; _InstInfo II_E4 = {1, 1, 1, 34, _I8P "\x02" "IN", 0}; _InstInfo II_E5 = {1, 1, 1, 37, _I8P "\x02" "IN", 0}; _InstInfo II_E6 = {1, 1, 34, 1, _I8P "\x03" "OUT", 0}; _InstInfo II_E7 = {1, 1, 37, 1, _I8P "\x03" "OUT", 0}; _InstInfo II_E8 = {1, 1, 0, 42, _I8P "\x04" "CALL", 0}; _InstInfo II_E9 = {1, 1, 0, 42, _I8P "\x03" "JMP", 0}; _InstInfo II_EA = {1, 1, 0, 39, _I8P "\x07" "JMP FAR", 8388608}; _InstInfo II_EB = {1, 1, 0, 41, _I8P "\x03" "JMP", 0}; _InstInfo II_EC = {1, 1, 59, 34, _I8P "\x02" "IN", 0}; _InstInfo II_ED = {1, 1, 59, 37, _I8P "\x02" "IN", 0}; _InstInfo II_EE = {1, 1, 34, 59, _I8P "\x03" "OUT", 0}; _InstInfo II_EF = {1, 1, 37, 59, _I8P "\x03" "OUT", 0}; _InstInfo II_F1 = {1, 1, 0, 0, _I8P "\x04" "INT1", 0}; _InstInfo II_F2_0F_10 = {1, 6, 72, 68, _I8P "\x05" "MOVSD", 9}; _InstInfo II_F2_0F_11 = {1, 6, 68, 72, _I8P "\x05" "MOVSD", 9}; _InstInfo II_F2_0F_12 = {1, 7, 72, 68, _I8P "\x07" "MOVDDUP", 9}; _InstInfo II_F2_0F_2A = {1, 6, 19, 68, _I8P "\x08" "CVTSI2SD", 50331657}; _InstInfo II_F2_0F_2B = {1, 11, 68, 46, _I8P "\x07" "MOVNTSD", 9}; _InstInfo II_F2_0F_2C = {1, 6, 72, 12, _I8P "\x09" "CVTTSD2SI", 50331657}; _InstInfo II_F2_0F_2D = {1, 6, 72, 12, _I8P "\x08" "CVTSD2SI", 50331657}; _InstInfo II_F2_0F_38_F0 = {1, 10, 15, 12, _I8P "\x05" "CRC32", 9}; _InstInfo II_F2_0F_38_F1 = {1, 10, 17, 12, _I8P "\x05" "CRC32", 9}; _InstInfo II_F2_0F_51 = {1, 6, 72, 68, _I8P "\x06" "SQRTSD", 9}; _InstInfo II_F2_0F_58 = {1, 6, 72, 68, _I8P "\x05" "ADDSD", 9}; _InstInfo II_F2_0F_59 = {1, 6, 72, 68, _I8P "\x05" "MULSD", 9}; _InstInfo II_F2_0F_5A = {1, 6, 72, 68, _I8P "\x08" "CVTSD2SS", 9}; _InstInfo II_F2_0F_5C = {1, 6, 72, 68, _I8P "\x05" "SUBSD", 9}; _InstInfo II_F2_0F_5D = {1, 6, 72, 68, _I8P "\x05" "MINSD", 9}; _InstInfo II_F2_0F_5E = {1, 6, 72, 68, _I8P "\x05" "DIVSD", 9}; _InstInfo II_F2_0F_5F = {1, 6, 72, 68, _I8P "\x05" "MAXSD", 9}; _InstInfoEx II_F2_0F_70 = {1, 6, 73, 68, _I8P "\x07" "PSHUFLW", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfoEx II_F2_0F_78 = {1, 11, 69, 68, _I8P "\x07" "INSERTQ", 1441801, 1, 1, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_F2_0F_79 = {1, 11, 69, 68, _I8P "\x07" "INSERTQ", 1048585}; _InstInfo II_F2_0F_7C = {1, 7, 73, 68, _I8P "\x06" "HADDPS", 9}; _InstInfo II_F2_0F_7D = {1, 7, 73, 68, _I8P "\x06" "HSUBPS", 9}; _InstInfoEx II_F2_0F_C2 = {1, 6, 72, 68, _I8P "\x03" "CMP", 4259849, 0, 0, _I8P "\x02" "SD", _I8P "\x00" ""}; _InstInfo II_F2_0F_D0 = {1, 7, 73, 68, _I8P "\x08" "ADDSUBPS", 9}; _InstInfo II_F2_0F_D6 = {1, 6, 69, 64, _I8P "\x07" "MOVDQ2Q", 1048585}; _InstInfo II_F2_0F_E6 = {1, 6, 73, 68, _I8P "\x08" "CVTPD2DQ", 9}; _InstInfo II_F2_0F_F0 = {1, 7, 43, 68, _I8P "\x05" "LDDQU", 9}; _InstInfo II_F3_0F_10 = {1, 5, 71, 68, _I8P "\x05" "MOVSS", 9}; _InstInfo II_F3_0F_11 = {1, 5, 68, 71, _I8P "\x05" "MOVSS", 9}; _InstInfo II_F3_0F_12 = {1, 7, 72, 68, _I8P "\x08" "MOVSLDUP", 9}; _InstInfo II_F3_0F_16 = {1, 7, 73, 68, _I8P "\x08" "MOVSHDUP", 9}; _InstInfo II_F3_0F_2A = {1, 5, 19, 68, _I8P "\x08" "CVTSI2SS", 50331657}; _InstInfo II_F3_0F_2B = {1, 11, 68, 44, _I8P "\x07" "MOVNTSS", 9}; _InstInfo II_F3_0F_2C = {1, 5, 71, 12, _I8P "\x09" "CVTTSS2SI", 50331657}; _InstInfo II_F3_0F_2D = {1, 5, 71, 12, _I8P "\x08" "CVTSS2SI", 50331657}; _InstInfo II_F3_0F_51 = {1, 5, 71, 68, _I8P "\x06" "SQRTSS", 9}; _InstInfo II_F3_0F_52 = {1, 5, 71, 68, _I8P "\x07" "RSQRTSS", 9}; _InstInfo II_F3_0F_53 = {1, 5, 71, 68, _I8P "\x05" "RCPSS", 9}; _InstInfo II_F3_0F_58 = {1, 5, 71, 68, _I8P "\x05" "ADDSS", 9}; _InstInfo II_F3_0F_59 = {1, 5, 71, 68, _I8P "\x05" "MULSS", 9}; _InstInfo II_F3_0F_5A = {1, 6, 71, 68, _I8P "\x08" "CVTSS2SD", 9}; _InstInfo II_F3_0F_5B = {1, 6, 73, 68, _I8P "\x09" "CVTTPS2DQ", 9}; _InstInfo II_F3_0F_5C = {1, 5, 71, 68, _I8P "\x05" "SUBSS", 9}; _InstInfo II_F3_0F_5D = {1, 5, 71, 68, _I8P "\x05" "MINSS", 9}; _InstInfo II_F3_0F_5E = {1, 5, 71, 68, _I8P "\x05" "DIVSS", 9}; _InstInfo II_F3_0F_5F = {1, 5, 71, 68, _I8P "\x05" "MAXSS", 9}; _InstInfo II_F3_0F_6F = {1, 6, 73, 68, _I8P "\x06" "MOVDQU", 9}; _InstInfoEx II_F3_0F_70 = {1, 6, 73, 68, _I8P "\x07" "PSHUFHW", 131081, 1, 0, _I8P "\x00" "", _I8P "\x00" ""}; _InstInfo II_F3_0F_7E = {1, 6, 72, 68, _I8P "\x04" "MOVQ", 9}; _InstInfo II_F3_0F_7F = {1, 6, 68, 73, _I8P "\x06" "MOVDQU", 9}; _InstInfo II_F3_0F_B8 = {1, 10, 17, 9, _I8P "\x06" "POPCNT", 9}; _InstInfo II_F3_0F_BD = {1, 1, 17, 9, _I8P "\x05" "LZCNT", 1}; _InstInfoEx II_F3_0F_C2 = {1, 5, 71, 68, _I8P "\x03" "CMP", 4259849, 0, 0, _I8P "\x02" "SS", _I8P "\x00" ""}; _InstInfo II_F3_0F_C7_06 = {1, 14, 0, 46, _I8P "\x05" "VMXON", 9}; _InstInfo II_F3_0F_D6 = {1, 6, 65, 68, _I8P "\x07" "MOVQ2DQ", 1048585}; _InstInfo II_F3_0F_E6 = {1, 6, 72, 68, _I8P "\x08" "CVTDQ2PD", 9}; _InstInfo II_F3_90 = {1, 6, 0, 0, _I8P "\x05" "PAUSE", 8}; _InstInfo II_F4 = {1, 1, 0, 0, _I8P "\x03" "HLT", 0}; _InstInfo II_F5 = {1, 1, 0, 0, _I8P "\x03" "CMC", 0}; _InstInfo II_F6_00 = {1, 1, 1, 15, _I8P "\x04" "TEST", 1}; _InstInfo II_F6_02 = {1, 1, 0, 15, _I8P "\x03" "NOT", 17}; _InstInfo II_F6_03 = {1, 1, 0, 15, _I8P "\x03" "NEG", 17}; _InstInfo II_F6_04 = {1, 1, 0, 15, _I8P "\x03" "MUL", 1}; _InstInfo II_F6_05 = {1, 1, 0, 15, _I8P "\x04" "IMUL", 1}; _InstInfo II_F6_06 = {1, 1, 0, 15, _I8P "\x03" "DIV", 1}; _InstInfo II_F6_07 = {1, 1, 0, 15, _I8P "\x04" "IDIV", 1}; _InstInfo II_F7_00 = {1, 1, 3, 17, _I8P "\x04" "TEST", 1}; _InstInfo II_F7_02 = {1, 1, 0, 17, _I8P "\x03" "NOT", 17}; _InstInfo II_F7_03 = {1, 1, 0, 17, _I8P "\x03" "NEG", 17}; _InstInfo II_F7_04 = {1, 1, 0, 17, _I8P "\x03" "MUL", 1}; _InstInfo II_F7_05 = {1, 1, 0, 17, _I8P "\x04" "IMUL", 1}; _InstInfo II_F7_06 = {1, 1, 0, 17, _I8P "\x03" "DIV", 1}; _InstInfo II_F7_07 = {1, 1, 0, 17, _I8P "\x04" "IDIV", 1}; _InstInfo II_F8 = {1, 1, 0, 0, _I8P "\x03" "CLC", 0}; _InstInfo II_F9 = {1, 1, 0, 0, _I8P "\x03" "STC", 0}; _InstInfo II_FA = {1, 1, 0, 0, _I8P "\x03" "CLI", 0}; _InstInfo II_FB = {1, 1, 0, 0, _I8P "\x03" "STI", 0}; _InstInfo II_FC = {1, 1, 0, 0, _I8P "\x03" "CLD", 0}; _InstInfo II_FD = {1, 1, 0, 0, _I8P "\x03" "STD", 0}; _InstInfo II_FE_00 = {1, 1, 0, 15, _I8P "\x03" "INC", 17}; _InstInfo II_FE_01 = {1, 1, 0, 15, _I8P "\x03" "DEC", 17}; _InstInfo II_FF_00 = {1, 1, 0, 17, _I8P "\x03" "INC", 17}; _InstInfo II_FF_01 = {1, 1, 0, 17, _I8P "\x03" "DEC", 17}; _InstInfo II_FF_02 = {1, 1, 75, 17, _I8P "\x04" "CALL", 16777217}; _InstInfo II_FF_03 = {1, 1, 0, 38, _I8P "\x08" "CALL FAR", 50331649}; _InstInfo II_FF_04 = {1, 1, 75, 17, _I8P "\x03" "JMP", 16777217}; _InstInfo II_FF_05 = {1, 1, 0, 38, _I8P "\x07" "JMP FAR", 50331649}; _InstInfo II_FF_06 = {1, 1, 0, 17, _I8P "\x04" "PUSH", 16777217}; uint8_t Table_FF_ids[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00}; _InstInfo* Table_FF_ptrs[8] = { NULL, &II_FF_00, &II_FF_01, &II_FF_02, &II_FF_03, &II_FF_04, &II_FF_05, &II_FF_06}; _InstNode Table_FF = {2, Table_FF_ids, Table_FF_ptrs}; uint8_t Table_FE_ids[8] = {0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_FE_ptrs[3] = { NULL, &II_FE_00, &II_FE_01}; _InstNode Table_FE = {2, Table_FE_ids, Table_FE_ptrs}; uint8_t Table_F7_ids[8] = {0x01, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_F7_ptrs[8] = { NULL, &II_F7_00, &II_F7_02, &II_F7_03, &II_F7_04, &II_F7_05, &II_F7_06, &II_F7_07}; _InstNode Table_F7 = {2, Table_F7_ids, Table_F7_ptrs}; uint8_t Table_F6_ids[8] = {0x01, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_F6_ptrs[8] = { NULL, &II_F6_00, &II_F6_02, &II_F6_03, &II_F6_04, &II_F6_05, &II_F6_06, &II_F6_07}; _InstNode Table_F6 = {2, Table_F6_ids, Table_F6_ptrs}; uint8_t Table_F3_0F_C7_ids[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}; _InstInfo* Table_F3_0F_C7_ptrs[2] = { NULL, &II_F3_0F_C7_06}; _InstNode Table_F3_0F_C7 = {2, Table_F3_0F_C7_ids, Table_F3_0F_C7_ptrs}; uint8_t Table_F3_0F_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0a, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_F3_0F_ptrs[30] = { NULL, &II_F3_0F_10, &II_F3_0F_11, &II_F3_0F_12, &II_F3_0F_16, &II_F3_0F_2A, &II_F3_0F_2B, &II_F3_0F_2C, &II_F3_0F_2D, &II_F3_0F_51, &II_F3_0F_52, &II_F3_0F_53, &II_F3_0F_58, &II_F3_0F_59, &II_F3_0F_5A, &II_F3_0F_5B, &II_F3_0F_5C, &II_F3_0F_5D, &II_F3_0F_5E, &II_F3_0F_5F, &II_F3_0F_6F, (_InstInfo*)&II_F3_0F_70, &II_F3_0F_7E, &II_F3_0F_7F, &II_F3_0F_B8, &II_F3_0F_BD, (_InstInfo*)&II_F3_0F_C2, (_InstInfo*)&Table_F3_0F_C7, &II_F3_0F_D6, &II_F3_0F_E6}; _InstNode Table_F3_0F = {3, Table_F3_0F_ids, Table_F3_0F_ptrs}; uint8_t Table_F3_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_F3_ptrs[3] = { NULL, (_InstInfo*)&Table_F3_0F, &II_F3_90}; _InstNode Table_F3 = {3, Table_F3_ids, Table_F3_ptrs}; uint8_t Table_F2_0F_38_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_F2_0F_38_ptrs[3] = { NULL, &II_F2_0F_38_F0, &II_F2_0F_38_F1}; _InstNode Table_F2_0F_38 = {3, Table_F2_0F_38_ids, Table_F2_0F_38_ptrs}; uint8_t Table_F2_0F_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x00, 0x0d, 0x0e, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13, 0x00, 0x00, 0x14, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_F2_0F_ptrs[27] = { NULL, &II_F2_0F_10, &II_F2_0F_11, &II_F2_0F_12, &II_F2_0F_2A, &II_F2_0F_2B, &II_F2_0F_2C, &II_F2_0F_2D, (_InstInfo*)&Table_F2_0F_38, &II_F2_0F_51, &II_F2_0F_58, &II_F2_0F_59, &II_F2_0F_5A, &II_F2_0F_5C, &II_F2_0F_5D, &II_F2_0F_5E, &II_F2_0F_5F, (_InstInfo*)&II_F2_0F_70, (_InstInfo*)&II_F2_0F_78, &II_F2_0F_79, &II_F2_0F_7C, &II_F2_0F_7D, (_InstInfo*)&II_F2_0F_C2, &II_F2_0F_D0, &II_F2_0F_D6, &II_F2_0F_E6, &II_F2_0F_F0}; _InstNode Table_F2_0F = {3, Table_F2_0F_ids, Table_F2_0F_ptrs}; uint8_t Table_F2_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_F2_ptrs[2] = { NULL, (_InstInfo*)&Table_F2_0F}; _InstNode Table_F2 = {3, Table_F2_ids, Table_F2_ptrs}; uint8_t Table_DF_ids[72] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_DF_ptrs[26] = { NULL, &II_DF_00, &II_DF_01, &II_DF_02, &II_DF_03, &II_DF_04, &II_DF_05, &II_DF_06, &II_DF_07, &II_DF_E0, &II_DF_E8, &II_DF_E8, &II_DF_E8, &II_DF_E8, &II_DF_E8, &II_DF_E8, &II_DF_E8, &II_DF_E8, &II_DF_F0, &II_DF_F0, &II_DF_F0, &II_DF_F0, &II_DF_F0, &II_DF_F0, &II_DF_F0, &II_DF_F0}; _InstNode Table_DF = {4, Table_DF_ids, Table_DF_ptrs}; uint8_t Table_DE_ids[72] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39}; _InstInfo* Table_DE_ptrs[58] = { NULL, &II_DE_00, &II_DE_01, &II_DE_02, &II_DE_03, &II_DE_04, &II_DE_05, &II_DE_06, &II_DE_07, &II_DE_C0, &II_DE_C1, &II_DE_C0, &II_DE_C0, &II_DE_C0, &II_DE_C0, &II_DE_C0, &II_DE_C0, &II_DE_C8, &II_DE_C9, &II_DE_C8, &II_DE_C8, &II_DE_C8, &II_DE_C8, &II_DE_C8, &II_DE_C8, &II_DE_D9, &II_DE_E0, &II_DE_E1, &II_DE_E0, &II_DE_E0, &II_DE_E0, &II_DE_E0, &II_DE_E0, &II_DE_E0, &II_DE_E8, &II_DE_E9, &II_DE_E8, &II_DE_E8, &II_DE_E8, &II_DE_E8, &II_DE_E8, &II_DE_E8, &II_DE_F0, &II_DE_F1, &II_DE_F0, &II_DE_F0, &II_DE_F0, &II_DE_F0, &II_DE_F0, &II_DE_F0, &II_DE_F8, &II_DE_F9, &II_DE_F8, &II_DE_F8, &II_DE_F8, &II_DE_F8, &II_DE_F8, &II_DE_F8}; _InstNode Table_DE = {4, Table_DE_ids, Table_DE_ptrs}; uint8_t Table_DD_ids[72] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_DD_ptrs[48] = { NULL, &II_DD_00, &II_DD_01, &II_DD_02, &II_DD_03, &II_DD_04, &II_DD_06, &II_DD_07, &II_DD_C0, &II_DD_C0, &II_DD_C0, &II_DD_C0, &II_DD_C0, &II_DD_C0, &II_DD_C0, &II_DD_C0, &II_DD_D0, &II_DD_D0, &II_DD_D0, &II_DD_D0, &II_DD_D0, &II_DD_D0, &II_DD_D0, &II_DD_D0, &II_DD_D8, &II_DD_D8, &II_DD_D8, &II_DD_D8, &II_DD_D8, &II_DD_D8, &II_DD_D8, &II_DD_D8, &II_DD_E0, &II_DD_E1, &II_DD_E0, &II_DD_E0, &II_DD_E0, &II_DD_E0, &II_DD_E0, &II_DD_E0, &II_DD_E8, &II_DD_E9, &II_DD_E8, &II_DD_E8, &II_DD_E8, &II_DD_E8, &II_DD_E8, &II_DD_E8}; _InstNode Table_DD = {4, Table_DD_ids, Table_DD_ptrs}; uint8_t Table_DC_ids[72] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}; _InstInfo* Table_DC_ptrs[57] = { NULL, &II_DC_00, &II_DC_01, &II_DC_02, &II_DC_03, &II_DC_04, &II_DC_05, &II_DC_06, &II_DC_07, &II_DC_C0, &II_DC_C0, &II_DC_C0, &II_DC_C0, &II_DC_C0, &II_DC_C0, &II_DC_C0, &II_DC_C0, &II_DC_C8, &II_DC_C8, &II_DC_C8, &II_DC_C8, &II_DC_C8, &II_DC_C8, &II_DC_C8, &II_DC_C8, &II_DC_E0, &II_DC_E0, &II_DC_E0, &II_DC_E0, &II_DC_E0, &II_DC_E0, &II_DC_E0, &II_DC_E0, &II_DC_E8, &II_DC_E8, &II_DC_E8, &II_DC_E8, &II_DC_E8, &II_DC_E8, &II_DC_E8, &II_DC_E8, &II_DC_F0, &II_DC_F0, &II_DC_F0, &II_DC_F0, &II_DC_F0, &II_DC_F0, &II_DC_F0, &II_DC_F0, &II_DC_F8, &II_DC_F8, &II_DC_F8, &II_DC_F8, &II_DC_F8, &II_DC_F8, &II_DC_F8, &II_DC_F8}; _InstNode Table_DC = {4, Table_DC_ids, Table_DC_ptrs}; uint8_t Table_DB_ids[72] = {0x01, 0x02, 0x03, 0x04, 0x00, 0x05, 0x00, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x00, 0x00, 0x00, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_DB_ptrs[60] = { NULL, &II_DB_00, &II_DB_01, &II_DB_02, &II_DB_03, &II_DB_05, &II_DB_07, &II_DB_C0, &II_DB_C0, &II_DB_C0, &II_DB_C0, &II_DB_C0, &II_DB_C0, &II_DB_C0, &II_DB_C0, &II_DB_C8, &II_DB_C8, &II_DB_C8, &II_DB_C8, &II_DB_C8, &II_DB_C8, &II_DB_C8, &II_DB_C8, &II_DB_D0, &II_DB_D0, &II_DB_D0, &II_DB_D0, &II_DB_D0, &II_DB_D0, &II_DB_D0, &II_DB_D0, &II_DB_D8, &II_DB_D8, &II_DB_D8, &II_DB_D8, &II_DB_D8, &II_DB_D8, &II_DB_D8, &II_DB_D8, &II_DB_E0, &II_DB_E1, &II_DB_E2, &II_DB_E3, &II_DB_E4, &II_DB_E8, &II_DB_E8, &II_DB_E8, &II_DB_E8, &II_DB_E8, &II_DB_E8, &II_DB_E8, &II_DB_E8, &II_DB_F0, &II_DB_F0, &II_DB_F0, &II_DB_F0, &II_DB_F0, &II_DB_F0, &II_DB_F0, &II_DB_F0}; _InstNode Table_DB = {4, Table_DB_ids, Table_DB_ptrs}; uint8_t Table_DA_ids[72] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_DA_ptrs[42] = { NULL, &II_DA_00, &II_DA_01, &II_DA_02, &II_DA_03, &II_DA_04, &II_DA_05, &II_DA_06, &II_DA_07, &II_DA_C0, &II_DA_C0, &II_DA_C0, &II_DA_C0, &II_DA_C0, &II_DA_C0, &II_DA_C0, &II_DA_C0, &II_DA_C8, &II_DA_C8, &II_DA_C8, &II_DA_C8, &II_DA_C8, &II_DA_C8, &II_DA_C8, &II_DA_C8, &II_DA_D0, &II_DA_D0, &II_DA_D0, &II_DA_D0, &II_DA_D0, &II_DA_D0, &II_DA_D0, &II_DA_D0, &II_DA_D8, &II_DA_D8, &II_DA_D8, &II_DA_D8, &II_DA_D8, &II_DA_D8, &II_DA_D8, &II_DA_D8, &II_DA_E9}; _InstNode Table_DA = {4, Table_DA_ids, Table_DA_ptrs}; uint8_t Table_D9_ids[72] = {0x01, 0x00, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x1a, 0x00, 0x00, 0x1b, 0x1c, 0x00, 0x00, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33}; _InstInfo* Table_D9_ptrs[52] = { NULL, &II_D9_00, &II_D9_02, &II_D9_03, &II_D9_04, &II_D9_05, &II_D9_06, &II_D9_07, &II_D9_C0, &II_D9_C0, &II_D9_C0, &II_D9_C0, &II_D9_C0, &II_D9_C0, &II_D9_C0, &II_D9_C0, &II_D9_C8, &II_D9_C9, &II_D9_C8, &II_D9_C8, &II_D9_C8, &II_D9_C8, &II_D9_C8, &II_D9_C8, &II_D9_D0, &II_D9_E0, &II_D9_E1, &II_D9_E4, &II_D9_E5, &II_D9_E8, &II_D9_E9, &II_D9_EA, &II_D9_EB, &II_D9_EC, &II_D9_ED, &II_D9_EE, &II_D9_F0, &II_D9_F1, &II_D9_F2, &II_D9_F3, &II_D9_F4, &II_D9_F5, &II_D9_F6, &II_D9_F7, &II_D9_F8, &II_D9_F9, &II_D9_FA, &II_D9_FB, &II_D9_FC, &II_D9_FD, &II_D9_FE, &II_D9_FF}; _InstNode Table_D9 = {4, Table_D9_ids, Table_D9_ptrs}; uint8_t Table_D8_ids[72] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47}; _InstInfo* Table_D8_ptrs[72] = { &II_D8_00, &II_D8_01, &II_D8_02, &II_D8_03, &II_D8_04, &II_D8_05, &II_D8_06, &II_D8_07, &II_D8_C0, &II_D8_C0, &II_D8_C0, &II_D8_C0, &II_D8_C0, &II_D8_C0, &II_D8_C0, &II_D8_C0, &II_D8_C8, &II_D8_C8, &II_D8_C8, &II_D8_C8, &II_D8_C8, &II_D8_C8, &II_D8_C8, &II_D8_C8, &II_D8_D0, &II_D8_D0, &II_D8_D0, &II_D8_D0, &II_D8_D0, &II_D8_D0, &II_D8_D0, &II_D8_D0, &II_D8_D8, &II_D8_D9, &II_D8_D8, &II_D8_D8, &II_D8_D8, &II_D8_D8, &II_D8_D8, &II_D8_D8, &II_D8_E0, &II_D8_E0, &II_D8_E0, &II_D8_E0, &II_D8_E0, &II_D8_E0, &II_D8_E0, &II_D8_E0, &II_D8_E8, &II_D8_E8, &II_D8_E8, &II_D8_E8, &II_D8_E8, &II_D8_E8, &II_D8_E8, &II_D8_E8, &II_D8_F0, &II_D8_F0, &II_D8_F0, &II_D8_F0, &II_D8_F0, &II_D8_F0, &II_D8_F0, &II_D8_F0, &II_D8_F8, &II_D8_F8, &II_D8_F8, &II_D8_F8, &II_D8_F8, &II_D8_F8, &II_D8_F8, &II_D8_F8}; _InstNode Table_D8 = {4, Table_D8_ids, Table_D8_ptrs}; uint8_t Table_D3_ids[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_D3_ptrs[8] = { &II_D3_00, &II_D3_01, &II_D3_02, &II_D3_03, &II_D3_04, &II_D3_05, &II_D3_06, &II_D3_07}; _InstNode Table_D3 = {2, Table_D3_ids, Table_D3_ptrs}; uint8_t Table_D2_ids[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_D2_ptrs[8] = { &II_D2_00, &II_D2_01, &II_D2_02, &II_D2_03, &II_D2_04, &II_D2_05, &II_D2_06, &II_D2_07}; _InstNode Table_D2 = {2, Table_D2_ids, Table_D2_ptrs}; uint8_t Table_D1_ids[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_D1_ptrs[8] = { &II_D1_00, &II_D1_01, &II_D1_02, &II_D1_03, &II_D1_04, &II_D1_05, &II_D1_06, &II_D1_07}; _InstNode Table_D1 = {2, Table_D1_ids, Table_D1_ptrs}; uint8_t Table_D0_ids[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_D0_ptrs[8] = { &II_D0_00, &II_D0_01, &II_D0_02, &II_D0_03, &II_D0_04, &II_D0_05, &II_D0_06, &II_D0_07}; _InstNode Table_D0 = {2, Table_D0_ids, Table_D0_ptrs}; uint8_t Table_C7_ids[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_C7_ptrs[2] = { NULL, &II_C7_00}; _InstNode Table_C7 = {2, Table_C7_ids, Table_C7_ptrs}; uint8_t Table_C6_ids[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_C6_ptrs[2] = { NULL, &II_C6_00}; _InstNode Table_C6 = {2, Table_C6_ids, Table_C6_ptrs}; uint8_t Table_C1_ids[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_C1_ptrs[8] = { &II_C1_00, &II_C1_01, &II_C1_02, &II_C1_03, &II_C1_04, &II_C1_05, &II_C1_06, &II_C1_07}; _InstNode Table_C1 = {2, Table_C1_ids, Table_C1_ptrs}; uint8_t Table_C0_ids[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_C0_ptrs[8] = { &II_C0_00, &II_C0_01, &II_C0_02, &II_C0_03, &II_C0_04, &II_C0_05, &II_C0_06, &II_C0_07}; _InstNode Table_C0 = {2, Table_C0_ids, Table_C0_ptrs}; uint8_t Table_9B_DF_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_9B_DF_ptrs[2] = { NULL, &II_9B_DF_E0}; _InstNode Table_9B_DF = {3, Table_9B_DF_ids, Table_9B_DF_ptrs}; uint8_t Table_9B_DD_ids[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02}; _InstInfo* Table_9B_DD_ptrs[3] = { NULL, &II_9B_DD_06, &II_9B_DD_07}; _InstNode Table_9B_DD = {2, Table_9B_DD_ids, Table_9B_DD_ptrs}; uint8_t Table_9B_DB_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_9B_DB_ptrs[3] = { NULL, &II_9B_DB_E2, &II_9B_DB_E3}; _InstNode Table_9B_DB = {3, Table_9B_DB_ids, Table_9B_DB_ptrs}; uint8_t Table_9B_D9_ids[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02}; _InstInfo* Table_9B_D9_ptrs[3] = { NULL, &II_9B_D9_06, &II_9B_D9_07}; _InstNode Table_9B_D9 = {2, Table_9B_D9_ids, Table_9B_D9_ptrs}; uint8_t Table_9B_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_9B_ptrs[5] = { NULL, (_InstInfo*)&Table_9B_D9, (_InstInfo*)&Table_9B_DB, (_InstInfo*)&Table_9B_DD, (_InstInfo*)&Table_9B_DF}; _InstNode Table_9B = {3, Table_9B_ids, Table_9B_ptrs}; uint8_t Table_8F_ids[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_8F_ptrs[2] = { NULL, &II_8F_00}; _InstNode Table_8F = {2, Table_8F_ids, Table_8F_ptrs}; uint8_t Table_83_ids[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_83_ptrs[8] = { &II_83_00, &II_83_01, &II_83_02, &II_83_03, &II_83_04, &II_83_05, &II_83_06, &II_83_07}; _InstNode Table_83 = {2, Table_83_ids, Table_83_ptrs}; uint8_t Table_82_ids[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_82_ptrs[8] = { &II_82_00, &II_82_01, &II_82_02, &II_82_03, &II_82_04, &II_82_05, &II_82_06, &II_82_07}; _InstNode Table_82 = {2, Table_82_ids, Table_82_ptrs}; uint8_t Table_81_ids[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_81_ptrs[8] = { &II_81_00, &II_81_01, &II_81_02, &II_81_03, &II_81_04, &II_81_05, &II_81_06, &II_81_07}; _InstNode Table_81 = {2, Table_81_ids, Table_81_ptrs}; uint8_t Table_80_ids[8] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}; _InstInfo* Table_80_ptrs[8] = { &II_80_00, &II_80_01, &II_80_02, &II_80_03, &II_80_04, &II_80_05, &II_80_06, &II_80_07}; _InstNode Table_80 = {2, Table_80_ids, Table_80_ptrs}; uint8_t Table_66_0F_C7_ids[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}; _InstInfo* Table_66_0F_C7_ptrs[2] = { NULL, &II_66_0F_C7_06}; _InstNode Table_66_0F_C7 = {2, Table_66_0F_C7_ids, Table_66_0F_C7_ptrs}; uint8_t Table_66_0F_78_ids[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_66_0F_78_ptrs[2] = { NULL, (_InstInfo*)&II_66_0F_78_00}; _InstNode Table_66_0F_78 = {2, Table_66_0F_78_ids, Table_66_0F_78_ptrs}; uint8_t Table_66_0F_73_ids[8] = {0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x03, 0x04}; _InstInfo* Table_66_0F_73_ptrs[5] = { NULL, &II_66_0F_73_02, &II_66_0F_73_03, &II_66_0F_73_06, &II_66_0F_73_07}; _InstNode Table_66_0F_73 = {2, Table_66_0F_73_ids, Table_66_0F_73_ptrs}; uint8_t Table_66_0F_72_ids[8] = {0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00}; _InstInfo* Table_66_0F_72_ptrs[4] = { NULL, &II_66_0F_72_02, &II_66_0F_72_04, &II_66_0F_72_06}; _InstNode Table_66_0F_72 = {2, Table_66_0F_72_ids, Table_66_0F_72_ptrs}; uint8_t Table_66_0F_71_ids[8] = {0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00}; _InstInfo* Table_66_0F_71_ptrs[4] = { NULL, &II_66_0F_71_02, &II_66_0F_71_04, &II_66_0F_71_06}; _InstNode Table_66_0F_71 = {2, Table_66_0F_71_ids, Table_66_0F_71_ptrs}; uint8_t Table_66_0F_3A_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0a, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_66_0F_3A_ptrs[23] = { NULL, (_InstInfo*)&II_66_0F_3A_08, (_InstInfo*)&II_66_0F_3A_09, (_InstInfo*)&II_66_0F_3A_0A, (_InstInfo*)&II_66_0F_3A_0B, (_InstInfo*)&II_66_0F_3A_0C, (_InstInfo*)&II_66_0F_3A_0D, (_InstInfo*)&II_66_0F_3A_0E, (_InstInfo*)&II_66_0F_3A_0F, (_InstInfo*)&II_66_0F_3A_14, (_InstInfo*)&II_66_0F_3A_15, (_InstInfo*)&II_66_0F_3A_16, (_InstInfo*)&II_66_0F_3A_17, (_InstInfo*)&II_66_0F_3A_20, (_InstInfo*)&II_66_0F_3A_21, (_InstInfo*)&II_66_0F_3A_22, (_InstInfo*)&II_66_0F_3A_40, (_InstInfo*)&II_66_0F_3A_41, (_InstInfo*)&II_66_0F_3A_42, (_InstInfo*)&II_66_0F_3A_60, (_InstInfo*)&II_66_0F_3A_61, (_InstInfo*)&II_66_0F_3A_62, (_InstInfo*)&II_66_0F_3A_63}; _InstNode Table_66_0F_3A = {3, Table_66_0F_3A_ids, Table_66_0F_3A_ptrs}; uint8_t Table_66_0F_38_ids[256] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x0f, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x11, 0x12, 0x13, 0x00, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00, 0x00, 0x1a, 0x1b, 0x1c, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x00, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_66_0F_38_ptrs[47] = { NULL, &II_66_0F_38_00, &II_66_0F_38_01, &II_66_0F_38_02, &II_66_0F_38_03, &II_66_0F_38_04, &II_66_0F_38_05, &II_66_0F_38_06, &II_66_0F_38_07, &II_66_0F_38_08, &II_66_0F_38_09, &II_66_0F_38_0A, &II_66_0F_38_0B, (_InstInfo*)&II_66_0F_38_10, (_InstInfo*)&II_66_0F_38_14, (_InstInfo*)&II_66_0F_38_15, &II_66_0F_38_17, &II_66_0F_38_1C, &II_66_0F_38_1D, &II_66_0F_38_1E, &II_66_0F_38_20, &II_66_0F_38_21, &II_66_0F_38_22, &II_66_0F_38_23, &II_66_0F_38_24, &II_66_0F_38_25, &II_66_0F_38_28, &II_66_0F_38_29, &II_66_0F_38_2A, &II_66_0F_38_2B, &II_66_0F_38_30, &II_66_0F_38_31, &II_66_0F_38_32, &II_66_0F_38_33, &II_66_0F_38_34, &II_66_0F_38_35, &II_66_0F_38_37, &II_66_0F_38_38, &II_66_0F_38_39, &II_66_0F_38_3A, &II_66_0F_38_3B, &II_66_0F_38_3C, &II_66_0F_38_3D, &II_66_0F_38_3E, &II_66_0F_38_3F, &II_66_0F_38_40, &II_66_0F_38_41}; _InstNode Table_66_0F_38 = {3, Table_66_0F_38_ids, Table_66_0F_38_ptrs}; uint8_t Table_66_0F_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x14, 0x00, 0x00, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x00, 0x38, 0x39, 0x00, 0x00, 0x3a, 0x3b, 0x3c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3f, 0x40, 0x41, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x00, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x00}; _InstInfo* Table_66_0F_ptrs[113] = { NULL, &II_66_0F_10, &II_66_0F_11, &II_66_0F_12, &II_66_0F_13, &II_66_0F_14, &II_66_0F_15, &II_66_0F_16, &II_66_0F_17, &II_66_0F_28, &II_66_0F_29, &II_66_0F_2A, &II_66_0F_2B, &II_66_0F_2C, &II_66_0F_2D, &II_66_0F_2E, &II_66_0F_2F, (_InstInfo*)&Table_66_0F_38, (_InstInfo*)&Table_66_0F_3A, &II_66_0F_50, &II_66_0F_51, &II_66_0F_54, &II_66_0F_55, &II_66_0F_56, &II_66_0F_57, &II_66_0F_58, &II_66_0F_59, &II_66_0F_5A, &II_66_0F_5B, &II_66_0F_5C, &II_66_0F_5D, &II_66_0F_5E, &II_66_0F_5F, &II_66_0F_60, &II_66_0F_61, &II_66_0F_62, &II_66_0F_63, &II_66_0F_64, &II_66_0F_65, &II_66_0F_66, &II_66_0F_67, &II_66_0F_68, &II_66_0F_69, &II_66_0F_6A, &II_66_0F_6B, &II_66_0F_6C, &II_66_0F_6D, (_InstInfo*)&II_66_0F_6E, &II_66_0F_6F, (_InstInfo*)&II_66_0F_70, (_InstInfo*)&Table_66_0F_71, (_InstInfo*)&Table_66_0F_72, (_InstInfo*)&Table_66_0F_73, &II_66_0F_74, &II_66_0F_75, &II_66_0F_76, (_InstInfo*)&Table_66_0F_78, &II_66_0F_79, &II_66_0F_7C, &II_66_0F_7D, (_InstInfo*)&II_66_0F_7E, &II_66_0F_7F, (_InstInfo*)&II_66_0F_C2, (_InstInfo*)&II_66_0F_C4, (_InstInfo*)&II_66_0F_C5, (_InstInfo*)&II_66_0F_C6, (_InstInfo*)&Table_66_0F_C7, &II_66_0F_D0, &II_66_0F_D1, &II_66_0F_D2, &II_66_0F_D3, &II_66_0F_D4, &II_66_0F_D5, &II_66_0F_D6, &II_66_0F_D7, &II_66_0F_D8, &II_66_0F_D9, &II_66_0F_DA, &II_66_0F_DB, &II_66_0F_DC, &II_66_0F_DD, &II_66_0F_DE, &II_66_0F_DF, &II_66_0F_E0, &II_66_0F_E1, &II_66_0F_E2, &II_66_0F_E3, &II_66_0F_E4, &II_66_0F_E5, &II_66_0F_E6, &II_66_0F_E7, &II_66_0F_E8, &II_66_0F_E9, &II_66_0F_EA, &II_66_0F_EB, &II_66_0F_EC, &II_66_0F_ED, &II_66_0F_EE, &II_66_0F_EF, &II_66_0F_F1, &II_66_0F_F2, &II_66_0F_F3, &II_66_0F_F4, &II_66_0F_F5, &II_66_0F_F6, &II_66_0F_F7, &II_66_0F_F8, &II_66_0F_F9, &II_66_0F_FA, &II_66_0F_FB, &II_66_0F_FC, &II_66_0F_FD, &II_66_0F_FE}; _InstNode Table_66_0F = {3, Table_66_0F_ids, Table_66_0F_ptrs}; uint8_t Table_66_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_66_ptrs[2] = { NULL, (_InstInfo*)&Table_66_0F}; _InstNode Table_66 = {3, Table_66_ids, Table_66_ptrs}; uint8_t Table_0F_C7_ids[8] = {0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03}; _InstInfo* Table_0F_C7_ptrs[4] = { NULL, (_InstInfo*)&II_0F_C7_01, &II_0F_C7_06, &II_0F_C7_07}; _InstNode Table_0F_C7 = {2, Table_0F_C7_ids, Table_0F_C7_ptrs}; uint8_t Table_0F_BA_ids[8] = {0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04}; _InstInfo* Table_0F_BA_ptrs[5] = { NULL, &II_0F_BA_04, &II_0F_BA_05, &II_0F_BA_06, &II_0F_BA_07}; _InstNode Table_0F_BA = {2, Table_0F_BA_ids, Table_0F_BA_ptrs}; uint8_t Table_0F_AE_ids[72] = {0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_0F_AE_ptrs[9] = { NULL, &II_0F_AE_00, &II_0F_AE_01, &II_0F_AE_02, &II_0F_AE_03, &II_0F_AE_07, &II_0F_AE_E8, &II_0F_AE_F0, &II_0F_AE_F8}; _InstNode Table_0F_AE = {4, Table_0F_AE_ids, Table_0F_AE_ptrs}; uint8_t Table_0F_73_ids[8] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00}; _InstInfo* Table_0F_73_ptrs[3] = { NULL, &II_0F_73_02, &II_0F_73_06}; _InstNode Table_0F_73 = {2, Table_0F_73_ids, Table_0F_73_ptrs}; uint8_t Table_0F_72_ids[8] = {0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00}; _InstInfo* Table_0F_72_ptrs[4] = { NULL, &II_0F_72_02, &II_0F_72_04, &II_0F_72_06}; _InstNode Table_0F_72 = {2, Table_0F_72_ids, Table_0F_72_ptrs}; uint8_t Table_0F_71_ids[8] = {0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00}; _InstInfo* Table_0F_71_ptrs[4] = { NULL, &II_0F_71_02, &II_0F_71_04, &II_0F_71_06}; _InstNode Table_0F_71 = {2, Table_0F_71_ids, Table_0F_71_ptrs}; uint8_t Table_0F_3A_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_0F_3A_ptrs[2] = { NULL, (_InstInfo*)&II_0F_3A_0F}; _InstNode Table_0F_3A = {3, Table_0F_3A_ids, Table_0F_3A_ptrs}; uint8_t Table_0F_38_ids[256] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_0F_38_ptrs[16] = { NULL, &II_0F_38_00, &II_0F_38_01, &II_0F_38_02, &II_0F_38_03, &II_0F_38_04, &II_0F_38_05, &II_0F_38_06, &II_0F_38_07, &II_0F_38_08, &II_0F_38_09, &II_0F_38_0A, &II_0F_38_0B, &II_0F_38_1C, &II_0F_38_1D, &II_0F_38_1E}; _InstNode Table_0F_38 = {3, Table_0F_38_ids, Table_0F_38_ptrs}; uint8_t Table_0F_1F_ids[8] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_0F_1F_ptrs[2] = { NULL, &II_0F_1F_00}; _InstNode Table_0F_1F = {2, Table_0F_1F_ids, Table_0F_1F_ptrs}; uint8_t Table_0F_18_ids[8] = {0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_0F_18_ptrs[5] = { NULL, &II_0F_18_00, &II_0F_18_01, &II_0F_18_02, &II_0F_18_03}; _InstNode Table_0F_18 = {2, Table_0F_18_ids, Table_0F_18_ptrs}; uint8_t Table_0F_0F_ids[256] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x09, 0x0a, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0f, 0x10, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x12, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x00, 0x15, 0x16, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_0F_0F_ptrs[25] = { NULL, &II_0F_0F_0C, &II_0F_0F_0D, &II_0F_0F_1C, &II_0F_0F_1D, &II_0F_0F_8A, &II_0F_0F_8E, &II_0F_0F_90, &II_0F_0F_94, &II_0F_0F_96, &II_0F_0F_97, &II_0F_0F_9A, &II_0F_0F_9E, &II_0F_0F_A0, &II_0F_0F_A4, &II_0F_0F_A6, &II_0F_0F_A7, &II_0F_0F_AA, &II_0F_0F_AE, &II_0F_0F_B0, &II_0F_0F_B4, &II_0F_0F_B6, &II_0F_0F_B7, &II_0F_0F_BB, &II_0F_0F_BF}; _InstNode Table_0F_0F = {3, Table_0F_0F_ids, Table_0F_0F_ptrs}; uint8_t Table_0F_0D_ids[8] = {0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_0F_0D_ptrs[3] = { NULL, &II_0F_0D_00, &II_0F_0D_01}; _InstNode Table_0F_0D = {2, Table_0F_0D_ids, Table_0F_0D_ptrs}; uint8_t Table_0F_01_ids[72] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x00, 0x06, 0x07, 0x00, 0x08, 0x09, 0x0a, 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; _InstInfo* Table_0F_01_ptrs[24] = { NULL, &II_0F_01_00, &II_0F_01_01, &II_0F_01_02, &II_0F_01_03, &II_0F_01_04, &II_0F_01_06, &II_0F_01_07, &II_0F_01_C1, &II_0F_01_C2, &II_0F_01_C3, &II_0F_01_C4, &II_0F_01_C8, &II_0F_01_C9, &II_0F_01_D8, &II_0F_01_D9, &II_0F_01_DA, &II_0F_01_DB, &II_0F_01_DC, &II_0F_01_DD, &II_0F_01_DE, &II_0F_01_DF, &II_0F_01_F8, &II_0F_01_F9}; _InstNode Table_0F_01 = {4, Table_0F_01_ids, Table_0F_01_ptrs}; uint8_t Table_0F_00_ids[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x00, 0x00}; _InstInfo* Table_0F_00_ptrs[7] = { NULL, &II_0F_00_00, &II_0F_00_01, &II_0F_00_02, &II_0F_00_03, &II_0F_00_04, &II_0F_00_05}; _InstNode Table_0F_00 = {2, Table_0F_00_ids, Table_0F_00_ptrs}; uint8_t Table_0F_ids[256] = {0x01, 0x02, 0x03, 0x04, 0x00, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x00, 0x00, 0x2a, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x00, 0x00, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x00, 0x00, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x00, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0x00, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0x00, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0x00, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0x00, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0x00}; _InstInfo* Table_0F_ptrs[222] = { NULL, (_InstInfo*)&Table_0F_00, (_InstInfo*)&Table_0F_01, &II_0F_02, &II_0F_03, &II_0F_05, &II_0F_06, &II_0F_07, &II_0F_08, &II_0F_09, &II_0F_0B, (_InstInfo*)&Table_0F_0D, &II_0F_0E, (_InstInfo*)&Table_0F_0F, &II_0F_10, &II_0F_11, (_InstInfo*)&II_0F_12, &II_0F_13, &II_0F_14, &II_0F_15, (_InstInfo*)&II_0F_16, &II_0F_17, (_InstInfo*)&Table_0F_18, (_InstInfo*)&Table_0F_1F, &II_0F_20, &II_0F_21, &II_0F_22, &II_0F_23, &II_0F_28, &II_0F_29, &II_0F_2A, &II_0F_2B, &II_0F_2C, &II_0F_2D, &II_0F_2E, &II_0F_2F, &II_0F_30, &II_0F_31, &II_0F_32, &II_0F_33, &II_0F_34, &II_0F_35, (_InstInfo*)&Table_0F_38, (_InstInfo*)&Table_0F_3A, &II_0F_40, &II_0F_41, &II_0F_42, &II_0F_43, &II_0F_44, &II_0F_45, &II_0F_46, &II_0F_47, &II_0F_48, &II_0F_49, &II_0F_4A, &II_0F_4B, &II_0F_4C, &II_0F_4D, &II_0F_4E, &II_0F_4F, &II_0F_50, &II_0F_51, &II_0F_52, &II_0F_53, &II_0F_54, &II_0F_55, &II_0F_56, &II_0F_57, &II_0F_58, &II_0F_59, &II_0F_5A, &II_0F_5B, &II_0F_5C, &II_0F_5D, &II_0F_5E, &II_0F_5F, &II_0F_60, &II_0F_61, &II_0F_62, &II_0F_63, &II_0F_64, &II_0F_65, &II_0F_66, &II_0F_67, &II_0F_68, &II_0F_69, &II_0F_6A, &II_0F_6B, (_InstInfo*)&II_0F_6E, &II_0F_6F, (_InstInfo*)&II_0F_70, (_InstInfo*)&Table_0F_71, (_InstInfo*)&Table_0F_72, (_InstInfo*)&Table_0F_73, &II_0F_74, &II_0F_75, &II_0F_76, &II_0F_77, &II_0F_78, &II_0F_79, (_InstInfo*)&II_0F_7E, &II_0F_7F, &II_0F_80, &II_0F_81, &II_0F_82, &II_0F_83, &II_0F_84, &II_0F_85, &II_0F_86, &II_0F_87, &II_0F_88, &II_0F_89, &II_0F_8A, &II_0F_8B, &II_0F_8C, &II_0F_8D, &II_0F_8E, &II_0F_8F, &II_0F_90, &II_0F_91, &II_0F_92, &II_0F_93, &II_0F_94, &II_0F_95, &II_0F_96, &II_0F_97, &II_0F_98, &II_0F_99, &II_0F_9A, &II_0F_9B, &II_0F_9C, &II_0F_9D, &II_0F_9E, &II_0F_9F, &II_0F_A0, &II_0F_A1, &II_0F_A2, &II_0F_A3, (_InstInfo*)&II_0F_A4, (_InstInfo*)&II_0F_A5, &II_0F_A8, &II_0F_A9, &II_0F_AA, &II_0F_AB, (_InstInfo*)&II_0F_AC, (_InstInfo*)&II_0F_AD, (_InstInfo*)&Table_0F_AE, &II_0F_AF, &II_0F_B0, &II_0F_B1, &II_0F_B2, &II_0F_B3, &II_0F_B4, &II_0F_B5, &II_0F_B6, &II_0F_B7, &II_0F_B9, (_InstInfo*)&Table_0F_BA, &II_0F_BB, &II_0F_BC, &II_0F_BD, &II_0F_BE, &II_0F_BF, &II_0F_C0, &II_0F_C1, (_InstInfo*)&II_0F_C2, &II_0F_C3, (_InstInfo*)&II_0F_C4, (_InstInfo*)&II_0F_C5, (_InstInfo*)&II_0F_C6, (_InstInfo*)&Table_0F_C7, &II_0F_C8, &II_0F_C8, &II_0F_C8, &II_0F_C8, &II_0F_C8, &II_0F_C8, &II_0F_C8, &II_0F_C8, &II_0F_D1, &II_0F_D2, &II_0F_D3, &II_0F_D4, &II_0F_D5, &II_0F_D7, &II_0F_D8, &II_0F_D9, &II_0F_DA, &II_0F_DB, &II_0F_DC, &II_0F_DD, &II_0F_DE, &II_0F_DF, &II_0F_E0, &II_0F_E1, &II_0F_E2, &II_0F_E3, &II_0F_E4, &II_0F_E5, &II_0F_E7, &II_0F_E8, &II_0F_E9, &II_0F_EA, &II_0F_EB, &II_0F_EC, &II_0F_ED, &II_0F_EE, &II_0F_EF, &II_0F_F1, &II_0F_F2, &II_0F_F3, &II_0F_F4, &II_0F_F5, &II_0F_F6, &II_0F_F7, &II_0F_F8, &II_0F_F9, &II_0F_FA, &II_0F_FB, &II_0F_FC, &II_0F_FD, &II_0F_FE}; _InstNode Table_0F = {3, Table_0F_ids, Table_0F_ptrs}; uint8_t Instructions_ids[256] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x00, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x00, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x00, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x00, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x00, 0x00, 0x61, 0x00, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0x00, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8}; _InstInfo* Instructions_ptrs[249] = { NULL, &II_00, &II_01, &II_02, &II_03, &II_04, &II_05, &II_06, &II_07, &II_08, &II_09, &II_0A, &II_0B, &II_0C, &II_0D, &II_0E, (_InstInfo*)&Table_0F, &II_10, &II_11, &II_12, &II_13, &II_14, &II_15, &II_16, &II_17, &II_18, &II_19, &II_1A, &II_1B, &II_1C, &II_1D, &II_1E, &II_1F, &II_20, &II_21, &II_22, &II_23, &II_24, &II_25, &II_27, &II_28, &II_29, &II_2A, &II_2B, &II_2C, &II_2D, &II_2F, &II_30, &II_31, &II_32, &II_33, &II_34, &II_35, &II_37, &II_38, &II_39, &II_3A, &II_3B, &II_3C, &II_3D, &II_3F, &II_40, &II_40, &II_40, &II_40, &II_40, &II_40, &II_40, &II_40, &II_48, &II_48, &II_48, &II_48, &II_48, &II_48, &II_48, &II_48, &II_50, &II_50, &II_50, &II_50, &II_50, &II_50, &II_50, &II_50, &II_58, &II_58, &II_58, &II_58, &II_58, &II_58, &II_58, &II_58, &II_60, &II_61, &II_62, &II_63, (_InstInfo*)&Table_66, &II_68, (_InstInfo*)&II_69, &II_6A, (_InstInfo*)&II_6B, &II_6C, &II_6D, &II_6E, &II_6F, &II_70, &II_71, &II_72, &II_73, &II_74, &II_75, &II_76, &II_77, &II_78, &II_79, &II_7A, &II_7B, &II_7C, &II_7D, &II_7E, &II_7F, (_InstInfo*)&Table_80, (_InstInfo*)&Table_81, (_InstInfo*)&Table_82, (_InstInfo*)&Table_83, &II_84, &II_85, &II_86, &II_87, &II_88, &II_89, &II_8A, &II_8B, &II_8C, &II_8D, &II_8E, (_InstInfo*)&Table_8F, &II_90, &II_91, &II_92, &II_93, &II_94, &II_95, &II_96, &II_97, (_InstInfo*)&II_98, (_InstInfo*)&II_99, &II_9A, (_InstInfo*)&Table_9B, &II_9C, &II_9D, &II_9E, &II_9F, &II_A0, &II_A1, &II_A2, &II_A3, &II_A4, &II_A5, &II_A6, &II_A7, &II_A8, &II_A9, &II_AA, &II_AB, &II_AC, &II_AD, &II_AE, &II_AF, &II_B0, &II_B0, &II_B0, &II_B0, &II_B0, &II_B0, &II_B0, &II_B0, &II_B8, &II_B8, &II_B8, &II_B8, &II_B8, &II_B8, &II_B8, &II_B8, (_InstInfo*)&Table_C0, (_InstInfo*)&Table_C1, &II_C2, &II_C3, &II_C4, &II_C5, (_InstInfo*)&Table_C6, (_InstInfo*)&Table_C7, &II_C8, &II_C9, &II_CA, &II_CB, &II_CC, &II_CD, &II_CE, &II_CF, (_InstInfo*)&Table_D0, (_InstInfo*)&Table_D1, (_InstInfo*)&Table_D2, (_InstInfo*)&Table_D3, &II_D4, &II_D5, &II_D6, &II_D7, (_InstInfo*)&Table_D8, (_InstInfo*)&Table_D9, (_InstInfo*)&Table_DA, (_InstInfo*)&Table_DB, (_InstInfo*)&Table_DC, (_InstInfo*)&Table_DD, (_InstInfo*)&Table_DE, (_InstInfo*)&Table_DF, &II_E0, &II_E1, &II_E2, (_InstInfo*)&II_E3, &II_E4, &II_E5, &II_E6, &II_E7, &II_E8, &II_E9, &II_EA, &II_EB, &II_EC, &II_ED, &II_EE, &II_EF, &II_F1, (_InstInfo*)&Table_F2, (_InstInfo*)&Table_F3, &II_F4, &II_F5, (_InstInfo*)&Table_F6, (_InstInfo*)&Table_F7, &II_F8, &II_F9, &II_FA, &II_FB, &II_FC, &II_FD, (_InstInfo*)&Table_FE, (_InstInfo*)&Table_FF}; _InstNode Instructions = {3, Instructions_ids, Instructions_ptrs}; #undef _I8P distorm64-1.7.30/src/insts.h0000644000175000017500000000076611013167250014516 0ustar enderender/* insts.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #ifndef INSTS_H #define INSTS_H #include "instructions.h" /* Root Trie DB */ extern _InstNode Instructions; /* 3DNow! Trie DB */ extern _InstNode Table_0F_0F; /* NOP/XCHG instruction. */ extern _InstInfo II_90; /* LEA instruction. */ extern _InstInfo II_8D; /* See instructions.cpp for more info. */ #endif /* INSTS_H */ distorm64-1.7.30/src/operands.c0000644000175000017500000015331111014441700015153 0ustar enderender/* operands.c Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #include "../config.h" #include "operands.h" #include "x86defs.h" #include /* For abs only. */ /* * SIB decoding is the most confusing part when decoding IA-32 instructions. * This explanation should clear up some stuff. * * ! When base == 5, use EBP as the base register ! * if (rm == 4) { * if mod == 01, decode SIB byte and ALSO read a 8 bits displacement. * if mod == 10, decode SIB byte and ALSO read a 32 bits displacement. * if mod == 11 <-- EXCEPTION, this is a general-purpose register and mustn't lead to SIB decoding! * ; So far so good, now the confusing part comes in with mod == 0 and base=5, but no worry. * if (mod == 00) { * decode SIB byte WITHOUT any displacement. * EXCEPTION!!! when base == 5, read a 32 bits displacement, but this time DO NOT use (EBP) BASE at all! * } * * NOTE: base could be specify None (no base register) if base==5 and mod==5, but then you also need DISP32. * } */ static int extract_sib(const uint8_t** code, int* codeLen, _OffsetType* codeOffset, _WString* instructionHex, _WString* operandText, _PrefixState* ps,_DecodeType dt, unsigned int mod, unsigned int sib, _OperandSizeType opSize) { unsigned int scale = 0, index = 0, base = 0, rex = 0; const uint8_t* code0 = *code; _iflags totalPrefixes = ps->totalPrefixes; /* * SIB bits: * |7---6-5----3-2---0| * |SCALE| INDEX| BASE| * |------------------| */ scale = (sib >> 6) & 3; index = (sib >> 3) & 7; base = sib & 7; if (ps->isREXPrefixValid) rex = *ps->rexpos; /* * format= seg: [base + index * scale + disp8/32] * whereas base/index/scale/disp8/32 are ALL optional by specific rules! */ str_indirection_text(operandText, opSize); str_seg_text(operandText, ps, dt); chrcat_WS(operandText, OPEN_CHR); if (base != 5) { if (rex & PREFIX_REX_B) ps->usedPrefixes |= INST_PRE_REX; if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode64Bits) str_x86def(operandText, &_BASE64[base + ((rex & PREFIX_REX_B) == PREFIX_REX_B ? REX_GPR_BASE : 0)]); else str_x86def(operandText, &_BASE32[base + ((rex & PREFIX_REX_B) == PREFIX_REX_B ? REX_GPR_BASE : 0)]); } else if (mod != 0) { /* * if base == 5 then you have to decode according to MOD. * mod(00) - disp32. * mod(01) - disp8 + rBP * mod(10) - disp32 + rBP * mod(11) - not possible, it's a general-purpose register. */ if (rex & PREFIX_REX_B) ps->usedPrefixes |= INST_PRE_REX; if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode64Bits) str_x86def(operandText, &_BASE64[5 + ((rex & PREFIX_REX_B) == PREFIX_REX_B ? REX_GPR_BASE : 0)]); else str_x86def(operandText, &_BASE32[5 + ((rex & PREFIX_REX_B) == PREFIX_REX_B ? REX_GPR_BASE : 0)]); } /* In 64 bits the REX prefix might affect the index of the SIB byte. */ if (rex & PREFIX_REX_X) { ps->usedPrefixes |= INST_PRE_REX; index += REX_GPR_BASE; } if (index != 4) { /* In 64 bits decoding mode, if index == R12, it's valid! */ /* Concat '+' only if we have a base or index. */ if ((mod != 0) || (base != 5)) chrcat_WS(operandText, PLUS_DISP_CHR); if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode64Bits) str_x86def(operandText, &_INDEX64[index]); else str_x86def(operandText, &_INDEX32[index]); str_x86def(operandText, &_SCALE32[scale]); } /* Read the displacement if required, according to MOD. */ switch (mod) { case 0: /* * It might be there's only disp32 left in this case, * so we have to check for index existance(!=4), because otherwise we would have a spare '+'. */ /* When mod=0 there's no force for disp32, unless base=5. */ if (base == 5) { /* disp32 */ *codeLen -= sizeof(int32_t); if (*codeLen < 0) return FALSE; str_hex_sp_dw(instructionHex, RULONG(code0)); if (index != 4) { /* If an index was used make it signed relative address: */ chrcat_WS(operandText, (RLONG(code0) >= 0) ? PLUS_DISP_CHR : MINUS_DISP_CHR); str_code_hdw(operandText, abs(RLONG(code0))); } else { /* Otherwise it's a disp32 only, so make it absolute. */ str_code_hdw(operandText, RULONG(code0)); } *code += sizeof(int32_t); *codeOffset += sizeof(int32_t); } break; case 1: /* disp8 */ *codeLen -= sizeof(int8_t); if (*codeLen < 0) return FALSE; str_hex_sp_b(instructionHex, *code0); chrcat_WS(operandText, (*(int8_t*)code0 >= 0) ? PLUS_DISP_CHR : MINUS_DISP_CHR); str_code_hb(operandText, abs(*(int8_t*)code0)); *code += sizeof(int8_t); *codeOffset += sizeof(int8_t); break; case 2: /* disp32 */ *codeLen -= sizeof(int32_t); if (*codeLen < 0) return FALSE; str_hex_sp_dw(instructionHex, RULONG(code0)); /* Signed relative address: */ chrcat_WS(operandText, (RLONG(code0) >= 0) ? PLUS_DISP_CHR : MINUS_DISP_CHR); str_code_hdw(operandText, abs(RLONG(code0))); *code += sizeof(int32_t); *codeOffset += sizeof(int32_t); break; /* case 3: break; --> It's a general-purpose register. 3rd time -ice cream?! */ } chrcat_WS(operandText, CLOSE_CHR); return TRUE; } /* * This seems to be the hardest part in decoding the operands. * If you take a look carefully at Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte, * you will understand it's easy to decode the operands. * First we check the DT, so we can decide according to which Table in the documentation we are supposed to decode. * Then we follow the specific table whether it's 16 bits or 32/64 bits. * Don't forget that Operand Size AND Address Size prefixes may change the decoding! * Some instructions force the use of RM16 or other specific types, so take it into account. */ static int extract_modrm(_CodeInfo* ci, _WString* instructionHex, _WString* operandText, _OpType type, _OperandNumberType opNum, _PrefixState* ps, _DecodeType dt, int* lockableInstruction, unsigned int mod, unsigned int rm, _iflags instFlags, _OperandSizeType opSize) { unsigned int sib = 0, rex = 0; const uint8_t* code = ci->code; int codeLen = ci->codeLen; _OffsetType codeOffset = ci->codeOffset; _iflags totalPrefixes = ps->totalPrefixes; if (ps->isREXPrefixValid) rex = *ps->rexpos; if (mod == 3) { /* General-purpose register is handled the same way in 16/32/64 bits decoding modes. */ switch(type) { case OT_RFULL_M16: case OT_RM_FULL: switch (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags)) { case Decode16Bits: ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } str_x86def(operandText, &_REGS16[rm]); break; case Decode32Bits: ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } str_x86def(operandText, &_REGS32[rm]); break; case Decode64Bits: /* V 1.5.15 - A fix for SMSW RAX which use the REX prefix. */ if (type == OT_RFULL_M16) ps->usedPrefixes |= (totalPrefixes & INST_PRE_REX); /* CALL NEAR/PUSH/POP defaults to 64 bits. --> INST_64BITS, REX isn't required, thus ignored anyways. */ if (instFlags & INST_PRE_REX) ps->usedPrefixes |= INST_PRE_REX; /* V 1.5.14 - include REX is used for REX.B. */ if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } str_x86def(operandText, &_REGS64[rm]); break; } break; case OT_RM32: if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } str_x86def(operandText, &_REGS32[rm]); break; case OT_R32_64_M8: /* FALL THROUGH, decode 32 or 64 bits register. */ case OT_R32_64_M16: /* FALL THROUGH, decode 32 or 64 bits register. */ case OT_RM32_64: /* Take care specifically in MOVNTI/MOVD/CVT's instructions, making it _REG64 with REX or if they are promoted. */ if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } /* Is it a promoted instruction? (only INST_64BITS is set and REX isn't required.) */ if ((dt == Decode64Bits) && ((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS)) { str_x86def(operandText, &_REGS64[rm]); break; } /* Give a chance to REX.W. Because if it was a promoted instruction we don't care about REX.W anyways. */ if (rex & PREFIX_REX_W) { ps->usedPrefixes |= INST_PRE_REX; str_x86def(operandText, &_REGS64[rm]); } else str_x86def(operandText, &_REGS32[rm]); break; case OT_RM16_32: /* Ver 1.5.16 - Used only with MOVZXD instruction to support 16 bits operand. */ if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } /* Is it 16 bits operand size? */ if (ps->totalPrefixes & INST_PRE_OP_SIZE) { ps->usedPrefixes |= INST_PRE_OP_SIZE; str_x86def(operandText, &_REGS16[rm]); } else str_x86def(operandText, &_REGS32[rm]); break; case OT_RM16: if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } str_x86def(operandText, &_REGS16[rm]); break; case OT_RM8: if (ps->isREXPrefixValid) { ps->usedPrefixes |= INST_PRE_REX; str_x86def(operandText, &_REGS8_REX[rm + ((rex & PREFIX_REX_B) == PREFIX_REX_B ? REX_GPR_BASE : 0)]); } else str_x86def(operandText, &_REGS8[rm]); break; case OT_MM32: case OT_MM64: /* MMX doesn't support extended registers. */ str_x86def(operandText, &_REGSMMX[rm]); break; case OT_XMM16: case OT_XMM32: case OT_XMM64: case OT_XMM128: if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } str_x86def(operandText, &_REGSSSE[rm]); break; case OT_R32_M8: /* FALL THROUGH, decode 32 bits register. */ case OT_R32_M16: if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } if (dt == Decode16Bits) str_x86def(operandText, &_REGS16[rm]); else str_x86def(operandText, &_REGS32[rm]); break; default: return FALSE; } /* * It's ok if we don't update the pointers parameters when we will return FALSE, because * they are to be ignored anyways. */ ci->code = code; ci->codeLen = codeLen; ci->codeOffset = codeOffset; return TRUE; } if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode16Bits) { /* Decoding according to Table 2-1. (16 bits) */ switch (mod) { case 0x00: /* Indirection */ ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); if ((opNum == ONT_1) && (totalPrefixes & INST_PRE_LOCK)) *lockableInstruction = 1; if (rm == 6) { /* 6 is a special case - only 16 bits displacement. */ codeLen -= sizeof(int16_t); if (codeLen < 0) return FALSE; str_hex_sp_w(instructionHex, RUSHORT(code)); str_indirection_text(operandText, opSize); str_seg_text(operandText, ps, dt); chrcat_WS(operandText, OPEN_CHR); str_code_hw(operandText, RUSHORT(code)); chrcat_WS(operandText, CLOSE_CHR); code += sizeof(int16_t); codeOffset += sizeof(int16_t); } else { str_indirection_text(operandText, opSize); str_seg_text(operandText, ps, dt); str_x86def(operandText, &_MODS16[rm]); chrcat_WS(operandText, CLOSE_CHR); } break; case 0x01: /* 8 bits displacement + indirection */ ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); if ((opNum == ONT_1) && (totalPrefixes & INST_PRE_LOCK)) *lockableInstruction = 1; codeLen -= sizeof(int8_t); if (codeLen < 0) return FALSE; str_hex_sp_b(instructionHex, *code); str_indirection_text(operandText, opSize); str_seg_text(operandText, ps, dt); str_x86def(operandText, &_MODS16[rm]); chrcat_WS(operandText, (*(int8_t*)code >= 0) ? PLUS_DISP_CHR : MINUS_DISP_CHR); str_code_hb(operandText, abs(*(int8_t*)code)); chrcat_WS(operandText, CLOSE_CHR); code += sizeof(int8_t); codeOffset += sizeof(int8_t); break; case 0x02: /* 16 bits displacement + indirection */ ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); if ((opNum == ONT_1) && (totalPrefixes & INST_PRE_LOCK)) *lockableInstruction = 1; codeLen -= sizeof(int16_t); if (codeLen < 0) return FALSE; str_hex_sp_w(instructionHex, RUSHORT(code)); str_indirection_text(operandText, opSize); str_seg_text(operandText, ps, dt); str_x86def(operandText, &_MODS16[rm]); /* Signed relative address: */ chrcat_WS(operandText, (RSHORT(code) >= 0) ? PLUS_DISP_CHR : MINUS_DISP_CHR); str_code_hw(operandText, abs(RSHORT(code))); chrcat_WS(operandText, CLOSE_CHR); code += sizeof(int16_t); codeOffset += sizeof(int16_t); break; } } else { /* Decode32Bits or Decode64Bits! */ /* * Remember that from 32/64 bits ModR/M byte a SIB byte could follow! * Decodes 64 bits now as well. */ switch (mod) { case 0x00: /* Indirection */ ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); if ((opNum == ONT_1) && (totalPrefixes & INST_PRE_LOCK)) *lockableInstruction = 1; if (rm == 4) { /* 4 is a special case - SIB byte follows! */ /* Skip SIB byte. */ if (--codeLen < 0) return FALSE; sib = *code; str_hex_b(instructionHex, sib); code += sizeof(int8_t); codeOffset += sizeof(int8_t); if (!extract_sib(&code, &codeLen, &codeOffset, instructionHex, operandText, ps, dt, mod, sib, opSize)) return FALSE; } else if (rm == 5) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); /* 5 is a special case - only 32 bits displacement. */ codeLen -= sizeof(int32_t); if (codeLen < 0) return FALSE; str_hex_sp_dw(instructionHex, RULONG(code)); str_indirection_text(operandText, opSize); str_seg_text(operandText, ps, dt); chrcat_WS(operandText, OPEN_CHR); if (dt == Decode64Bits) { /* In 64 bits decoding mode depsite of the address size, a RIP-relative address it is. */ strcat_WSN(operandText, REG_RIP_TEXT); /* Make it a signed relative address: */ chrcat_WS(operandText, (RLONG(code) >= 0) ? PLUS_DISP_CHR : MINUS_DISP_CHR); str_code_hdw(operandText, abs(RLONG(code))); } else { /* Absolute address: */ str_code_hdw(operandText, RULONG(code)); } chrcat_WS(operandText, CLOSE_CHR); code += sizeof(int32_t); codeOffset += sizeof(int32_t); } else { str_indirection_text(operandText, opSize); str_seg_text(operandText, ps, dt); if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode64Bits) str_x86def(operandText, &_MODS64[rm]); else str_x86def(operandText, &_MODS32[rm]); chrcat_WS(operandText, CLOSE_CHR); } break; case 0x01: /* 8 bits displacement + indirection */ ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); if ((opNum == ONT_1) && (totalPrefixes & INST_PRE_LOCK)) *lockableInstruction = 1; if (rm == 4) { /* 4 is a special case - SIB byte + disp8 follows! */ /* Skip SIB byte. */ if (--codeLen < 0) return FALSE; sib = *code; str_hex_b(instructionHex, sib); code += sizeof(int8_t); codeOffset += sizeof(int8_t); if (!extract_sib(&code, &codeLen, &codeOffset, instructionHex, operandText, ps, dt, mod, sib, opSize)) return FALSE; } else { codeLen -= sizeof(int8_t); if (codeLen < 0) return FALSE; str_hex_sp_b(instructionHex, *code); str_indirection_text(operandText, opSize); str_seg_text(operandText, ps, dt); if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode64Bits) str_x86def(operandText, &_MODS64[rm]); else str_x86def(operandText, &_MODS32[rm]); chrcat_WS(operandText, (*(int8_t*)code >= 0) ? PLUS_DISP_CHR : MINUS_DISP_CHR); str_code_hb(operandText, abs(*(int8_t*)code)); chrcat_WS(operandText, CLOSE_CHR); code += sizeof(int8_t); codeOffset += sizeof(int8_t); } break; case 0x02: /* 32 bits displacement + indirection */ ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); if ((opNum == ONT_1) && (totalPrefixes & INST_PRE_LOCK)) *lockableInstruction = 1; if (rm == 4) { /* 4 is a special case - SIB byte + disp32 follows! */ /* Skip SIB byte. */ if (--codeLen < 0) return FALSE; sib = *code; str_hex_b(instructionHex, sib); code += sizeof(int8_t); codeOffset += sizeof(int8_t); if (!extract_sib(&code, &codeLen, &codeOffset, instructionHex, operandText, ps, dt, mod, sib, opSize)) return FALSE; } else { codeLen -= sizeof(int32_t); if (codeLen < 0) return FALSE; str_hex_sp_dw(instructionHex, RULONG(code)); str_indirection_text(operandText, opSize); str_seg_text(operandText, ps, dt); if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode64Bits)str_x86def(operandText, &_MODS64[rm]); else str_x86def(operandText, &_MODS32[rm]); /* Signed relative address: */ chrcat_WS(operandText, (RLONG(code) >= 0) ? PLUS_DISP_CHR : MINUS_DISP_CHR); str_code_hdw(operandText, abs(RLONG(code))); chrcat_WS(operandText, CLOSE_CHR); code += sizeof(int32_t); codeOffset += sizeof(int32_t); } break; default: return FALSE; } } /* * It's ok if we don't update the pointers parameters when we will return FALSE, because * they are to be ignored anyways. */ ci->code = code; ci->codeLen = codeLen; ci->codeOffset = codeOffset; return TRUE; } /* * This function is reponsible to textually format a required operand according to its type. * It is vital to understand that there are other operands than what the ModR/M byte specifies. * Only by decoding the operands of an instruction which got a LOCK prefix, we could tell whether it may use the LOCK prefix. * According to Intel, LOCK prefix must precede some specific instructions AND in their memory destination operand form (which means first operand). * LOCK INC EAX, would generate an exception, but LOCK INC [EAX] is alright. * Also LOCK ADD BX, [BP] would generate an exception. * Return code: * EO_CONTINUE - continue parsing the instruction and its operands, everything went right 'till now. * EO_HALT - not enough bytes, or invalid operands. * EO_SUFFIX - explicit operands instructions (such as: xlat, movs, scas etc...) should be output by their implicit form (AKA LODSB, XLATB, and not XLAT BYTE [BX+AL])... */ _ExOpRCType extract_operand(_CodeInfo* ci, _WString* instructionHex, _WString* operandText, _OpType type, _OpType op2, _OperandNumberType opNum, _iflags instFlags, unsigned int modrm, _PrefixState* ps, _DecodeType dt, int* lockableInstruction) { unsigned int mod = 0, reg = 0, rm = 0; _iflags tmpPrefixes = 0; _iflags totalPrefixes = ps->totalPrefixes; const uint8_t* code = ci->code; int codeLen = ci->codeLen; _OffsetType codeOffset = ci->codeOffset; int32_t joff = 0; _OffsetType reloff = 0; unsigned int rex = 0; /* Used to indicate the size of the MEMORY INDIRECTION. */ _OperandSizeType opSize = OPERAND_SIZE_NONE; *lockableInstruction = 0; /* * ModRM bits: * |7-6-5--------3-2-0| * |MOD|REG/OPCODE|RM | * |------------------| */ mod = (modrm >> 6) & 3; /* Mode(register-indirection, disp8+reg+indirection, disp16+reg+indirection, general-purpose register) */ reg = (modrm >> 3) & 7; /* Register(could be part of the opcode itself or general-purpose register) */ rm = modrm & 7; /* Specifies which general-purpose register or disp+reg to use. */ /* * In 64 bits, we have to take care for REX prefix, thus we have to extend the ModR/M and SIB values. * REX.R 3rd bit, extends REG, only GPR, XMM, Control or Debug. * REX.B 1st bit, extends */ if (ps->isREXPrefixValid) rex = *ps->rexpos; switch (type) { case OT_IMM8: codeLen -= sizeof(int8_t); if (codeLen < 0) return EO_HALT; str_hex_sp_b(instructionHex, *code); str_code_hb(operandText, *code); code += sizeof(int8_t); codeOffset += sizeof(int8_t); break; case OT_IMM_FULL: /* 16, 32 or 64, depends on prefixes. */ if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode16Bits) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); /* FALL THROUGH */ case OT_IMM16: /* Force 16 bits imm. */ codeLen -= sizeof(int16_t); if (codeLen < 0) return EO_HALT; str_hex_sp_w(instructionHex, RUSHORT(code)); str_code_hw(operandText, RUSHORT(code)); code += sizeof(int16_t); codeOffset += sizeof(int16_t); break; /* * Extension: MOV imm64?, requires REX. * Make sure it needs the REX. * REX must be present because op size function takes it consideration. */ } else if ((OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode64Bits) && ((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX))) { ps->usedPrefixes |= INST_PRE_REX; codeLen -= sizeof(int32_t)*2; if (codeLen < 0) return EO_HALT; str_hex_sp_qw(instructionHex, (uint8_t*)code); str_code_hqw(operandText, (uint8_t*)code); code += sizeof(int32_t)*2; codeOffset += sizeof(int32_t)*2; break; } else ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); /* FALL THROUGH BECAUSE dt==Decoded32Bits @-<----*/ case OT_IMM32: codeLen -= sizeof(int32_t); if (codeLen < 0) return EO_HALT; str_hex_sp_dw(instructionHex, RULONG(code)); if (dt == Decode64Bits) { /* * Imm32 is sign extended to 64 bits! * Show minus sign if the extension is lower than zero. * Positive values are normally displayed. */ if (RLONG(code) < 0) chrcat_WS(operandText, MINUS_DISP_CHR); str_code_hdw(operandText, abs(RLONG(code))); } else { /* Decode32Bits */ str_code_hdw(operandText, RULONG(code)); } code += sizeof(int32_t); codeOffset += sizeof(int32_t); break; case OT_IMM_AADM: /* Special case for AAD & AAM, will output value only if not 0xa (default Decimal Base). */ codeLen -= sizeof(int8_t); if (codeLen < 0) return EO_HALT; str_hex_sp_b(instructionHex, *code); if (*code != 0xa) str_code_hb(operandText, *code); code += sizeof(int8_t); codeOffset += sizeof(int8_t); break; case OT_SEIMM8: /* Sign extended immediate. */ codeLen -= sizeof(int8_t); if (codeLen < 0) return EO_HALT; str_hex_sp_b(instructionHex, *code); /* * PUSH SEIMM8 can back prefixed by operand size: * Input stream: 66, 6a, 55 * 64bits DT: push small 55 * 32bits DT: push small 55 * 16bits DT: push large 55 * small/large indicates the size of the eSP pointer advancement. * Check the instFlags (ii->flags) if it can be operand-size-prefixed and if the prefix exists. */ if ((instFlags & INST_PRE_OP_SIZE) && (totalPrefixes & INST_PRE_OP_SIZE)) { ps->usedPrefixes |= INST_PRE_OP_SIZE; switch (dt) { case Decode16Bits: strcat_WSN(operandText, LARGE_OPERAND); break; case Decode32Bits: case Decode64Bits: strcat_WSN(operandText, SMALL_OPERAND); break; } } /* Show only '-' character if required. */ if (*(int8_t*)code < 0) chrcat_WS(operandText, MINUS_DISP_CHR); str_code_hb(operandText, abs(*(int8_t*)code)); code += sizeof(int8_t); codeOffset += sizeof(int8_t); break; case OT_REG8: if (ps->isREXPrefixValid) { /* * If REX prefix is valid then we will have to use low bytes. * This is a PASSIVE behaviour changer of REX prefix, it affects operands even if its value is 0x40 ! */ ps->usedPrefixes |= INST_PRE_REX; str_x86def(operandText, &_REGS8_REX[reg + ((rex & PREFIX_REX_R) == PREFIX_REX_R ? REX_GPR_BASE : 0)]); } else str_x86def(operandText, &_REGS8[reg]); break; case OT_REG16: if (rex & PREFIX_REX_R) { ps->usedPrefixes |= INST_PRE_REX; reg += REX_GPR_BASE; } str_x86def(operandText, &_REGS16[reg]); break; case OT_REG_FULL: switch (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags)) { case Decode16Bits: ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); if (rex & PREFIX_REX_R) { ps->usedPrefixes |= INST_PRE_REX; reg += REX_GPR_BASE; } str_x86def(operandText, &_REGS16[reg]); break; case Decode32Bits: if (rex & PREFIX_REX_R) { ps->usedPrefixes |= INST_PRE_REX; reg += REX_GPR_BASE; } else ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); str_x86def(operandText, &_REGS32[reg]); break; case Decode64Bits: /* REX must be presented. */ ps->usedPrefixes |= INST_PRE_REX; str_x86def(operandText, &_REGS64[reg + ((rex & PREFIX_REX_R) == PREFIX_REX_R ? REX_GPR_BASE : 0)]); break; } break; case OT_REG32: if (rex & PREFIX_REX_R) { ps->usedPrefixes |= INST_PRE_REX; reg += REX_GPR_BASE; } str_x86def(operandText, &_REGS32[reg]); break; case OT_REG32_64: /* Handle CVT's, MOVxX and MOVNTI instructions which could be extended to 64 bits registers with REX. */ if (rex & PREFIX_REX_R) { ps->usedPrefixes |= INST_PRE_REX; reg += REX_GPR_BASE; } /* Is it a promoted instruction? (only INST_64BITS is set and REX isn't required.) */ if ((dt == Decode64Bits) && ((instFlags & (INST_64BITS | INST_PRE_REX)) == INST_64BITS)) { str_x86def(operandText, &_REGS64[reg]); break; } /* Give a chance to REX.W. Because if it was a promoted instruction we don't care about REX.W anyways. */ if (rex & PREFIX_REX_W) { ps->usedPrefixes |= INST_PRE_REX; str_x86def(operandText, &_REGS64[reg]); } else str_x86def(operandText, &_REGS32[reg]); break; case OT_REG64: /* MOVSXD uses 64 bits register. */ /* V 1.5.16 - MOVSXD is now being decoded properly (definition was incorrect in x86defs.c too). */ if (rex & PREFIX_REX_R) { ps->usedPrefixes |= INST_PRE_REX; reg += REX_GPR_BASE; } str_x86def(operandText, &_REGS64[reg]); break; case OT_REG32_RM: /* R32, this time from the RM field */ if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } str_x86def(operandText, &_REGS32[rm]); break; case OT_FREG32_64_RM: /* Force decoding mode. Used for MOV CR(n)/DR(n) which defaults to 64 bits operand size in 64 bits. */ if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } if (dt == Decode64Bits) str_x86def(operandText, &_REGS64[rm]); else str_x86def(operandText, &_REGS32[rm]); break; case OT_MM: /* MMX register */ str_x86def(operandText, &_REGSMMX[reg]); break; case OT_MM_RM: /* MMX register, this time from the RM field */ str_x86def(operandText, &_REGSMMX[rm]); break; case OT_XMM: /* SSE register */ if (rex & PREFIX_REX_R) { ps->usedPrefixes |= INST_PRE_REX; reg += REX_GPR_BASE; } str_x86def(operandText, &_REGSSSE[reg]); break; case OT_XMM_RM: /* SSE register, this time from the RM field */ if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; rm += REX_GPR_BASE; } str_x86def(operandText, &_REGSSSE[rm]); break; case OT_REGXMM0: /* Implicit XMM0 operand. */ str_x86def(operandText, &_REGSSSE[0]); break; /* -- Memory Indirection Operands -- */ case OT_MEM64_128: /* Used only by CMPXCHG8/16B. */ /* Make a specific check when the type is OT_MEM64_128 since the lockable CMPXCHG8B uses this one... */ if ((opNum == ONT_1) && (totalPrefixes & INST_PRE_LOCK)) *lockableInstruction = 1; if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode64Bits) { ps->usedPrefixes |= INST_PRE_REX; opSize = OPERAND_SIZE128; } else opSize = OPERAND_SIZE64; goto _FilterMod; case OT_MEM32: opSize = OPERAND_SIZE32; goto _FilterMod; case OT_MEM64: opSize = OPERAND_SIZE64; goto _FilterMod; case OT_MEM128: opSize = OPERAND_SIZE128; goto _FilterMod; case OT_MEM16_FULL: /* The size indicates about the second item of the pair. */ switch (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags)) { case Decode16Bits: ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); opSize = OPERAND_SIZE16; break; case Decode32Bits: ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); opSize = OPERAND_SIZE32; break; case Decode64Bits: /* Mark usage of REX only if it was required. */ if ((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX)) ps->usedPrefixes |= INST_PRE_REX; opSize = OPERAND_SIZE64; break; } goto _FilterMod; case OT_MEM16_3264: /* The size indicates about the second item of the pair. */ if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode64Bits) { /* Mark usage of REX only if it was required. */ if ((instFlags & INST_64BITS) == 0) ps->usedPrefixes |= INST_PRE_REX; opSize = OPERAND_SIZE64; } else { opSize = OPERAND_SIZE32; } goto _FilterMod; case OT_FPUM16: opSize = OPERAND_SIZE16; goto _FilterMod; case OT_FPUM32: opSize = OPERAND_SIZE32; goto _FilterMod; case OT_FPUM64: opSize = OPERAND_SIZE64; goto _FilterMod; case OT_FPUM80: opSize = OPERAND_SIZE80; /* goto _FilterMod; */ case OT_MEM32_64: /* Use by MOVNTI, size is known from second operand. */ case OT_MEM: /* No specific size. */ _FilterMod: /* All of the above types can't use a general-purpose register (a MOD of 3)!. */ if (mod == 0x3) { *lockableInstruction = 0; return EO_HALT; } goto _ExtractModRM; case OT_RM8: if (op2 == OT_NONE || op2 == OT_IMM8 || op2 == OT_IMM_FULL || op2 == OT_IMM32 || op2 == OT_SEIMM8 || op2 == OT_REGCL || op2 == OT_CONST1 || (op2 == OT_REG_FULL && mod != 3) || op2 == OT_REG32_64) opSize = OPERAND_SIZE8; goto _ExtractModRM; case OT_RM_FULL: if (op2 == OT_NONE || op2 == OT_IMM8 || op2 == OT_IMM_FULL || op2 == OT_IMM32 || op2 == OT_SEIMM8 || op2 == OT_REGCL || op2 == OT_CONST1 || op2 == OT_REG32_64) { ps->usedPrefixes |= (ps->totalPrefixes & INST_PRE_OP_SIZE); /* PUSH/JMP/CALL are automatically promoted to 64 bits! */ if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode32Bits) { opSize = OPERAND_SIZE32; goto _ExtractModRM; } else if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode64Bits) { /* Mark usage of REX only if it was required. */ if ((instFlags & INST_64BITS) == 0) ps->usedPrefixes |= INST_PRE_REX; opSize = OPERAND_SIZE64; goto _ExtractModRM; } } else goto _ExtractModRM; /* FALL THROUGH BECAUSE dt==Decoded16Bits @-<----*/ case OT_RM16: if (op2 == OT_NONE || op2 == OT_IMM8 || op2 == OT_IMM_FULL || op2 == OT_IMM32 || op2 == OT_SEIMM8 || op2 == OT_REGCL || op2 == OT_CONST1 || op2 == OT_REG32_64) { /* If we got here not from OT_RM16, then the prefix was used. */ if (type != OT_RM16) ps->usedPrefixes |= (ps->totalPrefixes & INST_PRE_OP_SIZE); opSize = OPERAND_SIZE16; } goto _ExtractModRM; case OT_RM32: if (op2 == OT_NONE || op2 == OT_IMM8 || op2 == OT_IMM_FULL || op2 == OT_IMM32 || op2 == OT_SEIMM8 || op2 == OT_REGCL || op2 == OT_CONST1) { opSize = OPERAND_SIZE32; } goto _ExtractModRM; case OT_RM32_64: /* V 1.5.18 - The default size was 64 (instead of 32), which supposed to be 64 with a REX only. - FIXED */ if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode64Bits) { opSize = OPERAND_SIZE64; /* Mark REX prefix as used if non-promoted instruction. */ if ((instFlags & (INST_64BITS | INST_PRE_REX)) == (INST_64BITS | INST_PRE_REX)) { ps->usedPrefixes |= INST_PRE_REX; } } else opSize = OPERAND_SIZE32; goto _ExtractModRM; case OT_RM16_32: /* Ignore REX, it's either 32 or 16 bits RM. */ if (ps->totalPrefixes & INST_PRE_OP_SIZE) { ps->usedPrefixes |= INST_PRE_OP_SIZE; opSize = OPERAND_SIZE16; } else opSize = OPERAND_SIZE_NONE; /* Default is 32 bits anyways. */ goto _ExtractModRM; case OT_R32_M8: opSize = OPERAND_SIZE8; goto _ExtractModRM; case OT_R32_M16: opSize = OPERAND_SIZE16; goto _ExtractModRM; case OT_R32_64_M8: opSize = OPERAND_SIZE8; goto _ExtractModRM; case OT_R32_64_M16: opSize = OPERAND_SIZE16; goto _ExtractModRM; case OT_RFULL_M16: ps->usedPrefixes |= (ps->totalPrefixes & INST_PRE_OP_SIZE); opSize = OPERAND_SIZE16; goto _ExtractModRM; case OT_MM32: opSize = OPERAND_SIZE32; goto _ExtractModRM; case OT_MM64: opSize = OPERAND_SIZE64; goto _ExtractModRM; case OT_XMM16: opSize = OPERAND_SIZE16; goto _ExtractModRM; case OT_XMM32: opSize = OPERAND_SIZE32; goto _ExtractModRM; case OT_XMM64: opSize = OPERAND_SIZE64; goto _ExtractModRM; case OT_XMM128: opSize = OPERAND_SIZE128; /* goto _ExtractModRM; */ /* --------------- MODR/M BYTE DECODING -------------------- */ _ExtractModRM: ci->code = code; ci->codeLen = codeLen; ci->codeOffset = codeOffset; if (!extract_modrm(ci, instructionHex, operandText, type, opNum, ps, dt, lockableInstruction, mod, rm, instFlags, opSize)) return EO_HALT; return EO_CONTINUE; case OT_CREG: /* * Don't parse if the reg exceeds the bounds of the array. * Most of the CR's are not implemented, so if there's no matching string, the operand is invalid. */ if (rex & PREFIX_REX_R) { ps->usedPrefixes |= INST_PRE_REX; reg += REX_GPR_BASE; } else if ((dt == Decode32Bits) && (ps->totalPrefixes & INST_PRE_LOCK)) { /* * NOTE: In 32 bits decoding mode, * if the lock prefix is set before MOV CR(n) it will become the 4th bit of the REG field like REX.R in 64 bits. */ reg += REX_GPR_BASE; ps->usedPrefixes |= INST_PRE_LOCK; } if (reg >= CREGS_MAX) return EO_HALT; if (_CREGS[reg].size == 0) return EO_HALT; str_x86def(operandText, &_CREGS[reg]); break; case OT_DREG: /* In 64 bits there are 16 debug registers, but dr8-15 aren't implemented anyways, thus they are ignored. */ if ((reg == 4) || (reg == 5)) return EO_HALT; str_x86def(operandText, &_DREGS[reg]); break; case OT_SREG: /* Works with REG16 only! */ if ((opNum == ONT_1) && (reg == 1)) return EO_HALT; /* Can't MOV CS, . */ /*Don't parse if the reg exceeds the bounds of the array. */ if (reg <= SEG_REGS_MAX-1) str_x86def(operandText, &_SREGS[reg]); else return EO_HALT; break; case OT_SEG: /* * Extract the SEG from ii->flags this time!!! * Check whether an operand size prefix is used. */ if (totalPrefixes & INST_PRE_OP_SIZE) { ps->usedPrefixes |= INST_PRE_OP_SIZE; if (dt == Decode16Bits) strcat_WSN(operandText, TEXT_32_BITS); else strcat_WSN(operandText, TEXT_16_BITS); } switch (instFlags & INST_PRE_SEGOVRD_MASK) { case INST_PRE_CS: strcat_WSN(operandText, PREFIX_CS_TEXT); break; case INST_PRE_SS: strcat_WSN(operandText, PREFIX_SS_TEXT); break; case INST_PRE_DS: strcat_WSN(operandText, PREFIX_DS_TEXT); break; case INST_PRE_ES: strcat_WSN(operandText, PREFIX_ES_TEXT); break; case INST_PRE_FS: strcat_WSN(operandText, PREFIX_FS_TEXT); break; case INST_PRE_GS: strcat_WSN(operandText, PREFIX_GS_TEXT); break; } break; case OT_ACC8: str_x86def(operandText, &_REGS8[0]); break; case OT_ACC16: str_x86def(operandText, &_REGS16[0]); break; case OT_ACC_FULL_NOT64: /* No REX.W support for IN/OUT. */ rex &= ~PREFIX_REX_W; case OT_ACC_FULL: if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode16Bits) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); str_x86def(operandText, &_REGS16[0]); } else if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode32Bits) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); str_x86def(operandText, &_REGS32[0]); } else { /* Decode64Bits */ /* Only non-promoted instructions need REX in order to decode in 64 bits. */ /* V 1.6.21 MEM-OFFSET MOV's are NOT automatically promoted to 64 bits. */ if (~instFlags & INST_64BITS) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_REX); } str_x86def(operandText, &_REGS64[0]); } break; case OT_PTR16_FULL: /* ptr16:full - full is size of operand size to read, therefore Operand Size Prefix affects this. So we need to handle it. */ if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode16Bits) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); codeLen -= sizeof(int16_t)*2; if (codeLen < 0) return EO_HALT; str_hex_sp_w(instructionHex, RUSHORT(code)); /* Read offset first. */ str_hex_sp_w(instructionHex, RUSHORT((code+sizeof(int16_t)))); /* And read segment. */ /* * If the Operand Size Prefix exists, we will have to explicitly indicate it's a SMALL offset. * This is correct behavior for decoding the code in 32 bits where a db 0x66 was used. */ if (totalPrefixes & INST_PRE_OP_SIZE) strcat_WSN(operandText, SMALL_OPERAND); str_code_hw(operandText, RUSHORT((code+sizeof(int16_t)))); chrcat_WS(operandText, SEG_OFF_CHR); str_code_hw(operandText, RUSHORT(code)); code += sizeof(int16_t)*2; codeOffset += sizeof(int16_t)*2; } else { /* Decode32Bits, for Decode64Bits this instruction is invalid. */ ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); codeLen -= sizeof(int32_t) + sizeof(int16_t); if (codeLen < 0) return EO_HALT; str_hex_sp_dw(instructionHex, RULONG(code)); /* Read 32bits offset this time. */ str_hex_sp_w(instructionHex, RUSHORT((code+sizeof(int32_t)))); /* And read segment, 16 bits. */ if (totalPrefixes & INST_PRE_OP_SIZE) strcat_WSN(operandText, LARGE_OPERAND); str_code_hw(operandText, RUSHORT((code+sizeof(int32_t)))); chrcat_WS(operandText, SEG_OFF_CHR); str_code_hdw(operandText, RULONG(code)); code += sizeof(int32_t) + sizeof(int16_t); codeOffset += sizeof(int32_t) + sizeof(int16_t); } break; case OT_RELCB: codeLen -= sizeof(int8_t); if (codeLen < 0) return EO_HALT; joff = *(int8_t*)code; str_hex_sp_b(instructionHex, (uint8_t)joff); /* strcat_WSN(operandText, SHORT_OPERAND); */ /* Just make sure the offset is output correctly. */ reloff = ((joff < 0) ? (codeOffset - abs(joff) + 1) : (codeOffset + joff + 1)); #ifdef SUPPORT_64BIT_OFFSET str_off64(operandText, reloff); #else str_code_hdw(operandText, (_OffsetType)reloff); #endif code += sizeof(int8_t); codeOffset += sizeof(int8_t); break; case OT_RELC_FULL: /* Yep, operand size prefix affects relc also. */ if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode16Bits) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); codeLen -= sizeof(int16_t); if (codeLen < 0) return EO_HALT; joff = RSHORT(code); str_hex_sp_w(instructionHex, (uint16_t)joff); if (totalPrefixes & INST_PRE_OP_SIZE) strcat_WSN(operandText, SMALL_OPERAND); reloff = ((joff < 0) ? (codeOffset - abs(joff) + 2) : (codeOffset + joff + 2)); str_code_hw(operandText, (uint16_t)((joff < 0) ? (codeOffset - abs(joff) + 2) : (codeOffset + joff + 2))); code += sizeof(int16_t); codeOffset += sizeof(int16_t); } else { /* Decode32Bits or Decode64Bits = for now they are the same */ ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); codeLen -= sizeof(int32_t); if (codeLen < 0) return EO_HALT; joff = RLONG(code); str_hex_sp_dw(instructionHex, RULONG(code)); if (totalPrefixes & INST_PRE_OP_SIZE) strcat_WSN(operandText, LARGE_OPERAND); reloff = ((joff < 0) ? (codeOffset - abs(joff) + 4) : (codeOffset + joff + 4)); #ifdef SUPPORT_64BIT_OFFSET str_off64(operandText, reloff); #else str_code_hdw(operandText, (_OffsetType)reloff); #endif /* * We add 4 to the new offset because, when you make the branch the processor's IP points to the next instruction, which * in 32 bits should be $+5, AKA current IP + 5. * So it comes out we added 1 to codeOffset for the jmp/call instruction itself we add 4 and not 5. */ code += sizeof(int32_t); codeOffset += sizeof(int32_t); } break; case OT_MOFFS: /* * Just a pointer to a BYTE, WORD, DWORD, QWORD. Works only with ACC8/16/32/64 respectively. * MOV [0x1234], AL ; MOV AX, [0x1234] ; MOV EAX, [0x1234], note that R/E/AX will be chosen by OT_ACC_FULL. */ if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode16Bits) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); codeLen -= sizeof(int16_t); if (codeLen < 0) return EO_HALT; str_hex_sp_w(instructionHex, RUSHORT(code)); str_seg_text(operandText, ps, dt); chrcat_WS(operandText, OPEN_CHR); str_code_hw(operandText, RUSHORT(code)); chrcat_WS(operandText, CLOSE_CHR); code += sizeof(int16_t); codeOffset += sizeof(int16_t); } else if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode32Bits) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); codeLen -= sizeof(int32_t); if (codeLen < 0) return EO_HALT; str_hex_sp_dw(instructionHex, RULONG(code)); str_seg_text(operandText, ps, dt); chrcat_WS(operandText, OPEN_CHR); str_code_hdw(operandText, RULONG(code)); chrcat_WS(operandText, CLOSE_CHR); code += sizeof(int32_t); codeOffset += sizeof(int32_t); } else { /* Decode64Bits */ codeLen -= sizeof(int32_t)*2; if (codeLen < 0) return EO_HALT; str_hex_sp_qw(instructionHex, (uint8_t*)code); str_seg_text(operandText, ps, dt); chrcat_WS(operandText, OPEN_CHR); str_code_hqw(operandText, (uint8_t*)code); chrcat_WS(operandText, CLOSE_CHR); code += sizeof(int32_t)*2; codeOffset += sizeof(int32_t)*2; } break; case OT_CONST1: strcat_WSN(operandText, ONE_CONST_TEXT); break; case OT_REGCL: str_x86def(operandText, &_REGS8[1]); break; case OT_FPU_SI: /* Low 3 bits specify the REG, similar to the MODR/M byte reg. */ reg = *(code-1) & 7; strcat_WSN(operandText, FPU_STACK_TEXT); chrcat_WS(operandText, OPEN_CHR0); chrcat_WS(operandText, (int8_t)reg + 0x30); chrcat_WS(operandText, CLOSE_CHR0); break; case OT_FPU_SSI: reg = *(code-1) & 7; strcat_WSN(operandText, FPU_STACK_TEXT); strcat_WSN(operandText, SEP_STR); strcat_WSN(operandText, FPU_STACK_TEXT); chrcat_WS(operandText, OPEN_CHR0); chrcat_WS(operandText, (int8_t)reg + 0x30); chrcat_WS(operandText, CLOSE_CHR0); break; case OT_FPU_SIS: reg = *(code-1) & 7; strcat_WSN(operandText, FPU_STACK_TEXT); chrcat_WS(operandText, OPEN_CHR0); chrcat_WS(operandText, (int8_t)reg + 0x30); chrcat_WS(operandText, CLOSE_CHR0); strcat_WSN(operandText, SEP_STR); strcat_WSN(operandText, FPU_STACK_TEXT); break; /* * Special treatment for Instructions-Block: * INC/DEC (only 16/32 bits) /PUSH/POP/XCHG instructions, which get their REG from their own binary code. * Notice these instructions are 1 or 2 byte long, * code points after the byte which represents the instruction itself, * thus, even if the instructions are 2 bytes long it will read its last byte which contains the REG info. */ case OT_IB_RB: /* Low 3 bits specify the REG, similar to the MODR/M byte reg. */ reg = *(code-1) & 7; if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; str_x86def(operandText, &_REGS8_REX[reg + REX_GPR_BASE]); } else if (ps->isREXPrefixValid) { ps->usedPrefixes |= INST_PRE_REX; str_x86def(operandText, &_REGS8_REX[reg]); } else str_x86def(operandText, &_REGS8[reg]); break; case OT_IB_R_DW_QW: /* BSWAP can't use 16 bits register. */ totalPrefixes &= ~INST_PRE_OP_SIZE; case OT_IB_R_FULL: reg = *(code-1) & 7; switch (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags)) { case Decode16Bits: ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; reg += REX_GPR_BASE; } str_x86def(operandText, &_REGS16[reg]); break; case Decode32Bits: if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; str_x86def(operandText, &_REGS32[reg + REX_GPR_BASE]); } else { ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); str_x86def(operandText, &_REGS32[reg]); } break; case Decode64Bits: /* * Automatically promoted instruction can drop REX prefix if not required. * PUSH/POP defaults to 64 bits. --> INST_64BITS * MOV imm64 / BSWAP requires REX.W to be 64 bits --> INST_64BITS | INST_PRE_REX */ if ((instFlags & INST_64BITS) && ((instFlags & INST_PRE_REX) == 0)) { if (rex & PREFIX_REX_B) { ps->usedPrefixes |= INST_PRE_REX; reg += REX_GPR_BASE; } str_x86def(operandText, &_REGS64[reg]); } else { ps->usedPrefixes |= INST_PRE_REX; str_x86def(operandText, &_REGS64[reg + ((rex & PREFIX_REX_B) == PREFIX_REX_B ? REX_GPR_BASE : 0)]); } break; } break; /* * Special treatment for repeatable instructions. * We want the following output: * If there's only the REP/NZ prefix, we won't output anything (All operands are implicit). * If there's an operand size prefix, we will change the suffix letter of the mnemonic, which specifies the size of operand to the required one. * If there's a segment override prefix, we will output the segment and the used index register (EDI/ESI). * If there's an address size prefix, we will output the (segment if needed and) the used and inverted index register (DI/SI). * Example: * :: Decoding in 16 bits mode! :: * AD ~ LODSW * 66 AD ~ LODSD * F3 AC ~ REP LODSB * F3 66 AD ~ REP LODSD * F3 3E AC ~ REP LODS BYTE DS:[SI] * F3 67 AD ~ REP LODS WORD [ESI] * The basic form of a repeatable instruction has its operands hidden and has a suffix letter * which implies on the size of operation being done. * Therefore, we cannot change the mnemonic here when we encounter another prefix and its not the decoder's responsibility to do so. * That's why the caller is responsible to add the suffix letter if no other prefixes are used. * And all we are doing here is formatting the operand correctly. */ case OT_REGI_ESI: tmpPrefixes = totalPrefixes & (INST_PRE_SEGOVRD_MASK | INST_PRE_OP_SIZE | INST_PRE_ADDR_SIZE | INST_PRE_REPS); /* First, make sure the instruction is repeatable before we make a move. */ if ((instFlags & INST_PRE_REPS) == 0) return EO_SUFFIX; ps->usedPrefixes |= (tmpPrefixes & INST_PRE_ADDR_SIZE); /* This might be a 16, 32 or 64 bits instruction, depends on the decoding mode. */ if (instFlags & INST_16BITS) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_OP_SIZE); /* Explicit operands only when there's a segment override or address size prefix. */ if ((tmpPrefixes & INST_PRE_OP_SIZE) == tmpPrefixes) return EO_SUFFIX; if ((tmpPrefixes & (INST_PRE_OP_SIZE | (instFlags & INST_PRE_REPS))) == tmpPrefixes) return EO_SUFFIX; if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode16Bits) strcat_WSN(operandText, TEXT_16_BITS); else if ((OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode64Bits) && (instFlags & INST_64BITS)) { ps->usedPrefixes |= INST_PRE_REX; strcat_WSN(operandText, TEXT_64_BITS); } else strcat_WSN(operandText, TEXT_32_BITS); } else { /* * Explicit operands only when there's a segment override or address size prefix. * Not all repeatable string instructions support 64 bits (IN/OUT). */ if ((tmpPrefixes & INST_PRE_OP_SIZE) == tmpPrefixes) return EO_SUFFIX; if ((tmpPrefixes & (INST_PRE_OP_SIZE | (instFlags & INST_PRE_REPS))) == tmpPrefixes) return EO_SUFFIX; strcat_WSN(operandText, TEXT_8_BITS); } str_seg_text(operandText, ps, dt); chrcat_WS(operandText, OPEN_CHR); if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode16Bits) str_x86def(operandText, &_REGS16[6]); else if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode32Bits) str_x86def(operandText, &_REGS32[6]); else str_x86def(operandText, &_REGS64[6]); chrcat_WS(operandText, CLOSE_CHR); break; case OT_REGI_EDI: tmpPrefixes = totalPrefixes & (INST_PRE_SEGOVRD_MASK | INST_PRE_OP_SIZE | INST_PRE_ADDR_SIZE | INST_PRE_REPS); /* First make sure the instruction is repeatable before we make a move. */ if ((instFlags & INST_PRE_REPS) == 0) return EO_SUFFIX; /* Implicit operand form, needs instruction suffix. */ ps->usedPrefixes |= (tmpPrefixes & INST_PRE_ADDR_SIZE); /* This might be a 16 or 32 bits instruction, depends on the decoding mode. */ if (instFlags & INST_16BITS) { ps->usedPrefixes |= (tmpPrefixes & INST_PRE_OP_SIZE); /* Explicit operands only when there's a segment override or address size prefix. */ if ((tmpPrefixes & INST_PRE_OP_SIZE) == tmpPrefixes) return EO_SUFFIX; if ((tmpPrefixes & (INST_PRE_OP_SIZE | INST_PRE_REPS)) == tmpPrefixes) return EO_SUFFIX; if (OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode16Bits) strcat_WSN(operandText, TEXT_16_BITS); else if ((OP_SIZE_AFFECT(dt, totalPrefixes, rex, instFlags) == Decode64Bits) && (instFlags & INST_64BITS)) { ps->usedPrefixes |= INST_PRE_REX; strcat_WSN(operandText, TEXT_64_BITS); } else strcat_WSN(operandText, TEXT_32_BITS); } else { /* Explicit operands only when there's a segment override or address size prefix. */ if ((tmpPrefixes & INST_PRE_OP_SIZE) == tmpPrefixes) return EO_SUFFIX; if ((tmpPrefixes & (INST_PRE_OP_SIZE | (instFlags & INST_PRE_REPS))) == tmpPrefixes) return EO_SUFFIX; strcat_WSN(operandText, TEXT_8_BITS); } str_seg_text(operandText, ps, dt); chrcat_WS(operandText, OPEN_CHR); if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode16Bits) str_x86def(operandText, &_REGS16[7]); else if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode32Bits) str_x86def(operandText, &_REGS32[7]); else str_x86def(operandText, &_REGS64[7]); chrcat_WS(operandText, CLOSE_CHR); break; /* Used for In/Out instructions varying forms. */ case OT_REGDX: /* Simple single IN/OUT instruction. */ if ((instFlags & INST_PRE_REPS) == 0) { str_x86def(operandText, &_REGS16[2]); } else { /* String instruction. */ /* * Do we need to use the DX register? - Only if the instruction is prefixed, so you will need implicitly output the register. * Otherwise, we need a suffix letter for operation-size indication. */ /* Exception is when there's only operand size prefix, suffix letter is enough then. */ if ((totalPrefixes & (INST_PRE_OP_SIZE | INST_PRE_REPS)) == totalPrefixes) return EO_SUFFIX; if ((totalPrefixes & (INST_PRE_SEGOVRD_MASK | INST_PRE_OP_SIZE | INST_PRE_ADDR_SIZE)) == 0) return EO_SUFFIX; str_x86def(operandText, &_REGS16[2]); } break; /* Used for INVLPGA instruction. */ case OT_REGECX: str_x86def(operandText, &_REGS32[1]); break; /* * XLAT special treatment: * 32 bit decoding: * D7 ~ XLATB * 67 D7 ~ XLAT BYTE [BX+AL] * 26 D7 ~ XLAT BYTE ES:[EBX+AL] * ; In 64 bits ES is ignored. * 26 D7 ~ db 0x26; XLAT */ case OT_REGI_EBXAL: /* Make sure there are other prefixes set. */ if ((totalPrefixes & (INST_PRE_SEGOVRD_MASK | INST_PRE_ADDR_SIZE)) == 0) return EO_SUFFIX; /* Implicit operand form, needs instruction suffix. */ ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); strcat_WSN(operandText, TEXT_8_BITS); str_seg_text(operandText, ps, dt); chrcat_WS(operandText, OPEN_CHR); if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode16Bits) str_x86def(operandText, &_REGS16[3]); else if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode32Bits) str_x86def(operandText, &_REGS32[3]); else { ps->usedPrefixes |= INST_PRE_REX; str_x86def(operandText, &_REGS64[3]); } chrcat_WS(operandText, PLUS_DISP_CHR); str_x86def(operandText, &_REGS8[0]); chrcat_WS(operandText, CLOSE_CHR); break; case OT_REGI_EAX: /* * Implicit rAX as memory indirection operand. Used by AMD's SVM instructions. * Since this is a memory indirection, the default address size in 64bits decoding mode is 64. */ chrcat_WS(operandText, OPEN_CHR); if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode64Bits) { str_x86def(operandText, &_REGS64[0]); } else if (ADDR_SIZE_AFFECT(dt, totalPrefixes) == Decode32Bits) { ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); str_x86def(operandText, &_REGS32[0]); } else { ps->usedPrefixes |= (totalPrefixes & INST_PRE_ADDR_SIZE); str_x86def(operandText, &_REGS16[0]); } chrcat_WS(operandText, CLOSE_CHR); break; default: return EO_HALT; } /* * It's ok if we don't update the pointers parameters when we will return EO_HALT or EO_SUFFIX, because * they are to be ignored anyways. */ ci->code = code; ci->codeLen = codeLen; ci->codeOffset = codeOffset; return EO_CONTINUE; } distorm64-1.7.30/src/operands.h0000644000175000017500000000142311013167242015161 0ustar enderender/* operands.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #ifndef OPERANDS_H #define OPERANDS_H #include "../config.h" #include "decoder.h" #include "prefix.h" #include "wstring.h" #include "instructions.h" /* Return codes from extract_operand. */ typedef enum {EO_HALT, EO_CONTINUE, EO_SUFFIX} _ExOpRCType; _ExOpRCType extract_operand(_CodeInfo* ci, _WString* instructionHex, _WString* operandText, _OpType type, _OpType op2, _OperandNumberType opNum, _iflags instFlags, unsigned int modrm, _PrefixState* ps, _DecodeType dt, int* lockableInstruction); #endif /* OPERANDS_H */ distorm64-1.7.30/src/prefix.c0000644000175000017500000003733611013167374014660 0ustar enderender/* prefix.c Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #include "prefix.h" #include "textdefs.h" #include "x86defs.h" #include "instructions.h" /* * The main purpose of this module is to keep track of all kind of prefixes a single instruction may have. * The problem is that a single instruction may have up to five different prefix-type. * That's why I have to detect such cases and drop those excess prefixes. */ int is_prefix(unsigned int ch, _DecodeType dt) { switch (ch) { /* for i in xrange(0x40, 0x50): print "case 0x%2x:" % i */ case 0x40: /* REX: */ case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: return (dt == Decode64Bits); case PREFIX_LOCK: return TRUE; case PREFIX_REPNZ: return TRUE; case PREFIX_REP: return TRUE; case PREFIX_CS: return TRUE; case PREFIX_SS: return TRUE; case PREFIX_DS: return TRUE; case PREFIX_ES: return TRUE; case PREFIX_FS: return TRUE; case PREFIX_GS: return TRUE; case PREFIX_OP_SIZE: return TRUE; case PREFIX_ADDR_SIZE: return TRUE; } return FALSE; } static const uint8_t* PREFIX_MIN(const uint8_t* a, const uint8_t* b, const uint8_t* c, const uint8_t* d, const uint8_t* def) { /* * Check for null. * Return smallest (=first good prefix to take into account). */ if (!a && !b && !c && !d) return def; if (!a) a = (const uint8_t*)~0; /* MAX PTR ? :) */ if (!b) b = (const uint8_t*)~0; if (!c) c = (const uint8_t*)~0; if (!d) d = (const uint8_t*)~0; if (b < a) a = b; if (c < a) a = c; if (d < a) a = d; return a == (const uint8_t*)~0 ? def : a; } /* Return the flag and type of given prefix. */ void get_prefix_flag(unsigned int ch, _PrefixInfo* pi, _DecodeType dt) { pi->flag = INST_FLAGS_NONE; pi->type = PRE_NONE; /* NOTE: AMD treat lock/rep as two different groups... But I am based on Intel. - Lock and Repeat: - 0xF0 — LOCK - 0xF2 — REPNE/REPNZ - 0xF3 - REP/REPE/REPZ - Segment Override: - 0x2E - CS - 0x36 - SS - 0x3E - DS - 0x26 - ES - 0x64 - FS - 0x65 - GS - Operand-Size Override: 0x66, switching default size. - Address-Size Override: 0x67, switching default size. 64 Bits: - REX: 0x40 - 0x4f, extends register access. */ switch (ch) { /* REX type, 64 bits decoding mode only: */ case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: if (dt == Decode64Bits) { pi->flag = INST_PRE_REX; pi->type = PRE_REX; } break; /* LOCK and REPx type: */ case PREFIX_LOCK: pi->flag = INST_PRE_LOCK; pi->type = PRE_LOKREP; break; case PREFIX_REPNZ: pi->flag = INST_PRE_REPNZ; pi->type = PRE_LOKREP; break; case PREFIX_REP: pi->flag = INST_PRE_REP; pi->type = PRE_LOKREP; break; /* Seg Overide type: */ case PREFIX_CS: pi->flag = INST_PRE_CS; pi->type = PRE_SEGOVRD; break; case PREFIX_SS: pi->flag = INST_PRE_SS; pi->type = PRE_SEGOVRD; break; case PREFIX_DS: pi->flag = INST_PRE_DS; pi->type = PRE_SEGOVRD; break; case PREFIX_ES: pi->flag = INST_PRE_ES; pi->type = PRE_SEGOVRD; break; case PREFIX_FS: pi->flag = INST_PRE_FS; pi->type = PRE_SEGOVRD; break; case PREFIX_GS: pi->flag = INST_PRE_GS; pi->type = PRE_SEGOVRD; break; /* Op Size type: */ case PREFIX_OP_SIZE: pi->flag = INST_PRE_OP_SIZE; pi->type = PRE_OPSIZE; break; /* Addr Size type: */ case PREFIX_ADDR_SIZE: pi->flag = INST_PRE_ADDR_SIZE; pi->type = PRE_ADDRSIZE; break; } } void decode_prefixes(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt) { /* * First thing to do, scan for prefixes, there are five types of prefixes. * There may be up to five prefixes before a single instruction, not the same type, no special order, * except REX must precede immediately the first opcode. * BTW - This is the reason why I didn't make the REP prefixes part of the instructions (STOS/SCAS/etc). * * Another thing, the instruction maximum size is 15 bytes, thus if we read more than 15 bytes, we will halt. */ _PrefixInfo pi; ps->start = code; while ((--codeLen >= 0) || (code - ps->start >= INST_MAXIMUM_SIZE)) { /* Examine what type of prefix we got. */ get_prefix_flag(*code, &pi, dt); if (pi.flag == INST_FLAGS_NONE) break; /* Halt scanning. */ /* * If we got something that is ALREADY included, * we will have to skip that many bytes 'till we get past the first occurrence. * Take a look: XYzABCUVz, the result would be: ABCUVz; XYz are being dropped (we have to skip them), * because then we would have z included twice, which is not allowed by 80x86. */ switch (pi.type) { case PRE_LOKREP: if ((ps->totalPrefixes & INST_PRE_LOKREP_MASK) != 0) { /* Is it second time we got this same type prefix? */ /* Remove all flags of this group, because we don't know which is the set one. */ ps->totalPrefixes &= ~INST_PRE_LOKREP_MASK; /* * Check whether we have to remove other types. * We remove other types if they appeared before the first repeating type. * We also have to update flags and positions. */ if (ps->segovrdPos && ps->segovrdPos < ps->lokrepPos) { /* Update flags, remove any flag that is segment override concerned. */ ps->totalPrefixes &= ~INST_PRE_SEGOVRD_MASK; ps->segovrdPos = NULL; } if (ps->opsizePos && ps->opsizePos < ps->lokrepPos) { ps->totalPrefixes &= ~INST_PRE_OP_SIZE; /* No need for mask, it's a single bit. */ ps->opsizePos = NULL; } if (ps->addrsizePos && ps->addrsizePos < ps->lokrepPos) { ps->totalPrefixes &= ~INST_PRE_ADDR_SIZE; ps->addrsizePos = NULL; } if (ps->rexpos && ps->rexpos < ps->lokrepPos) { ps->totalPrefixes &= ~INST_PRE_REX; ps->rexpos = NULL; } /* * Update current type position to last ^good^ position. * Notice we update the position ONLY after we removed dropped prefixes, so they're dropped relative to the old one. */ ps->lokrepPos = code; /* * start points to the first prefix we take into account (ignoring dropped prefixes). * Notice we do the assignment after the above if statements, because maybe they could affect the result. */ ps->start = PREFIX_MIN(ps->segovrdPos, ps->opsizePos, ps->addrsizePos, ps->rexpos, ps->lokrepPos); } else { /* Update position to first occurence. */ ps->lokrepPos = code; } /* Set flags anyways, if it's second time we cleaned the flags of this group already. */ ps->totalPrefixes |= pi.flag; break; case PRE_SEGOVRD: if ((ps->totalPrefixes & INST_PRE_SEGOVRD_MASK) != 0) { ps->totalPrefixes &= ~INST_PRE_SEGOVRD_MASK; if (ps->lokrepPos && ps->lokrepPos < ps->segovrdPos) { ps->totalPrefixes &= ~INST_PRE_LOKREP_MASK; ps->lokrepPos = NULL; } if (ps->opsizePos && ps->opsizePos < ps->segovrdPos) { ps->totalPrefixes &= ~INST_PRE_OP_SIZE; ps->opsizePos = NULL; } if (ps->addrsizePos && ps->addrsizePos < ps->segovrdPos) { ps->totalPrefixes &= ~INST_PRE_ADDR_SIZE; ps->addrsizePos = NULL; } if (ps->rexpos && ps->rexpos < ps->segovrdPos) { ps->totalPrefixes &= ~INST_PRE_REX; ps->rexpos = NULL; } ps->segovrdPos = code; ps->start = PREFIX_MIN(ps->lokrepPos, ps->opsizePos, ps->addrsizePos, ps->rexpos, ps->segovrdPos); } else { ps->segovrdPos = code; } ps->totalPrefixes |= pi.flag; break; case PRE_OPSIZE: if (ps->totalPrefixes & pi.flag) { if (ps->lokrepPos && ps->lokrepPos < ps->opsizePos) { ps->totalPrefixes &= ~INST_PRE_LOKREP_MASK; ps->lokrepPos = NULL; } if (ps->segovrdPos && ps->segovrdPos < ps->opsizePos) { ps->totalPrefixes &= ~INST_PRE_SEGOVRD_MASK; ps->segovrdPos = NULL; } if (ps->addrsizePos && ps->addrsizePos < ps->opsizePos) { ps->totalPrefixes &= ~INST_PRE_ADDR_SIZE; ps->addrsizePos = NULL; } if (ps->rexpos && ps->rexpos < ps->opsizePos) { ps->totalPrefixes &= ~INST_PRE_REX; ps->rexpos = NULL; } ps->opsizePos = code; ps->start = PREFIX_MIN(ps->lokrepPos, ps->segovrdPos, ps->addrsizePos, ps->rexpos, ps->opsizePos); } else { ps->totalPrefixes |= pi.flag; ps->opsizePos = code; } break; case PRE_ADDRSIZE: if (ps->totalPrefixes & pi.flag) { if (ps->lokrepPos && ps->lokrepPos < ps->addrsizePos) { ps->totalPrefixes &= ~INST_PRE_LOKREP_MASK; ps->lokrepPos = NULL; } if (ps->segovrdPos && ps->segovrdPos < ps->addrsizePos) { ps->totalPrefixes &= ~INST_PRE_SEGOVRD_MASK; ps->segovrdPos = NULL; } if (ps->opsizePos && ps->opsizePos < ps->addrsizePos) { ps->totalPrefixes &= ~INST_PRE_OP_SIZE; ps->opsizePos = NULL; } if (ps->rexpos && ps->rexpos < ps->addrsizePos) { ps->totalPrefixes &= ~INST_PRE_REX; ps->rexpos = NULL; } ps->addrsizePos = code; ps->start = PREFIX_MIN(ps->lokrepPos, ps->segovrdPos, ps->opsizePos, ps->rexpos, ps->addrsizePos); } else { ps->totalPrefixes |= pi.flag; ps->addrsizePos = code; } break; case PRE_REX: if (ps->totalPrefixes & pi.flag) { if (ps->lokrepPos && ps->lokrepPos < ps->rexpos) { ps->totalPrefixes &= ~INST_PRE_LOKREP_MASK; ps->lokrepPos = NULL; } if (ps->segovrdPos && ps->segovrdPos < ps->rexpos) { ps->totalPrefixes &= ~INST_PRE_SEGOVRD_MASK; ps->segovrdPos = NULL; } if (ps->opsizePos && ps->opsizePos < ps->rexpos) { ps->totalPrefixes &= ~INST_PRE_OP_SIZE; ps->opsizePos = NULL; } if (ps->addrsizePos && ps->addrsizePos < ps->rexpos) { ps->totalPrefixes &= ~INST_PRE_ADDR_SIZE; ps->addrsizePos = NULL; } ps->rexpos = code; ps->start = PREFIX_MIN(ps->lokrepPos, ps->segovrdPos, ps->opsizePos, ps->addrsizePos, ps->rexpos); } else { ps->totalPrefixes |= pi.flag; ps->rexpos = code; } break; default: return; } code++; } /* * Save last byte scanned address, so the decoder could keep on scanning from this point and on and on and on. * In addition the decoder is able to know that the last byte could lead to MMX/SSE instructions (preceding REX if exists). */ ps->last = code; /* ps->last points to the next byte following the last prefix byte! */ } /* * This function gets the prefix state of the last instruction and the total prefixes * of that instruction which we got from the code itself, * then it DB's everything which wasn't used, by looking at the instruction's prefixes we GOT * and the USED prefixes (which is returned by the extract_operand). * Finally, it returns a string of the output (unused prefixes). * Note: This function should get the valid prefixes which weren't dropped. * The Decode function deals with the dropped ones by itself. * Here is a small sample for showing a case where there are some prefixes which weren't used, and should be DB'ed. * 16 bits decoding mode: * 40 ~ INC AX * 66 40 ~ INC EAX * 66 2E 40 ~ DB 2E; INC EAX * 67 2E ~ DB 67; INC AX * The whole thing is working by using the usedPrefixes, this variable gets updated * whenever the decoder mechanism is affected by any one of the totalPrefixes prefixes. * There are a few spots in the code along some of the decoder functions which are responsible for updating the usedPrefixes. * When calling this function, you assume totalPrefixes contains all non-dropped prefixes for that instruction, * and also the usedPrefixes is filled already. */ void get_unused_prefixes_list(uint8_t unusedList[MAX_PREFIXES], _PrefixState* ps) { /* We might have 5 unused prefixes at most, up to 5 prefixes for one instruction. */ const uint8_t* ptrs[MAX_PREFIXES] = {0}; unsigned int i, j; const uint8_t* tmp = NULL; memset(unusedList, 0, MAX_PREFIXES); /* * We have to restore at this point flags that were disabled manually, because they are ignored in 64 bits. * Therefore, we will have to check whether they were set before we disabled them and now reenable them in order * to output them as unused prefixes. */ /* Check out whether the REX prefix was ignored... and reenable it, so we can see if it were used or not. */ if (ps->rexpos != NULL) { ps->totalPrefixes |= INST_PRE_REX; /* Reenable operand size prefix, so it will be dropped as unused. */ if ((ps->opsizePos != NULL) && (*ps->rexpos & PREFIX_REX_W)) ps->totalPrefixes |= INST_PRE_OP_SIZE; } /* It could be that we disabled any one of the segment overrides. */ if ((ps->segovrdPos != NULL) && ((ps->totalPrefixes & (INST_PRE_SEGOVRD_MASK)) == 0)) { /* * We have to reenable it manually. * Doesn't really matter which one we use to enable it. */ ps->totalPrefixes |= INST_PRE_CS; } /* Remove all used prefixes. */ ps->totalPrefixes &= ~ps->usedPrefixes; /* Caller function depends on this value, so it will know how many unused prefixes there are. */ ps->unusedCount = 0; /* All are used? Cool then. */ if (ps->totalPrefixes == ps->usedPrefixes) return ; /* * Determine what types of prefixes were unused. * Every type has only one pointer to that prefix. */ if (ps->totalPrefixes & INST_PRE_OP_SIZE) ptrs[ps->unusedCount++] = ps->opsizePos; if (ps->totalPrefixes & INST_PRE_ADDR_SIZE) ptrs[ps->unusedCount++] = ps->addrsizePos; if (ps->totalPrefixes & INST_PRE_LOKREP_MASK) ptrs[ps->unusedCount++] = ps->lokrepPos; if (ps->totalPrefixes & INST_PRE_SEGOVRD_MASK) ptrs[ps->unusedCount++] = ps->segovrdPos; if (ps->totalPrefixes & INST_PRE_REX) ptrs[ps->unusedCount++] = ps->rexpos; /* * Sort them, so you output them by their real order. * Bubble yak is good enough. */ for (i = 0; i < ps->unusedCount; i++) { for (j = 0; j < ps->unusedCount; j++) { if (ptrs[j] > ptrs[i]) { tmp = ptrs[j]; ptrs[j] = ptrs[i]; ptrs[i] = tmp; } } } /* Get values and store in the given array. */ for (i = 0; i < ps->unusedCount; i++) unusedList[i] = *ptrs[i]; } /* * Concatenates a string of the used segment by examining the prefixes. * Side Effects - This function will change the prefix state variables on certain cases. */ void str_seg_text(_WString* s, _PrefixState* ps, _DecodeType dt) { _iflags flags = ps->totalPrefixes & INST_PRE_SEGOVRD_MASK; /* Segment Override prefixes are ignored in 64 bits. */ if (flags == 0) return; /* 64 bits mode ignoers some prefixes. */ if (dt != Decode64Bits) { switch (flags) { case INST_PRE_CS: ps->usedPrefixes |= INST_PRE_CS; strcat_WSN(s, PREFIX_CS_TEXT); chrcat_WS(s, SEG_OFF_CHR); return; case INST_PRE_SS: ps->usedPrefixes |= INST_PRE_SS; strcat_WSN(s, PREFIX_SS_TEXT); chrcat_WS(s, SEG_OFF_CHR); return; case INST_PRE_DS: ps->usedPrefixes |= INST_PRE_DS; strcat_WSN(s, PREFIX_DS_TEXT); chrcat_WS(s, SEG_OFF_CHR); return; case INST_PRE_ES: ps->usedPrefixes |= INST_PRE_ES; strcat_WSN(s, PREFIX_ES_TEXT); chrcat_WS(s, SEG_OFF_CHR); return; } } switch (flags) { case INST_PRE_FS: ps->usedPrefixes |= INST_PRE_FS; strcat_WSN(s, PREFIX_FS_TEXT); chrcat_WS(s, SEG_OFF_CHR); return; case INST_PRE_GS: ps->usedPrefixes |= INST_PRE_GS; strcat_WSN(s, PREFIX_GS_TEXT); chrcat_WS(s, SEG_OFF_CHR); return; } } distorm64-1.7.30/src/prefix.h0000644000175000017500000000317611013167432014653 0ustar enderender/* prefix.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #ifndef PREFIX_H #define PREFIX_H #include "../config.h" #include "decoder.h" #include "wstring.h" /* * This holds the prefixes state for the current instruction we decode. * totalPrefixes includes all specific prefixes that the instruction got. * start is a pointer to the first prefix to take into account. * last is a pointer to the last byte we scanned. * Other pointers are used to keep track of prefixes positions and help us know if they appeared already and where. */ typedef struct { unsigned int unusedCount, specialPrefixesSize, isREXPrefixValid; _iflags totalPrefixes, usedPrefixes; const uint8_t *lokrepPos, *segovrdPos, *opsizePos, *addrsizePos, *rexpos, *start, *last; } _PrefixState; /* Describe the type of the prefix and which one it was in a flag manner. */ typedef enum {PRE_NONE = -1, PRE_LOKREP, PRE_SEGOVRD, PRE_OPSIZE, PRE_ADDRSIZE, PRE_REX} _PrefixType; typedef struct { _iflags flag; _PrefixType type; } _PrefixInfo; /* * Intel supports 4 types of prefixes, whereas AMD supports 5 types (lock is seperated from rep/nz). * REX is the fifth prefix type, this time I'm based on AMD64. */ #define MAX_PREFIXES (5) int is_prefix(unsigned int ch, _DecodeType dt); void decode_prefixes(const uint8_t* code, int codeLen, _PrefixState* ps, _DecodeType dt); void get_unused_prefixes_list(uint8_t unusedList[MAX_PREFIXES], _PrefixState* ps); void str_seg_text(_WString* s, _PrefixState* ps, _DecodeType dt); #endif /* PREFIX_H */ distorm64-1.7.30/src/pydistorm.c0000644000175000017500000001055311064272306015403 0ustar enderender/* pydistorm.c :[diStorm64}: Python Module Extension The ultimate disassembler library (80x86, AMD64) Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #include "decoder.h" #include "textdefs.h" #include "wstring.h" #include "pydistorm.h" /* PYTHON MODULE EXPORTS */ _DLLEXPORT_ void initdistorm() { PyObject* distormModule = Py_InitModule3("distorm", distormModulebMethods, ":[diStorm64}:"); PyModule_AddIntConstant(distormModule, "Decode16Bits", Decode16Bits); PyModule_AddIntConstant(distormModule, "Decode32Bits", Decode32Bits); PyModule_AddIntConstant(distormModule, "Decode64Bits", Decode64Bits); PyModule_AddIntConstant(distormModule, "OffsetTypeSize", sizeof(_OffsetType) * 8); PyModule_AddStringConstant(distormModule, "info", ":[diStorm64 1.7.30}:\r\nCopyright RageStorm (C) 2008, Gil Dabah \r\n\r\ndiStorm is licensed under the BSD license.\r\nhttp://ragestorm.net/distorm/\r\n"); } #define MAX_INSTRUCTIONS 1000 PyObject* distorm_Decode(PyObject* pSelf, PyObject* pArgs) { _DecodeType dt; uint8_t* code; int codeLen; _OffsetType codeOffset; _DecodeResult res = DECRES_NONE; _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; unsigned int decodedInstructionsCount = 0, i = 0, next = 0; uint8_t instructionText[MAX_TEXT_SIZE*2]; PyObject *ret = NULL, *pyObj = NULL, *dtObj = NULL; pSelf = pSelf; /* UNREFERENCED_PARAMETER */ /* Decode(int32/64 offset, string code, int type=Decode32Bits) */ if (!PyArg_ParseTuple(pArgs, _PY_OFF_INT_SIZE_ "s#|O", &codeOffset, &code, &codeLen, &dtObj)) return NULL; if (code == NULL) { PyErr_SetString(PyExc_IOError, "Error while reading code buffer."); return NULL; } if (codeLen < 0) { PyErr_SetString(PyExc_OverflowError, "Code buffer is too long."); return NULL; } /* Default parameter. */ if (dtObj == NULL) dt = Decode32Bits; else if (!PyInt_Check(dtObj)) { PyErr_SetString(PyExc_IndexError, "Third parameter must be either Decode16Bits, Decode32Bits or Decode64Bits (integer type)."); return NULL; } else dt = (_DecodeType)PyInt_AsUnsignedLongMask(dtObj); if ((dt != Decode16Bits) && (dt != Decode32Bits) && (dt != Decode64Bits)) { PyErr_SetString(PyExc_IndexError, "Decoding-type must be either Decode16Bits, Decode32Bits or Decode64Bits."); return NULL; } /* Construct an empty list, which later will be filled with tuples of (offset, size, mnemonic, hex). */ ret = PyList_New(0); if (ret == NULL) { PyErr_SetString(PyExc_MemoryError, "Not enough memory to initialize a list."); return NULL; } while (res != DECRES_SUCCESS) { res = internal_decode(codeOffset, code, codeLen, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); if ((res == DECRES_MEMORYERR) && (decodedInstructionsCount == 0)) break; for (i = 0; i < decodedInstructionsCount; i++) { if (decodedInstructions[i].mnemonic.pos > 0) { memcpy(instructionText, decodedInstructions[i].mnemonic.p, decodedInstructions[i].mnemonic.pos + 1); /* Include \0. */ if (decodedInstructions[i].operands.pos > 0) instructionText[decodedInstructions[i].mnemonic.pos] = SP_CHR; memcpy(&instructionText[decodedInstructions[i].mnemonic.pos+1], decodedInstructions[i].operands.p, decodedInstructions[i].operands.pos + 1); } else instructionText[0] = '\0'; pyObj = Py_BuildValue("(" _PY_OFF_INT_SIZE_ "bss)", decodedInstructions[i].offset, decodedInstructions[i].size, instructionText, decodedInstructions[i].instructionHex.p); if (pyObj == NULL) { Py_DECREF(ret); PyErr_SetString(PyExc_MemoryError, "Not enough memory to append an item into the list."); return NULL; } if (PyList_Append(ret, pyObj) == -1) { Py_DECREF(pyObj); Py_DECREF(ret); PyErr_SetString(PyExc_MemoryError, "Not enough memory to append an item into the list."); return NULL; } // V 1.7.25 - Memleak fixed, it is necessary to DECREF the object, because PyList_Append INCREFs it on its own. Py_DECREF(pyObj); } /* Get offset difference. */ next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - codeOffset); next += decodedInstructions[decodedInstructionsCount-1].size; /* Advance ptr and recalc offset. */ code += next; codeLen -= next; codeOffset += next; } return ret; } distorm64-1.7.30/src/pydistorm.h0000644000175000017500000000232111013167216015377 0ustar enderender/* pydistorm.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #ifndef PYDISTORM_H #define PYDISTORM_H #ifdef SUPPORT_64BIT_OFFSET /* * PyArg_ParseTuple/Py_BuildValue uses a format string in order to parse/build the offset. * type: int 64 */ #define _PY_OFF_INT_SIZE_ "K" #else #define _PY_OFF_INT_SIZE_ "k" #endif #include "decoder.h" #ifdef __GNUC__ #include #elif _MSC_VER #include #endif PyObject* distorm_Decode(PyObject* pSelf, PyObject* pArgs); char distorm_Decode_DOCSTR[] = "Disassemble a given buffer.\r\n" #ifdef SUPPORT_64BIT_OFFSET "Decode(INT64 offset, string code, int type)\r\n" #else "Decode(unsigned long offset, string code, int type)\r\n" #endif "type:\r\n" " Decode16Bits - 16 bits decoding.\r\n" " Decode32Bits - 32 bits decoding.\r\n" " Decode64Bits - AMD64 decoding.\r\n" "Returns a list of tuples of offset, size, mnemonic and hex string.\r\n"; static PyMethodDef distormModulebMethods[] = { {"Decode", distorm_Decode, METH_VARARGS, distorm_Decode_DOCSTR}, {NULL, NULL, 0, NULL} }; #endif /* PYDISTORM_H */ distorm64-1.7.30/src/textdefs.c0000644000175000017500000002501010753530316015173 0ustar enderender/* textdefs.c Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #include "textdefs.h" int8_t SEP_STR[] = ", "; /* * REMARK: The reason I use static table is to avoid dynamic allocation * and finally the manual call to "free all memory" which is irritating. * 8bits, unsigned text representation prebuilt made for optimizations. * The range it covers varies is from 0 to 256. */ int8_t TextBTable[256][4] = { /* * !!NOTE!! str_hex_sp_b is based on this elements' length. * def prebuilt(): * s = "" * for i in xrange(256): * if ((i % 0x10) == 0): * s += "\r\n" * s += "\" %02x\", " % (i) * return s */ " 00", " 01", " 02", " 03", " 04", " 05", " 06", " 07", " 08", " 09", " 0a", " 0b", " 0c", " 0d", " 0e", " 0f", " 10", " 11", " 12", " 13", " 14", " 15", " 16", " 17", " 18", " 19", " 1a", " 1b", " 1c", " 1d", " 1e", " 1f", " 20", " 21", " 22", " 23", " 24", " 25", " 26", " 27", " 28", " 29", " 2a", " 2b", " 2c", " 2d", " 2e", " 2f", " 30", " 31", " 32", " 33", " 34", " 35", " 36", " 37", " 38", " 39", " 3a", " 3b", " 3c", " 3d", " 3e", " 3f", " 40", " 41", " 42", " 43", " 44", " 45", " 46", " 47", " 48", " 49", " 4a", " 4b", " 4c", " 4d", " 4e", " 4f", " 50", " 51", " 52", " 53", " 54", " 55", " 56", " 57", " 58", " 59", " 5a", " 5b", " 5c", " 5d", " 5e", " 5f", " 60", " 61", " 62", " 63", " 64", " 65", " 66", " 67", " 68", " 69", " 6a", " 6b", " 6c", " 6d", " 6e", " 6f", " 70", " 71", " 72", " 73", " 74", " 75", " 76", " 77", " 78", " 79", " 7a", " 7b", " 7c", " 7d", " 7e", " 7f", " 80", " 81", " 82", " 83", " 84", " 85", " 86", " 87", " 88", " 89", " 8a", " 8b", " 8c", " 8d", " 8e", " 8f", " 90", " 91", " 92", " 93", " 94", " 95", " 96", " 97", " 98", " 99", " 9a", " 9b", " 9c", " 9d", " 9e", " 9f", " a0", " a1", " a2", " a3", " a4", " a5", " a6", " a7", " a8", " a9", " aa", " ab", " ac", " ad", " ae", " af", " b0", " b1", " b2", " b3", " b4", " b5", " b6", " b7", " b8", " b9", " ba", " bb", " bc", " bd", " be", " bf", " c0", " c1", " c2", " c3", " c4", " c5", " c6", " c7", " c8", " c9", " ca", " cb", " cc", " cd", " ce", " cf", " d0", " d1", " d2", " d3", " d4", " d5", " d6", " d7", " d8", " d9", " da", " db", " dc", " dd", " de", " df", " e0", " e1", " e2", " e3", " e4", " e5", " e6", " e7", " e8", " e9", " ea", " eb", " ec", " ed", " ee", " ef", " f0", " f1", " f2", " f3", " f4", " f5", " f6", " f7", " f8", " f9", " fa", " fb", " fc", " fd", " fe", " ff"}; int8_t TextHBTable[256][6] = { /* !!NOTE!! str_code_sp_hb is based on this elements' length. * def prebuilt(): * s = "" * for i in xrange(256): * if ((i % 0x10) == 0): * s += "\r\n" * s += "\" 0x%x\", " % (i) * return s */ " 0x0", " 0x1", " 0x2", " 0x3", " 0x4", " 0x5", " 0x6", " 0x7", " 0x8", " 0x9", " 0xa", " 0xb", " 0xc", " 0xd", " 0xe", " 0xf", " 0x10", " 0x11", " 0x12", " 0x13", " 0x14", " 0x15", " 0x16", " 0x17", " 0x18", " 0x19", " 0x1a", " 0x1b", " 0x1c", " 0x1d", " 0x1e", " 0x1f", " 0x20", " 0x21", " 0x22", " 0x23", " 0x24", " 0x25", " 0x26", " 0x27", " 0x28", " 0x29", " 0x2a", " 0x2b", " 0x2c", " 0x2d", " 0x2e", " 0x2f", " 0x30", " 0x31", " 0x32", " 0x33", " 0x34", " 0x35", " 0x36", " 0x37", " 0x38", " 0x39", " 0x3a", " 0x3b", " 0x3c", " 0x3d", " 0x3e", " 0x3f", " 0x40", " 0x41", " 0x42", " 0x43", " 0x44", " 0x45", " 0x46", " 0x47", " 0x48", " 0x49", " 0x4a", " 0x4b", " 0x4c", " 0x4d", " 0x4e", " 0x4f", " 0x50", " 0x51", " 0x52", " 0x53", " 0x54", " 0x55", " 0x56", " 0x57", " 0x58", " 0x59", " 0x5a", " 0x5b", " 0x5c", " 0x5d", " 0x5e", " 0x5f", " 0x60", " 0x61", " 0x62", " 0x63", " 0x64", " 0x65", " 0x66", " 0x67", " 0x68", " 0x69", " 0x6a", " 0x6b", " 0x6c", " 0x6d", " 0x6e", " 0x6f", " 0x70", " 0x71", " 0x72", " 0x73", " 0x74", " 0x75", " 0x76", " 0x77", " 0x78", " 0x79", " 0x7a", " 0x7b", " 0x7c", " 0x7d", " 0x7e", " 0x7f", " 0x80", " 0x81", " 0x82", " 0x83", " 0x84", " 0x85", " 0x86", " 0x87", " 0x88", " 0x89", " 0x8a", " 0x8b", " 0x8c", " 0x8d", " 0x8e", " 0x8f", " 0x90", " 0x91", " 0x92", " 0x93", " 0x94", " 0x95", " 0x96", " 0x97", " 0x98", " 0x99", " 0x9a", " 0x9b", " 0x9c", " 0x9d", " 0x9e", " 0x9f", " 0xa0", " 0xa1", " 0xa2", " 0xa3", " 0xa4", " 0xa5", " 0xa6", " 0xa7", " 0xa8", " 0xa9", " 0xaa", " 0xab", " 0xac", " 0xad", " 0xae", " 0xaf", " 0xb0", " 0xb1", " 0xb2", " 0xb3", " 0xb4", " 0xb5", " 0xb6", " 0xb7", " 0xb8", " 0xb9", " 0xba", " 0xbb", " 0xbc", " 0xbd", " 0xbe", " 0xbf", " 0xc0", " 0xc1", " 0xc2", " 0xc3", " 0xc4", " 0xc5", " 0xc6", " 0xc7", " 0xc8", " 0xc9", " 0xca", " 0xcb", " 0xcc", " 0xcd", " 0xce", " 0xcf", " 0xd0", " 0xd1", " 0xd2", " 0xd3", " 0xd4", " 0xd5", " 0xd6", " 0xd7", " 0xd8", " 0xd9", " 0xda", " 0xdb", " 0xdc", " 0xdd", " 0xde", " 0xdf", " 0xe0", " 0xe1", " 0xe2", " 0xe3", " 0xe4", " 0xe5", " 0xe6", " 0xe7", " 0xe8", " 0xe9", " 0xea", " 0xeb", " 0xec", " 0xed", " 0xee", " 0xef", " 0xf0", " 0xf1", " 0xf2", " 0xf3", " 0xf4", " 0xf5", " 0xf6", " 0xf7", " 0xf8", " 0xf9", " 0xfa", " 0xfb", " 0xfc", " 0xfd", " 0xfe", " 0xff"}; uint8_t Nibble2ChrTable[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; #define NIBBLE_TO_CHR Nibble2ChrTable[t] void _FASTCALL_ str_hex_b(_WString* s, unsigned int x) { /* * Skip first character (space). * Fixed length of 4 including null terminate character. Use one word copy. */ *(int16_t*)&s->p[s->pos] = *(int16_t*)(TextBTable[x & 255] + 1); s->p[s->pos + sizeof(int16_t) + 1] = '\0'; s->pos += sizeof(int16_t); } void _FASTCALL_ str_code_hb(_WString* s, unsigned int x) { x &= 255; /* Skip first character (space). */ if (x < 0x10) { /* < 0x10 has a fixed length of 4 including null terminate. */ *(int32_t*)&s->p[s->pos] = *(int32_t*)(TextHBTable[x] + 1); s->pos += sizeof(int32_t) - 1; } else { /* >= 0x10 has a fixed length of 5 including null terminate. */ *(int32_t*)&s->p[s->pos] = *(int32_t*)(TextHBTable[x] + 1); s->p[s->pos + sizeof(int32_t)] = '\0'; s->pos += sizeof(int32_t); } } void _FASTCALL_ str_hex_sp_b(_WString* s, unsigned int x) { /* Fixed length of 4 including null terminate character. Use one dword copy. */ *(int32_t*)&s->p[s->pos] = *(int32_t*)&TextBTable[x & 255]; s->pos += sizeof(int32_t) - 1; } void _FASTCALL_ str_code_sp_hb(_WString* s, unsigned int x) { x &= 255; if (x < 0x10) { /* < 0x10 has a fixed length of 5 including null terminate. */ *(int32_t*)&s->p[s->pos] = *(int32_t*)&TextHBTable[x]; s->p[s->pos + sizeof(int32_t)] = '\0'; s->pos += sizeof(int32_t) - 1; } else { /* >= 0x10 has a fixed length of 6 including null terminate. */ *(int32_t*)&s->p[s->pos] = *(int32_t*)&TextHBTable[x]; *(int16_t*)&s->p[s->pos + sizeof(int32_t)] = *(int16_t*)(TextHBTable[x] + sizeof(int32_t)); s->pos += sizeof(int32_t) + sizeof(int16_t) - 1; } } void _FASTCALL_ str_hex_sp_w(_WString* s, unsigned int x) { int8_t* buf; unsigned int t = (uint8_t)((x >> 4) & 0xf); buf = &s->p[s->pos]; s->pos += 5; buf[0] = ' '; buf[1] = NIBBLE_TO_CHR; t = x & 0xf; buf[2] = NIBBLE_TO_CHR; t = (x >> 12); buf[3] = NIBBLE_TO_CHR; t = (x >> 8) & 0xf; buf[4] = NIBBLE_TO_CHR; buf[5] = '\0'; } void _FASTCALL_ str_code_hw(_WString* s, unsigned int x) { int8_t* buf; int i = 0; unsigned int t = (uint8_t)((x >> 12) & 0xf); buf = &s->p[s->pos]; buf[0] = '0'; buf[1] = 'x'; buf += 2; if (t != 0) buf[i++] = NIBBLE_TO_CHR; t = (x >> 8) & 0xf; if (i | t) buf[i++] = NIBBLE_TO_CHR; t = (x >> 4) & 0xf; if (i | t) buf[i++] = NIBBLE_TO_CHR; t = x & 0xf; buf[i++] = NIBBLE_TO_CHR; s->pos += i + 2; buf[i] = '\0'; } void _FASTCALL_ str_hex_sp_dw(_WString* s, uint32_t x) { int8_t* buf; unsigned int t = (uint8_t)((x >> 4) & 0xf); buf = &s->p[s->pos]; s->pos += 9; buf[0] = ' '; buf[1] = NIBBLE_TO_CHR; t = x & 0xf; buf[2] = NIBBLE_TO_CHR; t = (x >> 12) & 0xf; buf[3] = NIBBLE_TO_CHR; t = (x >> 8) & 0xf; buf[4] = NIBBLE_TO_CHR; t = (x >> 20) & 0xf; buf[5] = NIBBLE_TO_CHR; t = (x >> 16) & 0xf; buf[6] = NIBBLE_TO_CHR; t = x >> 28; buf[7] = NIBBLE_TO_CHR; t = (x >> 24) & 0xf; buf[8] = NIBBLE_TO_CHR; buf[9] = '\0'; } void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x) { int8_t* buf; int i = 0, shift = 0; unsigned int t = 0; buf = &s->p[s->pos]; buf[0] = '0'; buf[1] = 'x'; buf += 2; for (shift = 28; shift != 0; shift -= 4) { t = (x >> shift) & 0xf; if (i | t) buf[i++] = NIBBLE_TO_CHR; } t = x & 0xf; buf[i++] = NIBBLE_TO_CHR; s->pos += i + 2; buf[i] = '\0'; } void _FASTCALL_ str_hex_sp_qw(_WString* s, uint8_t src[8]) { int8_t* buf; uint32_t x = RULONG(src); int t = (uint8_t)((x >> 4) & 0xf); buf = &s->p[s->pos]; s->pos += 17; buf[0] = ' '; buf[1] = NIBBLE_TO_CHR; t = x & 0xf; buf[2] = NIBBLE_TO_CHR; t = (x >> 12) & 0xf; buf[3] = NIBBLE_TO_CHR; t = (x >> 8) & 0xf; buf[4] = NIBBLE_TO_CHR; t = (x >> 20) & 0xf; buf[5] = NIBBLE_TO_CHR; t = (x >> 16) & 0xf; buf[6] = NIBBLE_TO_CHR; t = x >> 28; buf[7] = NIBBLE_TO_CHR; t = (x >> 24) & 0xf; buf[8] = NIBBLE_TO_CHR; x = RULONG(&src[sizeof(int32_t)]); t = (uint8_t)((x >> 4) & 0xf); buf[9] = NIBBLE_TO_CHR; t = x & 0xf; buf[10] = NIBBLE_TO_CHR; t = (x >> 12) & 0xf; buf[11] = NIBBLE_TO_CHR; t = (x >> 8) & 0xf; buf[12] = NIBBLE_TO_CHR; t = (x >> 20) & 0xf; buf[13] = NIBBLE_TO_CHR; t = (x >> 16) & 0xf; buf[14] = NIBBLE_TO_CHR; t = x >> 28; buf[15] = NIBBLE_TO_CHR; t = (x >> 24) & 0xf; buf[16] = NIBBLE_TO_CHR; buf[17] = '\0'; } void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]) { int8_t* buf; int i = 0, shift = 0; uint32_t x = RULONG(&src[sizeof(int32_t)]); int t; buf = &s->p[s->pos]; buf[0] = '0'; buf[1] = 'x'; buf += 2; for (shift = 28; shift != -4; shift -= 4) { t = (x >> shift) & 0xf; if (i | t) buf[i++] = NIBBLE_TO_CHR; } x = RULONG(src); for (shift = 28; shift != 0; shift -= 4) { t = (x >> shift) & 0xf; if (i | t) buf[i++] = NIBBLE_TO_CHR; } t = x & 0xf; buf[i++] = NIBBLE_TO_CHR; s->pos += i + 2; buf[i] = '\0'; } #ifdef SUPPORT_64BIT_OFFSET void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x) { int8_t* buf; int i = 0, shift = 0; OFFSET_INTEGER t = 0; buf = &s->p[s->pos]; buf[0] = '0'; buf[1] = 'x'; buf += 2; for (shift = 60; shift != 0; shift -= 4) { t = (x >> shift) & 0xf; if (i | t) buf[i++] = NIBBLE_TO_CHR; } t = x & 0xf; buf[i++] = NIBBLE_TO_CHR; s->pos += i + 2; buf[i] = '\0'; } #endif distorm64-1.7.30/src/textdefs.h0000644000175000017500000000366411013167176015213 0ustar enderender/* textdefs.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #ifndef TEXTDEFS_H #define TEXTDEFS_H #include "../config.h" #include "wstring.h" #define PLUS_DISP_CHR '+' #define MINUS_DISP_CHR '-' /* CHR0 is used for FPU, ST(i) register */ #define OPEN_CHR0 '(' #define CLOSE_CHR0 ')' #define OPEN_CHR '[' #define CLOSE_CHR ']' extern int8_t SEP_STR[3]; #define SEP_CHR ',' #define SP_CHR ' ' #define SEG_OFF_CHR ':' /* Naming Convention: * get - returns a pointer to a string. * str - concatenates to string. * hex - means the function is used for hex dump (number is padded to required size) - Little Endian output. * code - means the function is used for disassembled instruction - Big Endian output. * off - means the function is used for 64bit offset - Big Endian output. * sp - space character in front of the string. * h - '0x' in front of the string. * b - byte * w - word * dw - double word * qw - quad word * all numbers are in HEX. */ extern int8_t TextBTable[256][4]; _INLINE_ int8_t* get_hex_b(unsigned int x) { return &TextBTable[x & 255][1]; /* Skip space character. */ } void _FASTCALL_ str_hex_b(_WString* s, unsigned int x); void _FASTCALL_ str_code_hb(_WString* s, unsigned int x); void _FASTCALL_ str_hex_sp_b(_WString* s, unsigned int x); void _FASTCALL_ str_code_sp_hb(_WString* s, unsigned int x); void _FASTCALL_ str_hex_sp_w(_WString* s, unsigned int x); void _FASTCALL_ str_code_hw(_WString* s, unsigned int x); void _FASTCALL_ str_hex_sp_dw(_WString* s, uint32_t x); void _FASTCALL_ str_code_hdw(_WString* s, uint32_t x); void _FASTCALL_ str_hex_sp_qw(_WString* s, uint8_t src[8]); void _FASTCALL_ str_code_hqw(_WString* s, uint8_t src[8]); #ifdef SUPPORT_64BIT_OFFSET void _FASTCALL_ str_off64(_WString* s, OFFSET_INTEGER x); #endif #endif /* TEXTDEFS_H */ distorm64-1.7.30/src/wstring.c0000644000175000017500000000120010753530316015035 0ustar enderender/* wstring.c Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #include "wstring.h" void _FASTCALL_ strcpy_WS(_WString* s, const int8_t* buf) { s->pos = (unsigned int)strlen((const char*)buf); memcpy((int8_t*)s->p, buf, s->pos + 1); } void _FASTCALL_ strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len) { s->pos = len; memcpy((int8_t*)s->p, buf, len + 1); } void _FASTCALL_ strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len) { memcpy((int8_t*)&s->p[s->pos], buf, len + 1); s->pos += len; } distorm64-1.7.30/src/wstring.h0000644000175000017500000000230211013167144015041 0ustar enderender/* wstring.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #ifndef WSTRING_H #define WSTRING_H #include "../config.h" /* Make sure the buffer isn't overflowed. */ #define MAX_TEXT_SIZE (60) typedef struct { unsigned int pos; int8_t p[MAX_TEXT_SIZE]; } _WString; /* * Warning, this macro should be used only when the compiler knows the size of string in advance! * This macro is used in order to spare the call to strlen when the strings are known already. * Note: sizeof includes NULL terminated character. */ #define strcat_WSN(s, t) strcatlen_WS((s), (t), sizeof((t))-1) #define strcpy_WSN(s, t) strcpylen_WS((s), (t), sizeof((t))-1) void _FASTCALL_ strcpy_WS(_WString* s, const int8_t* buf); void _FASTCALL_ strcpylen_WS(_WString* s, const int8_t* buf, unsigned int len); void _FASTCALL_ strcatlen_WS(_WString* s, const int8_t* buf, unsigned int len); _INLINE_ void strclear_WS(_WString* s) { s->p[0] = '\0'; s->pos = 0; } _INLINE_ void chrcat_WS(_WString* s, uint8_t ch) { s->p[s->pos] = ch; s->p[s->pos + 1] = '\0'; s->pos += 1; } #endif /* WSTRING_H */ distorm64-1.7.30/src/x86defs.c0000644000175000017500000001330010753530360014632 0ustar enderender/* x86defs.c Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #include "x86defs.h" #include "instructions.h" /* NOTE: str_x86def is optimized to copy only 8 bytes from these strings. */ _DefText _CONDITIONS[16] = {{1, "O"}, {2, "NO"}, {1, "C"}, {2, "NC"}, {1, "Z"}, {2, "NZ"}, {2, "BE"}, {1, "A"}, {1, "S"}, {2, "NS"}, {1, "P"}, {2, "NP"}, {1, "L"}, {2, "GE"}, {2, "NG"}, {1, "G"}}; _DefText _CONDITIONS_PSEUDO[8] = {{2, "EQ"}, {2, "LT"}, {2, "LE"}, {5, "UNORD"}, {3, "NEQ"}, {3, "NLT"}, {3, "NLE"}, {3, "ORD"}}; _DefText _CREGS[CREGS_MAX] = {{3, "CR0"}, {0, ""}, {3, "CR2"}, {3, "CR3"}, {3, "CR4"}, {0, ""}, {0, ""}, {0, ""}, {3, "CR8"}}; _DefText _DREGS[DREGS_MAX] = {{3, "DR0"}, {3, "DR1"}, {3, "DR2"}, {3, "DR3"}, {0, ""}, {0, ""}, {3, "DR6"}, {3, "DR7"}}; _DefText _SREGS[SEG_REGS_MAX] = {{2, "ES"}, {2, "CS"}, {2, "SS"}, {2, "DS"}, {2, "FS"}, {2, "GS"}}; _DefText _REGS8[16] = {{2, "AL"}, {2, "CL"}, {2, "DL"}, {2, "BL"}, {2, "AH"}, {2, "CH"}, {2, "DH"}, {2, "BH"}, {3, "R8B"}, {3, "R9B"}, {4, "R10B"}, {4, "R11B"}, {4, "R12B"}, {4, "R13B"}, {4, "R14B"}, {4, "R15B"}}; _DefText _REGS8_REX[16] = {{2, "AL"}, {2, "CL"}, {2, "DL"}, {2, "BL"}, {3, "SPL"}, {3, "BPL"}, {3, "SIL"}, {3, "DIL"}, {3, "R8B"}, {3, "R9B"}, {4, "R10B"}, {4, "R11B"}, {4, "R12B"}, {4, "R13B"}, {4, "R14B"}, {4, "R15B"}}; _DefText _REGS16[16] = {{2, "AX"}, {2, "CX"}, {2, "DX"}, {2, "BX"}, {2, "SP"}, {2, "BP"}, {2, "SI"}, {2, "DI"}, {3, "R8W"}, {3, "R9W"}, {4, "R10W"}, {4, "R11W"}, {4, "R12W"}, {4, "R13W"}, {4, "R14W"}, {4, "R15W"}}; _DefText _REGS32[16] = {{3, "EAX"}, {3, "ECX"}, {3, "EDX"}, {3, "EBX"}, {3, "ESP"}, {3, "EBP"}, {3, "ESI"}, {3, "EDI"}, {3, "R8D"}, {3, "R9D"}, {4, "R10D"}, {4, "R11D"}, {4, "R12D"}, {4, "R13D"}, {4, "R14D"}, {4, "R15D"}}; _DefText _REGS64[16] = {{3, "RAX"}, {3, "RCX"}, {3, "RDX"}, {3, "RBX"}, {3, "RSP"}, {3, "RBP"}, {3, "RSI"}, {3, "RDI"}, {2, "R8"}, {2, "R9"}, {3, "R10"}, {3, "R11"}, {3, "R12"}, {3, "R13"}, {3, "R14"}, {3, "R15"}}; _DefText _REGSMMX[8] = {{3, "MM0"}, {3, "MM1"}, {3, "MM2"}, {3, "MM3"}, {3, "MM4"}, {3, "MM5"}, {3, "MM6"}, {3, "MM7"}}; _DefText _REGSSSE[16] = {{4, "XMM0"}, {4, "XMM1"}, {4, "XMM2"}, {4, "XMM3"}, {4, "XMM4"}, {4, "XMM5"}, {4, "XMM6"}, {4, "XMM7"}, {4, "XMM8"}, {4, "XMM9"}, {5, "XMM10"}, {5, "XMM11"}, {5, "XMM12"}, {5, "XMM13"}, {5, "XMM14"}, {5, "XMM15"}}; _DefText _MODS16[8] = {{6, "[BX+SI"}, {6, "[BX+DI"}, {6, "[BP+SI"}, {6, "[BP+DI"}, {3, "[SI"}, {3, "[DI"}, {3, "[BP"}, {3, "[BX"}}; _DefText _MODS32[16] = {{4, "[EAX"}, {4, "[ECX"}, {4, "[EDX"}, {4, "[EBX"}, {4, "[ESP"}, {4, "[EBP"}, {4, "[ESI"}, {4, "[EDI"}, {4, "[R8D"}, {4, "[R9D"}, {5, "[R10D"}, {5, "[R11D"}, {5, "[R12D"}, {5, "[R13D"}, {5, "[R14D"}, {5, "[R15D"}}; _DefText _MODS64[16] = {{4, "[RAX"}, {4, "[RCX"}, {4, "[RDX"}, {4, "[RBX"}, {4, "[RSP"}, {4, "[RBP"}, {4, "[RSI"}, {4, "[RDI"}, {3, "[R8"}, {3, "[R9"}, {4, "[R10"}, {4, "[R11"}, {4, "[R12"}, {4, "[R13"}, {4, "[R14"}, {4, "[R15"}}; /* There's no a base for EBP. */ _DefText _BASE32[16] = {{3, "EAX"}, {3, "ECX"}, {3, "EDX"}, {3, "EBX"}, {3, "ESP"}, {3, "EBP"}, {3, "ESI"}, {3, "EDI"}, {3, "R8D"}, {3, "R9D"}, {4, "R10D"}, {4, "R11D"}, {4, "R12D"}, {4, "R13D"}, {4, "R14D"}, {4, "R15D"}}; _DefText _BASE64[16] = {{3, "RAX"}, {3, "RCX"}, {3, "RDX"}, {3, "RBX"}, {3, "RSP"}, {3, "RBP"}, {3, "RSI"}, {3, "RDI"}, {2, "R8"}, {2, "R9"}, {3, "R10"}, {3, "R11"}, {3, "R12"}, {3, "R13"}, {3, "R14"}, {3, "R15"}}; /* There's no an index for rSP. */ _DefText _INDEX32[16] = {{3, "EAX"}, {3, "ECX"}, {3, "EDX"}, {3, "EBX"}, {0, ""}, {3, "EBP"}, {3, "ESI"}, {3, "EDI"}, {3, "R8D"}, {3, "R9D"}, {4, "R10D"}, {4, "R11D"}, {4, "R12D"}, {4, "R13D"}, {4, "R14D"}, {4, "R15D"}}; _DefText _INDEX64[16] = {{3, "RAX"}, {3, "RCX"}, {3, "RDX"}, {3, "RBX"}, {0, ""}, {3, "RBP"}, {3, "RSI"}, {3, "RDI"}, {2, "R8"}, {2, "R9"}, {3, "R10"}, {3, "R11"}, {3, "R12"}, {3, "R13"}, {3, "R14"}, {3, "R15"}}; _DefText _SCALE32[4] = {{0, ""} , {2, "*2"}, {2, "*4"}, {2, "*8"}}; int8_t FPU_STACK_TEXT[] = "ST"; int8_t ONE_CONST_TEXT[] = "0x1"; int8_t REG_RIP_TEXT[] = "RIP"; int8_t BYTE_UNDEFINED[] = "DB"; int8_t TEXT_8_BITS[] = "BYTE "; int8_t TEXT_16_BITS[] = "WORD "; int8_t TEXT_32_BITS[] = "DWORD "; int8_t TEXT_64_BITS[] = "QWORD "; int8_t TEXT_80_BITS[] = "TBYTE "; int8_t TEXT_128_BITS[] = "DQWORD "; int8_t PREFIX_LOCK_TEXT[] = "LOCK "; int8_t PREFIX_REP_TEXT[] = "REP "; int8_t PREFIX_REPNZ_TEXT[] = "REPNZ "; int8_t PREFIX_CS_TEXT[] = "CS"; int8_t PREFIX_SS_TEXT[] = "SS"; int8_t PREFIX_DS_TEXT[] = "DS"; int8_t PREFIX_ES_TEXT[] = "ES"; int8_t PREFIX_FS_TEXT[] = "FS"; int8_t PREFIX_GS_TEXT[] = "GS"; int8_t SUFFIX_SIZE_BYTE = 'B'; int8_t SUFFIX_SIZE_WORD = 'W'; int8_t SUFFIX_SIZE_DWORD = 'D'; int8_t SUFFIX_SIZE_QWORD = 'Q'; int8_t SHORT_OPERAND[] = "SHORT "; int8_t SMALL_OPERAND[] = "SMALL "; int8_t LARGE_OPERAND[] = "LARGE "; int8_t WAIT_INSTRUCTION_MNEMONIC[] = "WAIT"; _InstInfo II_arpl = {INT_INFO, ISCT_INTEGER, OT_REG16, OT_RM16, (int8_t*) "\x04" "ARPL", INST_INCLUDE_MODRM}; /* * 1.5.16 - MOVSXD is now being decoded properly, definition was incorrect. * When 0x63 is prefixed with 0x48, it becomes MOVSXD. * When 0x63 is NOT prefixed, it is MOVZXD. (Which is the same as MOV reg, reg in effectiveness, only in 64bits, of course). * Note: MOVZXD supports db 0x66 -> MOVZXDW RAX, AX. */ _InstInfoEx II_movsxd = {INT_INFO, ISCT_INTEGER, OT_RM16_32, OT_REG64, (int8_t*) "\x07" "MOVZXDW", INST_INCLUDE_MODRM | INST_USE_EXMNEMONIC | INST_USE_EXMNEMONIC2 | INST_PRE_REX | INST_64BITS, OT_NONE, OT_NONE, (int8_t*) "\x06" "MOVZXD", (int8_t*)"\x06" "MOVSXD"}; _InstInfo II_nop = {INT_INFO, ISCT_INTEGER, OT_NONE, OT_NONE, (int8_t*) "\x03" "NOP", INST_EXCLUDE_MODRM}; distorm64-1.7.30/src/x86defs.h0000644000175000017500000001050111013167276014641 0ustar enderender/* x86defs.h Copyright (C) 2003-2008 Gil Dabah, http://ragestorm.net/distorm/ This library is licensed under the BSD license. See the file COPYING. */ #ifndef X86DEFS_H #define X86DEFS_H #include "../config.h" #include "textdefs.h" #include "insts.h" #define SEG_REGS_MAX (6) #define CREGS_MAX (9) #define DREGS_MAX (8) /* * Definitions use this structure for faster copying. * str_x86def relies on this size, copying aligned dwords. */ #define DEF_TEXT_SIZE (8) typedef struct { unsigned int size; int8_t p[DEF_TEXT_SIZE]; } _DefText; extern _DefText _CONDITIONS[16]; extern _DefText _CONDITIONS_PSEUDO[8]; extern _DefText _CREGS[CREGS_MAX]; extern _DefText _DREGS[DREGS_MAX]; extern _DefText _SREGS[SEG_REGS_MAX]; extern _DefText _REGS8[16]; extern _DefText _REGS8_REX[16]; extern _DefText _REGS16[16]; extern _DefText _REGS32[16]; extern _DefText _REGS64[16]; extern _DefText _REGSMMX[8]; extern _DefText _REGSSSE[16]; extern _DefText _MODS16[8]; extern _DefText _MODS32[16]; extern _DefText _MODS64[16]; extern _DefText _BASE32[16]; extern _DefText _BASE64[16]; extern _DefText _INDEX32[16]; extern _DefText _INDEX64[16]; extern _DefText _SCALE32[4]; extern int8_t FPU_STACK_TEXT[3]; extern int8_t ONE_CONST_TEXT[4]; extern int8_t REG_RIP_TEXT[4]; extern int8_t BYTE_UNDEFINED[3]; extern int8_t TEXT_8_BITS[6]; extern int8_t TEXT_16_BITS[6]; extern int8_t TEXT_32_BITS[7]; extern int8_t TEXT_64_BITS[7]; extern int8_t TEXT_80_BITS[7]; extern int8_t TEXT_128_BITS[8]; extern int8_t PREFIX_LOCK_TEXT[6]; extern int8_t PREFIX_REP_TEXT[5]; extern int8_t PREFIX_REPNZ_TEXT[7]; extern int8_t PREFIX_CS_TEXT[3]; extern int8_t PREFIX_SS_TEXT[3]; extern int8_t PREFIX_DS_TEXT[3]; extern int8_t PREFIX_ES_TEXT[3]; extern int8_t PREFIX_FS_TEXT[3]; extern int8_t PREFIX_GS_TEXT[3]; extern int8_t SUFFIX_SIZE_BYTE; extern int8_t SUFFIX_SIZE_WORD; extern int8_t SUFFIX_SIZE_DWORD; extern int8_t SUFFIX_SIZE_QWORD; extern int8_t SHORT_OPERAND[7]; extern int8_t SMALL_OPERAND[7]; extern int8_t LARGE_OPERAND[7]; /* Maximum instruction size, including prefixes */ #define INST_MAXIMUM_SIZE (15) /* Maximum range of imm8 (comparison type) of special SSE instructions. */ #define INST_CMP_MAX_RANGE (8) /* Wait instruction byte code */ #define WAIT_INSTRUCTION_CODE (0x9b) extern int8_t WAIT_INSTRUCTION_MNEMONIC[5]; /* * Minimal MODR/M value of divided instructions. * It's 0xc0, two msb bits set, which indicates a general purpose register is used too. */ #define INST_DIVIDED_MODRM (0xc0) /* This is the escape byte value used for 3DNow! instructions. */ #define _3DNOW_ESCAPE_BYTE (0x0f) #define PREFIX_LOCK (0xf0) #define PREFIX_REPNZ (0xf2) #define PREFIX_REP (0xf3) #define PREFIX_CS (0x2e) #define PREFIX_SS (0x36) #define PREFIX_DS (0x3e) #define PREFIX_ES (0x26) #define PREFIX_FS (0x64) #define PREFIX_GS (0x65) #define PREFIX_OP_SIZE (0x66) #define PREFIX_ADDR_SIZE (0x67) /* REX prefix value range, 64 bits mode decoding only. */ #define PREFIX_REX_LOW (0x40) #define PREFIX_REX_HI (0x4f) /* In otder to use the extended GPR's we have to add 8 to the Modr/M info values. */ #define REX_GPR_BASE (8) /* Mask for REX features: */ /* Base */ #define PREFIX_REX_B (1) /* Index */ #define PREFIX_REX_X (2) /* Register */ #define PREFIX_REX_R (4) /* Operand Width */ #define PREFIX_REX_W (8) /* * The locate_inst will return on of these two instructions according to the specified decoding mode. * ARPL or MOVSXD on 64 bits is one byte instruction at index 0x63. */ #define INST_ARPL_INDEX (0x63) extern _InstInfo II_arpl; extern _InstInfoEx II_movsxd; /* * The NOP instruction can be prefixed by REX in 64bits, therefore we have to decide in runtime whether it's an XCHG or NOP instruction. * If 0x90 is prefixed by a useable REX it will become XCHG, otherwise it will become a NOP. */ #define INST_NOP_INDEX (0x90) extern _InstInfo II_nop; _INLINE_ void str_x86def(_WString* s, _DefText* d) { /* * Copy 2 aligned dwords to speed up things. * _WString should have that extra space, most of the times it will simply copy null-termianting characters. */ *(int32_t*)&s->p[s->pos] = *(int32_t*)d->p; *(int32_t*)&s->p[s->pos + sizeof(int32_t)] = *(int32_t*)&d->p[sizeof(int32_t)]; s->pos += d->size; } #endif /* X86DEFS_H */ distorm64-1.7.30/win32proj/0000755000175000017500000000000011065513456014254 5ustar enderenderdistorm64-1.7.30/win32proj/disasm.sln0000644000175000017500000000154710611346654016261 0ustar enderenderMicrosoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "disasm", "disasm.vcproj", "{91227BA8-F7EB-43CC-8C4A-A4944C00567B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Debug|Win32.ActiveCfg = Debug|Win32 {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Debug|Win32.Build.0 = Debug|Win32 {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Release|Win32.ActiveCfg = Release|Win32 {91227BA8-F7EB-43CC-8C4A-A4944C00567B}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal distorm64-1.7.30/win32proj/disasm.vcproj0000644000175000017500000001002211032007610016734 0ustar enderender distorm64-1.7.30/win32proj/main.cpp0000644000175000017500000001247011032006640015672 0ustar enderender// diStorm64 library sample // http://ragestorm.net/distorm/ // Arkon, Stefan, 2005 #include #include #include #include #include "../distorm.h" // Link the library into our project. #pragma comment(lib, "../distorm.lib") // The number of the array of instructions the decoder function will use to return the disassembled instructions. // Play with this value for performance... #define MAX_INSTRUCTIONS (1000) int main(int argc, char **argv) { // Version of used compiled library. unsigned long dver = 0; // Holds the result of the decoding. _DecodeResult res; // Decoded instruction information. _DecodedInst decodedInstructions[MAX_INSTRUCTIONS]; // next is used for instruction's offset synchronization. // decodedInstructionsCount holds the count of filled instructions' array by the decoder. unsigned int decodedInstructionsCount = 0, i, next; // Default decoding mode is 32 bits, could be set by command line. _DecodeType dt = Decode32Bits; // Default offset for buffer is 0, could be set in command line. _OffsetType offset = 0; char* errch = NULL; // Index to file name in argv. int param = 1; // Handling file. HANDLE file; DWORD filesize, bytesread; // Buffer to disassemble. unsigned char *buf, *buf2; // Disassembler version. dver = distorm_version(); printf("diStorm version: %d.%d.%d\n", (dver >> 16), ((dver) >> 8) & 0xff, dver & 0xff); // Check params. if (argc < 2 || argc > 4) { printf("Usage: disasm.exe [-b16] [-b64] filename [memory offset]\r\nRaw disassembler output.\r\nMemory offset is origin of binary file in memory (address in hex).\r\nDefault decoding mode is -b32.\r\nexample: disasm -b16 demo.com 789a\r\n"); return -1; } if (strncmp(argv[param], "-b16", 4) == 0) { dt = Decode16Bits; param++; } else if (strncmp(argv[param], "-b64", 4) == 0) { dt = Decode64Bits; param++; } else if (*argv[param] == '-') { printf("Decoding mode size isn't specified!"); return -1; } else if (argc == 4) { printf("Too many parameters are set."); return -1; } if (param >= argc) { printf("Filename is missing."); return -1; } if (param + 1 == argc-1) { // extra param? #ifdef SUPPORT_64BIT_OFFSET offset = _strtoui64(argv[param + 1], &errch, 16); #else offset = strtoul(argv[param + 1], &errch, 16); #endif if (*errch != '\0') { printf("Offset couldn't be converted."); return -1; } } file = CreateFile(argv[param], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file == INVALID_HANDLE_VALUE) { printf("Could not open file %s (error %d)\n", argv[param], GetLastError()); return -2; } if ((filesize = GetFileSize(file, NULL)) < 0) { printf("Error getting filesize (error %d)\n", GetLastError()); CloseHandle(file); return -3; } // We read the whole file into memory in order to make life easier, // otherwise we would have to synchronize the code buffer as well (so instructions won't be split). buf2 = buf = (unsigned char*)malloc(filesize); if (!ReadFile(file, buf, filesize, &bytesread, NULL)) { printf("Error reading file (error %d)\n", GetLastError()); CloseHandle(file); free(buf); return -3; } if (filesize != bytesread) { printf("Internal read-error in system\n"); CloseHandle(file); free(buf); return -3; } CloseHandle(file); printf("bits: %d\nfilename: %s\norigin: ", dt == Decode16Bits ? 16 : dt == Decode32Bits ? 32 : 64, argv[param]); #ifdef SUPPORT_64BIT_OFFSET if (dt != Decode64Bits) printf("%08I64x\n", offset); else printf("%016I64x\n", offset); #else printf("%08x\n", offset); #endif // Decode the buffer at given offset (virtual address). while (1) { // If you get an unresolved external symbol linker error for the following line, // change the SUPPORT_64BIT_OFFSET in distorm.h. res = distorm_decode(offset, (const unsigned char*)buf, filesize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount); if (res == DECRES_INPUTERR) { // Null buffer? Decode type not 16/32/64? printf("Input error, halting!"); free(buf2); return -4; } for (i = 0; i < decodedInstructionsCount; i++) { #ifdef SUPPORT_64BIT_OFFSET printf("%0*I64x (%02d) %-24s %s%s%s\r\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); #else printf("%08x (%02d) %-24s %s%s%s\r\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p); #endif } if (res == DECRES_SUCCESS) break; // All instructions were decoded. else if (decodedInstructionsCount == 0) break; // Synchronize: next = (unsigned long)(decodedInstructions[decodedInstructionsCount-1].offset - offset); next += decodedInstructions[decodedInstructionsCount-1].size; // Advance ptr and recalc offset. buf += next; filesize -= next; offset += next; } // Release buffer free(buf2); return 0; } distorm64-1.7.30/build/0000755000175000017500000000000011065513456013516 5ustar enderenderdistorm64-1.7.30/build/dmc/0000755000175000017500000000000011065513456014261 5ustar enderenderdistorm64-1.7.30/build/dmc/make.bat0000644000175000017500000000074610665672664015711 0ustar enderenderset DMCPATH=C:\dm\bin "%DMCPATH%\dmc" -c -DSUPPORT_64BIT_OFFSET ../../src/x86defs.c ../../src/wstring.c ../../src/textdefs.c ../../src/prefix.c ../../src/operands.c ../../src/insts.c ../../src/instructions.c ../../src/distorm.c ../../src/decoder.c "%DMCPATH%\lib" -n -c distorm.lib x86defs.obj wstring.obj textdefs.obj prefix.obj operands.obj insts.obj instructions.obj distorm.obj decoder.obj "%DMCPATH%\dmc" ../../linuxproj/main.c distorm.lib -o disasm.exe del *.obj;*.map;*.lib distorm64-1.7.30/build/dmc/README0000644000175000017500000000111710665474616015152 0ustar enderenderhttp://ragestorm.net/distorm/ Gil Dabah, Larry Lee Aug 2007 Support for Digital Mars Compiler (DOS/Windows) Make sure the DMCPATH variable is set to the DMC\Bin directory. The make.bat will create the disasm.exe of the linux project. I prefered to compile a library since it will make the compilation of the linux project easier. So you only have to link it with the created library. Thus it's a two-steps compilation/linkage. If you want to port it to other platforms, it should be easy now that you got where to start from, just change the make file and output file name... distorm64-1.7.30/build/linux/0000755000175000017500000000000011065513456014655 5ustar enderenderdistorm64-1.7.30/build/linux/instpython.sh0000644000175000017500000000207610337501002017416 0ustar enderender#!/bin/bash # # instpython.sh, Install .so into Python Library # # # Check for libdistorm64.so in given Directory # if [ ! -f libdistorm64.so ]; then echo "*** Error: Can't find libdistorm64.so!" exit 0 fi # # Lookup 'python' # PYTHONDIRS=`whereis python | awk -F ": " '{ print $2 }'` if [ -z "$PYTHONDIRS" ]; then echo "*** Error: Can't find Python at all!" exit 0 fi # # Go through result, looking for 'lib' # FOUND=0 for PDIR in $PYTHONDIRS; do echo $PDIR | grep "lib" > /dev/null # # Found lib Directory! # if [ $? == 0 ]; then # # Check if it include 'lib-dynload/' sub-directory # if [ -d $PDIR/lib-dynload/ ]; then FOUND=1 break fi fi done # # Found it? # if [ $FOUND == 0 ]; then echo "*** Error: Can't find Python 'lib' or 'lib/lib-dynload/' directory!" exit 0 fi # # Copy it # cp libdistorm64.so $PDIR/lib-dynload/distorm.so 2> /dev/null # # Everything went well? # if [ $? == 1 ]; then echo "*** Error: Unable to copy libdistorm64.so to $PDIR/lib-dynload, Permission denied?" exit 0 fi # # Done. # echo "* Done!" exit 1 distorm64-1.7.30/build/linux/Makefile0000644000175000017500000000165110727457120016317 0ustar enderender# # diStorm64 (Linux Port) # TARGET = libdistorm64.so COBJS = ../../src/x86defs.o ../../src/wstring.o ../../src/textdefs.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/distorm.o ../../src/decoder.o PYOBJS = ../../src/x86defs.o ../../src/wstring.o ../../src/textdefs.o ../../src/pydistorm.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/decoder.o CC = gcc CFLAGS = -O2 -Wall -fPIC -DSUPPORT_64BIT_OFFSET -D_DLL all: clib py clean: /bin/rm -rf ../../src/*.o ${TARGET} ../../distorm64.a clib: ${COBJS} ${CC} ${CFLAGS} ${VERSION} ${COBJS} -fPIC -shared -o ${TARGET} ar rs ../../distorm64.a ${COBJS} py: ${PYOBJS} ${CC} ${CFLAGS} ${VERSION} ${PYOBJS} -fPIC -shared -o ${TARGET} install: libdistorm64.so install -s ${TARGET} /usr/local/lib @echo "... running ldconfig might be smart ..." .c.o: ${CC} ${CFLAGS} ${VERSION} -c $< -o $@ distorm64-1.7.30/build/mac/0000755000175000017500000000000011065513456014256 5ustar enderenderdistorm64-1.7.30/build/mac/instpython.sh0000644000175000017500000000116010754767304017036 0ustar enderender#!/bin/bash # # instpython.sh, Install .so into Python2.3 Library # # # Check for libdistorm64.so in given Directory # if [ ! -f libdistorm64.dylib ]; then echo "*** Error: Can't find libdistorm64.dylib!" exit 0 fi # # Copy it # cp libdistorm64.so /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.5/lib-dynload/distorm.so 2> /dev/null # # Everything went well? # if [ $? == 1 ]; then echo "*** Error: Unable to copy libdistorm64.so to /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.5/lib-dynload, Permission denied?" exit 0 fi # # Done. # echo "* Done!" exit 1 distorm64-1.7.30/build/mac/Makefile0000644000175000017500000000160410727457134015723 0ustar enderender# # diStorm64 (Mac Port) # TARGET = libdistorm64.dylib COBJS = ../../src/x86defs.o ../../src/wstring.o ../../src/textdefs.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/distorm.o ../../src/decoder.o PYOBJS = ../../src/x86defs.o ../../src/wstring.o ../../src/textdefs.o ../../src/pydistorm.o ../../src/prefix.o ../../src/operands.o ../../src/insts.o ../../src/instructions.o ../../src/decoder.o CC = gcc CFLAGS = -O2 -Wall -fPIC -DSUPPORT_64BIT_OFFSET -D_DLL -I/System/Library/Frameworks/Python.framework/Headers all: clib py clean: /bin/rm -rf ../../src/*.o ${TARGET} ../../distorm64.dylib clib: ${COBJS} ${CC} ${CFLAGS} ${VERSION} ${COBJS} -fPIC -dynamiclib -o ${TARGET} ar rs ../../distorm64.a ${COBJS} py: ${PYOBJS} ${CC} ${CFLAGS} ${VERSION} ${PYOBJS} -fPIC -dynamiclib -o ${TARGET} -lpython .c.o: ${CC} ${CFLAGS} ${VERSION} -c $< -o $@ distorm64-1.7.30/build/tcc/0000755000175000017500000000000011065513456014267 5ustar enderenderdistorm64-1.7.30/build/tcc/make.bat0000644000175000017500000000046010662202704015665 0ustar enderenderset tccroot=c:\tcc\ "%tccroot%tcc\tcc.exe" "-I%tccroot%include" "-L%tccroot%lib" ../../src/x86defs.c ../../src/wstring.c ../../src/textdefs.c ../../src/prefix.c ../../src/operands.c ../../src/insts.c ../../src/instructions.c ../../src/distorm.c ../../src/decoder.c ../../linuxproj/main.c -o disasm.exe distorm64-1.7.30/build/tcc/README0000644000175000017500000000064310665473570015161 0ustar enderenderhttp://ragestorm.net/distorm/ Gil Dabah Aug 2007 Support for Tiny C Compiler (DOS/Windows) Set the path of TCC inside make.bat and then run it. Since you cannot compile a library with TCC, you have to build diStorm itself with the linuxproj directly along. Note that since TCC is buggy and is abandoned by the original author, I changed some code so it will be compiled well with the official version of TCC. distorm64-1.7.30/build/watcom/0000755000175000017500000000000011065513456015010 5ustar enderenderdistorm64-1.7.30/build/watcom/make.bat0000644000175000017500000000120410665671654016424 0ustar enderenderset watcom=c:\watcom "%watcom%\binnt\cl386" -O2 -c -DSUPPORT_64BIT_OFFSET ../../src/x86defs.c ../../src/wstring.c ../../src/textdefs.c ../../src/prefix.c ../../src/operands.c ../../src/insts.c ../../src/instructions.c ../../src/distorm.c ../../src/decoder.c -I%watcom%\h "%watcom%\binnt\lib386" -out:distorm.lib x86defs.obj wstring.obj textdefs.obj prefix.obj operands.obj insts.obj instructions.obj distorm.obj decoder.obj "%watcom%\binnt\cl386" -O2 -c ../../linuxproj/main.c -I%watcom%\h set path=%path%;%watcom%\binnt\ "%watcom%\binnt\wlink" FILE main.obj LIBRARY distorm.lib NAME disasm.exe OPTION STACK=512K del *.obj;*.lib;*.map distorm64-1.7.30/build/watcom/README0000644000175000017500000000120710665474374015702 0ustar enderenderhttp://ragestorm.net/distorm/ JvW, Gil Dabah 2007 Support for OpenWatcom Make sure the watcom variable, which must be set, points to the correct full path of the installed Watcom\ directory. The make.bat will create the disasm.exe of the linux project. I prefered to compile a library since it will make the compilation of the linux project easier. So you only have to link it with the created library. Thus it's a two-steps compilation/linkage. It can easily be changed to support other platforms but Windows. For now I chose to omit them and try to make the support as easy as possible. If you need further help just let me know. distorm64-1.7.30/build/win32/0000755000175000017500000000000011065513456014460 5ustar enderenderdistorm64-1.7.30/build/win32/cdistorm.vcproj0000644000175000017500000000664011015162664017533 0ustar enderender distorm64-1.7.30/build/win32/distorm.sln0000644000175000017500000000555411015163772016665 0ustar enderenderMicrosoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libdistorm", "cdistorm.vcproj", "{15051CE1-AB10-4239-973D-01B84F2AD0A9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pydistorm", "pydistorm.vcproj", "{E96298DA-D2F7-4619-BA93-26CCDBD13DDA}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dyndistorm", "dyndistorm.vcproj", "{3AC89F45-A773-435F-B001-012180AC4CBB}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution clib|Win32 = clib|Win32 dll|Win32 = dll|Win32 py23|Win32 = py23|Win32 py24|Win32 = py24|Win32 py25|Win32 = py25|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {15051CE1-AB10-4239-973D-01B84F2AD0A9}.clib|Win32.ActiveCfg = clib|Win32 {15051CE1-AB10-4239-973D-01B84F2AD0A9}.clib|Win32.Build.0 = clib|Win32 {15051CE1-AB10-4239-973D-01B84F2AD0A9}.dll|Win32.ActiveCfg = clib|Win32 {15051CE1-AB10-4239-973D-01B84F2AD0A9}.dll|Win32.Build.0 = clib|Win32 {15051CE1-AB10-4239-973D-01B84F2AD0A9}.py23|Win32.ActiveCfg = clib|Win32 {15051CE1-AB10-4239-973D-01B84F2AD0A9}.py24|Win32.ActiveCfg = clib|Win32 {15051CE1-AB10-4239-973D-01B84F2AD0A9}.py25|Win32.ActiveCfg = clib|Win32 {15051CE1-AB10-4239-973D-01B84F2AD0A9}.py25|Win32.Build.0 = clib|Win32 {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.clib|Win32.ActiveCfg = py23|Win32 {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.dll|Win32.ActiveCfg = py25|Win32 {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.dll|Win32.Build.0 = py25|Win32 {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py23|Win32.ActiveCfg = py23|Win32 {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py23|Win32.Build.0 = py23|Win32 {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py24|Win32.ActiveCfg = py24|Win32 {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py24|Win32.Build.0 = py24|Win32 {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py25|Win32.ActiveCfg = py25|Win32 {E96298DA-D2F7-4619-BA93-26CCDBD13DDA}.py25|Win32.Build.0 = py25|Win32 {3AC89F45-A773-435F-B001-012180AC4CBB}.clib|Win32.ActiveCfg = dll|Win32 {3AC89F45-A773-435F-B001-012180AC4CBB}.clib|Win32.Build.0 = dll|Win32 {3AC89F45-A773-435F-B001-012180AC4CBB}.dll|Win32.ActiveCfg = dll|Win32 {3AC89F45-A773-435F-B001-012180AC4CBB}.dll|Win32.Build.0 = dll|Win32 {3AC89F45-A773-435F-B001-012180AC4CBB}.py23|Win32.ActiveCfg = dll|Win32 {3AC89F45-A773-435F-B001-012180AC4CBB}.py23|Win32.Build.0 = dll|Win32 {3AC89F45-A773-435F-B001-012180AC4CBB}.py24|Win32.ActiveCfg = dll|Win32 {3AC89F45-A773-435F-B001-012180AC4CBB}.py24|Win32.Build.0 = dll|Win32 {3AC89F45-A773-435F-B001-012180AC4CBB}.py25|Win32.ActiveCfg = dll|Win32 {3AC89F45-A773-435F-B001-012180AC4CBB}.py25|Win32.Build.0 = dll|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal distorm64-1.7.30/build/win32/dyndistorm.vcproj0000644000175000017500000000772611063105050020076 0ustar enderender distorm64-1.7.30/build/win32/main.py0000644000175000017500000000304210764327410015753 0ustar enderenderimport distorm import binascii import random import time def decode16(hexcode): print "-----------------------Decode16Bits-----------------------" lines = distorm.Decode(0x100, binascii.unhexlify(hexcode), distorm.Decode16Bits) for i in lines: print "0x%08x (%02x) %-20s '%s'" % (i[0], i[1], i[3], i[2]) print def decode32(hexcode): print "-----------------------Decode32Bits-----------------------" lines = distorm.Decode(0x100, binascii.unhexlify(hexcode), distorm.Decode32Bits) for i in lines: print "0x%08x (%02x) %-20s '%s'" % (i[0], i[1], i[3], i[2]) print def decode64(hexcode): print "-----------------------Decode64Bits-----------------------" lines = distorm.Decode(0x100, binascii.unhexlify(hexcode), distorm.Decode64Bits) for i in lines: print "0x%08x (%02x) %-20s '%s'" % (i[0], i[1], i[3], i[2]) print def main(): print distorm.info hexcode = "658d00" decode16(hexcode) decode32(hexcode) decode64(hexcode) def main_old(): print distorm.info hexcode = "" random.seed(9879877) print "start generating: %s" % time.asctime(time.localtime()) for i in xrange(1024): hexcode += chr(random.randint(0, 255)) print "start unpacking: %s" % time.asctime(time.localtime()) hexcode *= (1024*5) print "start decoding: %s" % time.asctime(time.localtime()) lines = distorm.Decode(0x55551, hexcode, distorm.Decode32Bits) print "end: %s" % time.asctime(time.localtime()) for i in lines: print "0x%08x (%02x) %-20s '%s'" % (i[0], i[1], i[3], i[2]) #main_old() main() raw_input() distorm64-1.7.30/build/win32/pydistorm.vcproj0000644000175000017500000002076610764334264017755 0ustar enderender distorm64-1.7.30/build/win32/resource.h0000644000175000017500000000062210250452036016447 0ustar enderender//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by resource.rc // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1001 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif distorm64-1.7.30/build/win32/resource.rc0000644000175000017500000000436211064272456016643 0ustar enderender// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 2,1,7,30 PRODUCTVERSION 2,1,7,30 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x4L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "diStorm module" VALUE "FileVersion", "2, 1, 7, 30" VALUE "InternalName", "diStorm64" VALUE "LegalCopyright", "Gil Dabah Copyright (C) 2008" VALUE "OriginalFilename", "distorm.pyd" VALUE "ProductName", ":[diStorm64}:" VALUE "ProductVersion", "2, 1, 7, 30" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED