├── .gitignore ├── Makefile ├── asmx86.c ├── asmx86.h ├── asmx86.sln ├── asmx86.vcxproj ├── asmx86.vcxproj.filters ├── asmx86str.h ├── codegenx86.h ├── makeopstr.py └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.sdf 4 | *.suo 5 | Debug/ 6 | Release/ 7 | x64/ 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -std=gnu99 -Wall -Wshadow -Wimplicit -Wunused -Wstrict-aliasing=2 3 | 4 | all: libasmx86.a 5 | 6 | asmx86str.h: makeopstr.py asmx86.h 7 | python makeopstr.py asmx86.h asmx86str.h 8 | 9 | asmx86.o: asmx86.c asmx86.h asmx86str.h 10 | $(CC) $(CFLAGS) -O3 -fPIC -o asmx86.o -c asmx86.c 11 | 12 | libasmx86.a: asmx86.o 13 | rm -f libasmx86.a 14 | ar rc libasmx86.a asmx86.o 15 | 16 | clean: 17 | rm -rf *.o *.a 18 | -------------------------------------------------------------------------------- /asmx86.c: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006-2015, Rusty Wagner 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without modification, are permitted provided that 5 | // the following conditions are met: 6 | // 7 | // * Redistributions of source code must retain the above copyright notice, this list of conditions and the 8 | // following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 10 | // the following disclaimer in the documentation and/or other materials provided with the distribution. 11 | // 12 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 13 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 14 | // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 15 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 16 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 17 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 18 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 19 | // POSSIBILITY OF SUCH DAMAGE. 20 | 21 | #include 22 | #include "asmx86.h" 23 | 24 | #define DEC_FLAG_LOCK 0x0020 25 | #define DEC_FLAG_REP 0x0040 26 | #define DEC_FLAG_REP_COND 0x0080 27 | #define DEC_FLAG_BYTE 0x0100 28 | #define DEC_FLAG_FLIP_OPERANDS 0x0200 29 | #define DEC_FLAG_IMM_SX 0x0400 30 | #define DEC_FLAG_INC_OPERATION_FOR_64 0x0800 31 | #define DEC_FLAG_OPERATION_OP_SIZE 0x1000 32 | #define DEC_FLAG_FORCE_16BIT 0x2000 33 | #define DEC_FLAG_INVALID_IN_64BIT 0x4000 34 | #define DEC_FLAG_DEFAULT_TO_64BIT 0x8000 35 | 36 | #define DEC_FLAG_REG_RM_SIZE_MASK 0x03 37 | #define DEC_FLAG_REG_RM_2X_SIZE 0x01 38 | #define DEC_FLAG_REG_RM_FAR_SIZE 0x02 39 | #define DEC_FLAG_REG_RM_NO_SIZE 0x03 40 | 41 | 42 | #ifdef __cplusplus 43 | namespace x86 44 | { 45 | #endif 46 | enum RepPrefix 47 | { 48 | REP_PREFIX_NONE = 0, 49 | REP_PREFIX_REPNE, 50 | REP_PREFIX_REPE 51 | }; 52 | #ifndef __cplusplus 53 | typedef enum RepPrefix RepPrefix; 54 | #endif 55 | 56 | struct DecodeState 57 | { 58 | Instruction* result; 59 | InstructionOperand* operand0; 60 | InstructionOperand* operand1; 61 | const uint8_t* opcodeStart; 62 | const uint8_t* opcode; 63 | uint64_t addr; 64 | size_t len, origLen; 65 | uint16_t opSize, finalOpSize, addrSize; 66 | uint32_t flags; 67 | bool invalid; 68 | bool insufficientLength; 69 | bool opPrefix; 70 | RepPrefix rep; 71 | bool using64, rex; 72 | bool rexRM1, rexRM2, rexReg; 73 | int64_t* ripRelFixup; 74 | }; 75 | #ifndef __cplusplus 76 | typedef struct DecodeState DecodeState; 77 | #endif 78 | 79 | #include "asmx86str.h" 80 | 81 | typedef void (*DecodingFunction)(DecodeState* state); 82 | 83 | static void InvalidDecode(DecodeState* state); 84 | static void DecodeTwoByte(DecodeState* state); 85 | static void DecodeFpu(DecodeState* state); 86 | static void DecodeNoOperands(DecodeState* state); 87 | static void DecodeRegRM(DecodeState* state); 88 | static void DecodeRegRMImm(DecodeState* state); 89 | static void DecodeRMRegImm8(DecodeState* state); 90 | static void DecodeRMRegCL(DecodeState* state); 91 | static void DecodeEaxImm(DecodeState* state); 92 | static void DecodePushPopSeg(DecodeState* state); 93 | static void DecodeOpReg(DecodeState* state); 94 | static void DecodeEaxOpReg(DecodeState* state); 95 | static void DecodeOpRegImm(DecodeState* state); 96 | static void DecodeNop(DecodeState* state); 97 | static void DecodeImm(DecodeState* state); 98 | static void DecodeImm16Imm8(DecodeState* state); 99 | static void DecodeEdiDx(DecodeState* state); 100 | static void DecodeDxEsi(DecodeState* state); 101 | static void DecodeRelImm(DecodeState* state); 102 | static void DecodeRelImmAddrSize(DecodeState* state); 103 | static void DecodeGroupRM(DecodeState* state); 104 | static void DecodeGroupRMImm(DecodeState* state); 105 | static void DecodeGroupRMImm8V(DecodeState* state); 106 | static void DecodeGroupRMOne(DecodeState* state); 107 | static void DecodeGroupRMCl(DecodeState* state); 108 | static void DecodeGroupF6F7(DecodeState* state); 109 | static void DecodeGroupFF(DecodeState* state); 110 | static void DecodeGroup0F00(DecodeState* state); 111 | static void DecodeGroup0F01(DecodeState* state); 112 | static void DecodeGroup0FAE(DecodeState* state); 113 | static void Decode0FB8(DecodeState* state); 114 | static void DecodeRMSRegV(DecodeState* state); 115 | static void DecodeRM8(DecodeState* state); 116 | static void DecodeRMV(DecodeState* state); 117 | static void DecodeFarImm(DecodeState* state); 118 | static void DecodeEaxAddr(DecodeState* state); 119 | static void DecodeEdiEsi(DecodeState* state); 120 | static void DecodeEdiEax(DecodeState* state); 121 | static void DecodeEaxEsi(DecodeState* state); 122 | static void DecodeAlEbxAl(DecodeState* state); 123 | static void DecodeEaxImm8(DecodeState* state); 124 | static void DecodeEaxDx(DecodeState* state); 125 | static void Decode3DNow(DecodeState* state); 126 | static void DecodeSSETable(DecodeState* state); 127 | static void DecodeSSETableImm8(DecodeState* state); 128 | static void DecodeSSETableMem8(DecodeState* state); 129 | static void DecodeSSE(DecodeState* state); 130 | static void DecodeSSESingle(DecodeState* state); 131 | static void DecodeSSEPacked(DecodeState* state); 132 | static void DecodeMMX(DecodeState* state); 133 | static void DecodeMMXSSEOnly(DecodeState* state); 134 | static void DecodeMMXGroup(DecodeState* state); 135 | static void DecodePinsrw(DecodeState* state); 136 | static void DecodeRegCR(DecodeState* state); 137 | static void DecodeMovSXZX8(DecodeState* state); 138 | static void DecodeMovSXZX16(DecodeState* state); 139 | static void DecodeMem16(DecodeState* state); 140 | static void DecodeMem32(DecodeState* state); 141 | static void DecodeMem64(DecodeState* state); 142 | static void DecodeMem80(DecodeState* state); 143 | static void DecodeMemFloatEnv(DecodeState* state); 144 | static void DecodeMemFloatSave(DecodeState* state); 145 | static void DecodeFPUReg(DecodeState* state); 146 | static void DecodeFPURegST0(DecodeState* state); 147 | static void DecodeRegGroupNoOperands(DecodeState* state); 148 | static void DecodeRegGroupAX(DecodeState* state); 149 | static void DecodeCmpXch8B(DecodeState* state); 150 | static void DecodeMovNti(DecodeState* state); 151 | static void DecodeCrc32(DecodeState* state); 152 | static void DecodeArpl(DecodeState* state); 153 | 154 | 155 | // Instruction encodings, first is flags and second is decoder function 156 | #define ENC_INVALID 0, InvalidDecode 157 | #define ENC_TWO_BYTE 0, DecodeTwoByte 158 | #define ENC_FPU 0, DecodeFpu 159 | #define ENC_NO_OPERANDS 0, DecodeNoOperands 160 | #define ENC_OP_SIZE DEC_FLAG_OPERATION_OP_SIZE, DecodeNoOperands 161 | #define ENC_OP_SIZE_DEF64 DEC_FLAG_DEFAULT_TO_64BIT | DEC_FLAG_OPERATION_OP_SIZE, DecodeNoOperands 162 | #define ENC_OP_SIZE_NO64 DEC_FLAG_INVALID_IN_64BIT | DEC_FLAG_OPERATION_OP_SIZE, DecodeNoOperands 163 | #define ENC_REG_RM_8 DEC_FLAG_BYTE, DecodeRegRM 164 | #define ENC_RM_REG_8 DEC_FLAG_BYTE | DEC_FLAG_FLIP_OPERANDS, DecodeRegRM 165 | #define ENC_RM_REG_8_LOCK DEC_FLAG_BYTE | DEC_FLAG_FLIP_OPERANDS | DEC_FLAG_LOCK, DecodeRegRM 166 | #define ENC_RM_REG_16 DEC_FLAG_FLIP_OPERANDS | DEC_FLAG_FORCE_16BIT, DecodeRegRM 167 | #define ENC_REG_RM_V 0, DecodeRegRM 168 | #define ENC_RM_REG_V DEC_FLAG_FLIP_OPERANDS, DecodeRegRM 169 | #define ENC_RM_REG_V_LOCK DEC_FLAG_FLIP_OPERANDS | DEC_FLAG_LOCK, DecodeRegRM 170 | #define ENC_REG_RM2X_V DEC_FLAG_REG_RM_2X_SIZE, DecodeRegRM 171 | #define ENC_REG_RM_IMM_V 0, DecodeRegRMImm 172 | #define ENC_REG_RM_IMMSX_V DEC_FLAG_IMM_SX, DecodeRegRMImm 173 | #define ENC_REG_RM_0 DEC_FLAG_REG_RM_NO_SIZE, DecodeRegRM 174 | #define ENC_REG_RM_F DEC_FLAG_REG_RM_FAR_SIZE, DecodeRegRM 175 | #define ENC_RM_REG_DEF64 DEC_FLAG_FLIP_OPERANDS | DEC_FLAG_DEFAULT_TO_64BIT, DecodeRegRM 176 | #define ENC_RM_REG_IMM8_V 0, DecodeRMRegImm8 177 | #define ENC_RM_REG_CL_V 0, DecodeRMRegCL 178 | #define ENC_EAX_IMM_8 DEC_FLAG_BYTE, DecodeEaxImm 179 | #define ENC_EAX_IMM_V 0, DecodeEaxImm 180 | #define ENC_PUSH_POP_SEG 0, DecodePushPopSeg 181 | #define ENC_OP_REG_V 0, DecodeOpReg 182 | #define ENC_OP_REG_V_DEF64 DEC_FLAG_DEFAULT_TO_64BIT, DecodeOpReg 183 | #define ENC_EAX_OP_REG_V 0, DecodeEaxOpReg 184 | #define ENC_OP_REG_IMM_8 DEC_FLAG_BYTE, DecodeOpRegImm 185 | #define ENC_OP_REG_IMM_V 0, DecodeOpRegImm 186 | #define ENC_NOP 0, DecodeNop 187 | #define ENC_IMM_V_DEF64 DEC_FLAG_DEFAULT_TO_64BIT, DecodeImm 188 | #define ENC_IMMSX_V_DEF64 DEC_FLAG_IMM_SX | DEC_FLAG_DEFAULT_TO_64BIT, DecodeImm 189 | #define ENC_IMM_8 DEC_FLAG_BYTE, DecodeImm 190 | #define ENC_IMM_16 DEC_FLAG_FORCE_16BIT, DecodeImm 191 | #define ENC_IMM16_IMM8 0, DecodeImm16Imm8 192 | #define ENC_EDI_DX_8_REP DEC_FLAG_BYTE | DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP, DecodeEdiDx 193 | #define ENC_EDI_DX_OP_SIZE_REP DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP, DecodeEdiDx 194 | #define ENC_DX_ESI_8_REP DEC_FLAG_BYTE | DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP, DecodeDxEsi 195 | #define ENC_DX_ESI_OP_SIZE_REP DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP, DecodeDxEsi 196 | #define ENC_RELIMM_8_DEF64 DEC_FLAG_BYTE | DEC_FLAG_DEFAULT_TO_64BIT, DecodeRelImm 197 | #define ENC_RELIMM_V_DEF64 DEC_FLAG_DEFAULT_TO_64BIT, DecodeRelImm 198 | #define ENC_RELIMM_8_ADDR_SIZE_DEF64 DEC_FLAG_BYTE | DEC_FLAG_DEFAULT_TO_64BIT, DecodeRelImmAddrSize 199 | #define ENC_GROUP_RM_8 DEC_FLAG_BYTE, DecodeGroupRM 200 | #define ENC_GROUP_RM_V 0, DecodeGroupRM 201 | #define ENC_GROUP_RM_8_LOCK DEC_FLAG_BYTE | DEC_FLAG_LOCK, DecodeGroupRM 202 | #define ENC_GROUP_RM_0 DEC_FLAG_REG_RM_NO_SIZE, DecodeGroupRM 203 | #define ENC_GROUP_RM_IMM_8 DEC_FLAG_BYTE, DecodeGroupRMImm 204 | #define ENC_GROUP_RM_IMM_8_LOCK DEC_FLAG_BYTE | DEC_FLAG_LOCK, DecodeGroupRMImm 205 | #define ENC_GROUP_RM_IMM_8_NO64_LOCK DEC_FLAG_BYTE | DEC_FLAG_INVALID_IN_64BIT | DEC_FLAG_LOCK, DecodeGroupRMImm 206 | #define ENC_GROUP_RM_IMM8_V 0, DecodeGroupRMImm8V 207 | #define ENC_GROUP_RM_IMM_V 0, DecodeGroupRMImm 208 | #define ENC_GROUP_RM_IMM_V_LOCK DEC_FLAG_LOCK, DecodeGroupRMImm 209 | #define ENC_GROUP_RM_IMMSX_V_LOCK DEC_FLAG_IMM_SX | DEC_FLAG_LOCK, DecodeGroupRMImm 210 | #define ENC_GROUP_RM_ONE_8 DEC_FLAG_BYTE, DecodeGroupRMOne 211 | #define ENC_GROUP_RM_ONE_V 0, DecodeGroupRMOne 212 | #define ENC_GROUP_RM_CL_8 DEC_FLAG_BYTE, DecodeGroupRMCl 213 | #define ENC_GROUP_RM_CL_V 0, DecodeGroupRMCl 214 | #define ENC_GROUP_F6 DEC_FLAG_BYTE | DEC_FLAG_LOCK, DecodeGroupF6F7 215 | #define ENC_GROUP_F7 DEC_FLAG_LOCK, DecodeGroupF6F7 216 | #define ENC_GROUP_FF DEC_FLAG_LOCK, DecodeGroupFF 217 | #define ENC_GROUP_0F00 0, DecodeGroup0F00 218 | #define ENC_GROUP_0F01 0, DecodeGroup0F01 219 | #define ENC_GROUP_0FAE 0, DecodeGroup0FAE 220 | #define ENC_0FB8 0, Decode0FB8 221 | #define ENC_RM_SREG_V 0, DecodeRMSRegV 222 | #define ENC_SREG_RM_V DEC_FLAG_FLIP_OPERANDS, DecodeRMSRegV 223 | #define ENC_RM_8 0, DecodeRM8 224 | #define ENC_RM_V_DEF64 DEC_FLAG_DEFAULT_TO_64BIT, DecodeRMV 225 | #define ENC_FAR_IMM_NO64 DEC_FLAG_INVALID_IN_64BIT, DecodeFarImm 226 | #define ENC_EAX_ADDR_8 DEC_FLAG_BYTE, DecodeEaxAddr 227 | #define ENC_EAX_ADDR_V 0, DecodeEaxAddr 228 | #define ENC_ADDR_EAX_8 DEC_FLAG_BYTE | DEC_FLAG_FLIP_OPERANDS, DecodeEaxAddr 229 | #define ENC_ADDR_EAX_V DEC_FLAG_FLIP_OPERANDS, DecodeEaxAddr 230 | #define ENC_EDI_ESI_8_REP DEC_FLAG_BYTE | DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP, DecodeEdiEsi 231 | #define ENC_EDI_ESI_OP_SIZE_REP DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP, DecodeEdiEsi 232 | #define ENC_ESI_EDI_8_REPC DEC_FLAG_BYTE | DEC_FLAG_FLIP_OPERANDS | DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP_COND, DecodeEdiEsi 233 | #define ENC_ESI_EDI_OP_SIZE_REPC DEC_FLAG_FLIP_OPERANDS | DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP_COND, DecodeEdiEsi 234 | #define ENC_EDI_EAX_8_REP DEC_FLAG_BYTE | DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP, DecodeEdiEax 235 | #define ENC_EDI_EAX_OP_SIZE_REP DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP, DecodeEdiEax 236 | #define ENC_EAX_ESI_8_REP DEC_FLAG_BYTE | DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP, DecodeEaxEsi 237 | #define ENC_EAX_ESI_OP_SIZE_REP DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP, DecodeEaxEsi 238 | #define ENC_EAX_EDI_8_REPC DEC_FLAG_BYTE | DEC_FLAG_FLIP_OPERANDS | DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP_COND, DecodeEdiEax 239 | #define ENC_EAX_EDI_OP_SIZE_REPC DEC_FLAG_FLIP_OPERANDS | DEC_FLAG_OPERATION_OP_SIZE | DEC_FLAG_REP_COND, DecodeEdiEax 240 | #define ENC_AL_EBX_AL 0, DecodeAlEbxAl 241 | #define ENC_EAX_IMM8_8 DEC_FLAG_BYTE, DecodeEaxImm8 242 | #define ENC_EAX_IMM8_V 0, DecodeEaxImm8 243 | #define ENC_IMM8_EAX_8 DEC_FLAG_BYTE | DEC_FLAG_FLIP_OPERANDS, DecodeEaxImm8 244 | #define ENC_IMM8_EAX_V DEC_FLAG_FLIP_OPERANDS, DecodeEaxImm8 245 | #define ENC_EAX_DX_8 DEC_FLAG_BYTE, DecodeEaxDx 246 | #define ENC_EAX_DX_V 0, DecodeEaxDx 247 | #define ENC_DX_EAX_8 DEC_FLAG_BYTE | DEC_FLAG_FLIP_OPERANDS, DecodeEaxDx 248 | #define ENC_DX_EAX_V DEC_FLAG_FLIP_OPERANDS, DecodeEaxDx 249 | #define ENC_3DNOW 0, Decode3DNow 250 | #define ENC_SSE_TABLE 0, DecodeSSETable 251 | #define ENC_SSE_TABLE_FLIP DEC_FLAG_FLIP_OPERANDS, DecodeSSETable 252 | #define ENC_SSE_TABLE_IMM_8 0, DecodeSSETableImm8 253 | #define ENC_SSE_TABLE_IMM_8_FLIP DEC_FLAG_FLIP_OPERANDS, DecodeSSETableImm8 254 | #define ENC_SSE_TABLE_INCOP64 DEC_FLAG_INC_OPERATION_FOR_64, DecodeSSETable 255 | #define ENC_SSE_TABLE_INCOP64_FLIP DEC_FLAG_INC_OPERATION_FOR_64 | DEC_FLAG_FLIP_OPERANDS, DecodeSSETable 256 | #define ENC_SSE_TABLE_MEM8 0, DecodeSSETableMem8 257 | #define ENC_SSE_TABLE_MEM8_FLIP DEC_FLAG_FLIP_OPERANDS, DecodeSSETableMem8 258 | #define ENC_SSE 0, DecodeSSE 259 | #define ENC_SSE_SINGLE 0, DecodeSSESingle 260 | #define ENC_SSE_PACKED 0, DecodeSSEPacked 261 | #define ENC_MMX 0, DecodeMMX 262 | #define ENC_MMX_SSEONLY 0, DecodeMMXSSEOnly 263 | #define ENC_MMX_GROUP 0, DecodeMMXGroup 264 | #define ENC_PINSRW 0, DecodePinsrw 265 | #define ENC_REG_CR DEC_FLAG_DEFAULT_TO_64BIT | DEC_FLAG_LOCK, DecodeRegCR 266 | #define ENC_CR_REG DEC_FLAG_FLIP_OPERANDS | DEC_FLAG_DEFAULT_TO_64BIT | DEC_FLAG_LOCK, DecodeRegCR 267 | #define ENC_MOVSXZX_8 0, DecodeMovSXZX8 268 | #define ENC_MOVSXZX_16 0, DecodeMovSXZX16 269 | #define ENC_MEM_16 0, DecodeMem16 270 | #define ENC_MEM_32 0, DecodeMem32 271 | #define ENC_MEM_64 0, DecodeMem64 272 | #define ENC_MEM_80 0, DecodeMem80 273 | #define ENC_MEM_FLOATENV 0, DecodeMemFloatEnv 274 | #define ENC_MEM_FLOATSAVE 0, DecodeMemFloatSave 275 | #define ENC_FPUREG 0, DecodeFPUReg 276 | #define ENC_ST0_FPUREG DEC_FLAG_FLIP_OPERANDS, DecodeFPURegST0 277 | #define ENC_FPUREG_ST0 0, DecodeFPURegST0 278 | #define ENC_REGGROUP_NO_OPERANDS 0, DecodeRegGroupNoOperands 279 | #define ENC_REGGROUP_AX 0, DecodeRegGroupAX 280 | #define ENC_CMPXCH8B 0, DecodeCmpXch8B 281 | #define ENC_MOVNTI 0, DecodeMovNti 282 | #define ENC_CRC32_8 DEC_FLAG_BYTE, DecodeCrc32 283 | #define ENC_CRC32_V 0, DecodeCrc32 284 | #define ENC_ARPL 0, DecodeArpl 285 | 286 | 287 | struct InstructionEncoding 288 | { 289 | uint16_t operation; 290 | uint16_t flags; 291 | DecodingFunction func; 292 | }; 293 | #ifndef __cplusplus 294 | typedef struct InstructionEncoding InstructionEncoding; 295 | #endif 296 | 297 | struct SparseInstructionEncoding 298 | { 299 | uint8_t opcode; 300 | InstructionEncoding encoding; 301 | }; 302 | #ifndef __cplusplus 303 | typedef struct SparseInstructionEncoding SparseInstructionEncoding; 304 | #endif 305 | 306 | 307 | static const InstructionEncoding mainOpcodeMap[256] = 308 | { 309 | {ADD, ENC_RM_REG_8_LOCK}, {ADD, ENC_RM_REG_V_LOCK}, {ADD, ENC_REG_RM_8}, {ADD, ENC_REG_RM_V}, // 0x00 310 | {ADD, ENC_EAX_IMM_8}, {ADD, ENC_EAX_IMM_V}, {PUSH, ENC_PUSH_POP_SEG}, {POP, ENC_PUSH_POP_SEG}, // 0x04 311 | {OR, ENC_RM_REG_8_LOCK}, {OR, ENC_RM_REG_V_LOCK}, {OR, ENC_REG_RM_8}, {OR, ENC_REG_RM_V}, // 0x08 312 | {OR, ENC_EAX_IMM_8}, {OR, ENC_EAX_IMM_V}, {PUSH, ENC_PUSH_POP_SEG}, {INVALID, ENC_TWO_BYTE}, // 0x0c 313 | {ADC, ENC_RM_REG_8_LOCK}, {ADC, ENC_RM_REG_V_LOCK}, {ADC, ENC_REG_RM_8}, {ADC, ENC_REG_RM_V}, // 0x10 314 | {ADC, ENC_EAX_IMM_8}, {ADC, ENC_EAX_IMM_V}, {PUSH, ENC_PUSH_POP_SEG}, {POP, ENC_PUSH_POP_SEG}, // 0x14 315 | {SBB, ENC_RM_REG_8_LOCK}, {SBB, ENC_RM_REG_V_LOCK}, {SBB, ENC_REG_RM_8}, {SBB, ENC_REG_RM_V}, // 0x18 316 | {SBB, ENC_EAX_IMM_8}, {SBB, ENC_EAX_IMM_V}, {PUSH, ENC_PUSH_POP_SEG}, {POP, ENC_PUSH_POP_SEG}, // 0x1c 317 | {AND, ENC_RM_REG_8_LOCK}, {AND, ENC_RM_REG_V_LOCK}, {AND, ENC_REG_RM_8}, {AND, ENC_REG_RM_V}, // 0x20 318 | {AND, ENC_EAX_IMM_8}, {AND, ENC_EAX_IMM_V}, {INVALID, ENC_INVALID}, {DAA, ENC_NO_OPERANDS}, // 0x24 319 | {SUB, ENC_RM_REG_8_LOCK}, {SUB, ENC_RM_REG_V_LOCK}, {SUB, ENC_REG_RM_8}, {SUB, ENC_REG_RM_V}, // 0x28 320 | {SUB, ENC_EAX_IMM_8}, {SUB, ENC_EAX_IMM_V}, {INVALID, ENC_INVALID}, {DAS, ENC_NO_OPERANDS}, // 0x2c 321 | {XOR, ENC_RM_REG_8_LOCK}, {XOR, ENC_RM_REG_V_LOCK}, {XOR, ENC_REG_RM_8}, {XOR, ENC_REG_RM_V}, // 0x30 322 | {XOR, ENC_EAX_IMM_8}, {XOR, ENC_EAX_IMM_V}, {INVALID, ENC_INVALID}, {AAA, ENC_NO_OPERANDS}, // 0x34 323 | {CMP, ENC_RM_REG_8}, {CMP, ENC_RM_REG_V}, {CMP, ENC_REG_RM_8}, {CMP, ENC_REG_RM_V}, // 0x38 324 | {CMP, ENC_EAX_IMM_8}, {CMP, ENC_EAX_IMM_V}, {INVALID, ENC_INVALID}, {AAS, ENC_NO_OPERANDS}, // 0x3c 325 | {INC, ENC_OP_REG_V}, {INC, ENC_OP_REG_V}, {INC, ENC_OP_REG_V}, {INC, ENC_OP_REG_V}, // 0x40 326 | {INC, ENC_OP_REG_V}, {INC, ENC_OP_REG_V}, {INC, ENC_OP_REG_V}, {INC, ENC_OP_REG_V}, // 0x44 327 | {DEC, ENC_OP_REG_V}, {DEC, ENC_OP_REG_V}, {DEC, ENC_OP_REG_V}, {DEC, ENC_OP_REG_V}, // 0x48 328 | {DEC, ENC_OP_REG_V}, {DEC, ENC_OP_REG_V}, {DEC, ENC_OP_REG_V}, {DEC, ENC_OP_REG_V}, // 0x4c 329 | {PUSH, ENC_OP_REG_V_DEF64}, {PUSH, ENC_OP_REG_V_DEF64}, {PUSH, ENC_OP_REG_V_DEF64}, {PUSH, ENC_OP_REG_V_DEF64}, // 0x50 330 | {PUSH, ENC_OP_REG_V_DEF64}, {PUSH, ENC_OP_REG_V_DEF64}, {PUSH, ENC_OP_REG_V_DEF64}, {PUSH, ENC_OP_REG_V_DEF64}, // 0x54 331 | {POP, ENC_OP_REG_V_DEF64}, {POP, ENC_OP_REG_V_DEF64}, {POP, ENC_OP_REG_V_DEF64}, {POP, ENC_OP_REG_V_DEF64}, // 0x58 332 | {POP, ENC_OP_REG_V_DEF64}, {POP, ENC_OP_REG_V_DEF64}, {POP, ENC_OP_REG_V_DEF64}, {POP, ENC_OP_REG_V_DEF64}, // 0x5c 333 | {PUSHA, ENC_OP_SIZE_NO64}, {POPA, ENC_OP_SIZE_NO64}, {BOUND, ENC_REG_RM2X_V}, {ARPL, ENC_ARPL}, // 0x60 334 | {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, // 0x64 335 | {PUSH, ENC_IMM_V_DEF64}, {IMUL, ENC_REG_RM_IMM_V}, {PUSH, ENC_IMMSX_V_DEF64}, {IMUL, ENC_REG_RM_IMMSX_V}, // 0x68 336 | {INSB, ENC_EDI_DX_8_REP}, {INSW, ENC_EDI_DX_OP_SIZE_REP}, {OUTSB, ENC_DX_ESI_8_REP}, {OUTSW, ENC_DX_ESI_OP_SIZE_REP}, // 0x6c 337 | {JO, ENC_RELIMM_8_DEF64}, {JNO, ENC_RELIMM_8_DEF64}, {JB, ENC_RELIMM_8_DEF64}, {JAE, ENC_RELIMM_8_DEF64}, // 0x70 338 | {JE, ENC_RELIMM_8_DEF64}, {JNE, ENC_RELIMM_8_DEF64}, {JBE, ENC_RELIMM_8_DEF64}, {JA, ENC_RELIMM_8_DEF64}, // 0x74 339 | {JS, ENC_RELIMM_8_DEF64}, {JNS, ENC_RELIMM_8_DEF64}, {JPE, ENC_RELIMM_8_DEF64}, {JPO, ENC_RELIMM_8_DEF64}, // 0x78 340 | {JL, ENC_RELIMM_8_DEF64}, {JGE, ENC_RELIMM_8_DEF64}, {JLE, ENC_RELIMM_8_DEF64}, {JG, ENC_RELIMM_8_DEF64}, // 0x7c 341 | {0, ENC_GROUP_RM_IMM_8_LOCK}, {0, ENC_GROUP_RM_IMM_V_LOCK}, {0, ENC_GROUP_RM_IMM_8_NO64_LOCK}, {0, ENC_GROUP_RM_IMMSX_V_LOCK}, // 0x80 342 | {TEST, ENC_RM_REG_8}, {TEST, ENC_RM_REG_V}, {XCHG, ENC_RM_REG_8_LOCK}, {XCHG, ENC_RM_REG_V_LOCK}, // 0x84 343 | {MOV, ENC_RM_REG_8}, {MOV, ENC_RM_REG_V}, {MOV, ENC_REG_RM_8}, {MOV, ENC_REG_RM_V}, // 0x88 344 | {MOV, ENC_RM_SREG_V}, {LEA, ENC_REG_RM_0}, {MOV, ENC_SREG_RM_V}, {POP, ENC_RM_V_DEF64}, // 0x8c 345 | {NOP, ENC_NOP}, {XCHG, ENC_EAX_OP_REG_V}, {XCHG, ENC_EAX_OP_REG_V}, {XCHG, ENC_EAX_OP_REG_V}, // 0x90 346 | {XCHG, ENC_EAX_OP_REG_V}, {XCHG, ENC_EAX_OP_REG_V}, {XCHG, ENC_EAX_OP_REG_V}, {XCHG, ENC_EAX_OP_REG_V}, // 0x94 347 | {CBW, ENC_OP_SIZE}, {CWD, ENC_OP_SIZE}, {CALLF, ENC_FAR_IMM_NO64}, {FWAIT, ENC_NO_OPERANDS}, // 0x98 348 | {PUSHF, ENC_OP_SIZE_DEF64}, {POPF, ENC_OP_SIZE_DEF64}, {SAHF, ENC_NO_OPERANDS}, {LAHF, ENC_NO_OPERANDS}, // 0x9c 349 | {MOV, ENC_EAX_ADDR_8}, {MOV, ENC_EAX_ADDR_V}, {MOV, ENC_ADDR_EAX_8}, {MOV, ENC_ADDR_EAX_V}, // 0xa0 350 | {MOVSB, ENC_EDI_ESI_8_REP}, {MOVSW, ENC_EDI_ESI_OP_SIZE_REP}, {CMPSB, ENC_ESI_EDI_8_REPC}, {CMPSW, ENC_ESI_EDI_OP_SIZE_REPC}, // 0xa4 351 | {TEST, ENC_EAX_IMM_8}, {TEST, ENC_EAX_IMM_V}, {STOSB, ENC_EDI_EAX_8_REP}, {STOSW, ENC_EDI_EAX_OP_SIZE_REP}, // 0xa8 352 | {LODSB, ENC_EAX_ESI_8_REP}, {LODSW, ENC_EAX_ESI_OP_SIZE_REP}, {SCASB, ENC_EAX_EDI_8_REPC}, {SCASW, ENC_EAX_EDI_OP_SIZE_REPC}, // 0xac 353 | {MOV, ENC_OP_REG_IMM_8}, {MOV, ENC_OP_REG_IMM_8}, {MOV, ENC_OP_REG_IMM_8}, {MOV, ENC_OP_REG_IMM_8}, // 0xb0 354 | {MOV, ENC_OP_REG_IMM_8}, {MOV, ENC_OP_REG_IMM_8}, {MOV, ENC_OP_REG_IMM_8}, {MOV, ENC_OP_REG_IMM_8}, // 0xb4 355 | {MOV, ENC_OP_REG_IMM_V}, {MOV, ENC_OP_REG_IMM_V}, {MOV, ENC_OP_REG_IMM_V}, {MOV, ENC_OP_REG_IMM_V}, // 0xb8 356 | {MOV, ENC_OP_REG_IMM_V}, {MOV, ENC_OP_REG_IMM_V}, {MOV, ENC_OP_REG_IMM_V}, {MOV, ENC_OP_REG_IMM_V}, // 0xbc 357 | {1, ENC_GROUP_RM_IMM_8}, {1, ENC_GROUP_RM_IMM8_V}, {RETN, ENC_IMM_16}, {RETN, ENC_NO_OPERANDS}, // 0xc0 358 | {LES, ENC_REG_RM_F}, {LDS, ENC_REG_RM_F}, {2, ENC_GROUP_RM_IMM_8}, {2, ENC_GROUP_RM_IMM_V}, // 0xc4 359 | {ENTER, ENC_IMM16_IMM8}, {LEAVE, ENC_NO_OPERANDS}, {RETF, ENC_IMM_16}, {RETF, ENC_NO_OPERANDS}, // 0xc8 360 | {INT3, ENC_NO_OPERANDS}, {INT, ENC_IMM_8}, {INTO, ENC_NO_OPERANDS}, {IRET, ENC_NO_OPERANDS}, // 0xcc 361 | {1, ENC_GROUP_RM_ONE_8}, {1, ENC_GROUP_RM_ONE_V}, {1, ENC_GROUP_RM_CL_8}, {1, ENC_GROUP_RM_CL_V}, // 0xd0 362 | {AAM, ENC_IMM_8}, {AAD, ENC_IMM_8}, {INVALID, ENC_INVALID}, {XLAT, ENC_AL_EBX_AL}, // 0xd4 363 | {0, ENC_FPU}, {1, ENC_FPU}, {2, ENC_FPU}, {3, ENC_FPU}, // 0xd8 364 | {4, ENC_FPU}, {5, ENC_FPU}, {6, ENC_FPU}, {7, ENC_FPU}, // 0xdc 365 | {LOOPNE, ENC_RELIMM_8_DEF64}, {LOOPE, ENC_RELIMM_8_DEF64}, {LOOP, ENC_RELIMM_8_DEF64}, {JCXZ, ENC_RELIMM_8_ADDR_SIZE_DEF64}, // 0xe0 366 | {IN, ENC_EAX_IMM8_8}, {IN, ENC_EAX_IMM8_V}, {OUT, ENC_IMM8_EAX_8}, {OUT, ENC_IMM8_EAX_V}, // 0xe4 367 | {CALL, ENC_RELIMM_V_DEF64}, {JMP, ENC_RELIMM_V_DEF64}, {JMPF, ENC_FAR_IMM_NO64}, {JMP, ENC_RELIMM_8_DEF64}, // 0xe8 368 | {IN, ENC_EAX_DX_8}, {IN, ENC_EAX_DX_V}, {OUT, ENC_DX_EAX_8}, {OUT, ENC_DX_EAX_V}, // 0xec 369 | {INVALID, ENC_INVALID}, {INT1, ENC_NO_OPERANDS}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, // 0xf0 370 | {HLT, ENC_NO_OPERANDS}, {CMC, ENC_NO_OPERANDS}, {3, ENC_GROUP_F6}, {3, ENC_GROUP_F7}, // 0xf4 371 | {CLC, ENC_NO_OPERANDS}, {STC, ENC_NO_OPERANDS}, {CLI, ENC_NO_OPERANDS}, {STI, ENC_NO_OPERANDS}, // 0xf8 372 | {CLD, ENC_NO_OPERANDS}, {STD, ENC_NO_OPERANDS}, {4, ENC_GROUP_RM_8_LOCK}, {5, ENC_GROUP_FF}, // 0xfc 373 | }; 374 | 375 | 376 | static const InstructionEncoding twoByteOpcodeMap[256] = 377 | { 378 | {6, ENC_GROUP_0F00}, {7, ENC_GROUP_0F01}, {LAR, ENC_REG_RM_V}, {LSL, ENC_REG_RM_V}, // 0x00 379 | {INVALID, ENC_INVALID}, {SYSCALL, ENC_NO_OPERANDS}, {CLTS, ENC_NO_OPERANDS}, {SYSRET, ENC_NO_OPERANDS}, // 0x04 380 | {INVD, ENC_NO_OPERANDS}, {WBINVD, ENC_NO_OPERANDS}, {INVALID, ENC_INVALID}, {UD2, ENC_NO_OPERANDS}, // 0x08 381 | {INVALID, ENC_INVALID}, {8, ENC_GROUP_RM_0}, {FEMMS, ENC_NO_OPERANDS}, {0, ENC_3DNOW}, // 0x0c 382 | {0, ENC_SSE_TABLE}, {0, ENC_SSE_TABLE_FLIP}, {1, ENC_SSE_TABLE}, {2, ENC_SSE_TABLE_FLIP}, // 0x10 383 | {3, ENC_SSE_TABLE}, {4, ENC_SSE_TABLE}, {5, ENC_SSE_TABLE}, {6, ENC_SSE_TABLE_FLIP}, // 0x14 384 | {9, ENC_GROUP_RM_0}, {10, ENC_GROUP_RM_0}, {10, ENC_GROUP_RM_0}, {10, ENC_GROUP_RM_0}, // 0x18 385 | {10, ENC_GROUP_RM_0}, {10, ENC_GROUP_RM_0}, {10, ENC_GROUP_RM_0}, {10, ENC_GROUP_RM_0}, // 0x1c 386 | {REG_CR0, ENC_REG_CR}, {REG_DR0, ENC_REG_CR}, {REG_CR0, ENC_CR_REG}, {REG_DR0, ENC_CR_REG}, // 0x20 387 | {REG_TR0, ENC_REG_CR}, {INVALID, ENC_INVALID}, {REG_TR0, ENC_CR_REG}, {INVALID, ENC_INVALID}, // 0x24 388 | {7, ENC_SSE_TABLE}, {7, ENC_SSE_TABLE_FLIP}, {8, ENC_SSE_TABLE}, {9, ENC_SSE_TABLE_FLIP}, // 0x28 389 | {10, ENC_SSE_TABLE}, {11, ENC_SSE_TABLE}, {12, ENC_SSE_TABLE}, {13, ENC_SSE_TABLE}, // 0x2c 390 | {WRMSR, ENC_NO_OPERANDS}, {RDTSC, ENC_NO_OPERANDS}, {RDMSR, ENC_NO_OPERANDS}, {RDPMC, ENC_NO_OPERANDS}, // 0x30 391 | {SYSENTER, ENC_NO_OPERANDS}, {SYSEXIT, ENC_NO_OPERANDS}, {INVALID, ENC_INVALID}, {GETSEC, ENC_NO_OPERANDS}, // 0x34 392 | {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, // 0x38 393 | {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, // 0x3c 394 | {CMOVO, ENC_REG_RM_V}, {CMOVNO, ENC_REG_RM_V}, {CMOVB, ENC_REG_RM_V}, {CMOVAE, ENC_REG_RM_V}, // 0x40 395 | {CMOVE, ENC_REG_RM_V}, {CMOVNE, ENC_REG_RM_V}, {CMOVBE, ENC_REG_RM_V}, {CMOVA, ENC_REG_RM_V}, // 0x44 396 | {CMOVS, ENC_REG_RM_V}, {CMOVNS, ENC_REG_RM_V}, {CMOVPE, ENC_REG_RM_V}, {CMOVPO, ENC_REG_RM_V}, // 0x48 397 | {CMOVL, ENC_REG_RM_V}, {CMOVGE, ENC_REG_RM_V}, {CMOVLE, ENC_REG_RM_V}, {CMOVG, ENC_REG_RM_V}, // 0x4c 398 | {14, ENC_SSE_TABLE}, {SQRTPS, ENC_SSE}, {RSQRTPS, ENC_SSE_SINGLE}, {RCPPS, ENC_SSE_SINGLE}, // 0x50 399 | {ANDPS, ENC_SSE_PACKED}, {ANDNPS, ENC_SSE_PACKED}, {ORPS, ENC_SSE_PACKED}, {XORPS, ENC_SSE_PACKED}, // 0x54 400 | {ADDPS, ENC_SSE}, {MULPS, ENC_SSE}, {15, ENC_SSE_TABLE}, {16, ENC_SSE_TABLE}, // 0x58 401 | {SUBPS, ENC_SSE}, {MINPS, ENC_SSE}, {DIVPS, ENC_SSE}, {MAXPS, ENC_SSE}, // 0x5c 402 | {17, ENC_SSE_TABLE}, {18, ENC_SSE_TABLE}, {19, ENC_SSE_TABLE}, {PACKSSWB, ENC_MMX}, // 0x60 403 | {PCMPGTB, ENC_MMX}, {PCMPGTW, ENC_MMX}, {PCMPGTD, ENC_MMX}, {PACKUSWB, ENC_MMX}, // 0x64 404 | {PUNPCKHBW, ENC_MMX}, {PUNPCKHWD, ENC_MMX}, {PUNPCKHDQ, ENC_MMX}, {PACKSSDW, ENC_MMX}, // 0x68 405 | {PUNPCKLQDQ, ENC_MMX_SSEONLY}, {PUNPCKHQDQ, ENC_MMX_SSEONLY}, {20, ENC_SSE_TABLE_INCOP64}, {21, ENC_SSE_TABLE}, // 0x6c 406 | {22, ENC_SSE_TABLE_IMM_8}, {0, ENC_MMX_GROUP}, {1, ENC_MMX_GROUP}, {2, ENC_MMX_GROUP}, // 0x70 407 | {PCMPEQB, ENC_MMX}, {PCMPEQW, ENC_MMX}, {PCMPEQD, ENC_MMX}, {EMMS, ENC_NO_OPERANDS}, // 0x74 408 | {VMREAD, ENC_RM_REG_DEF64}, {VMWRITE, ENC_RM_REG_DEF64}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, // 0x78 409 | {23, ENC_SSE_TABLE}, {24, ENC_SSE_TABLE}, {25, ENC_SSE_TABLE_INCOP64_FLIP}, {21, ENC_SSE_TABLE_FLIP}, // 0x7c 410 | {JO, ENC_RELIMM_V_DEF64}, {JNO, ENC_RELIMM_V_DEF64}, {JB, ENC_RELIMM_V_DEF64}, {JAE, ENC_RELIMM_V_DEF64}, // 0x80 411 | {JE, ENC_RELIMM_V_DEF64}, {JNE, ENC_RELIMM_V_DEF64}, {JBE, ENC_RELIMM_V_DEF64}, {JA, ENC_RELIMM_V_DEF64}, // 0x84 412 | {JS, ENC_RELIMM_V_DEF64}, {JNS, ENC_RELIMM_V_DEF64}, {JPE, ENC_RELIMM_V_DEF64}, {JPO, ENC_RELIMM_V_DEF64}, // 0x88 413 | {JL, ENC_RELIMM_V_DEF64}, {JGE, ENC_RELIMM_V_DEF64}, {JLE, ENC_RELIMM_V_DEF64}, {JG, ENC_RELIMM_V_DEF64}, // 0x8c 414 | {SETO, ENC_RM_8}, {SETNO, ENC_RM_8}, {SETB, ENC_RM_8}, {SETAE, ENC_RM_8}, // 0x90 415 | {SETE, ENC_RM_8}, {SETNE, ENC_RM_8}, {SETBE, ENC_RM_8}, {SETA, ENC_RM_8}, // 0x94 416 | {SETS, ENC_RM_8}, {SETNS, ENC_RM_8}, {SETPE, ENC_RM_8}, {SETPO, ENC_RM_8}, // 0x98 417 | {SETL, ENC_RM_8}, {SETGE, ENC_RM_8}, {SETLE, ENC_RM_8}, {SETG, ENC_RM_8}, // 0x9c 418 | {PUSH, ENC_PUSH_POP_SEG}, {POP, ENC_PUSH_POP_SEG}, {CPUID, ENC_NO_OPERANDS}, {BT, ENC_RM_REG_V}, // 0xa0 419 | {SHLD, ENC_RM_REG_IMM8_V}, {SHLD, ENC_RM_REG_CL_V}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, // 0xa4 420 | {PUSH, ENC_PUSH_POP_SEG}, {POP, ENC_PUSH_POP_SEG}, {RSM, ENC_NO_OPERANDS}, {BTS, ENC_RM_REG_V}, // 0xa8 421 | {SHRD, ENC_RM_REG_IMM8_V}, {SHRD, ENC_RM_REG_CL_V}, {24, ENC_GROUP_0FAE}, {IMUL, ENC_REG_RM_V}, // 0xac 422 | {CMPXCHG, ENC_RM_REG_8_LOCK}, {CMPXCHG, ENC_RM_REG_V_LOCK}, {LSS, ENC_REG_RM_F}, {BTR, ENC_RM_REG_V}, // 0xb0 423 | {LFS, ENC_REG_RM_F}, {LGS, ENC_REG_RM_F}, {MOVZX, ENC_MOVSXZX_8}, {MOVZX, ENC_MOVSXZX_16}, // 0xb4 424 | {POPCNT, ENC_0FB8}, {INVALID, ENC_INVALID}, {11, ENC_GROUP_RM_IMM8_V}, {BTC, ENC_RM_REG_V}, // 0xb8 425 | {BSF, ENC_REG_RM_V}, {BSR, ENC_REG_RM_V}, {MOVSX, ENC_MOVSXZX_8}, {MOVSX, ENC_MOVSXZX_16}, // 0xbc 426 | {XADD, ENC_RM_REG_8}, {XADD, ENC_RM_REG_V_LOCK}, {26, ENC_SSE_TABLE_IMM_8}, {MOVNTI, ENC_MOVNTI}, // 0xc0 427 | {27, ENC_PINSRW}, {28, ENC_SSE_TABLE_IMM_8_FLIP}, {29, ENC_SSE_TABLE_IMM_8}, {CMPXCH8B, ENC_CMPXCH8B}, // 0xc4 428 | {BSWAP, ENC_OP_REG_V}, {BSWAP, ENC_OP_REG_V}, {BSWAP, ENC_OP_REG_V}, {BSWAP, ENC_OP_REG_V}, // 0xc8 429 | {BSWAP, ENC_OP_REG_V}, {BSWAP, ENC_OP_REG_V}, {BSWAP, ENC_OP_REG_V}, {BSWAP, ENC_OP_REG_V}, // 0xcc 430 | {30, ENC_SSE_TABLE}, {PSRLW, ENC_MMX}, {PSRLD, ENC_MMX}, {PSRLQ, ENC_MMX}, // 0xd0 431 | {PADDQ, ENC_MMX}, {PMULLW, ENC_MMX}, {31, ENC_SSE_TABLE}, {32, ENC_SSE_TABLE}, // 0xd4 432 | {PSUBUSB, ENC_MMX}, {PSUBUSW, ENC_MMX}, {PMINUB, ENC_MMX}, {PAND, ENC_MMX}, // 0xd8 433 | {PADDUSB, ENC_MMX}, {PADDUSW, ENC_MMX}, {PMAXUB, ENC_MMX}, {PANDN, ENC_MMX}, // 0xdc 434 | {PAVGB, ENC_MMX}, {PSRAW, ENC_MMX}, {PSRAD, ENC_MMX}, {PAVGW, ENC_MMX}, // 0xe0 435 | {PMULHUW, ENC_MMX}, {PMULHW, ENC_MMX}, {33, ENC_SSE_TABLE}, {34, ENC_SSE_TABLE_FLIP}, // 0xe4 436 | {PSUBSB, ENC_MMX}, {PSUBSW, ENC_MMX}, {PMINSW, ENC_MMX}, {POR, ENC_MMX}, // 0xe8 437 | {PADDSB, ENC_MMX}, {PADDSW, ENC_MMX}, {PMAXSW, ENC_MMX}, {PXOR, ENC_MMX}, // 0xec 438 | {35, ENC_SSE_TABLE}, {PSLLW, ENC_MMX}, {PSLLD, ENC_MMX}, {PSLLQ, ENC_MMX}, // 0xf0 439 | {PMULUDQ, ENC_MMX}, {PMADDWD, ENC_MMX}, {PSADBW, ENC_MMX}, {36, ENC_SSE_TABLE}, // 0xf4 440 | {PSUBB, ENC_MMX}, {PSUBW, ENC_MMX}, {PSUBD, ENC_MMX}, {PSUBQ, ENC_MMX}, // 0xf8 441 | {PADDB, ENC_MMX}, {PADDW, ENC_MMX}, {PADDD, ENC_MMX}, {INVALID, ENC_INVALID} // 0xfc 442 | }; 443 | 444 | 445 | static const SparseInstructionEncoding threeByte0F38Map[] = 446 | { 447 | {0x00, {PSHUFB, ENC_MMX}}, {0x01, {PHADDW, ENC_MMX}}, {0x02, {PHADDD, ENC_MMX}}, {0x03, {PHADDSW, ENC_MMX}}, 448 | {0x04, {PMADDUBSW, ENC_MMX}}, {0x05, {PHSUBW, ENC_MMX}}, {0x06, {PHSUBD, ENC_MMX}}, {0x07, {PHSUBSW, ENC_MMX}}, 449 | {0x08, {PSIGNB, ENC_MMX}}, {0x09, {PSIGNW, ENC_MMX}}, {0x0a, {PSIGND, ENC_MMX}}, {0x0b, {PMULHRSW, ENC_MMX}}, 450 | {0x10, {PBLENDVB, ENC_MMX_SSEONLY}}, {0x14, {BLENDVPS, ENC_MMX_SSEONLY}}, {0x15, {BLENDVPD, ENC_MMX_SSEONLY}}, 451 | {0x17, {PTEST, ENC_MMX_SSEONLY}}, {0x1c, {PABSB, ENC_MMX}}, {0x1d, {PABSW, ENC_MMX}}, {0x1e, {PABSD, ENC_MMX}}, 452 | {0x20, {37, ENC_SSE_TABLE}}, {0x21, {38, ENC_SSE_TABLE}}, {0x22, {39, ENC_SSE_TABLE}}, {0x23, {40, ENC_SSE_TABLE}}, 453 | {0x24, {41, ENC_SSE_TABLE}}, {0x25, {42, ENC_SSE_TABLE}}, {0x28, {PMULDQ, ENC_MMX_SSEONLY}}, {0x29, {PCMPEQQ, ENC_MMX_SSEONLY}}, 454 | {0x2a, {43, ENC_SSE_TABLE}}, {0x2b, {PACKUSDW, ENC_MMX_SSEONLY}}, {0x30, {44, ENC_SSE_TABLE}}, {0x31, {45, ENC_SSE_TABLE}}, 455 | {0x32, {46, ENC_SSE_TABLE}}, {0x33, {47, ENC_SSE_TABLE}}, {0x34, {48, ENC_SSE_TABLE}}, {0x35, {49, ENC_SSE_TABLE}}, 456 | {0x37, {PCMPGTQ, ENC_MMX_SSEONLY}}, {0x38, {PMINSB, ENC_MMX_SSEONLY}}, {0x39, {PMINSD, ENC_MMX_SSEONLY}}, 457 | {0x3a, {PMINUW, ENC_MMX_SSEONLY}}, {0x3b, {PMINUD, ENC_MMX_SSEONLY}}, {0x3c, {PMAXSB, ENC_MMX_SSEONLY}}, 458 | {0x3d, {PMAXSD, ENC_MMX_SSEONLY}}, {0x3e, {PMAXUW, ENC_MMX_SSEONLY}}, {0x3f, {PMAXUD, ENC_MMX_SSEONLY}}, 459 | {0x40, {PMULLD, ENC_MMX_SSEONLY}}, {0x41, {PHMINPOSUW, ENC_MMX_SSEONLY}}, {0xf0, {CRC32, ENC_CRC32_8}}, {0xf1, {CRC32, ENC_CRC32_V}} 460 | }; 461 | 462 | 463 | static const SparseInstructionEncoding threeByte0F3AMap[] = 464 | { 465 | {0x08, {ROUNDPS, ENC_MMX_SSEONLY}}, {0x09, {ROUNDPD, ENC_MMX_SSEONLY}}, {0x0a, {50, ENC_SSE_TABLE}}, {0x0b, {51, ENC_SSE_TABLE}}, 466 | {0x0c, {BLENDPS, ENC_MMX_SSEONLY}}, {0x0d, {BLENDPD, ENC_MMX_SSEONLY}}, {0x0e, {PBLENDW, ENC_MMX_SSEONLY}}, {0x0f, {PALIGNR, ENC_MMX}}, 467 | {0x14, {52, ENC_SSE_TABLE_MEM8_FLIP}}, {0x15, {53, ENC_SSE_TABLE_FLIP}}, {0x16, {54, ENC_SSE_TABLE_INCOP64_FLIP}}, 468 | {0x17, {55, ENC_SSE_TABLE_FLIP}}, {0x20, {56, ENC_SSE_TABLE_MEM8}}, {0x21, {57, ENC_SSE_TABLE}}, {0x22, {58, ENC_SSE_TABLE_INCOP64}}, 469 | {0x40, {DPPS, ENC_MMX_SSEONLY}}, {0x41, {DPPD, ENC_MMX_SSEONLY}}, {0x42, {MPSADBW, ENC_MMX_SSEONLY}}, 470 | {0x60, {PCMPESTRM, ENC_MMX_SSEONLY}}, {0x61, {PCMPESTRI, ENC_MMX_SSEONLY}}, {0x62, {PCMPISTRM, ENC_MMX_SSEONLY}}, 471 | {0x63, {PCMPISTRI, ENC_MMX_SSEONLY}} 472 | }; 473 | 474 | 475 | static const InstructionEncoding fpuMemOpcodeMap[8][8] = 476 | { 477 | { // 0xd8 478 | {FADD, ENC_MEM_32}, {FMUL, ENC_MEM_32}, {FCOM, ENC_MEM_32}, {FCOMP, ENC_MEM_32}, // 0 479 | {FSUB, ENC_MEM_32}, {FSUBR, ENC_MEM_32}, {FDIV, ENC_MEM_32}, {FDIVR, ENC_MEM_32} // 4 480 | }, 481 | { // 0xd9 482 | {FLD, ENC_MEM_32}, {INVALID, ENC_INVALID}, {FST, ENC_MEM_32}, {FSTP, ENC_MEM_32}, // 0 483 | {FLDENV, ENC_MEM_FLOATENV}, {FLDCW, ENC_MEM_16}, {FSTENV, ENC_MEM_FLOATENV}, {FSTCW, ENC_MEM_16} // 4 484 | }, 485 | { // 0xda 486 | {FIADD, ENC_MEM_32}, {FIMUL, ENC_MEM_32}, {FICOM, ENC_MEM_32}, {FICOMP, ENC_MEM_32}, // 0 487 | {FISUB, ENC_MEM_32}, {FISUBR, ENC_MEM_32}, {FIDIV, ENC_MEM_32}, {FIDIVR, ENC_MEM_32} // 4 488 | }, 489 | { // 0xdb 490 | {FILD, ENC_MEM_32}, {FISTTP, ENC_MEM_32}, {FIST, ENC_MEM_32}, {FISTP, ENC_MEM_32}, // 0 491 | {INVALID, ENC_INVALID}, {FLD, ENC_MEM_80}, {INVALID, ENC_INVALID}, {FSTP, ENC_MEM_80} // 4 492 | }, 493 | { // 0xdc 494 | {FADD, ENC_MEM_64}, {FMUL, ENC_MEM_64}, {FCOM, ENC_MEM_64}, {FCOMP, ENC_MEM_64}, // 0 495 | {FSUB, ENC_MEM_64}, {FSUBR, ENC_MEM_64}, {FDIV, ENC_MEM_64}, {FDIVR, ENC_MEM_64} // 4 496 | }, 497 | { // 0xdd 498 | {FLD, ENC_MEM_64}, {FISTTP, ENC_MEM_64}, {FST, ENC_MEM_64}, {FSTP, ENC_MEM_64}, // 0 499 | {FRSTOR, ENC_MEM_FLOATSAVE}, {INVALID, ENC_INVALID}, {FSAVE, ENC_MEM_FLOATSAVE}, {FSTSW, ENC_MEM_16} // 4 500 | }, 501 | { // 0xde 502 | {FIADD, ENC_MEM_16}, {FIMUL, ENC_MEM_16}, {FICOM, ENC_MEM_16}, {FICOMP, ENC_MEM_16}, // 0 503 | {FISUB, ENC_MEM_16}, {FISUBR, ENC_MEM_16}, {FIDIV, ENC_MEM_16}, {FIDIVR, ENC_MEM_16} // 4 504 | }, 505 | { // 0xdf 506 | {FILD, ENC_MEM_16}, {FISTTP, ENC_MEM_16}, {FIST, ENC_MEM_16}, {FISTP, ENC_MEM_16}, // 0 507 | {FBLD, ENC_MEM_80}, {FILD, ENC_MEM_64}, {FBSTP, ENC_MEM_80}, {FISTP, ENC_MEM_64} 508 | } 509 | }; 510 | 511 | 512 | static const InstructionEncoding fpuRegOpcodeMap[8][8] = 513 | { 514 | { // 0xd8 515 | {FADD, ENC_ST0_FPUREG}, {FMUL, ENC_ST0_FPUREG}, {FCOM, ENC_ST0_FPUREG}, {FCOMP, ENC_ST0_FPUREG}, // 0 516 | {FSUB, ENC_ST0_FPUREG}, {FSUBR, ENC_ST0_FPUREG}, {FDIV, ENC_ST0_FPUREG}, {FDIVR, ENC_ST0_FPUREG} // 4 517 | }, 518 | { // 0xd9 519 | {FLD, ENC_FPUREG}, {FXCH, ENC_ST0_FPUREG}, {12, ENC_REGGROUP_NO_OPERANDS}, {INVALID, ENC_INVALID}, // 0 520 | {13, ENC_REGGROUP_NO_OPERANDS}, {14, ENC_REGGROUP_NO_OPERANDS}, {15, ENC_REGGROUP_NO_OPERANDS}, {16, ENC_REGGROUP_NO_OPERANDS} // 4 521 | }, 522 | { // 0xda 523 | {FCMOVB, ENC_ST0_FPUREG}, {FCMOVE, ENC_ST0_FPUREG}, {FCMOVBE, ENC_ST0_FPUREG}, {FCMOVU, ENC_ST0_FPUREG}, // 0 524 | {INVALID, ENC_INVALID}, {17, ENC_REGGROUP_NO_OPERANDS}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID} // 4 525 | }, 526 | { // 0xdb 527 | {FCMOVNB, ENC_ST0_FPUREG}, {FCMOVNE, ENC_ST0_FPUREG}, {FCMOVNBE, ENC_ST0_FPUREG}, {FCMOVNU, ENC_ST0_FPUREG}, // 0 528 | {18, ENC_REGGROUP_NO_OPERANDS}, {FUCOMI, ENC_ST0_FPUREG}, {FCOMI, ENC_ST0_FPUREG}, {21, ENC_REGGROUP_NO_OPERANDS} // 4 529 | }, 530 | { // 0xdc 531 | {FADD, ENC_FPUREG_ST0}, {FMUL, ENC_FPUREG_ST0}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, // 0 532 | {FSUBR, ENC_FPUREG_ST0}, {FSUB, ENC_FPUREG_ST0}, {FDIVR, ENC_FPUREG_ST0}, {FDIV, ENC_FPUREG_ST0} // 4 533 | }, 534 | { // 0xdd 535 | {FFREE, ENC_FPUREG}, {INVALID, ENC_INVALID}, {FST, ENC_FPUREG}, {FSTP, ENC_FPUREG}, // 0 536 | {FUCOM, ENC_ST0_FPUREG}, {FUCOMP, ENC_ST0_FPUREG}, {INVALID, ENC_INVALID}, {22, ENC_REGGROUP_NO_OPERANDS} // 4 537 | }, 538 | { // 0xde 539 | {FADDP, ENC_FPUREG_ST0}, {FMULP, ENC_FPUREG_ST0}, {INVALID, ENC_INVALID}, {19, ENC_REGGROUP_NO_OPERANDS}, // 0 540 | {FSUBRP, ENC_FPUREG_ST0}, {FSUBP, ENC_FPUREG_ST0}, {FDIVRP, ENC_FPUREG_ST0}, {FDIVP, ENC_FPUREG_ST0} // 4 541 | }, 542 | { // 0xdf 543 | {FFREEP, ENC_FPUREG}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, {INVALID, ENC_INVALID}, // 0 544 | {20, ENC_REGGROUP_AX}, {FUCOMIP, ENC_ST0_FPUREG}, {FCOMIP, ENC_ST0_FPUREG}, {23, ENC_REGGROUP_NO_OPERANDS} // 4 545 | } 546 | }; 547 | 548 | 549 | static const uint16_t groupOperations[26][8] = 550 | { 551 | {ADD, OR, ADC, SBB, AND, SUB, XOR, CMP}, // Group 0 552 | {ROL, ROR, RCL, RCR, SHL, SHR, SHL, SAR}, // Group 1 553 | {MOV, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID}, // Group 2 554 | {TEST, TEST, NOT, NEG, MUL, IMUL, DIV, IDIV}, // Group 3 555 | {INC, DEC, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID}, // Group 4 556 | {INC, DEC, CALL, CALLF, JMP, JMPF, PUSH, INVALID}, // Group 5 557 | {SLDT, STR, LLDT, LTR, VERR, VERW, INVALID, INVALID}, // Group 6 558 | {SGDT, SIDT, LGDT, LIDT, SMSW, INVALID, LMSW, INVLPG}, // Group 7 559 | {PREFETCH, PREFETCHW, PREFETCH, PREFETCH, PREFETCH, PREFETCH, PREFETCH, PREFETCH}, // Group 8 560 | {PREFETCHNTA, PREFETCHT0, PREFETCHT1, PREFETCHT2, MMXNOP, MMXNOP, MMXNOP, MMXNOP}, // Group 9 561 | {MMXNOP, MMXNOP, MMXNOP, MMXNOP, MMXNOP, MMXNOP, MMXNOP, MMXNOP}, // Group 10 562 | {INVALID, INVALID, INVALID, INVALID, BT, BTS, BTR, BTC}, // Group 11 563 | {FNOP, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID}, // Group 12 564 | {FCHS, FABS, INVALID, INVALID, FTST, FXAM, INVALID, INVALID}, // Group 13 565 | {FLD1, FLDL2T, FLDL2E, FLDPI, FLDLG2, FLDLN2, FLDZ, INVALID}, // Group 14 566 | {F2XM1, FYL2X, FPTAN, FPATAN, FXTRACT, FPREM1, FDECSTP, FINCSTP}, // Group 15 567 | {FPREM, FYL2XP1, FSQRT, FSINCOS, FRNDINT, FSCALE, FSIN, FCOS}, // Group 16 568 | {INVALID, FUCOMPP, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID}, // Group 17 569 | {FENI, FDISI, FCLEX, FINIT, FSETPM, FRSTPM, INVALID, INVALID}, // Group 18 570 | {INVALID, FCOMPP, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID}, // Group 19 571 | {FSTSW, FSTDW, FSTSG, INVALID, INVALID, INVALID, INVALID, INVALID}, // Group 20 572 | {INVALID, INVALID, INVALID, INVALID, FRINT2, INVALID, INVALID, INVALID}, // Group 21 573 | {INVALID, INVALID, INVALID, INVALID, FRICHOP, INVALID, INVALID, INVALID}, // Group 22 574 | {INVALID, INVALID, INVALID, INVALID, FRINEAR, INVALID, INVALID, INVALID}, // Group 23 575 | {FXSAVE, FXRSTOR, LDMXCSR, STMXCSR, XSAVE, XRSTOR, INVALID, CLFLUSH}, // Group 24 576 | {INVALID, INVALID, INVALID, INVALID, INVALID, LFENCE, MFENCE, SFENCE}, // Group 25 577 | }; 578 | 579 | 580 | static const uint16_t group0F01RegOperations[8][8] = 581 | { 582 | {INVALID, VMCALL, VMLAUNCH, VMRESUME, VMXOFF, INVALID, INVALID, INVALID}, 583 | {MONITOR, MWAIT, CLAC, STAC, INVALID, INVALID, INVALID, ENCLS}, 584 | {XGETBV, XSETBV, INVALID, INVALID, VMFUNC, XEND, XTEXT, ENCLU}, 585 | {INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID}, 586 | {INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID}, 587 | {INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID}, 588 | {INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID}, 589 | {SWAPGS, RDTSCP, INVALID, INVALID, INVALID, INVALID, INVALID, INVALID} 590 | }; 591 | 592 | 593 | static const uint16_t mmxGroupOperations[3][8][2] = 594 | { 595 | { // Group 0 596 | {INVALID, INVALID}, {INVALID, INVALID}, {PSRLW, PSRLW}, {INVALID, INVALID}, 597 | {PSRAW, PSRAW}, {INVALID, INVALID}, {PSLLW, PSLLW}, {INVALID, INVALID} 598 | }, 599 | { // Group 1 600 | {INVALID, INVALID}, {INVALID, INVALID}, {PSRLD, PSRLD}, {INVALID, INVALID}, 601 | {PSRAD, PSRAD}, {INVALID, INVALID}, {PSLLD, PSLLD}, {INVALID, INVALID} 602 | }, 603 | { // Group 2 604 | {INVALID, INVALID}, {INVALID, INVALID}, {PSRLQ, PSRLQ}, {INVALID, PSRLDQ}, 605 | {INVALID, INVALID}, {INVALID, INVALID}, {PSLLQ, PSLLQ}, {INVALID, PSLLDQ} 606 | } 607 | }; 608 | 609 | 610 | enum SSETableOperandType 611 | { 612 | SSE_16, 613 | SSE_32, 614 | SSE_64, 615 | SSE_64_FLIP, 616 | SSE_128, 617 | SSE_128_FLIP, 618 | GPR_32_OR_64, 619 | MMX_32, 620 | MMX_64 621 | }; 622 | 623 | struct SSETableOperationEntry 624 | { 625 | uint16_t operation; 626 | uint8_t regType; 627 | uint8_t rmType; 628 | }; 629 | 630 | #ifndef __cplusplus 631 | typedef struct SSETableOperationEntry SSETableOperationEntry; 632 | #endif 633 | 634 | struct SSETableEntry 635 | { 636 | SSETableOperationEntry regOps[4]; 637 | SSETableOperationEntry memOps[4]; 638 | }; 639 | 640 | #ifndef __cplusplus 641 | typedef struct SSETableEntry SSETableEntry; 642 | #endif 643 | 644 | static const SSETableEntry sseTable[] = 645 | { 646 | { // Entry 0 647 | {{MOVUPS, SSE_128, SSE_128}, {MOVUPD, SSE_128, SSE_128}, {MOVSD, SSE_128, SSE_128}, {MOVSS, SSE_128, SSE_128}}, 648 | {{MOVUPS, SSE_128, SSE_128}, {MOVUPD, SSE_128, SSE_128}, {MOVSD, SSE_128, SSE_64}, {MOVSS, SSE_128, SSE_32}} 649 | }, 650 | { // Entry 1 651 | {{INVALID, 0, 0}, {MOVHLPS, SSE_128, SSE_128}, {MOVDDUP, SSE_128, SSE_128}, {MOVSLDUP, SSE_128, SSE_128}}, 652 | {{MOVLPS, SSE_128, SSE_64}, {MOVLPD, SSE_128, SSE_64}, {MOVDDUP, SSE_128, SSE_64}, {MOVSLDUP, SSE_128, SSE_128}} 653 | }, 654 | { // Entry 2 655 | {{INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 656 | {{MOVLPS, SSE_128, SSE_64}, {MOVLPD, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 657 | }, 658 | { // Entry 3 659 | {{UNPCKLPS, SSE_128, SSE_128}, {UNPCKLPD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 660 | {{UNPCKLPS, SSE_128, SSE_128}, {UNPCKLPD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}} 661 | }, 662 | { // Entry 4 663 | {{UNPCKHPS, SSE_128, SSE_128}, {UNPCKHPD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 664 | {{UNPCKHPS, SSE_128, SSE_128}, {UNPCKHPD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}} 665 | }, 666 | { // Entry 5 667 | {{INVALID, 0, 0}, {MOVLHPS, SSE_128, SSE_128}, {INVALID, 0, 0}, {MOVSHDUP, SSE_128, SSE_128}}, 668 | {{MOVHPS, SSE_128, SSE_64}, {MOVHPD, SSE_128, SSE_64}, {INVALID, 0, 0}, {MOVSHDUP, SSE_128, SSE_128}} 669 | }, 670 | { // Entry 6 671 | {{INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 672 | {{MOVHPS, SSE_128, SSE_64}, {MOVHPD, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 673 | }, 674 | { // Entry 7 675 | {{MOVAPS, SSE_128, SSE_128}, {MOVAPD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 676 | {{MOVAPS, SSE_128, SSE_128}, {MOVAPD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}} 677 | }, 678 | { // Entry 8 679 | {{CVTPI2PS, SSE_128, MMX_64}, {CVTPI2PD, SSE_128, MMX_64}, {CVTSI2SD, SSE_128, GPR_32_OR_64}, {CVTSI2SS, SSE_128, GPR_32_OR_64}}, 680 | {{CVTPI2PS, SSE_128, MMX_64}, {CVTPI2PD, SSE_128, MMX_64}, {CVTSI2SD, SSE_128, GPR_32_OR_64}, {CVTSI2SS, SSE_128, GPR_32_OR_64}} 681 | }, 682 | { // Entry 9 683 | {{INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 684 | {{MOVNTPS, SSE_128, SSE_128}, {MOVNTPD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}} 685 | }, 686 | { // Entry 10 687 | {{CVTTPS2PI, MMX_64, SSE_128}, {CVTTPD2PI, MMX_64, SSE_128}, {CVTTSD2SI, GPR_32_OR_64, SSE_128}, {CVTTSS2SI, GPR_32_OR_64, SSE_128}}, 688 | {{CVTTPS2PI, MMX_64, SSE_64}, {CVTTPD2PI, MMX_64, SSE_128}, {CVTTSD2SI, GPR_32_OR_64, SSE_64}, {CVTTSS2SI, GPR_32_OR_64, SSE_32}} 689 | }, 690 | { // Entry 11 691 | {{CVTPS2PI, MMX_64, SSE_128}, {CVTPD2PI, MMX_64, SSE_128}, {CVTSD2SI, GPR_32_OR_64, SSE_128}, {CVTSS2SI, GPR_32_OR_64, SSE_128}}, 692 | {{CVTPS2PI, MMX_64, SSE_64}, {CVTPD2PI, MMX_64, SSE_128}, {CVTSD2SI, GPR_32_OR_64, SSE_64}, {CVTSS2SI, GPR_32_OR_64, SSE_32}} 693 | }, 694 | { // Entry 12 695 | {{UCOMISS, SSE_128, SSE_128}, {UCOMISD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 696 | {{UCOMISS, SSE_128, SSE_32}, {UCOMISD, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 697 | }, 698 | { // Entry 13 699 | {{COMISS, SSE_128, SSE_128}, {COMISD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 700 | {{COMISS, SSE_128, SSE_32}, {COMISD, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 701 | }, 702 | { // Entry 14 703 | {{MOVMSKPS, GPR_32_OR_64, SSE_128}, {MOVMSKPD, GPR_32_OR_64, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 704 | {{INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}} 705 | }, 706 | { // Entry 15 707 | {{CVTPS2PD, SSE_128, SSE_128}, {CVTPD2PS, SSE_128, SSE_128}, {CVTSD2SS, SSE_128, SSE_128}, {CVTSS2SD, SSE_128, SSE_128}}, 708 | {{CVTPS2PD, SSE_128, SSE_64}, {CVTPD2PS, SSE_128, SSE_128}, {CVTSD2SS, SSE_128, SSE_64}, {CVTSS2SD, SSE_128, SSE_32}} 709 | }, 710 | { // Entry 16 711 | {{CVTDQ2PS, SSE_128, SSE_128}, {CVTPS2DQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {CVTTPS2DQ, SSE_128, SSE_128}}, 712 | {{CVTDQ2PS, SSE_128, SSE_128}, {CVTPS2DQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {CVTTPS2DQ, SSE_128, SSE_128}} 713 | }, 714 | { // Entry 17 715 | {{PUNPCKLBW, MMX_64, MMX_64}, {PUNPCKLBW, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 716 | {{PUNPCKLBW, MMX_64, MMX_32}, {PUNPCKLBW, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}} 717 | }, 718 | { // Entry 18 719 | {{PUNPCKLWD, MMX_64, MMX_64}, {PUNPCKLWD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 720 | {{PUNPCKLWD, MMX_64, MMX_32}, {PUNPCKLWD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}} 721 | }, 722 | { // Entry 19 723 | {{PUNPCKLDQ, MMX_64, MMX_64}, {PUNPCKLDQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 724 | {{PUNPCKLDQ, MMX_64, MMX_32}, {PUNPCKLDQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}} 725 | }, 726 | { // Entry 20 727 | {{MOVD, MMX_64, GPR_32_OR_64}, {MOVD, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 728 | {{MOVD, MMX_64, GPR_32_OR_64}, {MOVD, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 729 | }, 730 | { // Entry 21 731 | {{MOVQ, MMX_64, MMX_64}, {MOVDQA, SSE_128, SSE_128}, {INVALID, 0, 0}, {MOVDQU, SSE_128, SSE_128}}, 732 | {{MOVQ, MMX_64, MMX_64}, {MOVDQA, SSE_128, SSE_128}, {INVALID, 0, 0}, {MOVDQU, SSE_128, SSE_128}} 733 | }, 734 | { // Entry 22 735 | {{PSHUFW, MMX_64, MMX_64}, {PSHUFD, SSE_128, SSE_128}, {PSHUFLW, SSE_128, SSE_128}, {PSHUFHW, SSE_128, SSE_128}}, 736 | {{PSHUFW, MMX_64, MMX_64}, {PSHUFD, SSE_128, SSE_128}, {PSHUFLW, SSE_128, SSE_128}, {PSHUFHW, SSE_128, SSE_128}} 737 | }, 738 | { // Entry 23 739 | {{INVALID, 0, 0}, {HADDPD, SSE_128, SSE_128}, {HADDPS, SSE_128, SSE_128}, {INVALID, 0, 0}}, 740 | {{INVALID, 0, 0}, {HADDPD, SSE_128, SSE_128}, {HADDPS, SSE_128, SSE_128}, {INVALID, 0, 0}} 741 | }, 742 | { // Entry 24 743 | {{INVALID, 0, 0}, {HSUBPD, SSE_128, SSE_128}, {HSUBPS, SSE_128, SSE_128}, {INVALID, 0, 0}}, 744 | {{INVALID, 0, 0}, {HSUBPD, SSE_128, SSE_128}, {HSUBPS, SSE_128, SSE_128}, {INVALID, 0, 0}} 745 | }, 746 | { // Entry 25 747 | {{MOVD, MMX_64, GPR_32_OR_64}, {MOVD, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {MOVQ, SSE_128_FLIP, SSE_128_FLIP}}, 748 | {{MOVD, MMX_64, GPR_32_OR_64}, {MOVD, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {MOVQ, SSE_128_FLIP, SSE_64_FLIP}} 749 | }, 750 | { // Entry 26 751 | {{CMPPS, SSE_128, SSE_128}, {CMPPD, SSE_128, SSE_128}, {CMPSD, SSE_128, SSE_128}, {CMPSS, SSE_128, SSE_128}}, 752 | {{CMPPS, SSE_128, SSE_128}, {CMPPD, SSE_128, SSE_128}, {CMPSD, SSE_128, SSE_64}, {CMPSS, SSE_128, SSE_32}} 753 | }, 754 | { // Entry 27 755 | {{PINSRW, MMX_64, GPR_32_OR_64}, {PINSRW, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 756 | {{PINSRW, MMX_64, GPR_32_OR_64}, {PINSRW, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 757 | }, 758 | { // Entry 28 759 | {{PEXTRW, MMX_64, GPR_32_OR_64}, {PEXTRW, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 760 | {{PEXTRW, MMX_64, GPR_32_OR_64}, {PEXTRW, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 761 | }, 762 | { // Entry 29 763 | {{SHUFPS, SSE_128, SSE_128}, {SHUFPD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 764 | {{SHUFPS, SSE_128, SSE_128}, {SHUFPD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}} 765 | }, 766 | { // Entry 30 767 | {{INVALID, 0, 0}, {ADDSUBPD, SSE_128, SSE_128}, {ADDSUBPS, SSE_128, SSE_128}, {INVALID, 0, 0}}, 768 | {{INVALID, 0, 0}, {ADDSUBPD, SSE_128, SSE_128}, {ADDSUBPS, SSE_128, SSE_128}, {INVALID, 0, 0}} 769 | }, 770 | { // Entry 31 771 | {{INVALID, 0, 0}, {MOVQ, SSE_128_FLIP, SSE_128_FLIP}, {MOVDQ2Q, MMX_64, SSE_128}, {MOVQ2DQ, SSE_128, MMX_64}}, 772 | {{INVALID, 0, 0}, {MOVQ, SSE_128_FLIP, SSE_64_FLIP}, {INVALID, 0, 0}, {INVALID, 0, 0}} 773 | }, 774 | { // Entry 32 775 | {{PMOVMSKB, GPR_32_OR_64, MMX_64}, {PMOVMSKB, GPR_32_OR_64, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 776 | {{INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}} 777 | }, 778 | { // Entry 33 779 | {{INVALID, 0, 0}, {CVTTPD2DQ, SSE_128, SSE_128}, {CVTPD2DQ, SSE_128, SSE_128}, {CVTDQ2PD, SSE_128, SSE_128}}, 780 | {{INVALID, 0, 0}, {CVTTPD2DQ, SSE_128, SSE_128}, {CVTPD2DQ, SSE_128, SSE_128}, {CVTDQ2PD, SSE_128, SSE_128}} 781 | }, 782 | { // Entry 34 783 | {{INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 784 | {{MOVNTQ, MMX_64, MMX_64}, {MOVNTDQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}} 785 | }, 786 | { // Entry 35 787 | {{INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 788 | {{INVALID, 0, 0}, {INVALID, 0, 0}, {LDDQU, SSE_128, SSE_128}, {INVALID, 0, 0}} 789 | }, 790 | { // Entry 36 791 | {{MASKMOVQ, MMX_64, MMX_64}, {MASKMOVDQU, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 792 | {{INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}} 793 | }, 794 | { // Entry 37 795 | {{INVALID, 0, 0}, {PMOVSXBW, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 796 | {{INVALID, 0, 0}, {PMOVSXBW, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 797 | }, 798 | { // Entry 38 799 | {{INVALID, 0, 0}, {PMOVSXBD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 800 | {{INVALID, 0, 0}, {PMOVSXBD, SSE_128, SSE_32}, {INVALID, 0, 0}, {INVALID, 0, 0}} 801 | }, 802 | { // Entry 39 803 | {{INVALID, 0, 0}, {PMOVSXBQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 804 | {{INVALID, 0, 0}, {PMOVSXBQ, SSE_128, SSE_16}, {INVALID, 0, 0}, {INVALID, 0, 0}} 805 | }, 806 | { // Entry 40 807 | {{INVALID, 0, 0}, {PMOVSXWD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 808 | {{INVALID, 0, 0}, {PMOVSXWD, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 809 | }, 810 | { // Entry 41 811 | {{INVALID, 0, 0}, {PMOVSXWQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 812 | {{INVALID, 0, 0}, {PMOVSXWQ, SSE_128, SSE_32}, {INVALID, 0, 0}, {INVALID, 0, 0}} 813 | }, 814 | { // Entry 42 815 | {{INVALID, 0, 0}, {PMOVSXDQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 816 | {{INVALID, 0, 0}, {PMOVSXDQ, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 817 | }, 818 | { // Entry 43 819 | {{INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 820 | {{INVALID, 0, 0}, {MOVNTDQA, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}} 821 | }, 822 | { // Entry 44 823 | {{INVALID, 0, 0}, {PMOVZXBW, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 824 | {{INVALID, 0, 0}, {PMOVZXBW, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 825 | }, 826 | { // Entry 45 827 | {{INVALID, 0, 0}, {PMOVZXBD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 828 | {{INVALID, 0, 0}, {PMOVZXBD, SSE_128, SSE_32}, {INVALID, 0, 0}, {INVALID, 0, 0}} 829 | }, 830 | { // Entry 46 831 | {{INVALID, 0, 0}, {PMOVZXBQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 832 | {{INVALID, 0, 0}, {PMOVZXBQ, SSE_128, SSE_16}, {INVALID, 0, 0}, {INVALID, 0, 0}} 833 | }, 834 | { // Entry 47 835 | {{INVALID, 0, 0}, {PMOVZXWD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 836 | {{INVALID, 0, 0}, {PMOVZXWD, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 837 | }, 838 | { // Entry 48 839 | {{INVALID, 0, 0}, {PMOVZXWQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 840 | {{INVALID, 0, 0}, {PMOVZXWQ, SSE_128, SSE_32}, {INVALID, 0, 0}, {INVALID, 0, 0}} 841 | }, 842 | { // Entry 49 843 | {{INVALID, 0, 0}, {PMOVZXDQ, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 844 | {{INVALID, 0, 0}, {PMOVZXDQ, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 845 | }, 846 | { // Entry 50 847 | {{INVALID, 0, 0}, {ROUNDSS, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 848 | {{INVALID, 0, 0}, {ROUNDSS, SSE_128, SSE_32}, {INVALID, 0, 0}, {INVALID, 0, 0}} 849 | }, 850 | { // Entry 51 851 | {{INVALID, 0, 0}, {ROUNDSD, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 852 | {{INVALID, 0, 0}, {ROUNDSD, SSE_128, SSE_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 853 | }, 854 | { // Entry 52 855 | {{INVALID, 0, 0}, {PEXTRB, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 856 | {{INVALID, 0, 0}, {PEXTRB, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 857 | }, 858 | { // Entry 53 859 | {{INVALID, 0, 0}, {PEXTRW, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 860 | {{INVALID, 0, 0}, {PEXTRW, SSE_128, SSE_16}, {INVALID, 0, 0}, {INVALID, 0, 0}} 861 | }, 862 | { // Entry 54 863 | {{INVALID, 0, 0}, {PEXTRD, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 864 | {{INVALID, 0, 0}, {PEXTRD, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 865 | }, 866 | { // Entry 55 867 | {{INVALID, 0, 0}, {EXTRACTPS, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 868 | {{INVALID, 0, 0}, {EXTRACTPS, SSE_128, SSE_32}, {INVALID, 0, 0}, {INVALID, 0, 0}} 869 | }, 870 | { // Entry 56 871 | {{INVALID, 0, 0}, {PINSRB, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 872 | {{INVALID, 0, 0}, {PINSRB, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 873 | }, 874 | { // Entry 57 875 | {{INVALID, 0, 0}, {INSERTPS, SSE_128, SSE_128}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 876 | {{INVALID, 0, 0}, {INSERTPS, SSE_128, SSE_32}, {INVALID, 0, 0}, {INVALID, 0, 0}} 877 | }, 878 | { // Entry 58 879 | {{INVALID, 0, 0}, {PINSRD, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}}, 880 | {{INVALID, 0, 0}, {PINSRD, SSE_128, GPR_32_OR_64}, {INVALID, 0, 0}, {INVALID, 0, 0}} 881 | } 882 | }; 883 | 884 | 885 | struct SparseOpEntry 886 | { 887 | uint8_t opcode; 888 | uint16_t operation; 889 | }; 890 | #ifndef __cplusplus 891 | typedef struct SparseOpEntry SparseOpEntry; 892 | #endif 893 | 894 | static const SparseOpEntry sparse3DNowOpcodes[] = 895 | { 896 | {0x0c, PI2FW}, {0x0d, PI2FD}, 897 | {0x1c, PF2IW}, {0x1d, PF2ID}, 898 | {0x86, PFRCPV}, {0x87, PFRSQRTV}, {0x8a, PFNACC}, {0x8e, PFPNACC}, 899 | {0x90, PFCMPGE}, {0x94, PFMIN}, {0x96, PFRCP}, {0x97, PFRSQRT}, {0x9a, PFSUB}, {0x9e, PFADD}, 900 | {0xa0, PFCMPGT}, {0xa4, PFMAX}, {0xa6, PFRCPIT1}, {0xa7, PFRSQIT1}, {0xaa, PFSUBR}, {0xae, PFACC}, 901 | {0xb0, PFCMPEQ}, {0xb4, PFMUL}, {0xb6, PFRCPIT2}, {0xb7, PMULHRW}, {0xbb, PSWAPD}, {0xbf, PAVGUSB} 902 | }; 903 | 904 | 905 | typedef uint8_t RegDef; 906 | static const RegDef reg8List[8] = {REG_AL, REG_CL, REG_DL, REG_BL, REG_AH, REG_CH, REG_DH, REG_BH}; 907 | static const RegDef reg8List64[16] = {REG_AL, REG_CL, REG_DL, REG_BL, REG_SPL, REG_BPL, REG_SIL, REG_DIL, 908 | REG_R8B, REG_R9B, REG_R10B, REG_R11B, REG_R12B, REG_R13B, REG_R14B, REG_R15B}; 909 | static const RegDef reg16List[16] = {REG_AX, REG_CX, REG_DX, REG_BX, REG_SP, REG_BP, REG_SI, REG_DI, 910 | REG_R8W, REG_R9W, REG_R10W, REG_R11W, REG_R12W, REG_R13W, REG_R14W, REG_R15W}; 911 | static const RegDef reg32List[16] = {REG_EAX, REG_ECX, REG_EDX, REG_EBX, REG_ESP, REG_EBP, REG_ESI, REG_EDI, 912 | REG_R8D, REG_R9D, REG_R10D, REG_R11D, REG_R12D, REG_R13D, REG_R14D, REG_R15D}; 913 | static const RegDef reg64List[16] = {REG_RAX, REG_RCX, REG_RDX, REG_RBX, REG_RSP, REG_RBP, REG_RSI, REG_RDI, 914 | REG_R8, REG_R9, REG_R10, REG_R11, REG_R12, REG_R13, REG_R14, REG_R15}; 915 | static const RegDef mmxRegList[16] = {REG_MM0, REG_MM1, REG_MM2, REG_MM3, REG_MM4, REG_MM5, REG_MM6, REG_MM7, 916 | REG_MM0, REG_MM1, REG_MM2, REG_MM3, REG_MM4, REG_MM5, REG_MM6, REG_MM7}; 917 | static const RegDef xmmRegList[16] = {REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7, 918 | REG_XMM8, REG_XMM9, REG_XMM10, REG_XMM11, REG_XMM12, REG_XMM13, REG_XMM14, REG_XMM15}; 919 | static const RegDef fpuRegList[16] = {REG_ST0, REG_ST1, REG_ST2, REG_ST3, REG_ST4, REG_ST5, REG_ST6, REG_ST7, 920 | REG_ST0, REG_ST1, REG_ST2, REG_ST3, REG_ST4, REG_ST5, REG_ST6, REG_ST7}; 921 | 922 | 923 | struct RMDef 924 | { 925 | OperandType first; 926 | OperandType second; 927 | SegmentRegister segment; 928 | }; 929 | #ifndef __cplusplus 930 | typedef struct RMDef RMDef; 931 | #endif 932 | 933 | 934 | static const RegDef* GetByteRegList(DecodeState* state) 935 | { 936 | if (state->rex) 937 | return reg8List64; 938 | return reg8List; 939 | } 940 | 941 | 942 | static const RegDef* GetRegListForOpSize(DecodeState* state) 943 | { 944 | switch (state->opSize) 945 | { 946 | case 2: 947 | return reg16List; 948 | case 4: 949 | return reg32List; 950 | case 8: 951 | return reg64List; 952 | default: 953 | return NULL; 954 | } 955 | } 956 | 957 | 958 | static const RegDef* GetRegListForFinalOpSize(DecodeState* state) 959 | { 960 | switch (state->finalOpSize) 961 | { 962 | case 1: 963 | return GetByteRegList(state); 964 | case 2: 965 | return reg16List; 966 | case 4: 967 | return reg32List; 968 | case 8: 969 | return reg64List; 970 | default: 971 | return NULL; 972 | } 973 | } 974 | 975 | 976 | static const RegDef* GetRegListForAddrSize(DecodeState* state) 977 | { 978 | switch (state->addrSize) 979 | { 980 | case 2: 981 | return reg16List; 982 | case 4: 983 | return reg32List; 984 | case 8: 985 | return reg64List; 986 | default: 987 | return NULL; 988 | } 989 | } 990 | 991 | 992 | static uint16_t GetFinalOpSize(DecodeState* state) 993 | { 994 | if (state->flags & DEC_FLAG_BYTE) 995 | return 1; 996 | return state->opSize; 997 | } 998 | 999 | 1000 | static uint8_t Read8(DecodeState* state) 1001 | { 1002 | uint8_t val; 1003 | 1004 | if (state->len < 1) 1005 | { 1006 | // Read past end of buffer, returning 0xcc from now on will guarantee exit 1007 | state->invalid = true; 1008 | state->insufficientLength = true; 1009 | state->len = 0; 1010 | return 0xcc; 1011 | } 1012 | 1013 | val = *(state->opcode++); 1014 | state->len--; 1015 | return val; 1016 | } 1017 | 1018 | 1019 | static uint8_t Peek8(DecodeState* state) 1020 | { 1021 | uint8_t val; 1022 | 1023 | if (state->len < 1) 1024 | { 1025 | // Read past end of buffer, returning 0xcc from now on will guarantee exit 1026 | state->invalid = true; 1027 | state->insufficientLength = true; 1028 | state->len = 0; 1029 | return 0xcc; 1030 | } 1031 | 1032 | val = *state->opcode; 1033 | return val; 1034 | } 1035 | 1036 | 1037 | static uint16_t Read16(DecodeState* state) 1038 | { 1039 | uint16_t val; 1040 | 1041 | if (state->len < 2) 1042 | { 1043 | // Read past end of buffer 1044 | state->invalid = true; 1045 | state->insufficientLength = true; 1046 | state->len = 0; 1047 | return 0; 1048 | } 1049 | 1050 | val = *((uint16_t*)state->opcode); 1051 | state->opcode += 2; 1052 | state->len -= 2; 1053 | return val; 1054 | } 1055 | 1056 | 1057 | static uint32_t Read32(DecodeState* state) 1058 | { 1059 | uint32_t val; 1060 | 1061 | if (state->len < 4) 1062 | { 1063 | // Read past end of buffer 1064 | state->invalid = true; 1065 | state->insufficientLength = true; 1066 | state->len = 0; 1067 | return 0; 1068 | } 1069 | 1070 | val = *((uint32_t*)state->opcode); 1071 | state->opcode += 4; 1072 | state->len -= 4; 1073 | return val; 1074 | } 1075 | 1076 | 1077 | static uint64_t Read64(DecodeState* state) 1078 | { 1079 | uint64_t val; 1080 | 1081 | if (state->len < 8) 1082 | { 1083 | // Read past end of buffer 1084 | state->invalid = true; 1085 | state->insufficientLength = true; 1086 | state->len = 0; 1087 | return 0; 1088 | } 1089 | 1090 | val = *((uint64_t*)state->opcode); 1091 | state->opcode += 8; 1092 | state->len -= 8; 1093 | return val; 1094 | } 1095 | 1096 | 1097 | static int64_t ReadSigned8(DecodeState* state) 1098 | { 1099 | return (int64_t)(int8_t)Read8(state); 1100 | } 1101 | 1102 | 1103 | static int64_t ReadSigned16(DecodeState* state) 1104 | { 1105 | return (int64_t)(int16_t)Read16(state); 1106 | } 1107 | 1108 | 1109 | static int64_t ReadSigned32(DecodeState* state) 1110 | { 1111 | return (int64_t)(int32_t)Read32(state); 1112 | } 1113 | 1114 | 1115 | static int64_t ReadFinalOpSize(DecodeState* state) 1116 | { 1117 | if (state->flags & DEC_FLAG_IMM_SX) 1118 | return ReadSigned8(state); 1119 | switch (state->finalOpSize) 1120 | { 1121 | case 1: 1122 | return Read8(state); 1123 | case 2: 1124 | return Read16(state); 1125 | case 4: 1126 | return Read32(state); 1127 | case 8: 1128 | return ReadSigned32(state); 1129 | } 1130 | return 0; 1131 | } 1132 | 1133 | 1134 | static int64_t ReadAddrSize(DecodeState* state) 1135 | { 1136 | switch (state->addrSize) 1137 | { 1138 | case 2: 1139 | return Read16(state); 1140 | case 4: 1141 | case 8: 1142 | return Read32(state); 1143 | } 1144 | return 0; 1145 | } 1146 | 1147 | 1148 | static int64_t ReadSignedFinalOpSize(DecodeState* state) 1149 | { 1150 | switch (state->finalOpSize) 1151 | { 1152 | case 1: 1153 | return ReadSigned8(state); 1154 | case 2: 1155 | return ReadSigned16(state); 1156 | case 4: 1157 | case 8: 1158 | return ReadSigned32(state); 1159 | } 1160 | return 0; 1161 | } 1162 | 1163 | 1164 | static void UpdateOperationForAddrSize(DecodeState* state) 1165 | { 1166 | if (state->addrSize == 4) 1167 | state->result->operation = (InstructionOperation)(state->result->operation + 1); 1168 | else if (state->addrSize == 8) 1169 | state->result->operation = (InstructionOperation)(state->result->operation + 2); 1170 | } 1171 | 1172 | 1173 | static void ProcessEncoding(DecodeState* state, const InstructionEncoding* encoding) 1174 | { 1175 | state->result->operation = (InstructionOperation)encoding->operation; 1176 | 1177 | state->flags = encoding->flags; 1178 | if (state->using64 && (state->flags & DEC_FLAG_INVALID_IN_64BIT)) 1179 | { 1180 | state->invalid = true; 1181 | return; 1182 | } 1183 | if (state->using64 && (state->flags & DEC_FLAG_DEFAULT_TO_64BIT)) 1184 | state->opSize = state->opPrefix ? 4 : 8; 1185 | state->finalOpSize = GetFinalOpSize(state); 1186 | 1187 | if (state->flags & DEC_FLAG_FLIP_OPERANDS) 1188 | { 1189 | state->operand0 = &state->result->operands[1]; 1190 | state->operand1 = &state->result->operands[0]; 1191 | } 1192 | else 1193 | { 1194 | state->operand0 = &state->result->operands[0]; 1195 | state->operand1 = &state->result->operands[1]; 1196 | } 1197 | 1198 | if (state->flags & DEC_FLAG_FORCE_16BIT) 1199 | state->finalOpSize = 2; 1200 | 1201 | if (state->flags & DEC_FLAG_OPERATION_OP_SIZE) 1202 | { 1203 | if (state->finalOpSize == 4) 1204 | state->result->operation = (InstructionOperation)(state->result->operation + 1); 1205 | else if (state->finalOpSize == 8) 1206 | state->result->operation = (InstructionOperation)(state->result->operation + 2); 1207 | } 1208 | 1209 | if (state->flags & DEC_FLAG_REP) 1210 | { 1211 | if (state->rep != REP_PREFIX_NONE) 1212 | state->result->flags |= X86_FLAG_REP; 1213 | } 1214 | else if (state->flags & DEC_FLAG_REP_COND) 1215 | { 1216 | if (state->rep == REP_PREFIX_REPNE) 1217 | state->result->flags |= X86_FLAG_REPNE; 1218 | else if (state->rep == REP_PREFIX_REPE) 1219 | state->result->flags |= X86_FLAG_REPE; 1220 | } 1221 | 1222 | encoding->func(state); 1223 | 1224 | if (state->result->operation == INVALID) 1225 | state->invalid = true; 1226 | 1227 | if (state->result->flags & X86_FLAG_LOCK) 1228 | { 1229 | // Ensure instruction allows lock and it has proper semantics 1230 | if (!(state->flags & DEC_FLAG_LOCK)) 1231 | state->invalid = true; 1232 | else if (state->result->operation == CMP) 1233 | state->invalid = true; 1234 | else if ((state->result->operands[0].operand != MEM) && (state->result->operands[1].operand != MEM)) 1235 | state->invalid = true; 1236 | } 1237 | } 1238 | 1239 | 1240 | static void ProcessOpcode(DecodeState* state, const InstructionEncoding* map, uint8_t opcode) 1241 | { 1242 | ProcessEncoding(state, &map[opcode]); 1243 | } 1244 | 1245 | 1246 | static void ProcessSparseOpcode(DecodeState* state, const SparseInstructionEncoding* map, size_t mapSize, uint8_t opcode) 1247 | { 1248 | int i, min, max; 1249 | state->result->operation = INVALID; 1250 | for (min = 0, max = (int)mapSize - 1, i = (min + max) / 2; 1251 | min <= max; i = (min + max) / 2) 1252 | { 1253 | if (opcode > map[i].opcode) 1254 | min = i + 1; 1255 | else if (opcode < map[i].opcode) 1256 | max = i - 1; 1257 | else 1258 | { 1259 | ProcessEncoding(state, &map[i].encoding); 1260 | break; 1261 | } 1262 | } 1263 | } 1264 | 1265 | 1266 | static SegmentRegister GetFinalSegment(DecodeState* state, SegmentRegister seg) 1267 | { 1268 | return (state->result->segment == SEG_DEFAULT) ? seg : state->result->segment; 1269 | } 1270 | 1271 | 1272 | static void SetMemOperand(DecodeState* state, InstructionOperand* oper, const RMDef* def, int64_t immed) 1273 | { 1274 | oper->operand = MEM; 1275 | oper->components[0] = def->first; 1276 | oper->components[1] = def->second; 1277 | oper->immediate = immed; 1278 | oper->segment = GetFinalSegment(state, def->segment); 1279 | } 1280 | 1281 | 1282 | static void DecodeRM(DecodeState* state, InstructionOperand* rmOper, const RegDef* regList, uint16_t rmSize, uint8_t* regOper) 1283 | { 1284 | uint8_t rmByte = Read8(state); 1285 | uint8_t mod = rmByte >> 6; 1286 | uint8_t rm = rmByte & 7; 1287 | InstructionOperand temp; 1288 | 1289 | if (regOper) 1290 | *regOper = (rmByte >> 3) & 7; 1291 | 1292 | if (!rmOper) 1293 | rmOper = &temp; 1294 | 1295 | rmOper->size = rmSize; 1296 | if (state->addrSize == 2) 1297 | { 1298 | static const RMDef rm16Components[9] = {{REG_BX, REG_SI, SEG_DS}, {REG_BX, REG_DI, SEG_DS}, 1299 | {REG_BP, REG_SI, SEG_SS}, {REG_BP, REG_DI, SEG_SS}, {REG_SI, NONE, SEG_DS}, 1300 | {REG_DI, NONE, SEG_DS}, {REG_BP, NONE, SEG_SS}, {REG_BX, NONE, SEG_DS}, 1301 | {NONE, NONE, SEG_DS}}; 1302 | switch (mod) 1303 | { 1304 | case 0: 1305 | if (rm == 6) 1306 | { 1307 | rm = 8; 1308 | SetMemOperand(state, rmOper, &rm16Components[rm], Read16(state)); 1309 | } 1310 | else 1311 | SetMemOperand(state, rmOper, &rm16Components[rm], 0); 1312 | break; 1313 | case 1: 1314 | SetMemOperand(state, rmOper, &rm16Components[rm], ReadSigned8(state)); 1315 | break; 1316 | case 2: 1317 | SetMemOperand(state, rmOper, &rm16Components[rm], ReadSigned16(state)); 1318 | break; 1319 | case 3: 1320 | rmOper->operand = (OperandType)regList[rm]; 1321 | break; 1322 | } 1323 | if (rmOper->components[0] == NONE) 1324 | rmOper->immediate &= 0xffff; 1325 | } 1326 | else 1327 | { 1328 | const RegDef* addrRegList = GetRegListForAddrSize(state); 1329 | uint8_t rmReg1Offset = state->rexRM1 ? 8 : 0; 1330 | uint8_t rmReg2Offset = state->rexRM2 ? 8 : 0; 1331 | SegmentRegister seg = SEG_DEFAULT; 1332 | rmOper->operand = MEM; 1333 | if ((mod != 3) && (rm == 4)) 1334 | { 1335 | // SIB byte present 1336 | uint8_t sibByte = Read8(state); 1337 | uint8_t base = sibByte & 7; 1338 | uint8_t index = (sibByte >> 3) & 7; 1339 | rmOper->scale = 1 << (sibByte >> 6); 1340 | if ((mod != 0) || (base != 5)) 1341 | rmOper->components[0] = (OperandType)addrRegList[base + rmReg1Offset]; 1342 | if ((index + rmReg2Offset) != 4) 1343 | rmOper->components[1] = (OperandType)addrRegList[index + rmReg2Offset]; 1344 | switch (mod) 1345 | { 1346 | case 0: 1347 | if (base == 5) 1348 | rmOper->immediate = ReadSigned32(state); 1349 | break; 1350 | case 1: 1351 | rmOper->immediate = ReadSigned8(state); 1352 | break; 1353 | case 2: 1354 | rmOper->immediate = ReadSigned32(state); 1355 | break; 1356 | } 1357 | if (((base + rmReg1Offset) == 4) || ((base + rmReg1Offset) == 5)) 1358 | seg = SEG_SS; 1359 | else 1360 | seg = SEG_DS; 1361 | } 1362 | else 1363 | { 1364 | switch (mod) 1365 | { 1366 | case 0: 1367 | if (rm == 5) 1368 | { 1369 | rmOper->immediate = ReadSigned32(state); 1370 | if (state->addrSize == 8) 1371 | { 1372 | state->ripRelFixup = &rmOper->immediate; 1373 | rmOper->relative = true; 1374 | } 1375 | } 1376 | else 1377 | rmOper->components[0] = (OperandType)addrRegList[rm + rmReg1Offset]; 1378 | seg = SEG_DS; 1379 | break; 1380 | case 1: 1381 | rmOper->components[0] = (OperandType)addrRegList[rm + rmReg1Offset]; 1382 | rmOper->immediate = ReadSigned8(state); 1383 | seg = (rm == 5) ? SEG_SS : SEG_DS; 1384 | break; 1385 | case 2: 1386 | rmOper->components[0] = (OperandType)addrRegList[rm + rmReg1Offset]; 1387 | rmOper->immediate = ReadSigned32(state); 1388 | seg = (rm == 5) ? SEG_SS : SEG_DS; 1389 | break; 1390 | case 3: 1391 | rmOper->operand = (OperandType)regList[rm + rmReg1Offset]; 1392 | break; 1393 | } 1394 | } 1395 | if (seg != SEG_DEFAULT) 1396 | rmOper->segment = GetFinalSegment(state, seg); 1397 | } 1398 | } 1399 | 1400 | 1401 | static void DecodeRMReg(DecodeState* state, InstructionOperand* rmOper, const RegDef* rmRegList, uint16_t rmSize, 1402 | InstructionOperand* regOper, const RegDef* regList, uint16_t regSize) 1403 | { 1404 | uint8_t reg; 1405 | DecodeRM(state, rmOper, rmRegList, rmSize, ®); 1406 | if (regOper) 1407 | { 1408 | uint8_t regOffset = state->rexReg ? 8 : 0; 1409 | regOper->size = regSize; 1410 | regOper->operand = (OperandType)regList[reg + regOffset]; 1411 | } 1412 | } 1413 | 1414 | 1415 | static void SetOperandToEsEdi(DecodeState* state, InstructionOperand* oper, uint16_t size) 1416 | { 1417 | const RegDef* addrRegList = GetRegListForAddrSize(state); 1418 | oper->operand = MEM; 1419 | oper->components[0] = (OperandType)addrRegList[7]; 1420 | oper->size = size; 1421 | oper->segment = SEG_ES; 1422 | } 1423 | 1424 | 1425 | static void SetOperandToDsEsi(DecodeState* state, InstructionOperand* oper, uint16_t size) 1426 | { 1427 | const RegDef* addrRegList = GetRegListForAddrSize(state); 1428 | oper->operand = MEM; 1429 | oper->components[0] = (OperandType)addrRegList[6]; 1430 | oper->size = size; 1431 | oper->segment = GetFinalSegment(state, SEG_DS); 1432 | } 1433 | 1434 | 1435 | static void SetOperandToImmAddr(DecodeState* state, InstructionOperand* oper) 1436 | { 1437 | oper->operand = MEM; 1438 | oper->immediate = ReadAddrSize(state); 1439 | oper->segment = GetFinalSegment(state, SEG_DS); 1440 | oper->size = state->finalOpSize; 1441 | } 1442 | 1443 | 1444 | static void SetOperandToEaxFinalOpSize(DecodeState* state, InstructionOperand* oper) 1445 | { 1446 | const RegDef* regList = GetRegListForFinalOpSize(state); 1447 | oper->operand = (OperandType)regList[0]; 1448 | oper->size = state->finalOpSize; 1449 | } 1450 | 1451 | 1452 | static void SetOperandToOpReg(DecodeState* state, InstructionOperand* oper) 1453 | { 1454 | const RegDef* regList = GetRegListForFinalOpSize(state); 1455 | uint8_t regOffset = state->rexRM1 ? 8 : 0; 1456 | oper->operand = (OperandType)regList[(state->opcode[-1] & 7) + regOffset]; 1457 | oper->size = state->finalOpSize; 1458 | } 1459 | 1460 | 1461 | static void SetOperandToImm(DecodeState* state, InstructionOperand* oper) 1462 | { 1463 | oper->operand = IMM; 1464 | oper->size = state->finalOpSize; 1465 | oper->immediate = ReadFinalOpSize(state); 1466 | } 1467 | 1468 | 1469 | static void SetOperandToImm8(DecodeState* state, InstructionOperand* oper) 1470 | { 1471 | oper->operand = IMM; 1472 | oper->size = 1; 1473 | oper->immediate = Read8(state); 1474 | } 1475 | 1476 | 1477 | static void SetOperandToImm16(DecodeState* state, InstructionOperand* oper) 1478 | { 1479 | oper->operand = IMM; 1480 | oper->size = 2; 1481 | oper->immediate = Read16(state); 1482 | } 1483 | 1484 | 1485 | static uint8_t DecodeSSEPrefix(DecodeState* state) 1486 | { 1487 | if (state->opPrefix) 1488 | { 1489 | state->opPrefix = false; 1490 | return 1; 1491 | } 1492 | else if (state->rep == REP_PREFIX_REPNE) 1493 | { 1494 | state->rep = REP_PREFIX_NONE; 1495 | return 2; 1496 | } 1497 | else if (state->rep == REP_PREFIX_REPE) 1498 | { 1499 | state->rep = REP_PREFIX_NONE; 1500 | return 3; 1501 | } 1502 | return 0; 1503 | } 1504 | 1505 | 1506 | static uint16_t GetSizeForSSEType(uint8_t type) 1507 | { 1508 | if (type == 2) 1509 | return 8; 1510 | if (type == 3) 1511 | return 4; 1512 | return 16; 1513 | } 1514 | 1515 | 1516 | static InstructionOperand* GetOperandForSSEEntryType(DecodeState* state, uint16_t type, uint8_t operandIndex) 1517 | { 1518 | if (type == SSE_128_FLIP || type == SSE_64_FLIP) { 1519 | operandIndex = 1 - operandIndex; 1520 | } 1521 | if (operandIndex == 0) 1522 | return state->operand0; 1523 | return state->operand1; 1524 | } 1525 | 1526 | 1527 | static const RegDef* GetRegListForSSEEntryType(DecodeState* state, uint16_t type) 1528 | { 1529 | switch (type) 1530 | { 1531 | case MMX_32: 1532 | case MMX_64: 1533 | return mmxRegList; 1534 | case GPR_32_OR_64: 1535 | return (state->opSize == 8) ? reg64List : reg32List; 1536 | default: 1537 | return xmmRegList; 1538 | } 1539 | } 1540 | 1541 | 1542 | static uint16_t GetSizeForSSEEntryType(DecodeState* state, uint16_t type) 1543 | { 1544 | switch (type) 1545 | { 1546 | case SSE_16: 1547 | return 2; 1548 | case SSE_32: 1549 | case MMX_32: 1550 | return 4; 1551 | case SSE_64: 1552 | case MMX_64: 1553 | case SSE_64_FLIP: 1554 | return 8; 1555 | case GPR_32_OR_64: 1556 | return (state->opSize == 8) ? 8 : 4; 1557 | default: 1558 | return 16; 1559 | } 1560 | } 1561 | 1562 | 1563 | static void UpdateOperationForSSEEntryType(DecodeState* state, uint16_t type) 1564 | { 1565 | if ((type == GPR_32_OR_64) && (state->opSize == 8)) 1566 | state->result->operation = (InstructionOperation)((int)state->result->operation + 1); 1567 | } 1568 | 1569 | 1570 | static void InvalidDecode(DecodeState* state) 1571 | { 1572 | state->invalid = true; 1573 | } 1574 | 1575 | 1576 | static void DecodeTwoByte(DecodeState* state) 1577 | { 1578 | uint8_t opcode = Read8(state); 1579 | if (opcode == 0x38) 1580 | ProcessSparseOpcode(state, threeByte0F38Map, sizeof(threeByte0F38Map) / sizeof(SparseInstructionEncoding), Read8(state)); 1581 | else if (opcode == 0x3a) 1582 | { 1583 | ProcessSparseOpcode(state, threeByte0F3AMap, sizeof(threeByte0F3AMap) / sizeof(SparseInstructionEncoding), Read8(state)); 1584 | SetOperandToImm8(state, &state->result->operands[2]); 1585 | } 1586 | else 1587 | ProcessOpcode(state, twoByteOpcodeMap, opcode); 1588 | } 1589 | 1590 | 1591 | static void DecodeFpu(DecodeState* state) 1592 | { 1593 | uint8_t modRM = Peek8(state); 1594 | uint8_t reg = (modRM >> 3) & 7; 1595 | uint8_t op = (uint8_t)state->result->operation; 1596 | 1597 | const InstructionEncoding* map; 1598 | if ((modRM & 0xc0) == 0xc0) 1599 | map = fpuRegOpcodeMap[op]; 1600 | else 1601 | map = fpuMemOpcodeMap[op]; 1602 | ProcessEncoding(state, &map[reg]); 1603 | } 1604 | 1605 | 1606 | static void DecodeNoOperands(DecodeState* state) 1607 | { 1608 | } 1609 | 1610 | 1611 | static void DecodeRegRM(DecodeState* state) 1612 | { 1613 | uint16_t size = state->finalOpSize; 1614 | const RegDef* regList = GetRegListForFinalOpSize(state); 1615 | switch (state->flags & DEC_FLAG_REG_RM_SIZE_MASK) 1616 | { 1617 | case 0: 1618 | break; 1619 | case DEC_FLAG_REG_RM_2X_SIZE: 1620 | size *= 2; 1621 | break; 1622 | case DEC_FLAG_REG_RM_FAR_SIZE: 1623 | size += 2; 1624 | break; 1625 | case DEC_FLAG_REG_RM_NO_SIZE: 1626 | size = 0; 1627 | break; 1628 | } 1629 | 1630 | DecodeRMReg(state, state->operand1, regList, size, state->operand0, regList, state->finalOpSize); 1631 | 1632 | if ((size != state->finalOpSize) && (state->operand1->operand != MEM)) 1633 | state->invalid = true; 1634 | } 1635 | 1636 | 1637 | static void DecodeRegRMImm(DecodeState* state) 1638 | { 1639 | const RegDef* regList = GetRegListForFinalOpSize(state); 1640 | DecodeRMReg(state, state->operand1, regList, state->finalOpSize, state->operand0, regList, state->finalOpSize); 1641 | SetOperandToImm(state, &state->result->operands[2]); 1642 | } 1643 | 1644 | 1645 | static void DecodeRMRegImm8(DecodeState* state) 1646 | { 1647 | const RegDef* regList = GetRegListForFinalOpSize(state); 1648 | DecodeRMReg(state, state->operand0, regList, state->finalOpSize, state->operand1, regList, state->finalOpSize); 1649 | SetOperandToImm8(state, &state->result->operands[2]); 1650 | } 1651 | 1652 | 1653 | static void DecodeRMRegCL(DecodeState* state) 1654 | { 1655 | const RegDef* regList = GetRegListForFinalOpSize(state); 1656 | DecodeRMReg(state, state->operand0, regList, state->finalOpSize, state->operand1, regList, state->finalOpSize); 1657 | state->result->operands[2].operand = REG_CL; 1658 | state->result->operands[2].size = 1; 1659 | } 1660 | 1661 | 1662 | static void DecodeEaxImm(DecodeState* state) 1663 | { 1664 | SetOperandToEaxFinalOpSize(state, state->operand0); 1665 | SetOperandToImm(state, state->operand1); 1666 | } 1667 | 1668 | 1669 | static void DecodePushPopSeg(DecodeState* state) 1670 | { 1671 | int8_t offset = 0; 1672 | if (state->opcode[-1] >= 0xa0) // FS/GS 1673 | offset = -16; 1674 | state->operand0->operand = (OperandType)(REG_ES + (state->opcode[-1] >> 3) + offset); 1675 | state->operand0->size = state->opSize; 1676 | } 1677 | 1678 | 1679 | static void DecodeOpReg(DecodeState* state) 1680 | { 1681 | SetOperandToOpReg(state, state->operand0); 1682 | } 1683 | 1684 | 1685 | static void DecodeEaxOpReg(DecodeState* state) 1686 | { 1687 | SetOperandToEaxFinalOpSize(state, state->operand0); 1688 | SetOperandToOpReg(state, state->operand1); 1689 | } 1690 | 1691 | 1692 | static void DecodeOpRegImm(DecodeState* state) 1693 | { 1694 | SetOperandToOpReg(state, state->operand0); 1695 | state->operand1->operand = IMM; 1696 | state->operand1->size = state->finalOpSize; 1697 | state->operand1->immediate = (state->opSize == 8) ? Read64(state) : ReadFinalOpSize(state); 1698 | } 1699 | 1700 | 1701 | static void DecodeNop(DecodeState* state) 1702 | { 1703 | if (state->rexRM1) 1704 | { 1705 | state->result->operation = XCHG; 1706 | DecodeEaxOpReg(state); 1707 | } 1708 | } 1709 | 1710 | 1711 | static void DecodeImm(DecodeState* state) 1712 | { 1713 | SetOperandToImm(state, state->operand0); 1714 | } 1715 | 1716 | 1717 | static void DecodeImm16Imm8(DecodeState* state) 1718 | { 1719 | SetOperandToImm16(state, state->operand0); 1720 | SetOperandToImm8(state, state->operand1); 1721 | } 1722 | 1723 | 1724 | static void DecodeEdiDx(DecodeState* state) 1725 | { 1726 | SetOperandToEsEdi(state, state->operand0, state->finalOpSize); 1727 | state->operand1->operand = REG_DX; 1728 | state->operand1->size = 2; 1729 | } 1730 | 1731 | 1732 | static void DecodeDxEsi(DecodeState* state) 1733 | { 1734 | state->operand0->operand = REG_DX; 1735 | state->operand0->size = 2; 1736 | SetOperandToDsEsi(state, state->operand1, state->finalOpSize); 1737 | } 1738 | 1739 | 1740 | static void DecodeRelImm(DecodeState* state) 1741 | { 1742 | state->operand0->operand = IMM; 1743 | state->operand0->size = state->opSize; 1744 | state->operand0->immediate = ReadSignedFinalOpSize(state); 1745 | state->operand0->immediate += state->addr + (state->opcode - state->opcodeStart); 1746 | } 1747 | 1748 | 1749 | static void DecodeRelImmAddrSize(DecodeState* state) 1750 | { 1751 | DecodeRelImm(state); 1752 | UpdateOperationForAddrSize(state); 1753 | } 1754 | 1755 | 1756 | static void DecodeGroupRM(DecodeState* state) 1757 | { 1758 | const RegDef* regList = GetRegListForFinalOpSize(state); 1759 | uint8_t regField; 1760 | DecodeRM(state, state->operand0, regList, state->finalOpSize, ®Field); 1761 | state->result->operation = (InstructionOperation)groupOperations[(int)state->result->operation][regField]; 1762 | } 1763 | 1764 | 1765 | static void DecodeGroupRMImm(DecodeState* state) 1766 | { 1767 | DecodeGroupRM(state); 1768 | SetOperandToImm(state, state->operand1); 1769 | } 1770 | 1771 | 1772 | static void DecodeGroupRMImm8V(DecodeState* state) 1773 | { 1774 | DecodeGroupRM(state); 1775 | SetOperandToImm8(state, state->operand1); 1776 | } 1777 | 1778 | 1779 | static void DecodeGroupRMOne(DecodeState* state) 1780 | { 1781 | DecodeGroupRM(state); 1782 | state->operand1->operand = IMM; 1783 | state->operand1->size = 1; 1784 | state->operand1->immediate = 1; 1785 | } 1786 | 1787 | 1788 | static void DecodeGroupRMCl(DecodeState* state) 1789 | { 1790 | DecodeGroupRM(state); 1791 | state->operand1->operand = REG_CL; 1792 | state->operand1->size = 1; 1793 | } 1794 | 1795 | 1796 | static void DecodeGroupF6F7(DecodeState* state) 1797 | { 1798 | DecodeGroupRM(state); 1799 | if (state->result->operation == TEST) 1800 | SetOperandToImm(state, state->operand1); 1801 | // Check for valid locking semantics 1802 | if ((state->result->flags & X86_FLAG_LOCK) && (state->result->operation != NOT) && (state->result->operation != NEG)) 1803 | state->invalid = true; 1804 | } 1805 | 1806 | 1807 | static void DecodeGroupFF(DecodeState* state) 1808 | { 1809 | if (state->using64) 1810 | { 1811 | // Default to 64-bit for jumps and calls 1812 | uint8_t rm = Peek8(state); 1813 | uint8_t regField = (rm >> 3) & 7; 1814 | if ((regField >= 2) && (regField <= 5)) 1815 | state->finalOpSize = state->opSize = state->opPrefix ? 4 : 8; 1816 | else if (regField == 6) 1817 | state->finalOpSize = state->opSize = 8; // Prefix doesn't matter for 64 bit push 1818 | } 1819 | DecodeGroupRM(state); 1820 | // Check for valid far jump/call semantics 1821 | if ((state->result->operation == CALLF) || (state->result->operation == JMPF)) 1822 | { 1823 | if (state->operand0->operand != MEM) 1824 | state->invalid = true; 1825 | state->operand0->size += 2; 1826 | } 1827 | // Check for valid locking semantics 1828 | if ((state->result->flags & X86_FLAG_LOCK) && (state->result->operation != INC) && (state->result->operation != DEC)) 1829 | state->invalid = true; 1830 | } 1831 | 1832 | 1833 | static void DecodeGroup0F00(DecodeState* state) 1834 | { 1835 | uint8_t rm = Peek8(state); 1836 | uint8_t regField = (rm >> 3) & 7; 1837 | if (regField >= 2) 1838 | state->opSize = 2; 1839 | DecodeGroupRM(state); 1840 | } 1841 | 1842 | 1843 | static void DecodeGroup0F01(DecodeState* state) 1844 | { 1845 | uint8_t rm = Peek8(state); 1846 | uint8_t modField = (rm >> 6) & 3; 1847 | uint8_t regField = (rm >> 3) & 7; 1848 | uint8_t rmField = rm & 7; 1849 | 1850 | if ((modField == 3) && (regField != 4) && (regField != 6)) 1851 | { 1852 | state->result->operation = (InstructionOperation)group0F01RegOperations[regField][rmField]; 1853 | Read8(state); 1854 | return; 1855 | } 1856 | 1857 | if (regField < 4) 1858 | state->opSize = state->using64 ? 10 : 6; 1859 | else if (regField != 7) 1860 | state->opSize = 2; 1861 | else 1862 | state->opSize = 1; 1863 | DecodeGroupRM(state); 1864 | } 1865 | 1866 | 1867 | static void DecodeGroup0FAE(DecodeState* state) 1868 | { 1869 | uint8_t rm = Peek8(state); 1870 | uint8_t modField = (rm >> 6) & 3; 1871 | uint8_t regField = (rm >> 3) & 7; 1872 | 1873 | if (((rm & 0xf8) == 0xe8) || ((rm & 0xf8) == 0xf8) || ((rm & 0xf8) == 0xf0)) 1874 | { 1875 | state->result->operation = (InstructionOperation)groupOperations[(int)state->result->operation + 1][regField]; 1876 | Read8(state); 1877 | return; 1878 | } 1879 | 1880 | if (modField == 3) 1881 | { 1882 | state->result->operation = (InstructionOperation)groupOperations[(int)state->result->operation + 1][regField]; 1883 | return; 1884 | } 1885 | 1886 | if ((regField & 2) == 0) 1887 | state->opSize = 512; 1888 | else if ((regField & 6) == 2) 1889 | state->opSize = 4; 1890 | else 1891 | state->opSize = 1; 1892 | DecodeGroupRM(state); 1893 | } 1894 | 1895 | 1896 | static void Decode0FB8(DecodeState* state) 1897 | { 1898 | if (state->rep != REP_PREFIX_REPE) 1899 | { 1900 | if (state->using64) 1901 | state->opSize = state->opPrefix ? 4 : 8; 1902 | state->finalOpSize = GetFinalOpSize(state); 1903 | DecodeRelImm(state); 1904 | return; 1905 | } 1906 | 1907 | DecodeRegRM(state); 1908 | } 1909 | 1910 | 1911 | static void DecodeRMSRegV(DecodeState* state) 1912 | { 1913 | const RegDef* regList = GetRegListForOpSize(state); 1914 | uint8_t regField; 1915 | DecodeRM(state, state->operand0, regList, state->opSize, ®Field); 1916 | if (regField >= 6) 1917 | state->invalid = true; 1918 | state->operand1->operand = (OperandType)(REG_ES + regField); 1919 | state->operand1->size = 2; 1920 | if (state->result->operands[0].operand == REG_CS) 1921 | state->invalid = true; 1922 | } 1923 | 1924 | 1925 | static void DecodeRM8(DecodeState* state) 1926 | { 1927 | const RegDef* regList = GetByteRegList(state); 1928 | DecodeRM(state, state->operand0, regList, 1, NULL); 1929 | } 1930 | 1931 | 1932 | static void DecodeRMV(DecodeState* state) 1933 | { 1934 | const RegDef* regList = GetRegListForOpSize(state); 1935 | DecodeRM(state, state->operand0, regList, state->opSize, NULL); 1936 | } 1937 | 1938 | 1939 | static void DecodeFarImm(DecodeState* state) 1940 | { 1941 | SetOperandToImm(state, state->operand1); 1942 | SetOperandToImm16(state, state->operand0); 1943 | } 1944 | 1945 | 1946 | static void DecodeEaxAddr(DecodeState* state) 1947 | { 1948 | SetOperandToEaxFinalOpSize(state, state->operand0); 1949 | SetOperandToImmAddr(state, state->operand1); 1950 | } 1951 | 1952 | 1953 | static void DecodeEdiEsi(DecodeState* state) 1954 | { 1955 | SetOperandToEsEdi(state, state->operand0, state->finalOpSize); 1956 | SetOperandToDsEsi(state, state->operand1, state->finalOpSize); 1957 | } 1958 | 1959 | 1960 | static void DecodeEdiEax(DecodeState* state) 1961 | { 1962 | SetOperandToEsEdi(state, state->operand0, state->finalOpSize); 1963 | SetOperandToEaxFinalOpSize(state, state->operand1); 1964 | } 1965 | 1966 | 1967 | static void DecodeEaxEsi(DecodeState* state) 1968 | { 1969 | SetOperandToEaxFinalOpSize(state, state->operand0); 1970 | SetOperandToDsEsi(state, state->operand1, state->finalOpSize); 1971 | } 1972 | 1973 | 1974 | static void DecodeAlEbxAl(DecodeState* state) 1975 | { 1976 | const RegDef* regList = GetRegListForAddrSize(state); 1977 | state->operand0->operand = REG_AL; 1978 | state->operand0->size = 1; 1979 | state->operand1->operand = MEM; 1980 | state->operand1->components[0] = (OperandType)regList[3]; 1981 | state->operand1->components[1] = REG_AL; 1982 | state->operand1->size = 1; 1983 | state->operand1->segment = GetFinalSegment(state, SEG_DS); 1984 | } 1985 | 1986 | 1987 | static void DecodeEaxImm8(DecodeState* state) 1988 | { 1989 | SetOperandToEaxFinalOpSize(state, state->operand0); 1990 | SetOperandToImm8(state, state->operand1); 1991 | } 1992 | 1993 | 1994 | static void DecodeEaxDx(DecodeState* state) 1995 | { 1996 | SetOperandToEaxFinalOpSize(state, state->operand0); 1997 | state->operand1->operand = REG_DX; 1998 | state->operand1->size = 2; 1999 | } 2000 | 2001 | 2002 | static void Decode3DNow(DecodeState* state) 2003 | { 2004 | uint8_t op; 2005 | int i, min, max; 2006 | DecodeRMReg(state, state->operand1, mmxRegList, 8, state->operand0, mmxRegList, 8); 2007 | op = Read8(state); 2008 | state->result->operation = INVALID; 2009 | for (min = 0, max = (int)(sizeof(sparse3DNowOpcodes) / sizeof(SparseOpEntry)) - 1, i = (min + max) / 2; 2010 | min <= max; i = (min + max) / 2) 2011 | { 2012 | if (op > sparse3DNowOpcodes[i].opcode) 2013 | min = i + 1; 2014 | else if (op < sparse3DNowOpcodes[i].opcode) 2015 | max = i - 1; 2016 | else 2017 | { 2018 | state->result->operation = (InstructionOperation)sparse3DNowOpcodes[i].operation; 2019 | break; 2020 | } 2021 | } 2022 | } 2023 | 2024 | 2025 | static void DecodeSSETable(DecodeState* state) 2026 | { 2027 | uint8_t type = DecodeSSEPrefix(state); 2028 | uint8_t rm = Peek8(state); 2029 | uint8_t modField = (rm >> 6) & 3; 2030 | 2031 | const SSETableEntry* entry = &sseTable[(int)state->result->operation]; 2032 | const SSETableOperationEntry* opEntry; 2033 | 2034 | if (modField == 3) 2035 | opEntry = &entry->regOps[type]; 2036 | else 2037 | opEntry = &entry->memOps[type]; 2038 | 2039 | state->result->operation = (InstructionOperation)opEntry->operation; 2040 | DecodeRMReg(state, GetOperandForSSEEntryType(state, opEntry->rmType, 1), GetRegListForSSEEntryType(state, opEntry->rmType), 2041 | GetSizeForSSEEntryType(state, opEntry->rmType), GetOperandForSSEEntryType(state, opEntry->regType, 0), 2042 | GetRegListForSSEEntryType(state, opEntry->regType), GetSizeForSSEEntryType(state, opEntry->regType)); 2043 | 2044 | if (state->flags & DEC_FLAG_INC_OPERATION_FOR_64) 2045 | { 2046 | UpdateOperationForSSEEntryType(state, opEntry->regType); 2047 | UpdateOperationForSSEEntryType(state, opEntry->rmType); 2048 | } 2049 | } 2050 | 2051 | 2052 | static void DecodeSSETableImm8(DecodeState* state) 2053 | { 2054 | DecodeSSETable(state); 2055 | SetOperandToImm8(state, &state->result->operands[2]); 2056 | } 2057 | 2058 | 2059 | static void DecodeSSETableMem8(DecodeState* state) 2060 | { 2061 | DecodeSSETable(state); 2062 | if (state->operand0->operand == MEM) 2063 | state->operand0->size = 1; 2064 | if (state->operand1->operand == MEM) 2065 | state->operand1->size = 1; 2066 | } 2067 | 2068 | 2069 | static void DecodeSSE(DecodeState* state) 2070 | { 2071 | uint8_t type = DecodeSSEPrefix(state); 2072 | uint8_t rm = Peek8(state); 2073 | uint8_t modField = (rm >> 6) & 3; 2074 | uint16_t size; 2075 | 2076 | state->result->operation = (InstructionOperation)((int)state->result->operation + type); 2077 | if (modField == 3) 2078 | size = 16; 2079 | else 2080 | size = GetSizeForSSEType(type); 2081 | DecodeRMReg(state, state->operand1, xmmRegList, size, state->operand0, xmmRegList, 16); 2082 | } 2083 | 2084 | 2085 | static void DecodeSSESingle(DecodeState* state) 2086 | { 2087 | uint8_t type = DecodeSSEPrefix(state); 2088 | 2089 | if ((type == 1) || (type == 2)) 2090 | { 2091 | state->invalid = true; 2092 | return; 2093 | } 2094 | 2095 | state->result->operation = (InstructionOperation)((int)state->result->operation + (type & 1)); 2096 | DecodeRMReg(state, state->operand1, xmmRegList, 16, state->operand0, xmmRegList, 16); 2097 | } 2098 | 2099 | 2100 | static void DecodeSSEPacked(DecodeState* state) 2101 | { 2102 | uint8_t type = DecodeSSEPrefix(state); 2103 | 2104 | if ((type == 2) || (type == 3)) 2105 | { 2106 | state->invalid = true; 2107 | return; 2108 | } 2109 | 2110 | state->result->operation = (InstructionOperation)((int)state->result->operation + (type & 1)); 2111 | DecodeRMReg(state, state->operand1, xmmRegList, 16, state->operand0, xmmRegList, 16); 2112 | } 2113 | 2114 | 2115 | static void DecodeMMX(DecodeState* state) 2116 | { 2117 | if (state->opPrefix) 2118 | DecodeRMReg(state, state->operand1, xmmRegList, 16, state->operand0, xmmRegList, 16); 2119 | else 2120 | DecodeRMReg(state, state->operand1, mmxRegList, 8, state->operand0, mmxRegList, 8); 2121 | } 2122 | 2123 | 2124 | static void DecodeMMXSSEOnly(DecodeState* state) 2125 | { 2126 | if (state->opPrefix) 2127 | DecodeRMReg(state, state->operand1, xmmRegList, 16, state->operand0, xmmRegList, 16); 2128 | else 2129 | state->invalid = true; 2130 | } 2131 | 2132 | 2133 | static void DecodeMMXGroup(DecodeState* state) 2134 | { 2135 | uint8_t regField; 2136 | if (state->opPrefix) 2137 | { 2138 | DecodeRM(state, state->operand0, xmmRegList, 16, ®Field); 2139 | state->result->operation = (InstructionOperation)mmxGroupOperations[(int)state->result->operation][regField][1]; 2140 | } 2141 | else 2142 | { 2143 | DecodeRM(state, state->operand0, mmxRegList, 8, ®Field); 2144 | state->result->operation = (InstructionOperation)mmxGroupOperations[(int)state->result->operation][regField][0]; 2145 | } 2146 | SetOperandToImm8(state, state->operand1); 2147 | } 2148 | 2149 | 2150 | static void DecodePinsrw(DecodeState* state) 2151 | { 2152 | DecodeSSETableImm8(state); 2153 | if (state->operand1->operand == MEM) 2154 | state->operand1->size = 2; 2155 | } 2156 | 2157 | 2158 | static void DecodeRegCR(DecodeState* state) 2159 | { 2160 | const RegDef* regList; 2161 | uint8_t reg; 2162 | if (state->opSize == 2) 2163 | state->opSize = 4; 2164 | regList = GetRegListForOpSize(state); 2165 | reg = Read8(state); 2166 | if (state->result->flags & X86_FLAG_LOCK) 2167 | { 2168 | state->result->flags &= ~X86_FLAG_LOCK; 2169 | state->rexReg = true; 2170 | } 2171 | state->operand0->operand = regList[(reg & 7) + (state->rexRM1 ? 8 : 0)]; 2172 | state->operand0->size = state->opSize; 2173 | state->operand1->operand = (OperandType)((int)state->result->operation + ((reg >> 3) & 7) + 2174 | (state->rexReg ? 8 : 0)); 2175 | state->operand1->size = state->opSize; 2176 | state->result->operation = MOV; 2177 | } 2178 | 2179 | 2180 | static void DecodeMovSXZX8(DecodeState* state) 2181 | { 2182 | DecodeRMReg(state, state->operand1, GetByteRegList(state), 1, state->operand0, GetRegListForOpSize(state), state->opSize); 2183 | } 2184 | 2185 | 2186 | static void DecodeMovSXZX16(DecodeState* state) 2187 | { 2188 | DecodeRMReg(state, state->operand1, reg16List, 2, state->operand0, GetRegListForOpSize(state), state->opSize); 2189 | } 2190 | 2191 | 2192 | static void DecodeMem16(DecodeState* state) 2193 | { 2194 | DecodeRM(state, state->operand0, reg32List, 2, NULL); 2195 | if (state->operand0->operand != MEM) 2196 | state->invalid = true; 2197 | } 2198 | 2199 | 2200 | static void DecodeMem32(DecodeState* state) 2201 | { 2202 | DecodeRM(state, state->operand0, reg32List, 4, NULL); 2203 | if (state->operand0->operand != MEM) 2204 | state->invalid = true; 2205 | } 2206 | 2207 | 2208 | static void DecodeMem64(DecodeState* state) 2209 | { 2210 | DecodeRM(state, state->operand0, reg32List, 8, NULL); 2211 | if (state->operand0->operand != MEM) 2212 | state->invalid = true; 2213 | } 2214 | 2215 | 2216 | static void DecodeMem80(DecodeState* state) 2217 | { 2218 | DecodeRM(state, state->operand0, reg32List, 10, NULL); 2219 | if (state->operand0->operand != MEM) 2220 | state->invalid = true; 2221 | } 2222 | 2223 | 2224 | static void DecodeMemFloatEnv(DecodeState* state) 2225 | { 2226 | DecodeRM(state, state->operand0, reg32List, (state->opSize == 2) ? 14 : 28, NULL); 2227 | if (state->operand0->operand != MEM) 2228 | state->invalid = true; 2229 | } 2230 | 2231 | 2232 | static void DecodeMemFloatSave(DecodeState* state) 2233 | { 2234 | DecodeRM(state, state->operand0, reg32List, (state->opSize == 2) ? 94 : 108, NULL); 2235 | if (state->operand0->operand != MEM) 2236 | state->invalid = true; 2237 | } 2238 | 2239 | 2240 | static void DecodeFPUReg(DecodeState* state) 2241 | { 2242 | DecodeRM(state, state->operand0, fpuRegList, 10, NULL); 2243 | } 2244 | 2245 | 2246 | static void DecodeFPURegST0(DecodeState* state) 2247 | { 2248 | DecodeFPUReg(state); 2249 | state->operand1->operand = REG_ST0; 2250 | state->operand1->size = 10; 2251 | } 2252 | 2253 | 2254 | static void DecodeRegGroupNoOperands(DecodeState* state) 2255 | { 2256 | uint8_t rmByte = Read8(state); 2257 | state->result->operation = (InstructionOperation)groupOperations[(int)state->result->operation][rmByte & 7]; 2258 | } 2259 | 2260 | 2261 | static void DecodeRegGroupAX(DecodeState* state) 2262 | { 2263 | DecodeRegGroupNoOperands(state); 2264 | state->operand0->operand = REG_AX; 2265 | state->operand0->size = 2; 2266 | } 2267 | 2268 | 2269 | static void DecodeCmpXch8B(DecodeState* state) 2270 | { 2271 | uint8_t rm = Peek8(state); 2272 | uint8_t regField = (rm >> 3) & 7; 2273 | 2274 | if (regField == 1) 2275 | { 2276 | if (state->opSize == 2) 2277 | state->opSize = 4; 2278 | else if (state->opSize == 8) 2279 | state->result->operation = CMPXCH16B; 2280 | DecodeRM(state, state->operand0, GetRegListForOpSize(state), state->opSize * 2, NULL); 2281 | } 2282 | else if (regField == 6) 2283 | { 2284 | if (state->opPrefix) 2285 | state->result->operation = VMCLEAR; 2286 | else if (state->rep == REP_PREFIX_REPE) 2287 | state->result->operation = VMXON; 2288 | else 2289 | state->result->operation = VMPTRLD; 2290 | DecodeRM(state, state->operand0, reg64List, 8, NULL); 2291 | } 2292 | else if (regField == 7) 2293 | { 2294 | state->result->operation = VMPTRST; 2295 | DecodeRM(state, state->operand0, reg64List, 8, NULL); 2296 | } 2297 | else 2298 | state->invalid = true; 2299 | 2300 | if (state->operand0->operand != MEM) 2301 | state->invalid = true; 2302 | } 2303 | 2304 | 2305 | static void DecodeMovNti(DecodeState* state) 2306 | { 2307 | if (state->opSize == 2) 2308 | state->opSize = 4; 2309 | DecodeRMReg(state, state->operand0, GetRegListForOpSize(state), state->opSize, state->operand1, GetRegListForOpSize(state), state->opSize); 2310 | if (state->operand0->operand != MEM) 2311 | state->invalid = true; 2312 | } 2313 | 2314 | 2315 | static void DecodeCrc32(DecodeState* state) 2316 | { 2317 | const RegDef* srcRegList = GetRegListForFinalOpSize(state); 2318 | const RegDef* destRegList = (state->opSize == 8) ? reg64List : reg32List; 2319 | uint16_t destSize = (state->opSize == 8) ? 8 : 4; 2320 | DecodeRMReg(state, state->operand1, srcRegList, state->finalOpSize, state->operand0, destRegList, destSize); 2321 | } 2322 | 2323 | 2324 | static void DecodeArpl(DecodeState* state) 2325 | { 2326 | if (state->using64) 2327 | { 2328 | // In 64-bit ARPL is repurposed to MOVSXD 2329 | const RegDef* regList = GetRegListForFinalOpSize(state); 2330 | state->result->operation = MOVSXD; 2331 | DecodeRMReg(state, state->operand1, reg32List, 4, state->operand0, regList, state->finalOpSize); 2332 | } 2333 | else 2334 | { 2335 | // ARPL instruction 2336 | state->operand0 = &state->result->operands[1]; 2337 | state->operand1 = &state->result->operands[0]; 2338 | state->finalOpSize = 2; 2339 | DecodeRegRM(state); 2340 | } 2341 | } 2342 | 2343 | 2344 | static void ProcessPrefixes(DecodeState* state) 2345 | { 2346 | uint8_t rex = 0; 2347 | bool addrPrefix = false; 2348 | 2349 | while (!state->invalid) 2350 | { 2351 | uint8_t prefix = Read8(state); 2352 | if ((prefix >= 0x26) && (prefix <= 0x3e) && ((prefix & 7) == 6)) 2353 | { 2354 | // Segment prefix 2355 | state->result->segment = (SegmentRegister)(SEG_ES + ((prefix >> 3) - 4)); 2356 | } 2357 | else if ((prefix == 0x64) || (prefix == 0x65)) 2358 | { 2359 | // FS/GS prefix 2360 | state->result->segment = (SegmentRegister)(SEG_ES + (prefix - 0x60)); 2361 | } 2362 | else if (prefix == 0x66) 2363 | { 2364 | state->opPrefix = true; 2365 | state->result->flags |= X86_FLAG_OPSIZE; 2366 | } 2367 | else if (prefix == 0x67) 2368 | { 2369 | addrPrefix = true; 2370 | state->result->flags |= X86_FLAG_ADDRSIZE; 2371 | } 2372 | else if (prefix == 0xf0) 2373 | state->result->flags |= X86_FLAG_LOCK; 2374 | else if (prefix == 0xf2) 2375 | state->rep = REP_PREFIX_REPNE; 2376 | else if (prefix == 0xf3) 2377 | state->rep = REP_PREFIX_REPE; 2378 | else if (state->using64 && (prefix >= 0x40) && (prefix <= 0x4f)) 2379 | { 2380 | // REX prefix 2381 | rex = prefix; 2382 | continue; 2383 | } 2384 | else 2385 | { 2386 | // Not a prefix, continue instruction processing 2387 | state->opcode--; 2388 | state->len++; 2389 | break; 2390 | } 2391 | 2392 | // Force ignore REX unless it is the last prefix 2393 | rex = 0; 2394 | } 2395 | 2396 | if (state->opPrefix) 2397 | state->opSize = (state->opSize == 2) ? 4 : 2; 2398 | if (addrPrefix) 2399 | state->addrSize = (state->addrSize == 4) ? 2 : 4; 2400 | 2401 | if (rex) 2402 | { 2403 | // REX prefix found before opcode 2404 | state->rex = true; 2405 | state->rexRM1 = (rex & 1) != 0; 2406 | state->rexRM2 = (rex & 2) != 0; 2407 | state->rexReg = (rex & 4) != 0; 2408 | if (rex & 8) 2409 | state->opSize = 8; 2410 | } 2411 | } 2412 | 2413 | 2414 | static void ClearOperand(InstructionOperand* oper) 2415 | { 2416 | oper->operand = NONE; 2417 | oper->components[0] = NONE; 2418 | oper->components[1] = NONE; 2419 | oper->scale = 1; 2420 | oper->immediate = 0; 2421 | oper->relative = false; 2422 | } 2423 | 2424 | 2425 | static void InitDisassemble(DecodeState* state) 2426 | { 2427 | ClearOperand(&state->result->operands[0]); 2428 | ClearOperand(&state->result->operands[1]); 2429 | ClearOperand(&state->result->operands[2]); 2430 | state->result->operation = INVALID; 2431 | state->result->flags = 0; 2432 | state->result->segment = SEG_DEFAULT; 2433 | state->invalid = false; 2434 | state->insufficientLength = false; 2435 | state->opPrefix = false; 2436 | state->rep = REP_PREFIX_NONE; 2437 | state->ripRelFixup = NULL; 2438 | state->rex = false; 2439 | state->rexReg = false; 2440 | state->rexRM1 = false; 2441 | state->rexRM2 = false; 2442 | state->origLen = state->len; 2443 | } 2444 | 2445 | 2446 | static void FinishDisassemble(DecodeState* state) 2447 | { 2448 | state->result->length = state->opcode - state->opcodeStart; 2449 | if (state->ripRelFixup) 2450 | *state->ripRelFixup += state->addr + state->result->length; 2451 | if (state->insufficientLength && (state->origLen < 15)) 2452 | state->result->flags |= X86_FLAG_INSUFFICIENT_LENGTH; 2453 | } 2454 | 2455 | 2456 | bool Disassemble16(const uint8_t* opcode, uint64_t addr, size_t maxLen, Instruction* result) 2457 | { 2458 | DecodeState state; 2459 | state.result = result; 2460 | state.opcodeStart = opcode; 2461 | state.opcode = opcode; 2462 | state.addr = addr; 2463 | state.len = (maxLen > 15) ? 15 : maxLen; 2464 | state.addrSize = 2; 2465 | state.opSize = 2; 2466 | state.using64 = false; 2467 | InitDisassemble(&state); 2468 | 2469 | ProcessPrefixes(&state); 2470 | ProcessOpcode(&state, mainOpcodeMap, Read8(&state)); 2471 | FinishDisassemble(&state); 2472 | return !state.invalid; 2473 | } 2474 | 2475 | 2476 | bool Disassemble32(const uint8_t* opcode, uint64_t addr, size_t maxLen, Instruction* result) 2477 | { 2478 | DecodeState state; 2479 | state.result = result; 2480 | state.opcodeStart = opcode; 2481 | state.opcode = opcode; 2482 | state.addr = addr; 2483 | state.len = (maxLen > 15) ? 15 : maxLen; 2484 | state.addrSize = 4; 2485 | state.opSize = 4; 2486 | state.using64 = false; 2487 | InitDisassemble(&state); 2488 | 2489 | ProcessPrefixes(&state); 2490 | ProcessOpcode(&state, mainOpcodeMap, Read8(&state)); 2491 | FinishDisassemble(&state); 2492 | return !state.invalid; 2493 | } 2494 | 2495 | 2496 | bool Disassemble64(const uint8_t* opcode, uint64_t addr, size_t maxLen, Instruction* result) 2497 | { 2498 | DecodeState state; 2499 | state.result = result; 2500 | state.opcodeStart = opcode; 2501 | state.opcode = opcode; 2502 | state.addr = addr; 2503 | state.len = (maxLen > 15) ? 15 : maxLen; 2504 | state.addrSize = 8; 2505 | state.opSize = 4; 2506 | state.using64 = true; 2507 | InitDisassemble(&state); 2508 | 2509 | ProcessPrefixes(&state); 2510 | ProcessOpcode(&state, mainOpcodeMap, Read8(&state)); 2511 | FinishDisassemble(&state); 2512 | return !state.invalid; 2513 | } 2514 | 2515 | 2516 | static void WriteChar(char** out, size_t* outMaxLen, char ch) 2517 | { 2518 | if (*outMaxLen > 1) 2519 | { 2520 | *((*out)++) = ch; 2521 | (*outMaxLen)--; 2522 | } 2523 | } 2524 | 2525 | 2526 | static void WriteString(char** out, size_t* outMaxLen, const char* str) 2527 | { 2528 | for (; *str; str++) 2529 | WriteChar(out, outMaxLen, *str); 2530 | } 2531 | 2532 | 2533 | static void WriteHex(char** out, size_t* outMaxLen, uint64_t val, uint32_t width, bool prefix) 2534 | { 2535 | char temp[17]; 2536 | int32_t i; 2537 | if (prefix) 2538 | WriteString(out, outMaxLen, "0x"); 2539 | if (width > 16) 2540 | width = 16; 2541 | for (i = (width - 1); i >= 0; i--, val >>= 4) 2542 | { 2543 | char digit = (char)(val & 0xf); 2544 | if (digit < 10) 2545 | temp[i] = digit + '0'; 2546 | else 2547 | temp[i] = digit + 'a' - 10; 2548 | } 2549 | temp[width] = 0; 2550 | WriteString(out, outMaxLen, temp); 2551 | } 2552 | 2553 | 2554 | static const char* GetSizeString(uint16_t size) 2555 | { 2556 | switch (size) 2557 | { 2558 | case 1: 2559 | return "byte "; 2560 | case 2: 2561 | return "word "; 2562 | case 4: 2563 | return "dword "; 2564 | case 6: 2565 | return "fword "; 2566 | case 8: 2567 | return "qword "; 2568 | case 10: 2569 | return "tword "; 2570 | case 16: 2571 | return "oword "; 2572 | default: 2573 | return ""; 2574 | } 2575 | } 2576 | 2577 | 2578 | static void WriteOperand(char** out, size_t* outMaxLen, OperandType type, uint8_t scale, bool plus) 2579 | { 2580 | if (plus) 2581 | WriteString(out, outMaxLen, "+"); 2582 | WriteString(out, outMaxLen, operandString[type]); 2583 | if (scale != 1) 2584 | { 2585 | WriteChar(out, outMaxLen, '*'); 2586 | WriteChar(out, outMaxLen, scale + '0'); 2587 | } 2588 | } 2589 | 2590 | 2591 | size_t FormatInstructionString(char* out, size_t outMaxLen, const char* fmt, const uint8_t* opcode, 2592 | uint64_t addr, const Instruction* instr) 2593 | { 2594 | char* start = out; 2595 | size_t len; 2596 | for (; *fmt; fmt++) 2597 | { 2598 | if (*fmt == '%') 2599 | { 2600 | uint32_t width = 0; 2601 | for (fmt++; *fmt; fmt++) 2602 | { 2603 | if (*fmt == 'a') 2604 | { 2605 | if (width == 0) 2606 | width = sizeof(void*) * 2; 2607 | WriteHex(&out, &outMaxLen, addr, width, false); 2608 | break; 2609 | } 2610 | else if (*fmt == 'b') 2611 | { 2612 | size_t i; 2613 | for (i = 0; i < instr->length; i++) 2614 | WriteHex(&out, &outMaxLen, opcode[i], 2, false); 2615 | for (; i < width; i++) 2616 | WriteString(&out, &outMaxLen, " "); 2617 | break; 2618 | } 2619 | else if (*fmt == 'i') 2620 | { 2621 | char* operationStart = out; 2622 | if (instr->flags & X86_FLAG_ANY_REP) 2623 | { 2624 | WriteString(&out, &outMaxLen, "rep"); 2625 | if (instr->flags & X86_FLAG_REPNE) 2626 | WriteChar(&out, &outMaxLen, 'n'); 2627 | if (instr->flags & (X86_FLAG_REPNE | X86_FLAG_REPE)) 2628 | WriteChar(&out, &outMaxLen, 'e'); 2629 | WriteChar(&out, &outMaxLen, ' '); 2630 | } 2631 | if (instr->flags & X86_FLAG_LOCK) 2632 | WriteString(&out, &outMaxLen, "lock "); 2633 | WriteString(&out, &outMaxLen, operationString[instr->operation]); 2634 | for (; ((size_t)(out - operationStart) < (size_t)width) && (outMaxLen > 1); ) 2635 | WriteChar(&out, &outMaxLen, ' '); 2636 | break; 2637 | } 2638 | else if (*fmt == 'o') 2639 | { 2640 | uint32_t i; 2641 | for (i = 0; i < 3; i++) 2642 | { 2643 | if (instr->operands[i].operand == NONE) 2644 | break; 2645 | if (i != 0) 2646 | WriteString(&out, &outMaxLen, ", "); 2647 | if (instr->operands[i].operand == IMM) 2648 | WriteHex(&out, &outMaxLen, instr->operands[i].immediate, instr->operands[i].size * 2, true); 2649 | else if (instr->operands[i].operand == MEM) 2650 | { 2651 | bool plus = false; 2652 | WriteString(&out, &outMaxLen, GetSizeString(instr->operands[i].size)); 2653 | if ((instr->segment != SEG_DEFAULT) || (instr->operands[i].segment == SEG_ES)) 2654 | { 2655 | WriteOperand(&out, &outMaxLen, (OperandType)(instr->operands[i].segment + REG_ES), 1, false); 2656 | WriteChar(&out, &outMaxLen, ':'); 2657 | } 2658 | WriteChar(&out, &outMaxLen, '['); 2659 | if (instr->operands[i].components[0] != NONE) 2660 | { 2661 | WriteOperand(&out, &outMaxLen, instr->operands[i].components[0], 1, false); 2662 | plus = true; 2663 | } 2664 | if (instr->operands[i].components[1] != NONE) 2665 | { 2666 | WriteOperand(&out, &outMaxLen, instr->operands[i].components[1], instr->operands[i].scale, plus); 2667 | plus = true; 2668 | } 2669 | if ((instr->operands[i].immediate != 0) || ((instr->operands[i].components[0] == NONE) && 2670 | (instr->operands[i].components[1] == NONE))) 2671 | { 2672 | if (plus && ((int64_t)instr->operands[i].immediate >= -0x80) && 2673 | ((int64_t)instr->operands[i].immediate < 0)) 2674 | { 2675 | WriteChar(&out, &outMaxLen, '-'); 2676 | WriteHex(&out, &outMaxLen, -(int64_t)instr->operands[i].immediate, 2, true); 2677 | } 2678 | else if (plus && ((int64_t)instr->operands[i].immediate > 0) && 2679 | ((int64_t)instr->operands[i].immediate <= 0x7f)) 2680 | { 2681 | WriteChar(&out, &outMaxLen, '+'); 2682 | WriteHex(&out, &outMaxLen, instr->operands[i].immediate, 2, true); 2683 | } 2684 | else 2685 | { 2686 | if (plus) 2687 | WriteChar(&out, &outMaxLen, '+'); 2688 | WriteHex(&out, &outMaxLen, instr->operands[i].immediate, 8, true); 2689 | } 2690 | } 2691 | WriteChar(&out, &outMaxLen, ']'); 2692 | } 2693 | else 2694 | WriteOperand(&out, &outMaxLen, instr->operands[i].operand, 1, false); 2695 | } 2696 | break; 2697 | } 2698 | else if ((*fmt >= '0') && (*fmt <= '9')) 2699 | width = (width * 10) + (*fmt - '0'); 2700 | else 2701 | { 2702 | WriteChar(&out, &outMaxLen, *fmt); 2703 | break; 2704 | } 2705 | } 2706 | } 2707 | else 2708 | WriteChar(&out, &outMaxLen, *fmt); 2709 | } 2710 | len = out - start; 2711 | if (outMaxLen > 0) 2712 | *(out++) = 0; 2713 | return len; 2714 | } 2715 | 2716 | 2717 | size_t DisassembleToString16(char* out, size_t outMaxLen, const char* fmt, const uint8_t* opcode, 2718 | uint64_t addr, size_t maxLen, Instruction* instr) 2719 | { 2720 | if (!Disassemble16(opcode, addr, maxLen, instr)) 2721 | return 0; 2722 | return FormatInstructionString(out, outMaxLen, fmt, opcode, addr, instr); 2723 | } 2724 | 2725 | 2726 | size_t DisassembleToString32(char* out, size_t outMaxLen, const char* fmt, const uint8_t* opcode, 2727 | uint64_t addr, size_t maxLen, Instruction* instr) 2728 | { 2729 | if (!Disassemble32(opcode, addr, maxLen, instr)) 2730 | return 0; 2731 | return FormatInstructionString(out, outMaxLen, fmt, opcode, addr, instr); 2732 | } 2733 | 2734 | 2735 | size_t DisassembleToString64(char* out, size_t outMaxLen, const char* fmt, const uint8_t* opcode, 2736 | uint64_t addr, size_t maxLen, Instruction* instr) 2737 | { 2738 | if (!Disassemble64(opcode, addr, maxLen, instr)) 2739 | return 0; 2740 | return FormatInstructionString(out, outMaxLen, fmt, opcode, addr, instr); 2741 | } 2742 | #ifdef __cplusplus 2743 | } 2744 | #endif 2745 | -------------------------------------------------------------------------------- /asmx86.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2006-2015, Rusty Wagner 2 | // All rights reserved. 3 | // 4 | // Redistribution and use in source and binary forms, with or without modification, are permitted provided that 5 | // the following conditions are met: 6 | // 7 | // * Redistributions of source code must retain the above copyright notice, this list of conditions and the 8 | // following disclaimer. 9 | // * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 10 | // the following disclaimer in the documentation and/or other materials provided with the distribution. 11 | // 12 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 13 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 14 | // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 15 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 16 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 17 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 18 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 19 | // POSSIBILITY OF SUCH DAMAGE. 20 | 21 | #ifndef __ASMX86_H__ 22 | #define __ASMX86_H__ 23 | 24 | #ifndef _MSC_VER 25 | #ifndef __cplusplus 26 | #include 27 | #endif 28 | #include 29 | #else 30 | #ifndef __cplusplus 31 | typedef unsigned char bool; 32 | #define true 1 33 | #define false 0 34 | #endif 35 | typedef ptrdiff_t ssize_t; 36 | #endif 37 | 38 | #ifndef WIN32 39 | #include 40 | #endif 41 | 42 | #include 43 | 44 | #undef IN 45 | #undef OUT 46 | 47 | 48 | #define X86_FLAG_LOCK 1 49 | #define X86_FLAG_REP 2 50 | #define X86_FLAG_REPNE 4 51 | #define X86_FLAG_REPE 8 52 | #define X86_FLAG_OPSIZE 16 53 | #define X86_FLAG_ADDRSIZE 32 54 | 55 | #define X86_FLAG_INSUFFICIENT_LENGTH 0x80000000 56 | 57 | #define X86_FLAG_ANY_REP (X86_FLAG_REP | X86_FLAG_REPE | X86_FLAG_REPNE) 58 | 59 | 60 | #ifdef __cplusplus 61 | namespace asmx86 62 | { 63 | #endif 64 | enum InstructionOperation 65 | { 66 | // Independent operations 67 | INVALID = 0, AAA, AAD, AAM, AAS, ADD, ADC, AND, ARPL, BLENDPD, BLENDPS, BLENDVPD, BLENDVPS, 68 | BOUND, BSF, BSR, BSWAP, BT, BTC, BTR, BTS, 69 | CALLF, CALL, CLC, CLD, CLFLUSH, CLI, 70 | CLTS, CMC, CMP, CMPXCH16B, CMPXCH8B, CMPXCHG, CPUID, CRC32, 71 | DAA, DAS, DEC, DIV, DPPD, DPPS, EMMS, ENTER, F2XM1, FABS, FADD, FADDP, FBLD, FBSTP, FCHS, FCLEX, 72 | FCMOVB, FCMOVBE, FCMOVE, FCMOVNB, FCMOVNBE, FCMOVNE, FCMOVNU, FCMOVU, 73 | FCOM, FCOMI, FCOMIP, FCOMP, FCOMPP, FCOS, 74 | FDECSTP, FDISI, FDIV, FDIVP, FDIVR, FDIVRP, FEMMS, FENI, FFREE, FFREEP, FIADD, FICOM, FICOMP, FIDIV, FIDIVR, FILD, 75 | FIMUL, FINCSTP, FINIT, FIST, FISTP, FISTTP, FISUB, FISUBR, 76 | FLD, FLD1, FLDCW, FLDENV, FLDL2E, FLDL2T, FLDLG2, FLDLN2, FLDPI, FLDZ, 77 | FMUL, FMULP, FNOP, FPATAN, FPREM, FPREM1, FPTAN, FRICHOP, FRINEAR, FRINT2, FRNDINT, FRSTOR, FRSTPM, 78 | FSAVE, FSCALE, FSETPM, FSIN, FSINCOS, FSQRT, 79 | FST, FSTCW, FSTDW, FSTENV, FSTP, FSTSG, FSTSW, FSUB, FSUBP, FSUBR, FSUBRP, 80 | FTST, FUCOM, FUCOMI, FUCOMIP, FUCOMP, FUCOMPP, FWAIT, FXAM, FXCH, FXRSTOR, FXSAVE, FXTRACT, FYL2X, FYL2XP1, 81 | GETSEC, HLT, IDIV, IMUL, IN, INC, INT, INT1, INT3, INTO, INVD, INVLPG, IRET, JMPF, JMP, 82 | LAHF, LAR, LDMXCSR, LDS, LEA, LEAVE, LES, LFENCE, LFS, LGS, 83 | LOOP, LOOPE, LOOPNE, LSL, LSS, MFENCE, MOV, MOVNTI, MOVSS, MOVSX, MOVSXD, MOVUPD, MOVUPS, MOVZX, 84 | MPSADBW, MUL, NEG, NOP, NOT, OR, OUT, PACKSSDW, PACKSSWB, PACKUSDW, PACKUSWB, PABSB, PABSD, PABSW, 85 | PADDB, PADDD, PADDQ, PADDW, PADDSB, PADDSW, PADDUSB, PADDUSW, PALIGNR, 86 | PAND, PANDN, PAUSE, PAVGB, PAVGUSB, PAVGW, PBLENDVB, PBLENDW, 87 | PCMPEQB, PCMPEQD, PCMPEQQ, PCMPEQW, PCMPESTRI, PCMPESTRM, PCMPGTB, PCMPGTD, PCMPGTQ, PCMPGTW, 88 | PCMPISTRI, PCMPISTRM, PF2ID, PF2IW, PFACC, PFADD, PFCMPEQ, PFCMPGE, PFCMPGT, PFMAX, PFMIN, 89 | PFMUL, PFNACC, PFPNACC, PFRCP, PFRCPIT1, PFRCPIT2, PFRCPV, PFRSQIT1, PFRSQRT, PFRSQRTV, PFSUB, 90 | PFSUBR, PHADDD, PHADDSW, PHADDW, PHMINPOSUW, PHSUBD, PHSUBSW, PHSUBW, 91 | PI2FD, PI2FW, PMADDWD, PMADDUBSW, PMAXSB, PMAXSD, PMAXSW, PMAXUB, PMAXUD, PMAXUW, 92 | PMINSB, PMINSD, PMINSW, PMINUB, PMINUD, PMINUW, 93 | PMULDQ, PMULHRSW, PMULHRW, PMULHUW, PMULHW, PMULLD, PMULLW, PMULUDQ, 94 | POP, POPCNT, POR, PSADBW, PSHUFB, PSIGNB, PSIGND, PSIGNW, PSLLD, PSLLDQ, PSLLQ, PSLLW, 95 | PSRAD, PSRAW, PSRLD, PSRLDQ, PSRLQ, PSRLW, PSUBB, PSUBD, PSUBQ, PSUBW, PSUBSB, PSUBSW, PSUBUSB, PSUBUSW, 96 | PSWAPD, PTEST, PUNPCKHBW, PUNPCKHDQ, PUNPCKHQDQ, PUNPCKHWD, PUNPCKLQDQ, 97 | PUSH, PXOR, RDMSR, RDPMC, RDTSC, RETF, RETN, RCL, RCR, ROL, ROR, ROUNDPS, ROUNDPD, RSM, 98 | SAHF, SALC, SAR, SBB, SFENCE, SHL, SHLD, SHR, SHRD, 99 | SUB, STC, STD, STI, STMXCSR, SYSCALL, SYSENTER, SYSEXIT, SYSRET, TEST, UD2, 100 | VMREAD, VMWRITE, WBINVD, WRMSR, XCHG, XLAT, XADD, XOR, XRSTOR, XSAVE, 101 | 102 | // Grouped operations (ordering within each line is critical) 103 | ADDPS, ADDPD, ADDSD, ADDSS, ADDSUBPD, ADDSUBPS, 104 | ANDNPS, ANDNPD, 105 | ANDPS, ANDPD, 106 | CBW, CWDE, CDQE, 107 | CMPSB, CMPSW, CMPSD, CMPSQ, 108 | CMOVO, CMOVNO, CMOVB, CMOVAE, CMOVE, CMOVNE, CMOVBE, CMOVA, CMOVS, CMOVNS, CMOVPE, CMOVPO, CMOVL, CMOVGE, CMOVLE, CMOVG, 109 | CWD, CDQ, CQO, 110 | DIVPS, DIVPD, DIVSD, DIVSS, 111 | INSB, INSW, INSD, INSQ, 112 | JCXZ, JECXZ, JRCXZ, 113 | JO, JNO, JB, JAE, JE, JNE, JBE, JA, JS, JNS, JPE, JPO, JL, JGE, JLE, JG, 114 | LODSB, LODSW, LODSD, LODSQ, 115 | MAXPS, MAXPD, MAXSD, MAXSS, 116 | MINPS, MINPD, MINSD, MINSS, 117 | MOVD, MOVQ, 118 | MOVSB, MOVSW, MOVSD, MOVSQ, 119 | MULPS, MULPD, MULSD, MULSS, 120 | ORPS, ORPD, 121 | OUTSB, OUTSW, OUTSD, OUTSQ, 122 | PEXTRD, PEXTRQ, 123 | PINSRD, PINSRQ, 124 | POPA, POPAD, 125 | POPF, POPFD, POPFQ, 126 | PUSHA, PUSHAD, 127 | PUSHF, PUSHFD, PUSHFQ, 128 | RCPPS, RCPSS, 129 | RSQRTPS, RSQRTSS, 130 | SCASB, SCASW, SCASD, SCASQ, 131 | SETO, SETNO, SETB, SETAE, SETE, SETNE, SETBE, SETA, SETS, SETNS, SETPE, SETPO, SETL, SETGE, SETLE, SETG, 132 | SQRTPS, SQRTPD, SQRTSD, SQRTSS, 133 | STOSB, STOSW, STOSD, STOSQ, 134 | SUBPS, SUBPD, SUBSD, SUBSS, 135 | XORPS, XORPD, 136 | 137 | // Operations that do not need to be in the first 512 (MMX/SSE operations in table) 138 | CMPPD, CMPPS, CMPSS, 139 | COMISD, COMISS, 140 | CVTDQ2PD, CVTDQ2PS, CVTPD2DQ, CVTPD2PI, CVTPD2PS, CVTPI2PD, CVTPI2PS, CVTPS2DQ, CVTPS2PD, CVTPS2PI, 141 | CVTSD2SI, CVTSD2SS, CVTSI2SD, CVTSI2SS, CVTSS2SD, CVTSS2SI, 142 | CVTTPD2DQ, CVTTPD2PI, CVTTPS2DQ, CVTTPS2PI, CVTTSD2SI, CVTTSS2SI, EXTRACTPS, 143 | HADDPD, HADDPS, HSUBPD, HSUBPS, INSERTPS, LDDQU, LGDT, LIDT, LLDT, LMSW, LTR, 144 | MASKMOVQ, MASKMOVDQU, MMXNOP, MONITOR, MOVAPD, MOVAPS, MOVDDUP, MOVDQ2Q, MOVDQA, MOVDQU, MOVHLPS, MOVHPD, MOVHPS, 145 | MOVSHDUP, MOVSLDUP, MOVLHPS, MOVLPD, MOVLPS, 146 | MOVMSKPD, MOVMSKPS, MOVNTDQ, MOVNTDQA, MOVNTPD, MOVNTPS, MOVNTQ, MOVQ2DQ, MWAIT, 147 | PINSRB, PINSRW, PEXTRB, PEXTRW, PMOVMSKB, PMOVSXBD, PMOVSXBQ, PMOVSXDQ, PMOVSXBW, PMOVSXWD, PMOVSXWQ, 148 | PMOVZXBD, PMOVZXBQ, PMOVZXDQ, PMOVZXBW, PMOVZXWD, PMOVZXWQ, 149 | PREFETCH, PREFETCHNTA, PREFETCHT0, PREFETCHT1, PREFETCHT2, PREFETCHW, PSHUFD, PSHUFHW, PSHUFLW, PSHUFW, 150 | PUNPCKLBW, PUNPCKLDQ, PUNPCKLWD, ROUNDSD, ROUNDSS, 151 | SGDT, SIDT, SLDT, SHUFPD, SHUFPS, SMSW, STR, SWAPGS, 152 | UCOMISD, UCOMISS, UNPCKHPD, UNPCKHPS, UNPCKLPD, UNPCKLPS, VERR, VERW, 153 | VMCALL, VMCLEAR, VMLAUNCH, VMPTRLD, VMPTRST, VMRESUME, VMXOFF, VMXON, XGETBV, XSETBV, 154 | CLAC, STAC, ENCLS, VMFUNC, XEND, XTEXT, ENCLU, RDTSCP 155 | }; 156 | #ifndef __cplusplus 157 | typedef enum InstructionOperation InstructionOperation; 158 | #endif 159 | 160 | 161 | enum SegmentRegister 162 | { 163 | SEG_ES = 0, SEG_CS = 1, SEG_SS = 2, SEG_DS = 3, SEG_FS = 4, SEG_GS = 5, 164 | SEG_DEFAULT = 7 165 | }; 166 | #ifndef __cplusplus 167 | typedef enum SegmentRegister SegmentRegister; 168 | #endif 169 | 170 | 171 | #ifdef X86_ALT_OPERAND_NAMES 172 | #define __X86_OPER(n) X86_ ## n 173 | #else 174 | #define __X86_OPER(n) n 175 | #endif 176 | 177 | enum OperandType 178 | { 179 | NONE = 0, IMM, MEM, 180 | __X86_OPER(REG_AL), __X86_OPER(REG_CL), __X86_OPER(REG_DL), __X86_OPER(REG_BL), __X86_OPER(REG_AH), __X86_OPER(REG_CH), __X86_OPER(REG_DH), __X86_OPER(REG_BH), 181 | __X86_OPER(REG_SPL), __X86_OPER(REG_BPL), __X86_OPER(REG_SIL), __X86_OPER(REG_DIL), 182 | __X86_OPER(REG_R8B), __X86_OPER(REG_R9B), __X86_OPER(REG_R10B), __X86_OPER(REG_R11B), __X86_OPER(REG_R12B), __X86_OPER(REG_R13B), __X86_OPER(REG_R14B), __X86_OPER(REG_R15B), 183 | __X86_OPER(REG_AX), __X86_OPER(REG_CX), __X86_OPER(REG_DX), __X86_OPER(REG_BX), __X86_OPER(REG_SP), __X86_OPER(REG_BP), __X86_OPER(REG_SI), __X86_OPER(REG_DI), 184 | __X86_OPER(REG_R8W), __X86_OPER(REG_R9W), __X86_OPER(REG_R10W), __X86_OPER(REG_R11W), __X86_OPER(REG_R12W), __X86_OPER(REG_R13W), __X86_OPER(REG_R14W), __X86_OPER(REG_R15W), 185 | __X86_OPER(REG_EAX), __X86_OPER(REG_ECX), __X86_OPER(REG_EDX), __X86_OPER(REG_EBX), __X86_OPER(REG_ESP), __X86_OPER(REG_EBP), __X86_OPER(REG_ESI), __X86_OPER(REG_EDI), 186 | __X86_OPER(REG_R8D), __X86_OPER(REG_R9D), __X86_OPER(REG_R10D), __X86_OPER(REG_R11D), __X86_OPER(REG_R12D), __X86_OPER(REG_R13D), __X86_OPER(REG_R14D), __X86_OPER(REG_R15D), 187 | __X86_OPER(REG_RAX), __X86_OPER(REG_RCX), __X86_OPER(REG_RDX), __X86_OPER(REG_RBX), __X86_OPER(REG_RSP), __X86_OPER(REG_RBP), __X86_OPER(REG_RSI), __X86_OPER(REG_RDI), 188 | __X86_OPER(REG_R8), __X86_OPER(REG_R9), __X86_OPER(REG_R10), __X86_OPER(REG_R11), __X86_OPER(REG_R12), __X86_OPER(REG_R13), __X86_OPER(REG_R14), __X86_OPER(REG_R15), 189 | __X86_OPER(REG_ST0), __X86_OPER(REG_ST1), __X86_OPER(REG_ST2), __X86_OPER(REG_ST3), __X86_OPER(REG_ST4), __X86_OPER(REG_ST5), __X86_OPER(REG_ST6), __X86_OPER(REG_ST7), 190 | __X86_OPER(REG_MM0), __X86_OPER(REG_MM1), __X86_OPER(REG_MM2), __X86_OPER(REG_MM3), __X86_OPER(REG_MM4), __X86_OPER(REG_MM5), __X86_OPER(REG_MM6), __X86_OPER(REG_MM7), 191 | __X86_OPER(REG_XMM0), __X86_OPER(REG_XMM1), __X86_OPER(REG_XMM2), __X86_OPER(REG_XMM3), __X86_OPER(REG_XMM4), __X86_OPER(REG_XMM5), __X86_OPER(REG_XMM6), __X86_OPER(REG_XMM7), 192 | __X86_OPER(REG_XMM8), __X86_OPER(REG_XMM9), __X86_OPER(REG_XMM10), __X86_OPER(REG_XMM11), __X86_OPER(REG_XMM12), __X86_OPER(REG_XMM13), __X86_OPER(REG_XMM14), __X86_OPER(REG_XMM15), 193 | __X86_OPER(REG_CR0), __X86_OPER(REG_CR1), __X86_OPER(REG_CR2), __X86_OPER(REG_CR3), __X86_OPER(REG_CR4), __X86_OPER(REG_CR5), __X86_OPER(REG_CR6), __X86_OPER(REG_CR7), 194 | __X86_OPER(REG_CR8), __X86_OPER(REG_CR9), __X86_OPER(REG_CR10), __X86_OPER(REG_CR11), __X86_OPER(REG_CR12), __X86_OPER(REG_CR13), __X86_OPER(REG_CR14), __X86_OPER(REG_CR15), 195 | __X86_OPER(REG_DR0), __X86_OPER(REG_DR1), __X86_OPER(REG_DR2), __X86_OPER(REG_DR3), __X86_OPER(REG_DR4), __X86_OPER(REG_DR5), __X86_OPER(REG_DR6), __X86_OPER(REG_DR7), 196 | __X86_OPER(REG_DR8), __X86_OPER(REG_DR9), __X86_OPER(REG_DR10), __X86_OPER(REG_DR11), __X86_OPER(REG_DR12), __X86_OPER(REG_DR13), __X86_OPER(REG_DR14), __X86_OPER(REG_DR15), 197 | __X86_OPER(REG_TR0), __X86_OPER(REG_TR1), __X86_OPER(REG_TR2), __X86_OPER(REG_TR3), __X86_OPER(REG_TR4), __X86_OPER(REG_TR5), __X86_OPER(REG_TR6), __X86_OPER(REG_TR7), 198 | __X86_OPER(REG_TR8), __X86_OPER(REG_TR9), __X86_OPER(REG_TR10), __X86_OPER(REG_TR11), __X86_OPER(REG_TR12), __X86_OPER(REG_TR13), __X86_OPER(REG_TR14), __X86_OPER(REG_TR15), 199 | __X86_OPER(REG_ES), __X86_OPER(REG_CS), __X86_OPER(REG_SS), __X86_OPER(REG_DS), __X86_OPER(REG_FS), __X86_OPER(REG_GS), 200 | __X86_OPER(REG_RIP) 201 | }; 202 | #ifndef __cplusplus 203 | typedef enum OperandType OperandType; 204 | #endif 205 | 206 | 207 | struct InstructionOperand 208 | { 209 | OperandType operand; 210 | OperandType components[2]; 211 | uint8_t scale; 212 | uint16_t size; 213 | int64_t immediate; 214 | SegmentRegister segment; 215 | bool relative; 216 | }; 217 | #ifndef __cplusplus 218 | typedef struct InstructionOperand InstructionOperand; 219 | #endif 220 | 221 | 222 | struct Instruction 223 | { 224 | InstructionOperation operation; 225 | InstructionOperand operands[3]; 226 | uint32_t flags; 227 | SegmentRegister segment; 228 | size_t length; 229 | }; 230 | #ifndef __cplusplus 231 | typedef struct Instruction Instruction; 232 | #endif 233 | 234 | 235 | #ifdef __cplusplus 236 | extern "C" 237 | { 238 | #endif 239 | bool Disassemble16(const uint8_t* opcode, uint64_t addr, size_t maxLen, Instruction* result); 240 | bool Disassemble32(const uint8_t* opcode, uint64_t addr, size_t maxLen, Instruction* result); 241 | bool Disassemble64(const uint8_t* opcode, uint64_t addr, size_t maxLen, Instruction* result); 242 | 243 | size_t FormatInstructionString(char* out, size_t outMaxLen, const char* fmt, const uint8_t* opcode, 244 | uint64_t addr, const Instruction* instr); 245 | 246 | size_t DisassembleToString16(char* out, size_t outMaxLen, const char* fmt, const uint8_t* opcode, 247 | uint64_t addr, size_t maxLen, Instruction* instr); 248 | size_t DisassembleToString32(char* out, size_t outMaxLen, const char* fmt, const uint8_t* opcode, 249 | uint64_t addr, size_t maxLen, Instruction* instr); 250 | size_t DisassembleToString64(char* out, size_t outMaxLen, const char* fmt, const uint8_t* opcode, 251 | uint64_t addr, size_t maxLen, Instruction* instr); 252 | #ifdef __cplusplus 253 | } 254 | } 255 | #endif 256 | 257 | 258 | #ifndef X86_ALT_OPERAND_NAMES // Code generator does not support altername naming 259 | 260 | #define __CODEGENX86_32BIT 261 | #include "codegenx86.h" 262 | #undef __CODEGENX86_32BIT 263 | 264 | #define __CODEGENX86_64BIT 265 | #include "codegenx86.h" 266 | #undef __CODEGENX86_64BIT 267 | 268 | #endif 269 | 270 | 271 | #endif 272 | -------------------------------------------------------------------------------- /asmx86.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asmx86", "asmx86.vcxproj", "{56CE5693-11CA-4ADD-9B2F-C4F3366C54C5}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {56CE5693-11CA-4ADD-9B2F-C4F3366C54C5}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {56CE5693-11CA-4ADD-9B2F-C4F3366C54C5}.Debug|Win32.Build.0 = Debug|Win32 18 | {56CE5693-11CA-4ADD-9B2F-C4F3366C54C5}.Debug|x64.ActiveCfg = Debug|x64 19 | {56CE5693-11CA-4ADD-9B2F-C4F3366C54C5}.Debug|x64.Build.0 = Debug|x64 20 | {56CE5693-11CA-4ADD-9B2F-C4F3366C54C5}.Release|Win32.ActiveCfg = Release|Win32 21 | {56CE5693-11CA-4ADD-9B2F-C4F3366C54C5}.Release|Win32.Build.0 = Release|Win32 22 | {56CE5693-11CA-4ADD-9B2F-C4F3366C54C5}.Release|x64.ActiveCfg = Release|x64 23 | {56CE5693-11CA-4ADD-9B2F-C4F3366C54C5}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /asmx86.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {56CE5693-11CA-4ADD-9B2F-C4F3366C54C5} 23 | asmx86 24 | Win32Proj 25 | 26 | 27 | 28 | StaticLibrary 29 | v120 30 | Unicode 31 | true 32 | 33 | 34 | StaticLibrary 35 | v120 36 | Unicode 37 | true 38 | 39 | 40 | StaticLibrary 41 | v120 42 | Unicode 43 | 44 | 45 | StaticLibrary 46 | v120 47 | Unicode 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | <_ProjectFileVersion>12.0.30501.0 67 | 68 | 69 | $(SolutionDir)$(Configuration)\ 70 | $(Configuration)\ 71 | 72 | 73 | 74 | $(SolutionDir)$(Configuration)\ 75 | $(Configuration)\ 76 | 77 | 78 | 79 | 80 | Performing Custom Build Step 81 | 82 | 83 | 84 | Disabled 85 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 86 | true 87 | EnableFastChecks 88 | MultiThreadedDebugDLL 89 | 90 | Level3 91 | EditAndContinue 92 | 93 | 94 | 95 | 96 | Performing Custom Build Step 97 | 98 | 99 | 100 | 101 | Disabled 102 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 103 | EnableFastChecks 104 | MultiThreadedDebugDLL 105 | 106 | 107 | Level3 108 | ProgramDatabase 109 | 110 | 111 | 112 | 113 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 114 | MultiThreadedDLL 115 | 116 | Level3 117 | ProgramDatabase 118 | 119 | 120 | 121 | 122 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 123 | MultiThreadedDLL 124 | 125 | 126 | Level3 127 | ProgramDatabase 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /asmx86.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | 14 | 15 | Source Files 16 | 17 | 18 | 19 | 20 | Header Files 21 | 22 | 23 | Header Files 24 | 25 | 26 | Header Files 27 | 28 | 29 | -------------------------------------------------------------------------------- /asmx86str.h: -------------------------------------------------------------------------------- 1 | static const char* operationString[] = { 2 | "", 3 | "aaa", 4 | "aad", 5 | "aam", 6 | "aas", 7 | "add", 8 | "adc", 9 | "and", 10 | "arpl", 11 | "blendpd", 12 | "blendps", 13 | "blendvpd", 14 | "blendvps", 15 | "bound", 16 | "bsf", 17 | "bsr", 18 | "bswap", 19 | "bt", 20 | "btc", 21 | "btr", 22 | "bts", 23 | "callf", 24 | "call", 25 | "clc", 26 | "cld", 27 | "clflush", 28 | "cli", 29 | "clts", 30 | "cmc", 31 | "cmp", 32 | "cmpxch16b", 33 | "cmpxch8b", 34 | "cmpxchg", 35 | "cpuid", 36 | "crc32", 37 | "daa", 38 | "das", 39 | "dec", 40 | "div", 41 | "dppd", 42 | "dpps", 43 | "emms", 44 | "enter", 45 | "f2xm1", 46 | "fabs", 47 | "fadd", 48 | "faddp", 49 | "fbld", 50 | "fbstp", 51 | "fchs", 52 | "fclex", 53 | "fcmovb", 54 | "fcmovbe", 55 | "fcmove", 56 | "fcmovnb", 57 | "fcmovnbe", 58 | "fcmovne", 59 | "fcmovnu", 60 | "fcmovu", 61 | "fcom", 62 | "fcomi", 63 | "fcomip", 64 | "fcomp", 65 | "fcompp", 66 | "fcos", 67 | "fdecstp", 68 | "fdisi", 69 | "fdiv", 70 | "fdivp", 71 | "fdivr", 72 | "fdivrp", 73 | "femms", 74 | "feni", 75 | "ffree", 76 | "ffreep", 77 | "fiadd", 78 | "ficom", 79 | "ficomp", 80 | "fidiv", 81 | "fidivr", 82 | "fild", 83 | "fimul", 84 | "fincstp", 85 | "finit", 86 | "fist", 87 | "fistp", 88 | "fisttp", 89 | "fisub", 90 | "fisubr", 91 | "fld", 92 | "fld1", 93 | "fldcw", 94 | "fldenv", 95 | "fldl2e", 96 | "fldl2t", 97 | "fldlg2", 98 | "fldln2", 99 | "fldpi", 100 | "fldz", 101 | "fmul", 102 | "fmulp", 103 | "fnop", 104 | "fpatan", 105 | "fprem", 106 | "fprem1", 107 | "fptan", 108 | "frichop", 109 | "frinear", 110 | "frint2", 111 | "frndint", 112 | "frstor", 113 | "frstpm", 114 | "fsave", 115 | "fscale", 116 | "fsetpm", 117 | "fsin", 118 | "fsincos", 119 | "fsqrt", 120 | "fst", 121 | "fstcw", 122 | "fstdw", 123 | "fstenv", 124 | "fstp", 125 | "fstsg", 126 | "fstsw", 127 | "fsub", 128 | "fsubp", 129 | "fsubr", 130 | "fsubrp", 131 | "ftst", 132 | "fucom", 133 | "fucomi", 134 | "fucomip", 135 | "fucomp", 136 | "fucompp", 137 | "fwait", 138 | "fxam", 139 | "fxch", 140 | "fxrstor", 141 | "fxsave", 142 | "fxtract", 143 | "fyl2x", 144 | "fyl2xp1", 145 | "getsec", 146 | "hlt", 147 | "idiv", 148 | "imul", 149 | "in", 150 | "inc", 151 | "int", 152 | "int1", 153 | "int3", 154 | "into", 155 | "invd", 156 | "invlpg", 157 | "iret", 158 | "jmpf", 159 | "jmp", 160 | "lahf", 161 | "lar", 162 | "ldmxcsr", 163 | "lds", 164 | "lea", 165 | "leave", 166 | "les", 167 | "lfence", 168 | "lfs", 169 | "lgs", 170 | "loop", 171 | "loope", 172 | "loopne", 173 | "lsl", 174 | "lss", 175 | "mfence", 176 | "mov", 177 | "movnti", 178 | "movss", 179 | "movsx", 180 | "movsxd", 181 | "movupd", 182 | "movups", 183 | "movzx", 184 | "mpsadbw", 185 | "mul", 186 | "neg", 187 | "nop", 188 | "not", 189 | "or", 190 | "out", 191 | "packssdw", 192 | "packsswb", 193 | "packusdw", 194 | "packuswb", 195 | "pabsb", 196 | "pabsd", 197 | "pabsw", 198 | "paddb", 199 | "paddd", 200 | "paddq", 201 | "paddw", 202 | "paddsb", 203 | "paddsw", 204 | "paddusb", 205 | "paddusw", 206 | "palignr", 207 | "pand", 208 | "pandn", 209 | "pause", 210 | "pavgb", 211 | "pavgusb", 212 | "pavgw", 213 | "pblendvb", 214 | "pblendw", 215 | "pcmpeqb", 216 | "pcmpeqd", 217 | "pcmpeqq", 218 | "pcmpeqw", 219 | "pcmpestri", 220 | "pcmpestrm", 221 | "pcmpgtb", 222 | "pcmpgtd", 223 | "pcmpgtq", 224 | "pcmpgtw", 225 | "pcmpistri", 226 | "pcmpistrm", 227 | "pf2id", 228 | "pf2iw", 229 | "pfacc", 230 | "pfadd", 231 | "pfcmpeq", 232 | "pfcmpge", 233 | "pfcmpgt", 234 | "pfmax", 235 | "pfmin", 236 | "pfmul", 237 | "pfnacc", 238 | "pfpnacc", 239 | "pfrcp", 240 | "pfrcpit1", 241 | "pfrcpit2", 242 | "pfrcpv", 243 | "pfrsqit1", 244 | "pfrsqrt", 245 | "pfrsqrtv", 246 | "pfsub", 247 | "pfsubr", 248 | "phaddd", 249 | "phaddsw", 250 | "phaddw", 251 | "phminposuw", 252 | "phsubd", 253 | "phsubsw", 254 | "phsubw", 255 | "pi2fd", 256 | "pi2fw", 257 | "pmaddwd", 258 | "pmaddubsw", 259 | "pmaxsb", 260 | "pmaxsd", 261 | "pmaxsw", 262 | "pmaxub", 263 | "pmaxud", 264 | "pmaxuw", 265 | "pminsb", 266 | "pminsd", 267 | "pminsw", 268 | "pminub", 269 | "pminud", 270 | "pminuw", 271 | "pmuldq", 272 | "pmulhrsw", 273 | "pmulhrw", 274 | "pmulhuw", 275 | "pmulhw", 276 | "pmulld", 277 | "pmullw", 278 | "pmuludq", 279 | "pop", 280 | "popcnt", 281 | "por", 282 | "psadbw", 283 | "pshufb", 284 | "psignb", 285 | "psignd", 286 | "psignw", 287 | "pslld", 288 | "pslldq", 289 | "psllq", 290 | "psllw", 291 | "psrad", 292 | "psraw", 293 | "psrld", 294 | "psrldq", 295 | "psrlq", 296 | "psrlw", 297 | "psubb", 298 | "psubd", 299 | "psubq", 300 | "psubw", 301 | "psubsb", 302 | "psubsw", 303 | "psubusb", 304 | "psubusw", 305 | "pswapd", 306 | "ptest", 307 | "punpckhbw", 308 | "punpckhdq", 309 | "punpckhqdq", 310 | "punpckhwd", 311 | "punpcklqdq", 312 | "push", 313 | "pxor", 314 | "rdmsr", 315 | "rdpmc", 316 | "rdtsc", 317 | "retf", 318 | "retn", 319 | "rcl", 320 | "rcr", 321 | "rol", 322 | "ror", 323 | "roundps", 324 | "roundpd", 325 | "rsm", 326 | "sahf", 327 | "salc", 328 | "sar", 329 | "sbb", 330 | "sfence", 331 | "shl", 332 | "shld", 333 | "shr", 334 | "shrd", 335 | "sub", 336 | "stc", 337 | "std", 338 | "sti", 339 | "stmxcsr", 340 | "syscall", 341 | "sysenter", 342 | "sysexit", 343 | "sysret", 344 | "test", 345 | "ud2", 346 | "vmread", 347 | "vmwrite", 348 | "wbinvd", 349 | "wrmsr", 350 | "xchg", 351 | "xlat", 352 | "xadd", 353 | "xor", 354 | "xrstor", 355 | "xsave", 356 | "addps", 357 | "addpd", 358 | "addsd", 359 | "addss", 360 | "addsubpd", 361 | "addsubps", 362 | "andnps", 363 | "andnpd", 364 | "andps", 365 | "andpd", 366 | "cbw", 367 | "cwde", 368 | "cdqe", 369 | "cmpsb", 370 | "cmpsw", 371 | "cmpsd", 372 | "cmpsq", 373 | "cmovo", 374 | "cmovno", 375 | "cmovb", 376 | "cmovae", 377 | "cmove", 378 | "cmovne", 379 | "cmovbe", 380 | "cmova", 381 | "cmovs", 382 | "cmovns", 383 | "cmovpe", 384 | "cmovpo", 385 | "cmovl", 386 | "cmovge", 387 | "cmovle", 388 | "cmovg", 389 | "cwd", 390 | "cdq", 391 | "cqo", 392 | "divps", 393 | "divpd", 394 | "divsd", 395 | "divss", 396 | "insb", 397 | "insw", 398 | "insd", 399 | "insq", 400 | "jcxz", 401 | "jecxz", 402 | "jrcxz", 403 | "jo", 404 | "jno", 405 | "jb", 406 | "jae", 407 | "je", 408 | "jne", 409 | "jbe", 410 | "ja", 411 | "js", 412 | "jns", 413 | "jpe", 414 | "jpo", 415 | "jl", 416 | "jge", 417 | "jle", 418 | "jg", 419 | "lodsb", 420 | "lodsw", 421 | "lodsd", 422 | "lodsq", 423 | "maxps", 424 | "maxpd", 425 | "maxsd", 426 | "maxss", 427 | "minps", 428 | "minpd", 429 | "minsd", 430 | "minss", 431 | "movd", 432 | "movq", 433 | "movsb", 434 | "movsw", 435 | "movsd", 436 | "movsq", 437 | "mulps", 438 | "mulpd", 439 | "mulsd", 440 | "mulss", 441 | "orps", 442 | "orpd", 443 | "outsb", 444 | "outsw", 445 | "outsd", 446 | "outsq", 447 | "pextrd", 448 | "pextrq", 449 | "pinsrd", 450 | "pinsrq", 451 | "popa", 452 | "popad", 453 | "popf", 454 | "popfd", 455 | "popfq", 456 | "pusha", 457 | "pushad", 458 | "pushf", 459 | "pushfd", 460 | "pushfq", 461 | "rcpps", 462 | "rcpss", 463 | "rsqrtps", 464 | "rsqrtss", 465 | "scasb", 466 | "scasw", 467 | "scasd", 468 | "scasq", 469 | "seto", 470 | "setno", 471 | "setb", 472 | "setae", 473 | "sete", 474 | "setne", 475 | "setbe", 476 | "seta", 477 | "sets", 478 | "setns", 479 | "setpe", 480 | "setpo", 481 | "setl", 482 | "setge", 483 | "setle", 484 | "setg", 485 | "sqrtps", 486 | "sqrtpd", 487 | "sqrtsd", 488 | "sqrtss", 489 | "stosb", 490 | "stosw", 491 | "stosd", 492 | "stosq", 493 | "subps", 494 | "subpd", 495 | "subsd", 496 | "subss", 497 | "xorps", 498 | "xorpd", 499 | "cmppd", 500 | "cmpps", 501 | "cmpss", 502 | "comisd", 503 | "comiss", 504 | "cvtdq2pd", 505 | "cvtdq2ps", 506 | "cvtpd2dq", 507 | "cvtpd2pi", 508 | "cvtpd2ps", 509 | "cvtpi2pd", 510 | "cvtpi2ps", 511 | "cvtps2dq", 512 | "cvtps2pd", 513 | "cvtps2pi", 514 | "cvtsd2si", 515 | "cvtsd2ss", 516 | "cvtsi2sd", 517 | "cvtsi2ss", 518 | "cvtss2sd", 519 | "cvtss2si", 520 | "cvttpd2dq", 521 | "cvttpd2pi", 522 | "cvttps2dq", 523 | "cvttps2pi", 524 | "cvttsd2si", 525 | "cvttss2si", 526 | "extractps", 527 | "haddpd", 528 | "haddps", 529 | "hsubpd", 530 | "hsubps", 531 | "insertps", 532 | "lddqu", 533 | "lgdt", 534 | "lidt", 535 | "lldt", 536 | "lmsw", 537 | "ltr", 538 | "maskmovq", 539 | "maskmovdqu", 540 | "mmxnop", 541 | "monitor", 542 | "movapd", 543 | "movaps", 544 | "movddup", 545 | "movdq2q", 546 | "movdqa", 547 | "movdqu", 548 | "movhlps", 549 | "movhpd", 550 | "movhps", 551 | "movshdup", 552 | "movsldup", 553 | "movlhps", 554 | "movlpd", 555 | "movlps", 556 | "movmskpd", 557 | "movmskps", 558 | "movntdq", 559 | "movntdqa", 560 | "movntpd", 561 | "movntps", 562 | "movntq", 563 | "movq2dq", 564 | "mwait", 565 | "pinsrb", 566 | "pinsrw", 567 | "pextrb", 568 | "pextrw", 569 | "pmovmskb", 570 | "pmovsxbd", 571 | "pmovsxbq", 572 | "pmovsxdq", 573 | "pmovsxbw", 574 | "pmovsxwd", 575 | "pmovsxwq", 576 | "pmovzxbd", 577 | "pmovzxbq", 578 | "pmovzxdq", 579 | "pmovzxbw", 580 | "pmovzxwd", 581 | "pmovzxwq", 582 | "prefetch", 583 | "prefetchnta", 584 | "prefetcht0", 585 | "prefetcht1", 586 | "prefetcht2", 587 | "prefetchw", 588 | "pshufd", 589 | "pshufhw", 590 | "pshuflw", 591 | "pshufw", 592 | "punpcklbw", 593 | "punpckldq", 594 | "punpcklwd", 595 | "roundsd", 596 | "roundss", 597 | "sgdt", 598 | "sidt", 599 | "sldt", 600 | "shufpd", 601 | "shufps", 602 | "smsw", 603 | "str", 604 | "swapgs", 605 | "ucomisd", 606 | "ucomiss", 607 | "unpckhpd", 608 | "unpckhps", 609 | "unpcklpd", 610 | "unpcklps", 611 | "verr", 612 | "verw", 613 | "vmcall", 614 | "vmclear", 615 | "vmlaunch", 616 | "vmptrld", 617 | "vmptrst", 618 | "vmresume", 619 | "vmxoff", 620 | "vmxon", 621 | "xgetbv", 622 | "xsetbv", 623 | "clac", 624 | "stac", 625 | "encls", 626 | "vmfunc", 627 | "xend", 628 | "xtext", 629 | "enclu", 630 | "rdtscp" 631 | }; 632 | static const char* operandString[] = { 633 | "", 634 | "", 635 | "", 636 | "al", 637 | "cl", 638 | "dl", 639 | "bl", 640 | "ah", 641 | "ch", 642 | "dh", 643 | "bh", 644 | "spl", 645 | "bpl", 646 | "sil", 647 | "dil", 648 | "r8b", 649 | "r9b", 650 | "r10b", 651 | "r11b", 652 | "r12b", 653 | "r13b", 654 | "r14b", 655 | "r15b", 656 | "ax", 657 | "cx", 658 | "dx", 659 | "bx", 660 | "sp", 661 | "bp", 662 | "si", 663 | "di", 664 | "r8w", 665 | "r9w", 666 | "r10w", 667 | "r11w", 668 | "r12w", 669 | "r13w", 670 | "r14w", 671 | "r15w", 672 | "eax", 673 | "ecx", 674 | "edx", 675 | "ebx", 676 | "esp", 677 | "ebp", 678 | "esi", 679 | "edi", 680 | "r8d", 681 | "r9d", 682 | "r10d", 683 | "r11d", 684 | "r12d", 685 | "r13d", 686 | "r14d", 687 | "r15d", 688 | "rax", 689 | "rcx", 690 | "rdx", 691 | "rbx", 692 | "rsp", 693 | "rbp", 694 | "rsi", 695 | "rdi", 696 | "r8", 697 | "r9", 698 | "r10", 699 | "r11", 700 | "r12", 701 | "r13", 702 | "r14", 703 | "r15", 704 | "st0", 705 | "st1", 706 | "st2", 707 | "st3", 708 | "st4", 709 | "st5", 710 | "st6", 711 | "st7", 712 | "mm0", 713 | "mm1", 714 | "mm2", 715 | "mm3", 716 | "mm4", 717 | "mm5", 718 | "mm6", 719 | "mm7", 720 | "xmm0", 721 | "xmm1", 722 | "xmm2", 723 | "xmm3", 724 | "xmm4", 725 | "xmm5", 726 | "xmm6", 727 | "xmm7", 728 | "xmm8", 729 | "xmm9", 730 | "xmm10", 731 | "xmm11", 732 | "xmm12", 733 | "xmm13", 734 | "xmm14", 735 | "xmm15", 736 | "cr0", 737 | "cr1", 738 | "cr2", 739 | "cr3", 740 | "cr4", 741 | "cr5", 742 | "cr6", 743 | "cr7", 744 | "cr8", 745 | "cr9", 746 | "cr10", 747 | "cr11", 748 | "cr12", 749 | "cr13", 750 | "cr14", 751 | "cr15", 752 | "dr0", 753 | "dr1", 754 | "dr2", 755 | "dr3", 756 | "dr4", 757 | "dr5", 758 | "dr6", 759 | "dr7", 760 | "dr8", 761 | "dr9", 762 | "dr10", 763 | "dr11", 764 | "dr12", 765 | "dr13", 766 | "dr14", 767 | "dr15", 768 | "tr0", 769 | "tr1", 770 | "tr2", 771 | "tr3", 772 | "tr4", 773 | "tr5", 774 | "tr6", 775 | "tr7", 776 | "tr8", 777 | "tr9", 778 | "tr10", 779 | "tr11", 780 | "tr12", 781 | "tr13", 782 | "tr14", 783 | "tr15", 784 | "es", 785 | "cs", 786 | "ss", 787 | "ds", 788 | "fs", 789 | "gs", 790 | "rip" 791 | }; 792 | -------------------------------------------------------------------------------- /makeopstr.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | if len(sys.argv) < 2: 4 | print "Usage: %s []" 5 | sys.exit(1) 6 | 7 | hdr = open(sys.argv[1], "r") 8 | 9 | operation = False 10 | operand = False 11 | 12 | operation_list = [] 13 | operand_list = [] 14 | 15 | for line in hdr: 16 | if ("enum InstructionOperation" in line) and ("typedef" not in line): 17 | operation = True 18 | elif ("enum OperandType" in line) and ("typedef" not in line): 19 | operand = True 20 | elif "}" in line: 21 | operation = False 22 | operand = False 23 | elif (operation or operand) and ("{" not in line): 24 | parts = line.split("/")[0].split(",") 25 | for part in parts: 26 | text = part.split("=")[0].strip().lower() 27 | if len(text) == 0: 28 | continue 29 | if text in ["invalid", "none", "imm", "mem"]: 30 | text = "" 31 | if text.startswith("__x86_oper(reg_"): 32 | text = text[15:].split(")")[0].strip() 33 | if operation: 34 | operation_list.append(text) 35 | if operand: 36 | operand_list.append(text) 37 | 38 | if len(sys.argv) > 2: 39 | out = open(sys.argv[2], "w") 40 | else: 41 | out = sys.stdout 42 | 43 | out.write("static const char* operationString[] = {\n") 44 | for i in xrange(0, len(operation_list)): 45 | if i > 0: 46 | out.write(",\n") 47 | out.write('\t"%s"' % operation_list[i]) 48 | out.write("\n};\n") 49 | 50 | out.write("static const char* operandString[] = {\n") 51 | for i in xrange(0, len(operand_list)): 52 | if i > 0: 53 | out.write(",\n") 54 | out.write('\t"%s"' % operand_list[i]) 55 | out.write("\n};\n") 56 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Warning 2 | 3 | Note that this project is no longer under active use. Binary Ninja does not use this for disassembly since August of 2018. 4 | 5 | # asmx86 6 | This project is a disassembler library designed for emulation or automated analysis of x86 instructions. The primary output format of the disassembly is not text-based like most disassemblers. This library disassembles instructions to a structure containing the instruction mnemonic and the operands, which are in turn broken out into their components. Instruction mnemonics and operands are represented using an enumeration. This allows easier analysis or emulation of the instruction without costly parsing or string compares. 7 | 8 | When it is necessary to disassemble to a string to display to a user, functions are provided to easily convert the structure form of an instruction to a string. 9 | 10 | Also provided is an assembler library that is specifically designed to aid in the creation of run-time generated code. 11 | 12 | ### No dependencies 13 | The asmx86 library does not have any external dependencies. It is a single C source file that can be included in any C or C++ project. 14 | 15 | ### Open source 16 | Released under the [2-clause BSD license](http://opensource.org/licenses/BSD-2-Clause). Use it anywhere, even in a commercial product, for free. 17 | 18 | ### Thread-safe and allocation free 19 | The asmx86 library is designed to be efficient. There are no dynamic allocations anywhere in the code, and it uses a minimal amount of stack space with a completely stateless design. It safe to call directly even from multiprocessor kernel code. 20 | 21 | ### Fast disassembly 22 | A benchmark of text disassembly of 10 million instructions ran over 7 times faster than Capstone Engine. Structure-based disassembly is even faster and better aligned to the needs of emulation and automated analysis, as it provides the components of an instruction with no need for extra parsing. 23 | 24 | ## Disassembler API 25 | 26 | ### Instruction disassembly to structure 27 | Disassembly can be performed using one of the following functions, depending on the target operating mode of the processor: 28 | 29 | ``` 30 | bool Disassemble16(const uint8_t* opcode, 31 | uint64_t addr, 32 | size_t maxLen, 33 | Instruction* result); 34 | bool Disassemble32(const uint8_t* opcode, 35 | uint64_t addr, 36 | size_t maxLen, 37 | Instruction* result); 38 | bool Disassemble64(const uint8_t* opcode, 39 | uint64_t addr, 40 | size_t maxLen, 41 | Instruction* result); 42 | ``` 43 | 44 | Pass the bytes of the instruction as `opcode` and the length of this buffer as `maxLen`. Pass the address of the instruction on the target as `addr`. The results of the disassembly will be written to the `Instruction` structure pointed to by `result`. 45 | 46 | These functions return `true` if a valid instruction was disassembled, and `false` otherwise. 47 | 48 | ### Convert structure disassembly to string 49 | 50 | A function is also provided to convert an `Instruction` structure into a human readable string: 51 | 52 | ``` 53 | size_t FormatInstructionString(char* out, 54 | size_t outMaxLen, 55 | const char* fmt, 56 | const uint8_t* opcode, 57 | uint64_t addr, 58 | const Instruction* instr); 59 | ``` 60 | 61 | Pass a pointer to the output buffer as `out` and the size of this buffer in characters as `outMaxLen`. 62 | 63 | The `fmt` parameter contains a `printf`-like format string for displaying the instruction. The following format specifiers are defined: 64 | 65 | * `%a`: Shows the address of the instruction as passed in the `addr` parameter. 66 | * `%b`: Shows the bytes of the instruction. The `opcode` parameter should contain the same contents as the call to `Disassemble`. 67 | * `%i`: Shows the instruction mnemonic. 68 | * `%o`: Shows the operands. 69 | 70 | Width specifiers are allowed on the format specifiers. For example, the `fmt` string `"%8a %7i %o"` might show the following output: 71 | 72 | ``` 73 | 08041a98 mov eax, dword [ebp+0x14] 74 | ``` 75 | 76 | The `opcode` and `addr` parameters may be used by the format specifiers as described above. They are ignored if none of the provided format specifiers access them. 77 | 78 | The `instr` parameter should be a pointer to an `Instruction` structure that was the result of a call to the `Disassemble` APIs. 79 | 80 | This function returns the number of characters written. 81 | 82 | ### Instruction disassembly to string 83 | 84 | Functions are provided to disassemble instructions directly to a human readable string. These functions will output the structure disassembly as well. They are effectively a combined call to the `Disassemble` and `FormatInstructionString` APIs. 85 | 86 | ``` 87 | size_t DisassembleToString16(char* out, 88 | size_t outMaxLen, 89 | const char* fmt, 90 | const uint8_t* opcode, 91 | uint64_t addr, 92 | size_t maxLen, 93 | Instruction* instr); 94 | size_t DisassembleToString32(char* out, 95 | size_t outMaxLen, 96 | const char* fmt, 97 | const uint8_t* opcode, 98 | uint64_t addr, 99 | size_t maxLen, 100 | Instruction* instr); 101 | size_t DisassembleToString64(char* out, 102 | size_t outMaxLen, 103 | const char* fmt, 104 | const uint8_t* opcode, 105 | uint64_t addr, 106 | size_t maxLen, 107 | Instruction* instr); 108 | ``` 109 | 110 | The `out`, `outMaxLen`, and `fmt` parameters are the same as the `FormatInstructionString` function, see the above documentation. 111 | 112 | The `opcode` parameter is required and should contain the bytes of the instruction to disassemble, and the length of this buffer should be passed as `maxLen`. Pass the address of the instruction on the target as `addr`. 113 | 114 | The `instr` parameter is required and the provided `Instruction` structure will be written with the results of the disassembly. 115 | 116 | These functions return the number of characters written, or zero if the instruction is invalid. 117 | 118 | ### The `Instruction` structure 119 | 120 | Disassembly results are typically written to an `Instruction` structure, which is defined as follows: 121 | 122 | ``` 123 | struct Instruction 124 | { 125 | InstructionOperation operation; 126 | InstructionOperand operands[3]; 127 | uint32_t flags; 128 | SegmentRegister segment; 129 | size_t length; 130 | }; 131 | ``` 132 | 133 | The `operation` member is an enumeration which matches the name of the instruction mnemonic. See the header file for a full listing of the supported instructions. 134 | 135 | The `operands` array contains the operands to the instruction. Each operand is a structure and is defined below. 136 | 137 | The `flags` member is a bit field that may contain one of more of the following flags: 138 | 139 | * `X86_FLAG_LOCK`: The lock prefix was provided to this instruction. 140 | * `X86_FLAG_REP`: This instruction is an unconditional repeated string instruction. 141 | * `X86_FLAG_REPNE`: The repeated string instruction is conditional and uses the `REPNE` prefix. 142 | * `X86_FLAG_REPE`: The repeated string instruction is conditional and uses the `REPE` prefix. 143 | * `X86_FLAG_ANY_REP`: The instruction is any repeated string instruction. 144 | * `X86_FLAG_OPSIZE`: The operand size prefix was used. 145 | * `X86_FLAG_ADDRSIZE`: The address size prefix was used. 146 | * `X86_FLAG_INSUFFICIENT_LENGTH`: The instruction may be valid but an insufficient number of bytes were provided. The `Disassemble` function will return `false` when this flag is set. 147 | 148 | The `segment` member contains the segment prefix, if any. This will be either `SEG_DEFAULT` or a segment register (e.g. `SEG_ES`). 149 | 150 | The `length` member contains the length of the instruction in bytes. This can be used to continue disassembling at the next instruction. Be sure to check the return value of `Disassemble` as an invalid instruction may leave a zero here. 151 | 152 | Each operand is described by the structure below: 153 | 154 | ``` 155 | struct InstructionOperand 156 | { 157 | OperandType operand; 158 | OperandType components[2]; 159 | uint8_t scale; 160 | uint16_t size; 161 | int64_t immediate; 162 | SegmentRegister segment; 163 | }; 164 | ``` 165 | 166 | The `operand` member is an enumeration that contains the operand. This may be a register, or one of the following special enumeration members: 167 | 168 | * `NONE`: The operand is invalid. 169 | * `IMM`: The operand is a constant integer. See the `immediate` member. 170 | * `MEM`: The operand is a memory reference. 171 | 172 | If the `operand` member is `NONE`, none of the other members are defined. Otherwise, the `size` member contains the size in bytes of the operand. If the `operand` member is `IMM`, the `immediate` member is also defined. If the `operand` member is `MEM`, all other members are defined as below. 173 | 174 | The `components` member contains the address components of a memory operand. The first element is never scaled, and the second element is multiplied by the `scale` member. Any element can be `NONE`, which can be represented as a constant zero. If the element is not `NONE`, it will be a register. 175 | 176 | The `size` member contains the size of the operand in bytes. For register operands, this is the size of the register. For memory operands, this is the size of the memory access. 177 | 178 | The `immediate` member contains the value of a constant integer when the operand is the `IMM` type. When the operand is a memory reference, the `immediate` member contains a constant offset for the memory reference. 179 | 180 | The `segment` member contains the segment register that will be used for a memory access. This will always contain a segment register, as `SEG_DEFAULT` is resolved to the default register. 181 | 182 | For memory references, the address of the memory reference is effectively the following formula, where references to the `component` array should look up the current value of the register or substitute zero if the value is `NONE`: 183 | 184 | ``` 185 | address = components[0] + components[1] * scale + immediate 186 | ``` 187 | 188 | ## Assembler API 189 | 190 | The asmx86 library also provides an assembler library for emitting run-time generated code. It is designed to emit machine code using an easy-to-read API without going through any kind of string parsing. The compiled code is very close to the performance of writing machine code manually into a buffer. 191 | 192 | The following is a simple example of how to write code into a buffer: 193 | 194 | ``` 195 | uint8_t* code = allocate(); 196 | X86_DECLARE_JUMP_LABEL(loop); 197 | code += X86_EMIT64_R(code, push, REG_RBP); 198 | code += X86_EMIT64_RR(code, mov_64, REG_RBP, REG_RSP); 199 | code += X86_EMIT64_RI(code, sub_64, REG_RSP, 0x8); 200 | code += X86_EMIT64_MR(code, mov_32, X86_MEM(REG_RBP, -0x8), REG_EDI); 201 | code += X86_EMIT64_MR(code, mov_32, X86_MEM(REG_RBP, -0x4), REG_ESI); 202 | code += X86_EMIT64_RR(code, xor_32, REG_EAX, REG_EAX); 203 | code += X86_EMIT64_RM(code, mov_32, REG_ECX, X86_MEM(REG_RBP, -0x8)); 204 | code += X86_EMIT64_RM(code, mov_32, REG_EDX, X86_MEM(REG_RBP, -0x4)); 205 | X86_MARK_JUMP_LABEL_64(code, loop); 206 | code += X86_EMIT64_RR(code, add_32, REG_EAX, REG_EDX); 207 | code += X86_EMIT64_R(code, inc_32, REG_EDX); 208 | code += X86_EMIT64_R(code, dec_32, REG_ECX); 209 | code += X86_EMIT64_T(code, jnz, loop); 210 | code += X86_EMIT64_RR(code, mov_64, REG_RSP, REG_RBP); 211 | code += X86_EMIT64_R(code, pop, REG_RBP); 212 | code += X86_EMIT64(code, retn); 213 | ``` 214 | 215 | This emits a function to a buffer, which can then be executed by the processor. Often it is not possible to know the maximum size of the code before emitting it, so another set of APIs is available to allow dynamic allocation of buffer space as it is needed. 216 | 217 | These APIs are prefixed by `DYNALLOC`, for example: 218 | 219 | ``` 220 | X86_DYNALLOC_EMIT64_R(buffer, AllocSpaceForInstr, AdvanceForInstr, 221 | push, REG_RBP); 222 | ``` 223 | 224 | The `AllocSpaceForInstr` and `AdvanceForInstr` parameters are to be provided by the caller, and manage the buffer provided. The buffer passed can be any type of object (including a C++ class instance), which the functions provided can use as context to manage the buffer. 225 | 226 | The `AllocSpaceForInstr` function should have the following prototype (the name can be chosen by the caller): 227 | 228 | ``` 229 | uint8_t* AllocSpaceForInstr(void* buffer, size_t length); 230 | ``` 231 | 232 | This function will be called with the `buffer` parameter equal to the `EMIT` call, and the length of the instruction that is to be written. This function can perform any buffer management necessary, such as allocating extra space and emitting an unconditional jump instruction to the new buffer space. It should return a pointer to where the instruction should be written, and must have at least `length` bytes available for writing. The actual instruction written may not be as long as the length given, as some instruction lengths are dependent on the address of the instruction. It will never be longer than the length provided. 233 | 234 | The `AdvanceForInstr` function should have the following prototype: 235 | 236 | ``` 237 | void AdvanceForInstr(void* buffer, size_t length); 238 | ``` 239 | 240 | This function will be called after an instruction is written to the buffer. The `buffer` parameter will be equal to the one provided in the `EMIT` call, and the `length` parameter is the actual length of the instruction written (which may be less than the `length` parameter passed to the `AllocSpaceForInstr` function). The buffer management function can perform any updates necessary to mark the instruction as written and ensure that the next instruction will be written to the correct location following the one written. 241 | 242 | Instructions that have been written to buffers should not be moved in any way until all labels have been resolved. The label API internally keeps pointers to the instructions until they are resolved. 243 | 244 | It is recommended to define a set of pass-through macros that provide the necessary functions to the API automatically, such that the caller can write code like this: 245 | 246 | ``` 247 | CodeBufferObject buffer; 248 | EMIT_RR(&buffer, mov_64, REG_RAX, REG_RDI); 249 | EMIT_RR(&buffer, add_64, REG_RAX, REG_RSI); 250 | EMIT(&buffer, retn); 251 | buffer.Finalize(); 252 | ``` 253 | 254 | This API is not provided by asmx86, as it is dependent on the host system's memory management system, but demonstrates the intended use of the `DYNALLOC` set of APIs. The `EMIT_RR` and `EMIT` macros shown above should be written to resolve to something like the following: 255 | 256 | ``` 257 | X86_DYNALLOC_EMIT64_RR(&buffer, 258 | CodeBufferObject::AllocSpaceForInstr, 259 | CodeBufferObject::AdvanceForInstr, 260 | mov_64, REG_RAX, REG_RDI); 261 | X86_DYNALLOC_EMIT64_RR(&buffer, 262 | CodeBufferObject::AllocSpaceForInstr, 263 | CodeBufferObject::AdvanceForInstr, 264 | add_64, REG_RAX, REG_RSI); 265 | X86_DYNALLOC_EMIT64(&buffer, 266 | CodeBufferObject::AllocSpaceForInstr, 267 | CodeBufferObject::AdvanceForInstr, 268 | retn); 269 | ``` 270 | --------------------------------------------------------------------------------