1 // Copyright (C) 2004, Matt Conover (mconover@gmail.com)
2 #undef NDEBUG
3 #include <assert.h>
4 #include "disasm.h"
5 #include "cpu.h"
6
7 // Since addresses are internally represented as 64-bit, we need to specially handle
8 // cases where IP + Displacement wraps around for 16-bit/32-bit operand size
9 // Otherwise, ignorethe possibility of wraparounds
10 #define SUPPORT_WRAPAROUND
11
12 #ifdef NO_SANITY_CHECKS
13 #undef NDEBUG
14 #undef DEBUG_DISASM
15 #undef assert
16 #define assert(x)
17 #endif
18
19 #ifdef DEBUG_DISASM
20 #define DISASM_OUTPUT(x) printf x
21 #else
22 #define DISASM_OUTPUT(x)
23 #endif
24
25 #include "disasm_x86_tables.h"
26
27 #ifdef _WIN64
28 #ifdef _MSC_VER
29 #pragma warning(disable:4311 4312)
30 #endif
31 #endif
32
33 ////////////////////////////////////////////////////////////////////////
34 // Internal macros
35 ////////////////////////////////////////////////////////////////////////
36
37 #define VIRTUAL_ADDRESS ((U64)Instruction->Address + Instruction->VirtualAddressDelta)
38
39 #define AMD64_DIFF (AMD64_8BIT_OFFSET-X86_8BIT_OFFSET)
40 #define IS_AMD64() (INS_ARCH_TYPE(Instruction) == ARCH_X64)
41 #define IS_X86_32() (INS_ARCH_TYPE(Instruction) == ARCH_X86)
42 #define IS_X86_16() (INS_ARCH_TYPE(Instruction) == ARCH_X86_16)
43
44 #define X86_BOUND 0x62
45 #define X86_PUSH_REG 0x50
46 #define X86_PUSH_CS 0x0e
47 #define X86_PUSH_DS 0x1e
48 #define X86_PUSH_SS 0x16
49 #define X86_PUSH_ES 0x06
50 #define X86_PUSH_FS 0xa0
51 #define X86_PUSH_GS 0xa8
52 #define X86_PUSH_U8 0x6a
53 #define X86_PUSH_U32 0x68
54 #define X86_POP_DS 0x1f
55 #define X86_POP_ES 0x07
56 #define X86_POP_SS 0x17
57 #define X86_POP_FS 0xa1
58 #define X86_POP_GS 0xa9
59 #define X86_POP_REG 0x58
60
61 #define OPCSTR Instruction->String+Instruction->StringIndex
62 #define APPEND Instruction->StringIndex += (U8)_snprintf
63 #define APPENDPAD(x) \
64 { \
65 if (Instruction->StringAligned) \
66 { \
67 if (Instruction->StringIndex > x) assert(0); \
68 while (x != Instruction->StringIndex) APPENDB(' '); \
69 } \
70 else if (Instruction->StringIndex) \
71 { \
72 APPENDB(' '); \
73 } \
74 }
75
76 #define APPENDB(a) Instruction->String[Instruction->StringIndex++] = a
77 #define APPENDS(a) APPEND(OPCSTR, SIZE_LEFT, a);
78
79 #define SIZE_LEFT (MAX_OPCODE_DESCRIPTION-1 > Instruction->StringIndex ? MAX_OPCODE_DESCRIPTION-Instruction->StringIndex : 0)
80
81 // If an address size prefix is used for an instruction that doesn't make sense, restore it
82 // to the default
83
84 #define SANITY_CHECK_OPERAND_SIZE() \
85 { \
86 if (!Instruction->AnomalyOccurred && X86Instruction->HasOperandSizePrefix) \
87 { \
88 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected operand size prefix\n", VIRTUAL_ADDRESS); \
89 Instruction->AnomalyOccurred = TRUE; \
90 X86Instruction->HasOperandSizePrefix = FALSE; \
91 switch (X86Instruction->OperandSize) \
92 { \
93 case 4: X86Instruction->OperandSize = 2; break; \
94 case 2: X86Instruction->OperandSize = 4; break; \
95 default: assert(0); \
96 } \
97 } \
98 }
99
100 #define SANITY_CHECK_ADDRESS_SIZE() \
101 { \
102 if (!Instruction->AnomalyOccurred && X86Instruction->HasAddressSizePrefix) \
103 { \
104 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected address size prefix\n", VIRTUAL_ADDRESS); \
105 Instruction->AnomalyOccurred = TRUE; \
106 } \
107 X86Instruction->HasAddressSizePrefix = FALSE; \
108 switch (INS_ARCH_TYPE(Instruction)) \
109 { \
110 case ARCH_X64: X86Instruction->AddressSize = 8; break; \
111 case ARCH_X86: X86Instruction->AddressSize = 4; break; \
112 case ARCH_X86_16: X86Instruction->AddressSize = 2; break; \
113 } \
114 }
115
116 #define SANITY_CHECK_SEGMENT_OVERRIDE() \
117 if (!Instruction->AnomalyOccurred && X86Instruction->HasSegmentOverridePrefix) \
118 { \
119 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Unexpected segment override\n", VIRTUAL_ADDRESS); \
120 Instruction->AnomalyOccurred = TRUE; \
121 }
122
123 #define INSTR_INC(size) \
124 { \
125 Instruction->Length += size; \
126 Address += size; \
127 }
128
129 #define X86_SET_TARGET() \
130 { \
131 if (X86Instruction->HasSelector) \
132 { \
133 if (!Instruction->AnomalyOccurred) \
134 { \
135 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: unexpected segment 0x%02lX\n", VIRTUAL_ADDRESS, X86Instruction->Selector); \
136 Instruction->AnomalyOccurred = TRUE; \
137 } \
138 } \
139 else \
140 { \
141 switch (X86Instruction->Segment) \
142 { \
143 case SEG_CS: \
144 case SEG_DS: \
145 case SEG_SS: \
146 case SEG_ES: \
147 assert(!X86Instruction->HasSelector); \
148 Operand->TargetAddress = (U64)X86Instruction->Displacement; \
149 /* assert(!GetAbsoluteAddressFromSegment((BYTE)X86Instruction->Segment, (DWORD)X86Instruction->Displacement) || GetAbsoluteAddressFromSegment(X86Instruction->Segment, (DWORD)X86Instruction->Displacement) == Operand->TargetAddress); */ \
150 break; \
151 case SEG_FS: \
152 case SEG_GS: \
153 assert(!X86Instruction->HasSelector); \
154 Operand->TargetAddress = (U64)GetAbsoluteAddressFromSegment((BYTE)X86Instruction->Segment, (DWORD)X86Instruction->Displacement); \
155 break; \
156 default: \
157 assert(0); /* shouldn't be possible */ \
158 break; \
159 } \
160 } \
161 }
162
163 #define X86_SET_SEG(reg) \
164 { \
165 if (!X86Instruction->HasSegmentOverridePrefix && (reg == REG_EBP || reg == REG_ESP)) \
166 { \
167 assert(!X86Instruction->HasSelector); \
168 X86Instruction->Segment = SEG_SS; \
169 } \
170 }
171
172 #define X86_SET_ADDR() \
173 { \
174 if (Operand->Flags & OP_DST) \
175 { \
176 assert(!X86Instruction->HasDstAddressing); \
177 X86Instruction->HasDstAddressing = TRUE; \
178 X86Instruction->DstOpIndex[X86Instruction->DstOpCount] = (U8)OperandIndex; \
179 X86Instruction->DstOpCount++; \
180 X86Instruction->DstAddressIndex = (U8)OperandIndex; \
181 } \
182 if (Operand->Flags & OP_SRC) \
183 { \
184 if (Instruction->Type != ITYPE_STRCMP) assert(!X86Instruction->HasSrcAddressing); \
185 X86Instruction->HasSrcAddressing = TRUE; \
186 X86Instruction->SrcOpIndex[X86Instruction->SrcOpCount] = (U8)OperandIndex; \
187 X86Instruction->SrcOpCount++; \
188 X86Instruction->SrcAddressIndex = (U8)OperandIndex; \
189 } \
190 }
191
192 #define X86_SET_REG(reg) \
193 { \
194 if (Operand->Flags & OP_DST) \
195 { \
196 X86Instruction->DstOpIndex[X86Instruction->DstOpCount] = (U8)OperandIndex; \
197 X86Instruction->DstOpCount++; \
198 assert(OperandIndex < 2); \
199 if (Operand->Length > 1 && reg == REG_ESP) Instruction->Groups |= ITYPE_STACK; \
200 } \
201 if (Operand->Flags & OP_SRC) \
202 { \
203 X86Instruction->SrcOpIndex[X86Instruction->SrcOpCount] = (U8)OperandIndex; \
204 X86Instruction->SrcOpCount++; \
205 } \
206 }
207
208 #define CHECK_AMD64_REG() { if (IS_AMD64()) Operand->Register += AMD64_DIFF; }
209
210 ////////////////////////////////////////////////////////////////////////
211 // Internal structures/variables
212 ////////////////////////////////////////////////////////////////////////
213
214 ARCHITECTURE_FORMAT_FUNCTIONS X86 =
215 {
216 X86_InitInstruction,
217 NULL,
218 X86_GetInstruction,
219 X86_FindFunctionByPrologue
220 };
221
222 char *X86_Registers[0xE0] =
223 {
224 // Segments
225 "es", // 0x00
226 "cs", // 0x01
227 "ss", // 0x02
228 "ds", // 0x03
229 "fs", // 0x04
230 "gs", // 0x05
231 "flags", // 0x06
232 "eflags", // 0x07
233 "rflags", // 0x08
234 "ip+ilen", // 0x09
235 "eip+ilen", // 0x0A
236 "rip+ilen", // 0x0B
237 NULL, // 0x0C
238 NULL, // 0x0D
239 NULL, // 0x0E
240 NULL, // 0x0F
241
242 // Test
243 "tr0", // 0x10
244 "tr1", // 0x11
245 "tr2", // 0x12
246 "tr3", // 0x13
247 "tr4", // 0x14
248 "tr5", // 0x15
249 "tr6", // 0x16
250 "tr7", // 0x17
251 "tr8", // 0x18
252 "tr9", // 0x19
253 "tr10", // 0x1A
254 "tr11", // 0x1B
255 "tr12", // 0x1C
256 "tr13", // 0x1D
257 "tr14", // 0x1E
258 "tr15", // 0x1F
259
260 // Control
261 "cr0", // 0x20
262 "cr1", // 0x21
263 "cr2", // 0x22
264 "cr3", // 0x23
265 "cr4", // 0x24
266 "cr5", // 0x25
267 "cr6", // 0x26
268 "cr7", // 0x27
269 "cr8", // 0x18
270 "cr9", // 0x19
271 "cr10", // 0x1A
272 "cr11", // 0x1B
273 "cr12", // 0x1C
274 "cr13", // 0x1D
275 "cr14", // 0x1E
276 "cr15", // 0x1F
277
278 // Debug
279 "dr0", // 0x30
280 "dr1", // 0x31
281 "dr2", // 0x32
282 "dr3", // 0x33
283 "dr4", // 0x34
284 "dr5", // 0x35
285 "dr6", // 0x36
286 "dr7", // 0x37
287 "dr8", // 0x38
288 "dr9", // 0x39
289 "dr10", // 0x3A
290 "dr11", // 0x3B
291 "dr12", // 0x3C
292 "dr13", // 0x3D
293 "dr14", // 0x3E
294 "dr15", // 0x3F
295
296 // FPU
297 "st(0)", // 0x40
298 "st(1)", // 0x41
299 "st(2)", // 0x42
300 "st(3)", // 0x43
301 "st(4)", // 0x44
302 "st(5)", // 0x45
303 "st(6)", // 0x46
304 "st(7)", // 0x47
305 NULL, // 0x48
306 NULL, // 0x49
307 NULL, // 0x4A
308 NULL, // 0x4B
309 NULL, // 0x4C
310 NULL, // 0x4D
311 NULL, // 0x4E
312 NULL, // 0x4F
313
314 // MMX
315 "mm0", // 0x50
316 "mm1", //
317 "mm2",
318 "mm3",
319 "mm4",
320 "mm5",
321 "mm6",
322 "mm7",
323 NULL, // 0x58
324 NULL, // 0x59
325 NULL, // 0x5A
326 NULL, // 0x5B
327 NULL, // 0x5C
328 NULL, // 0x5D
329 NULL, // 0x5E
330 NULL, // 0x5F
331
332 // XMM
333 "xmm0", // 0x60
334 "xmm1", // 0x61
335 "xmm2", // 0x62
336 "xmm3", // 0x63
337 "xmm4", // 0x64
338 "xmm5", // 0x65
339 "xmm6", // 0x66
340 "xmm7", // 0x67
341 "xmm8", // 0x68
342 "xmm9", // 0x69
343 "xmm10", // 0x6a
344 "xmm11", // 0x6b
345 "xmm12", // 0x6c
346 "xmm13", // 0x6d
347 "xmm14", // 0x6e
348 "xmm15", // 0x6f
349
350 // 8-bit
351 "al", // 0x70
352 "cl", // 0x71
353 "dl", // 0x72
354 "bl", // 0x73
355 "ah", // 0x74
356 "ch", // 0x75
357 "dh", // 0x76
358 "bh", // 0x77
359 NULL, // 0x78
360 NULL, // 0x79
361 NULL, // 0x7A
362 NULL, // 0x7B
363 NULL, // 0x7C
364 NULL, // 0x7D
365 NULL, // 0x7E
366 NULL, // 0x7F
367
368 // 16-bit
369 "ax", // 0x80
370 "cx", // 0x81
371 "dx", // 0x82
372 "bx", // 0x83
373 "sp", // 0x84
374 "bp", // 0x85
375 "si", // 0x86
376 "di", // 0x87
377 NULL, // 0x88
378 NULL, // 0x89
379 NULL, // 0x8A
380 NULL, // 0x8B
381 NULL, // 0x8C
382 NULL, // 0x8D
383 NULL, // 0x8E
384 NULL, // 0x8F
385
386 // 32-bit
387 "eax", // 0x90
388 "ecx", // 0x91
389 "edx", // 0x92
390 "ebx", // 0x93
391 "esp", // 0x94
392 "ebp", // 0x95
393 "esi", // 0x96
394 "edi", // 0x97
395 NULL, // 0x98
396 NULL, // 0x99
397 NULL, // 0x9A
398 NULL, // 0x9B
399 NULL, // 0x9C
400 NULL, // 0x9D
401 NULL, // 0x9E
402 NULL, // 0x9F
403
404 // X86-64 8-bit register
405 "al", // 0xA0
406 "cl", // 0xA1
407 "dl", // 0xA2
408 "bl", // 0xA3
409 "spl", // 0xA4
410 "bpl", // 0xA5
411 "sil", // 0xA6
412 "dil", // 0xA7
413 "r8b", // 0xA8
414 "r9b", // 0xA9
415 "r10b", // 0xAA
416 "r11b", // 0xAB
417 "r12b", // 0xAC
418 "r13b", // 0xAD
419 "r14b", // 0xAE
420 "r15b", // 0xAF
421
422 // X86-64 16-bit register
423 "ax", // 0xB0
424 "cx", // 0xB1
425 "dx", // 0xB2
426 "bx", // 0xB3
427 "sp", // 0xB4
428 "bp", // 0xB5
429 "si", // 0xB6
430 "di", // 0xB7
431 "r8w", // 0xB8
432 "r9w", // 0xB9
433 "r10w", // 0xBA
434 "r11w", // 0xBB
435 "r12w", // 0xBC
436 "r13w", // 0xBD
437 "r14w", // 0xBE
438 "r15w", // 0xBF
439
440 // X86-64 32-bit register
441 "eax", // 0xC0
442 "ecx", // 0xC1
443 "edx", // 0xC2
444 "ebx", // 0xC3
445 "esp", // 0xC4
446 "ebp", // 0xC5
447 "esi", // 0xC6
448 "edi", // 0xC7
449 "r8d", // 0xC8
450 "r9d", // 0xC9
451 "r10d", // 0xCA
452 "r11d", // 0xCB
453 "r12d", // 0xCC
454 "r13d", // 0xCD
455 "r14d", // 0xCE
456 "r15d", // 0xCF
457
458 // X86-64 64-bit register
459 "rax", // 0xD0
460 "rcx", // 0xD1
461 "rdx", // 0xD2
462 "rbx", // 0xD3
463 "rsp", // 0xD4
464 "rbp", // 0xD5
465 "rsi", // 0xD6
466 "rdi", // 0xD7
467 "r8", // 0xD8
468 "r9", // 0xD9
469 "r10", // 0xDA
470 "r11", // 0xDB
471 "r12", // 0xDC
472 "r13", // 0xDD
473 "r14", // 0xDE
474 "r15" // 0xDF
475 };
476
477 void OutputBounds(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
478 void OutputGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
479 void OutputDescriptor(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
480 void OutputSegOffset(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
481 void OutputPackedReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
482 void OutputPackedBCD(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
483 void OutputScalarReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
484 void OutputScalarGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
485 void OutputFPUEnvironment(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
486 void OutputFPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
487 void OutputCPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
488
489 typedef void (*OUTPUT_OPTYPE)(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex);
490 #define OPTYPE_SHIFT 24
491 #define MAX_OPTYPE_INDEX 26
492 OUTPUT_OPTYPE OptypeHandlers[] =
493 {
494 NULL,
495 OutputBounds, // 01 OPTYPE_a
496 OutputGeneral, // 02 OPTYPE_b
497 OutputGeneral, // 03 OPTYPE_d
498 OutputSegOffset, // 04 OPTYPE_p
499 OutputGeneral, // 05 OPTYPE_q
500 OutputDescriptor, // 06 OPTYPE_dt
501 OutputGeneral, // 07 OPTYPE_v
502 OutputGeneral, // 08 OPTYPE_w
503 OutputPackedReal, // 09 OPTYPE_ps
504 OutputPackedReal, // 0A OPTYPE_pd
505 OutputPackedBCD, // 0B OPTYPE_pb
506 OutputScalarReal, // 0C OPTYPE_ss
507 OutputScalarReal, // 0D OPTYPE_sd
508 OutputScalarReal, // 0E OPTYPE_se
509 OutputFPUEnvironment, // 0F OPTYPE_fev
510 OutputFPUState, // 10 OPTYPE_fst1
511 OutputFPUState, // 11 OPTYPE_fst2
512 OutputGeneral, // 12 OPTYPE_z
513 OutputGeneral, // 13 OPTYPE_o
514 OutputGeneral, // 14 OPTYPE_dq
515 OutputGeneral, // 15 OPTYPE_mw
516 OutputScalarGeneral, // 16 OPTYPE_sso
517 OutputScalarGeneral, // 17 OPTYPE_sdo
518 OutputCPUState, // 18 OPTYPE_cpu
519 OutputGeneral, // 19 OPTYPE_lea
520 };
521
522 #define OPTYPE_a 0x01000000
523 #define OPTYPE_b 0x02000000
524 #define OPTYPE_d 0x03000000
525 #define OPTYPE_p 0x04000000
526 #define OPTYPE_q 0x05000000
527 #define OPTYPE_dt 0x06000000
528 #define OPTYPE_v 0x07000000
529 #define OPTYPE_w 0x08000000
530 #define OPTYPE_ps 0x09000000 // packed 128-bit single real
531 #define OPTYPE_pd 0x0A000000 // packed 128-bit double real
532 #define OPTYPE_pb 0x0B000000 // packed BCD (10 bytes, 18-bit precision)
533 #define OPTYPE_ss 0x0C000000 // scalar single real
534 #define OPTYPE_sd 0x0D000000 // scalar double real
535 #define OPTYPE_se 0x0E000000 // scalar extended real
536 #define OPTYPE_fev 0x0F000000 // FPU environment (28 bytes if 32-bit modes, 14 bytes in 16-bit mode)
537 #define OPTYPE_fst1 0x10000000 // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode)
538 #define OPTYPE_fst2 0x11000000 // FPU/MMX/XMM/MXCSR state (512 bytes)
539 #define OPTYPE_z 0x12000000
540 #define OPTYPE_o 0x13000000
541 #define OPTYPE_dq 0x14000000 // OPTYPE_d or OPTYPE_o
542 #define OPTYPE_mw 0x15000000 // word if memory, register size otherwise
543 #define OPTYPE_sso 0x16000000 // OPTYPE_ss or OPTYPE_o
544 #define OPTYPE_sdo 0x17000000 // OPTYPE_ss or OPTYPE_o
545 #define OPTYPE_cpu 0x18000000 // pointer to CPU state structure
546 #define OPTYPE_lea 0x19000000 // size set by other operand
547
548 ////////////////////////////////////////////////////////////////////////
549 // Internal functions
550 ////////////////////////////////////////////////////////////////////////
551
552 #ifdef TEST_DISASM // TODO: remove
553 U32 X86_GetLength(INSTRUCTION *Instruction, U8 *Address);
554 #endif
555
556 INTERNAL BOOL IsValidLockPrefix(X86_INSTRUCTION *Instruction, U8 Opcode, U32 OpcodeLength, U8 Group, U8 OpcodeExtension);
557 INTERNAL U8 *SetOperands(INSTRUCTION *Instruction, U8 *Address, U32 Flags);
558 INTERNAL U8 *SetModRM32(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors);
559 INTERNAL U8 *SetModRM16(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors);
560 INTERNAL U8 *SetSIB(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors);
561 INTERNAL U64 ApplyDisplacement(U64 Address, INSTRUCTION *Instruction);
562
563 //////////////////////////////////////////////////////////
564 // Instruction setup
565 //////////////////////////////////////////////////////////
566
567 #define APPLY_OFFSET(addr) \
568 { \
569 switch (X86Instruction->OperandSize) \
570 { \
571 case 8: addr = ((U64)(addr + Instruction->VirtualAddressDelta)); break; \
572 case 4: addr = (U64)((U32)(addr + Instruction->VirtualAddressDelta)); break; \
573 case 2: addr = (U64)((U8)(addr + Instruction->VirtualAddressDelta)); break; \
574 default: assert(0); break; \
575 } \
576 }
577
X86_InitInstruction(INSTRUCTION * Instruction)578 BOOL X86_InitInstruction(INSTRUCTION *Instruction)
579 {
580 X86_INSTRUCTION *X86Instruction;
581 #ifdef NO_SANITY_CHECKS
582 assert(0); // be sure assertions are disabled
583 #endif
584 X86Instruction = &Instruction->X86;
585 memset(X86Instruction, 0, sizeof(X86_INSTRUCTION));
586
587 switch (INS_ARCH_TYPE(Instruction))
588 {
589 case ARCH_X64:
590 X86Instruction->AddressSize = 8;
591 X86Instruction->OperandSize = 4;
592 break;
593 case ARCH_X86:
594 X86Instruction->AddressSize = 4;
595 X86Instruction->OperandSize = 4;
596 break;
597 case ARCH_X86_16:
598 X86Instruction->AddressSize = 2;
599 X86Instruction->OperandSize = 2;
600 break;
601 default:
602 assert(0);
603 return FALSE;
604 }
605 X86Instruction->Instruction = Instruction;
606 X86Instruction->Segment = SEG_DS;
607 return TRUE;
608 }
609
610 ////////////////////////////////////////////////////////////
611 // Formatting
612 // You can change these to whatever you prefer
613 ////////////////////////////////////////////////////////////
614
615 #define X86_WRITE_OPFLAGS() \
616 if (Flags & DISASM_SHOWFLAGS) \
617 { \
618 APPENDB('{'); \
619 assert(Operand->Flags & (OP_EXEC|OP_SRC|OP_DST)); \
620 if (Operand->Flags & OP_IPREL) APPENDB('r'); \
621 if (Operand->Flags & OP_FAR) APPENDB('f'); \
622 if (Operand->Flags & OP_CONDR) APPENDB('c'); \
623 if (Operand->Flags & OP_EXEC) APPENDB('X'); \
624 else if (Operand->Flags & OP_SRC) APPENDB('R'); \
625 if (Operand->Flags & OP_CONDW) APPENDB('c'); \
626 if (Operand->Flags & OP_DST) APPENDB('W'); \
627 if (Operand->Flags & OP_SYS) APPENDB('S'); \
628 if (Operand->Flags & OP_ADDRESS) APPENDB('A'); \
629 if (Operand->Flags & OP_PARAM) APPENDB('P'); \
630 if (Operand->Flags & OP_LOCAL) APPENDB('L'); \
631 if (Operand->Flags & OP_GLOBAL) APPENDB('G'); \
632 APPENDB('}'); \
633 }
634
635 #define X86_WRITE_IMMEDIATE() \
636 { \
637 switch (Operand->Length) \
638 { \
639 case 8: \
640 APPEND(OPCSTR, SIZE_LEFT, "0x%02I64X=", Operand->Value_U64); \
641 if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%I64u", Operand->Value_U64); \
642 /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02I64X=%I64d", -Operand->Value_S64, Operand->Value_S64);*/ \
643 else APPEND(OPCSTR, SIZE_LEFT, "%I64d", Operand->Value_S64); \
644 break; \
645 case 4: \
646 APPEND(OPCSTR, SIZE_LEFT, "0x%02lX=", (U32)Operand->Value_U64); \
647 if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%lu", (U32)Operand->Value_U64); \
648 /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02lX=%ld", (U32)-Operand->Value_S64, (S32)Operand->Value_S64);*/ \
649 else APPEND(OPCSTR, SIZE_LEFT, "%ld", (S32)Operand->Value_S64); \
650 break; \
651 case 2: \
652 APPEND(OPCSTR, SIZE_LEFT, "0x%02X=", (U16)Operand->Value_U64); \
653 if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%u", (U16)Operand->Value_U64); \
654 /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X=%d", (U16)-Operand->Value_S64, (S16)Operand->Value_S64);*/ \
655 else APPEND(OPCSTR, SIZE_LEFT, "%d", (S16)Operand->Value_S64); \
656 break; \
657 case 1: \
658 APPEND(OPCSTR, SIZE_LEFT, "0x%02X=", (U8)Operand->Value_U64); \
659 if (Operand->Value_S64 >= 0 || !(Operand->Flags & OP_SIGNED)) APPEND(OPCSTR, SIZE_LEFT, "%u", (U8)Operand->Value_U64); \
660 /*else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X=%d", (U8)-Operand->Value_S64, (S8)Operand->Value_S64);*/ \
661 else APPEND(OPCSTR, SIZE_LEFT, "%d", (S8)Operand->Value_S64); \
662 break; \
663 default: assert(0); break; \
664 } \
665 }
666
667 #define X86_WRITE_ABSOLUTE_DISPLACEMENT() \
668 { \
669 switch (X86Instruction->AddressSize) \
670 { \
671 case 8: \
672 APPEND(OPCSTR, SIZE_LEFT, "0x%04I64X", X86Instruction->Displacement); \
673 break; \
674 case 4: \
675 APPEND(OPCSTR, SIZE_LEFT, "0x%04lX", (U32)X86Instruction->Displacement); \
676 break; \
677 case 2: \
678 APPEND(OPCSTR, SIZE_LEFT, "0x%04X", (U16)X86Instruction->Displacement); \
679 break; \
680 default: assert(0); break; \
681 } \
682 }
683
684 #define X86_WRITE_RELATIVE_DISPLACEMENT64() \
685 if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02I64X", X86Instruction->Displacement); \
686 else APPEND(OPCSTR, SIZE_LEFT, "-0x%02I64X", -X86Instruction->Displacement);
687
688 #define X86_WRITE_RELATIVE_DISPLACEMENT32() \
689 if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02lX", (U32)X86Instruction->Displacement); \
690 else APPEND(OPCSTR, SIZE_LEFT, "-0x%02lX", (U32)-X86Instruction->Displacement);
691
692 #define X86_WRITE_RELATIVE_DISPLACEMENT16() \
693 if (X86Instruction->Displacement >= 0) APPEND(OPCSTR, SIZE_LEFT, "+0x%02X", (U16)X86Instruction->Displacement); \
694 else APPEND(OPCSTR, SIZE_LEFT, "-0x%02X", (U16)-X86Instruction->Displacement);
695
696 #define X86_WRITE_RELATIVE_DISPLACEMENT() \
697 { \
698 switch (X86Instruction->AddressSize) \
699 { \
700 case 8: \
701 X86_WRITE_RELATIVE_DISPLACEMENT64() \
702 break; \
703 case 4: \
704 X86_WRITE_RELATIVE_DISPLACEMENT32() \
705 break; \
706 case 2: \
707 X86_WRITE_RELATIVE_DISPLACEMENT16() \
708 break; \
709 default: assert(0); break; \
710 } \
711 }
712
713 #define X86_WRITE_IP_OFFSET(op) \
714 { \
715 switch (X86Instruction->OperandSize) \
716 { \
717 case 8: \
718 APPENDS("[rip+ilen"); \
719 assert((op)->TargetAddress); \
720 X86_WRITE_RELATIVE_DISPLACEMENT64() \
721 APPEND(OPCSTR, SIZE_LEFT, "]=0x%04I64X", (op)->TargetAddress+Instruction->VirtualAddressDelta); \
722 break; \
723 case 4: \
724 APPENDS("[eip+ilen"); \
725 assert((op)->TargetAddress); \
726 X86_WRITE_RELATIVE_DISPLACEMENT32() \
727 APPEND(OPCSTR, SIZE_LEFT, "]=0x%04lX", (U32)((op)->TargetAddress+Instruction->VirtualAddressDelta)); \
728 break; \
729 case 2: \
730 APPENDS("[ip+ilen"); \
731 X86_WRITE_RELATIVE_DISPLACEMENT16() \
732 APPEND(OPCSTR, SIZE_LEFT, "]=0x%04X", (U16)((op)->TargetAddress+Instruction->VirtualAddressDelta)); \
733 break; \
734 default: assert(0); break; \
735 } \
736 }
737
738 #define X86_WRITE_OFFSET(op) \
739 { \
740 assert((op)->Length <= 8); \
741 if (X86Instruction->HasSelector) \
742 { \
743 assert((op)->Flags & OP_FAR); \
744 APPEND(OPCSTR, SIZE_LEFT, "%s 0x%02lX:[", DataSizes[((op)->Length >> 1)], X86Instruction->Selector); \
745 } \
746 else \
747 { \
748 assert(!((op)->Flags & OP_FAR)); \
749 assert(X86Instruction->Segment < SEG_MAX) ; \
750 APPEND(OPCSTR, SIZE_LEFT, "%s %s:[", DataSizes[((op)->Length >> 1)], Segments[X86Instruction->Segment]); \
751 } \
752 X86_WRITE_ABSOLUTE_DISPLACEMENT() \
753 APPENDB(']'); \
754 }
755
OutputAddress(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)756 void OutputAddress(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
757 {
758 BOOL ShowDisplacement = FALSE;
759 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
760
761 assert(!X86Instruction->HasSelector);
762 assert(X86Instruction->SrcAddressIndex == OperandIndex || X86Instruction->DstAddressIndex == OperandIndex);
763 if (Operand->Length > 16 || (Operand->Length > 1 && (Operand->Length & 1))) APPEND(OPCSTR, SIZE_LEFT, "%d_byte ptr ", Operand->Length);
764 else APPEND(OPCSTR, SIZE_LEFT, "%s ", DataSizes[Operand->Length >> 1]);
765
766 //
767 // This attempts to display the address intelligently
768 // If it has a positive 32-bit displacement, it is shown as seg:Displacement[base+index*scale]
769 // If it is a negative displacement or 8-bit, it is shown as seg:[base+index*scale+displacement]
770 //
771 APPEND(OPCSTR, SIZE_LEFT, "%s:", Segments[X86Instruction->Segment]);
772 if (X86Instruction->HasBaseRegister)
773 {
774 if (X86Instruction->Displacement)
775 {
776 if (X86Instruction->HasFullDisplacement) X86_WRITE_ABSOLUTE_DISPLACEMENT()
777 else ShowDisplacement = TRUE;
778 }
779 APPEND(OPCSTR, SIZE_LEFT, "[%s", X86_Registers[X86Instruction->BaseRegister]);
780 if (X86Instruction->HasIndexRegister)
781 {
782 APPEND(OPCSTR, SIZE_LEFT, "+%s", X86_Registers[X86Instruction->IndexRegister]);
783 if (X86Instruction->Scale > 1) APPEND(OPCSTR, SIZE_LEFT, "*%d", X86Instruction->Scale);
784 }
785 if (ShowDisplacement) X86_WRITE_RELATIVE_DISPLACEMENT()
786 APPENDB(']');
787 if (X86Instruction->Relative)
788 {
789 U64 Address = Operand->TargetAddress;
790 assert(Address);
791 APPLY_OFFSET(Address)
792 APPEND(OPCSTR, SIZE_LEFT, "=[0x%04I64X]", Address);
793 }
794 }
795 else if (X86Instruction->HasIndexRegister)
796 {
797 if (X86Instruction->Displacement)
798 {
799 if (X86Instruction->HasFullDisplacement) X86_WRITE_ABSOLUTE_DISPLACEMENT()
800 else ShowDisplacement = TRUE;
801 }
802 APPEND(OPCSTR, SIZE_LEFT, "[%s", X86_Registers[X86Instruction->IndexRegister]);
803 if (X86Instruction->Scale > 1) APPEND(OPCSTR, SIZE_LEFT, "*%d", X86Instruction->Scale);
804 if (ShowDisplacement) X86_WRITE_RELATIVE_DISPLACEMENT()
805 APPENDB(']');
806 }
807 else // just a displacement
808 {
809 APPENDB('[');
810 X86_WRITE_ABSOLUTE_DISPLACEMENT()
811 APPENDB(']');
812 }
813 }
814
OutputBounds(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)815 void OutputBounds(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
816 {
817 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
818 assert(X86Instruction->HasSrcAddressing);
819 assert(!(Operand->Length & 1));
820 Operand->Length >>= 1;
821 APPENDB('(');
822 OutputAddress(Instruction, Operand, OperandIndex);
823 APPENDS(", ");
824 X86Instruction->Displacement += Operand->Length;
825 OutputAddress(Instruction, Operand, OperandIndex);
826 X86Instruction->Displacement -= Operand->Length;
827 APPENDB(')');
828 Operand->Length <<= 1;
829 }
830
OutputGeneral(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)831 void OutputGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
832 {
833 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
834 if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) ||
835 (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex))
836 {
837 OutputAddress(Instruction, Operand, OperandIndex);
838 }
839 else
840 {
841 APPENDS(X86_Registers[Operand->Register]);
842 }
843 }
844
OutputDescriptor(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)845 void OutputDescriptor(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
846 {
847 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
848 assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing);
849 OutputAddress(Instruction, Operand, OperandIndex);
850 }
851
OutputPackedReal(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)852 void OutputPackedReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
853 {
854 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
855 if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) ||
856 (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex))
857 {
858 OutputAddress(Instruction, Operand, OperandIndex);
859 }
860 else
861 {
862 APPENDS(X86_Registers[Operand->Register]);
863 }
864 }
865
OutputPackedBCD(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)866 void OutputPackedBCD(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
867 {
868 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
869 if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) ||
870 (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex))
871 {
872 OutputAddress(Instruction, Operand, OperandIndex);
873 }
874 else
875 {
876 APPENDS(X86_Registers[Operand->Register]);
877 }
878 }
879
OutputScalarReal(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)880 void OutputScalarReal(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
881 {
882 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
883 if ((X86Instruction->HasDstAddressing && X86Instruction->DstAddressIndex == OperandIndex) ||
884 (X86Instruction->HasSrcAddressing && X86Instruction->SrcAddressIndex == OperandIndex))
885 {
886 OutputAddress(Instruction, Operand, OperandIndex);
887 }
888 else
889 {
890 APPENDS(X86_Registers[Operand->Register]);
891 }
892 }
893
OutputScalarGeneral(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)894 void OutputScalarGeneral(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
895 {
896 if (Operand->Type == OPTYPE_FLOAT)
897 {
898 OutputScalarReal(Instruction, Operand, OperandIndex);
899 }
900 else
901 {
902 OutputGeneral(Instruction, Operand, OperandIndex);
903 }
904 }
905
OutputFPUEnvironment(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)906 void OutputFPUEnvironment(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
907 {
908 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
909 assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing);
910 OutputAddress(Instruction, Operand, OperandIndex);
911 }
912
OutputFPUState(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)913 void OutputFPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
914 {
915 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
916 assert(X86Instruction->HasSrcAddressing || X86Instruction->HasDstAddressing);
917 OutputAddress(Instruction, Operand, OperandIndex);
918 }
919
OutputCPUState(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)920 void OutputCPUState(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
921 {
922 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
923 assert(X86Instruction->HasSrcAddressing);
924 OutputAddress(Instruction, Operand, OperandIndex);
925 }
926
OutputSegOffset(INSTRUCTION * Instruction,INSTRUCTION_OPERAND * Operand,U32 OperandIndex)927 void OutputSegOffset(INSTRUCTION *Instruction, INSTRUCTION_OPERAND *Operand, U32 OperandIndex)
928 {
929 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
930 assert(X86Instruction->HasSrcAddressing);
931 OutputAddress(Instruction, Operand, OperandIndex);
932 }
933
934 ////////////////////////////////////////////////////////////
935 // Prologue support
936 ////////////////////////////////////////////////////////////
937
938 typedef struct _PROLOGUE
939 {
940 char *Data;
941 U32 Length;
942 } PROLOGUE;
943
944 PROLOGUE StandardPrologues[] =
945 {
946 { "\x55\x8b\xec", 3 },
947 { "\x55\x89\xe5", 3 },
948 { "\x83\xec", 2 },
949 { "\x81\xec", 2 },
950 // TODO: add AMD64 prologues
951 // TODO: add VS2003/VS2003 prologues
952 // TODO: add any unique prologues from other compilers
953 { NULL, 0 }
954 };
955
956 // Find the first function between StartAddress and EndAddress
957 //
958 // This will match a standard prologue and then analyze the following instructions to verify
959 // it is a valid function
X86_FindFunctionByPrologue(INSTRUCTION * Instruction,U8 * StartAddress,U8 * EndAddress,U32 Flags)960 U8 *X86_FindFunctionByPrologue(INSTRUCTION *Instruction, U8 *StartAddress, U8 *EndAddress, U32 Flags)
961 {
962 assert(0); // TODO
963 return NULL;
964 }
965
966 //////////////////////////////////////////////////////////
967 // Instruction decoder
968 //////////////////////////////////////////////////////////
969
X86_GetInstruction(INSTRUCTION * Instruction,U8 * Address,U32 Flags)970 BOOL X86_GetInstruction(INSTRUCTION *Instruction, U8 *Address, U32 Flags)
971 {
972 BOOL SpecialExtension = FALSE;
973 U8 Opcode = 0, OpcodeExtension = 0, Group = 0, SSE_Prefix = 0, Suffix;
974 U32 i = 0, Result = 0, tmpScale;
975 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
976 X86_OPCODE *X86Opcode;
977 #ifdef TEST_DISASM
978 U32 InstructionLength = 0;
979 #endif
980 INSTRUCTION_OPERAND *Operand, *Operand1 = NULL;
981 DISASSEMBLER *Disassembler = Instruction->Disassembler;
982 BOOL Decode = Flags & DISASM_DECODE;
983 BOOL Disassemble = Flags & DISASM_DISASSEMBLE;
984 BOOL SuppressErrors = Flags & DISASM_SUPPRESSERRORS;
985
986 if (Disassemble && !Decode)
987 {
988 assert(0);
989 Decode = TRUE;
990 }
991
992 if (!Address || !X86_InitInstruction(Instruction))
993 {
994 assert(0);
995 goto abort;
996 }
997
998 assert(Instruction->Address == Address);
999 assert(!Instruction->StringIndex && !Instruction->Length);
1000
1001 Disassembler->Stage1Count++;
1002 if (Flags & DISASM_ALIGNOUTPUT) Instruction->StringAligned = TRUE;
1003
1004 //
1005 // Get prefixes or three byte opcode
1006 //
1007 while (TRUE)
1008 {
1009 Opcode = *Address;
1010 INSTR_INC(1); // increment Instruction->Length and address
1011 X86Opcode = &X86_Opcodes_1[Opcode];
1012
1013 // Handle a misplaced REX prefix -- AMD64 manual says it is just ignored
1014 if (IS_AMD64() && (Opcode >= REX_PREFIX_START && Opcode <= REX_PREFIX_END) && X86_PREFIX((&X86_Opcodes_1[*Address])))
1015 {
1016 if (!Instruction->AnomalyOccurred)
1017 {
1018 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: REX prefix before legacy prefix 0x%02X\n", VIRTUAL_ADDRESS, Opcode);
1019 Instruction->AnomalyOccurred = TRUE;
1020 }
1021 continue;
1022 }
1023
1024 if (X86_PREFIX(X86Opcode))
1025 {
1026 if (!Instruction->AnomalyOccurred)
1027 {
1028 for (i = 0; i < Instruction->PrefixCount; i++)
1029 {
1030 if (Instruction->Prefixes[i] == Opcode)
1031 {
1032 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Duplicate prefix 0x%02X\n", VIRTUAL_ADDRESS, Opcode);
1033 Instruction->AnomalyOccurred = TRUE;
1034 break;
1035 }
1036 }
1037 }
1038
1039 switch (Opcode)
1040 {
1041 case PREFIX_REPNE: // may be three byte opcode
1042 SSE_Prefix = Opcode;
1043 if (!Instruction->AnomalyOccurred && X86Instruction->HasRepeatWhileEqualPrefix)
1044 {
1045 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS);
1046 Instruction->AnomalyOccurred = TRUE;
1047 }
1048 Instruction->Repeat = TRUE;
1049 X86Instruction->HasRepeatWhileEqualPrefix = FALSE;
1050 X86Instruction->HasRepeatWhileNotEqualPrefix = TRUE;
1051 break;
1052 case PREFIX_REP: // may be three byte opcode
1053 SSE_Prefix = Opcode;
1054 if (!Instruction->AnomalyOccurred && X86Instruction->HasRepeatWhileNotEqualPrefix)
1055 {
1056 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS);
1057 Instruction->AnomalyOccurred = TRUE;
1058 }
1059
1060 Instruction->Repeat = TRUE;
1061 X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE;
1062 X86Instruction->HasRepeatWhileEqualPrefix = TRUE;
1063 break;
1064
1065 case PREFIX_OPERAND_SIZE: // may be three byte opcode
1066 SSE_Prefix = Opcode;
1067 if (!Instruction->AnomalyOccurred && X86Instruction->HasOperandSizePrefix)
1068 {
1069 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS);
1070 Instruction->AnomalyOccurred = TRUE;
1071 }
1072
1073 if (X86Instruction->HasOperandSizePrefix) break;
1074 else X86Instruction->HasOperandSizePrefix = TRUE;
1075 switch (X86Instruction->OperandSize)
1076 {
1077 case 4: X86Instruction->OperandSize = 2; break;
1078 case 2: X86Instruction->OperandSize = 4; break;
1079 default: assert(0); goto abort;
1080 }
1081 break;
1082
1083 case PREFIX_ADDRESS_SIZE:
1084 if (!Instruction->AnomalyOccurred && X86Instruction->HasAddressSizePrefix)
1085 {
1086 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS);
1087 Instruction->AnomalyOccurred = TRUE;
1088 }
1089
1090 if (X86Instruction->HasAddressSizePrefix) break;
1091 else X86Instruction->HasAddressSizePrefix = TRUE;
1092 switch (X86Instruction->AddressSize)
1093 {
1094 case 8:
1095 X86Instruction->AddressSize = 4;
1096 break;
1097 case 4:
1098 assert(!IS_AMD64()); // this should not be possible
1099 X86Instruction->AddressSize = 2;
1100 break;
1101 case 2:
1102 X86Instruction->AddressSize = 4;
1103 break;
1104 default:
1105 assert(0); goto abort;
1106 }
1107 break;
1108
1109 case PREFIX_SEGMENT_OVERRIDE_ES:
1110 SANITY_CHECK_SEGMENT_OVERRIDE();
1111 if (!IS_AMD64())
1112 {
1113 X86Instruction->HasSegmentOverridePrefix = TRUE;
1114 X86Instruction->Segment = SEG_ES;
1115 }
1116 else if (!Instruction->AnomalyOccurred)
1117 {
1118 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS);
1119 Instruction->AnomalyOccurred = TRUE;
1120 }
1121 break;
1122 case PREFIX_SEGMENT_OVERRIDE_CS:
1123 SANITY_CHECK_SEGMENT_OVERRIDE();
1124 if (!IS_AMD64())
1125 {
1126 X86Instruction->HasSegmentOverridePrefix = TRUE;
1127 X86Instruction->Segment = SEG_CS;
1128 }
1129 else if (!Instruction->AnomalyOccurred)
1130 {
1131 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS);
1132 Instruction->AnomalyOccurred = TRUE;
1133 }
1134 break;
1135 case PREFIX_SEGMENT_OVERRIDE_SS:
1136 SANITY_CHECK_SEGMENT_OVERRIDE();
1137 if (!IS_AMD64())
1138 {
1139 X86Instruction->HasSegmentOverridePrefix = TRUE;
1140 X86Instruction->Segment = SEG_SS;
1141 }
1142 else if (!Instruction->AnomalyOccurred)
1143 {
1144 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS);
1145 Instruction->AnomalyOccurred = TRUE;
1146 }
1147 break;
1148 case PREFIX_SEGMENT_OVERRIDE_DS:
1149 SANITY_CHECK_SEGMENT_OVERRIDE();
1150 if (!IS_AMD64())
1151 {
1152 X86Instruction->HasSegmentOverridePrefix = TRUE;
1153 X86Instruction->Segment = SEG_DS;
1154 }
1155 else if (!Instruction->AnomalyOccurred)
1156 {
1157 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Meaningless segment override\n", VIRTUAL_ADDRESS);
1158 Instruction->AnomalyOccurred = TRUE;
1159 }
1160 break;
1161 case PREFIX_SEGMENT_OVERRIDE_FS:
1162 SANITY_CHECK_SEGMENT_OVERRIDE();
1163 X86Instruction->HasSegmentOverridePrefix = TRUE;
1164 X86Instruction->Segment = SEG_FS;
1165 break;
1166 case PREFIX_SEGMENT_OVERRIDE_GS:
1167 SANITY_CHECK_SEGMENT_OVERRIDE();
1168 X86Instruction->HasSegmentOverridePrefix = TRUE;
1169 X86Instruction->Segment = SEG_GS;
1170 break;
1171
1172 case PREFIX_LOCK:
1173 if (!Instruction->AnomalyOccurred && X86Instruction->HasLockPrefix)
1174 {
1175 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Conflicting prefix\n", VIRTUAL_ADDRESS);
1176 Instruction->AnomalyOccurred = TRUE;
1177 }
1178 X86Instruction->HasLockPrefix = TRUE;
1179 break;
1180
1181 default:
1182 assert(0);
1183 goto abort;
1184 }
1185
1186 if (Instruction->PrefixCount >= X86_MAX_INSTRUCTION_LEN)
1187 {
1188 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH);
1189 goto abort;
1190 }
1191 else if (Instruction->PrefixCount == X86_MAX_PREFIX_LENGTH)
1192 {
1193 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH);
1194 Instruction->AnomalyOccurred = TRUE;
1195 }
1196
1197 assert(Instruction->AnomalyOccurred || Instruction->PrefixCount < X86_MAX_PREFIX_LENGTH);
1198 Instruction->Prefixes[Instruction->PrefixCount] = Opcode;
1199 Instruction->PrefixCount++;
1200 //DISASM_OUTPUT(("[0x%08I64X] Prefix 0x%02X (prefix count %d)\n", VIRTUAL_ADDRESS, Opcode, Instruction->PrefixCount));
1201 }
1202 else
1203 {
1204 break;
1205 }
1206 }
1207
1208 // Check for REX opcode
1209 // This is checked here instead of the prefix loop above because it must be the
1210 // last prefix
1211 if (IS_AMD64() && (Opcode >= REX_PREFIX_START && Opcode <= REX_PREFIX_END))
1212 {
1213 if (Instruction->PrefixCount >= X86_MAX_INSTRUCTION_LEN)
1214 {
1215 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH);
1216 goto abort;
1217 }
1218 else if (!Instruction->AnomalyOccurred && Instruction->PrefixCount == AMD64_MAX_PREFIX_LENGTH)
1219 {
1220 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Reached maximum prefix count %d\n", VIRTUAL_ADDRESS, X86_MAX_PREFIX_LENGTH);
1221 Instruction->AnomalyOccurred = TRUE;
1222 }
1223
1224 assert(Instruction->AnomalyOccurred || Instruction->PrefixCount < AMD64_MAX_PREFIX_LENGTH);
1225
1226 Instruction->Prefixes[Instruction->PrefixCount] = Opcode;
1227 Instruction->PrefixCount++;
1228 X86Instruction->rex_b = Opcode;
1229 SET_REX(X86Instruction->rex, X86Instruction->rex_b);
1230 DISASM_OUTPUT(("[0x%08I64X] REX prefix 0x%02X (prefix count %d, w=%d, r=%d, x=%d, b=%d)\n", VIRTUAL_ADDRESS, Opcode, Instruction->PrefixCount, X86Instruction->rex.w, X86Instruction->rex.r, X86Instruction->rex.x, X86Instruction->rex.b));
1231
1232 assert(X86Instruction->AddressSize >= 4);
1233 if (X86Instruction->rex.w)
1234 {
1235 X86Instruction->OperandSize = 8;
1236 X86Instruction->HasOperandSizePrefix = FALSE;
1237 }
1238 else if (X86Instruction->HasOperandSizePrefix)
1239 {
1240 assert(X86Instruction->OperandSize == 2);
1241 }
1242 else if (X86Instruction->rex_b == REX_PREFIX_START)
1243 {
1244 if (!Instruction->AnomalyOccurred)
1245 {
1246 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: meaningless REX prefix used\n", VIRTUAL_ADDRESS);
1247 Instruction->AnomalyOccurred = TRUE;
1248 }
1249 X86Instruction->rex_b = 0;
1250 }
1251
1252 Opcode = *Address;
1253 INSTR_INC(1); // increment Instruction->Length and address
1254
1255 X86Opcode = &X86_Opcodes_1[Opcode];
1256 assert(!X86_PREFIX(X86Opcode));
1257 }
1258 //DISASM_OUTPUT(("[0x%08I64X] OperandSize = %d, AddressSize = %d\n", VIRTUAL_ADDRESS, X86Instruction->OperandSize, X86Instruction->AddressSize));
1259 Instruction->LastOpcode = Opcode;
1260 Instruction->OpcodeAddress = Address-1;
1261
1262 if (X86_INVALID(X86Opcode))
1263 {
1264 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid opcode 0x%02X\n", VIRTUAL_ADDRESS, Opcode);
1265 goto abort;
1266 }
1267
1268 if (Opcode == X86_TWO_BYTE_OPCODE)
1269 {
1270 //
1271 // Handle case that it is a group (with opcode extension), floating point, or two byte opcode
1272 //
1273 assert(!Instruction->OpcodeLength);
1274 Instruction->LastOpcode = Opcode = *Address;
1275 INSTR_INC(1); // increment Instruction->Length and address
1276 assert(X86Opcode->Table == X86_Opcodes_2);
1277 X86Opcode = &X86_Opcodes_2[Opcode];
1278
1279 //
1280 // Check for errors
1281 //
1282 if (X86_INVALID(X86Opcode))
1283 {
1284 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid two byte opcode 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode);
1285 goto abort;
1286 }
1287
1288 if (X86Instruction->AddressSize == 8)
1289 {
1290 if (X86_Invalid_Addr64_2[Opcode])
1291 {
1292 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X 0x%02X (\"%s\") illegal in 64-bit mode\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic);
1293 goto abort;
1294 }
1295 #if 0
1296 if (X86Instruction->rex_b &&
1297 (GET_REX_B(X86Instruction->rex_b) && !GET_REX_B(X86_REX_2[Opcode]) ||
1298 GET_REX_X(X86Instruction->rex_b) && !GET_REX_X(X86_REX_2[Opcode]) ||
1299 GET_REX_R(X86Instruction->rex_b) && !GET_REX_R(X86_REX_2[Opcode]) ||
1300 GET_REX_W(X86Instruction->rex_b) && !GET_REX_W(X86_REX_2[Opcode])))
1301 {
1302 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal REX prefix 0x%02X for opcode 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->rex_b, X86_TWO_BYTE_OPCODE, Opcode);
1303 assert(0);
1304 goto abort;
1305 }
1306 #endif
1307 }
1308
1309 if (X86Instruction->OperandSize == 2 && X86_Invalid_Op16_2[Opcode])
1310 {
1311 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X 0x%02X (\"%s\") illegal with 16-bit operand size\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic);
1312 goto abort;
1313 }
1314
1315 X86Instruction->HasModRM = X86_ModRM_2[Opcode];
1316 if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address;
1317 Instruction->OpcodeBytes[0] = X86_TWO_BYTE_OPCODE;
1318 Instruction->OpcodeBytes[1] = Opcode;
1319 Instruction->OpcodeLength = 2;
1320
1321 if (X86_SPECIAL_EXTENSION(X86Opcode))
1322 {
1323 DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode));
1324 SpecialExtension = TRUE;
1325 goto HasSpecialExtension;
1326 }
1327 else if (SSE_Prefix && !X86_INVALID(&X86_SSE[Opcode])) // SSEx instruction
1328 {
1329 Instruction->OpcodeLength = 3;
1330 Instruction->OpcodeBytes[2] = SSE_Prefix;
1331 assert(Instruction->OpcodeBytes[1] == Opcode);
1332
1333 // Since the prefix was really an opcode extension, remove it from
1334 // the prefix list
1335 for (i = 0; i < Instruction->PrefixCount; i++)
1336 {
1337 if (Instruction->Prefixes[i]) break;
1338 }
1339 assert(i != Instruction->PrefixCount);
1340 Instruction->PrefixCount--;
1341 Instruction->Prefixes[i] = 0;
1342
1343 // Slide any prefixes following the removed prefix down by 1
1344 memmove(&Instruction->Prefixes[i], &Instruction->Prefixes[i+1], Instruction->PrefixCount-i);
1345 Instruction->Prefixes[Instruction->PrefixCount] = 0;
1346 Instruction->Repeat = FALSE;
1347 X86Instruction->HasRepeatWhileEqualPrefix = FALSE;
1348 X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE;
1349 X86Instruction->HasOperandSizePrefix = FALSE;
1350 if (SSE_Prefix == PREFIX_OPERAND_SIZE)
1351 {
1352 if (IS_AMD64() && X86Instruction->rex.w) X86Instruction->OperandSize = 8;
1353 else X86Instruction->OperandSize = 4;
1354 }
1355
1356 if (IS_X86_16())
1357 {
1358 if (!SuppressErrors) printf("[0x%08I64X] ERROR: SSE invalid in 16-bit mode\n", VIRTUAL_ADDRESS);
1359 goto abort;
1360 }
1361
1362 assert(X86Instruction->HasModRM);
1363 switch (SSE_Prefix)
1364 {
1365 case PREFIX_OPERAND_SIZE: X86Opcode = &X86_SSE[0x000+Opcode]; break;
1366 case PREFIX_REPNE: X86Opcode = &X86_SSE[0x100+Opcode]; break;
1367 case PREFIX_REP: X86Opcode = &X86_SSE[0x200+Opcode]; break;
1368 }
1369
1370 if (X86_INVALID(X86Opcode))
1371 {
1372 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal SSE instruction opcode 0x%02X 0x%02X + prefix 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Instruction->OpcodeBytes[2]);
1373 goto abort;
1374 }
1375 else if (X86_EXTENDED_OPCODE(X86Opcode))
1376 {
1377 // SSE in group (13, 14, or 15)
1378 OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b);
1379 Group = X86_Groups_2[Opcode];
1380 X86Instruction->Group = (U8)Group;
1381 assert(Group >= 13 && Group <= 15 && X86Opcode->Table);
1382 switch (SSE_Prefix)
1383 {
1384 case PREFIX_OPERAND_SIZE: X86Opcode = &X86Opcode->Table[0x00+OpcodeExtension]; break;
1385 case PREFIX_REPNE: X86Opcode = &X86Opcode->Table[0x08+OpcodeExtension]; break;
1386 case PREFIX_REP: X86Opcode = &X86Opcode->Table[0x10+OpcodeExtension]; break;
1387 }
1388
1389 if (X86_INVALID(X86Opcode))
1390 {
1391 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal SSE instruction opcode 0x%02X 0x%02X + prefix 0x%02X + extension %d\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Instruction->OpcodeBytes[2], OpcodeExtension);
1392 goto abort;
1393 }
1394 }
1395
1396 Instruction->Repeat = FALSE;
1397 X86Instruction->HasRepeatWhileEqualPrefix = FALSE;
1398 X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE;
1399 X86Instruction->HasOperandSizePrefix = FALSE;
1400 switch (X86_GET_CATEGORY(X86Opcode))
1401 {
1402 case ITYPE_SSE: case ITYPE_SSE2: case ITYPE_SSE3: break;
1403 default: assert(0); goto abort;
1404 }
1405 }
1406 else if (X86_EXTENDED_OPCODE(X86Opcode)) // 2 byte group
1407 {
1408 assert(!X86Opcode->MnemonicFlags);
1409 OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b);
1410
1411 assert(X86Opcode->Table);
1412 X86Opcode = &X86Opcode->Table[OpcodeExtension];
1413 if (X86_INVALID(X86Opcode))
1414 {
1415 Instruction->Length++;
1416 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension);
1417 goto abort;
1418 }
1419
1420 assert(!X86_SPECIAL_EXTENSION(X86Opcode));
1421 Group = X86_Groups_2[Opcode];
1422 X86Instruction->Group = (U8)Group;
1423 assert(Group > 0 && Group <= 19);
1424 assert(X86Opcode->Mnemonic);
1425 DISASM_OUTPUT(("[0x%08I64X] Group %d (bytes 0x%02X 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension, X86Opcode->Mnemonic));
1426 }
1427 else
1428 {
1429 assert(X86Opcode->Mnemonic);
1430 DISASM_OUTPUT(("[0x%08I64X] Two byte opcode 0x%02X 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, X86Opcode->Mnemonic));
1431 X86Instruction->HasModRM = X86_ModRM_2[Opcode];
1432 if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address;
1433 }
1434 }
1435 else // 1-byte opcode
1436 {
1437 if (X86Instruction->AddressSize == 8)
1438 {
1439 if (X86_Invalid_Addr64_1[Opcode])
1440 {
1441 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X (\"%s\") illegal in 64-bit mode\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic);
1442 goto abort;
1443 }
1444
1445 #if 0
1446 if (X86Instruction->rex_b &&
1447 (GET_REX_B(X86Instruction->rex_b) && !GET_REX_B(X86_REX_1[Opcode]) ||
1448 GET_REX_X(X86Instruction->rex_b) && !GET_REX_X(X86_REX_1[Opcode]) ||
1449 GET_REX_R(X86Instruction->rex_b) && !GET_REX_R(X86_REX_1[Opcode]) ||
1450 GET_REX_W(X86Instruction->rex_b) && !GET_REX_W(X86_REX_1[Opcode])))
1451 {
1452 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal REX prefix 0x%02X for opcode 0x%02X\n", VIRTUAL_ADDRESS, X86Instruction->rex_b, Opcode);
1453 assert(0);
1454 goto abort;
1455 }
1456 #endif
1457 }
1458
1459 if (X86Instruction->OperandSize == 2 && X86_Invalid_Op16_1[Opcode])
1460 {
1461 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Opcode 0x%02X (\"%s\") illegal with 16-bit operand size\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic);
1462 goto abort;
1463 }
1464
1465 Instruction->OpcodeBytes[0] = Opcode;
1466 Instruction->OpcodeLength = 1;
1467 X86Instruction->HasModRM = X86_ModRM_1[Opcode];
1468 if (X86Instruction->HasModRM) X86Instruction->modrm_b = *Address;
1469
1470 if (X86_EXTENDED_OPCODE(X86Opcode)) // a group
1471 {
1472 assert(X86Instruction->HasModRM);
1473 OpcodeExtension = GET_MODRM_EXT(*Address); // leave Address pointing at ModRM byte
1474
1475 if (X86_SPECIAL_EXTENSION(X86Opcode))
1476 {
1477 DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode));
1478 SpecialExtension = TRUE;
1479 goto HasSpecialExtension;
1480 }
1481
1482 assert(X86Opcode->Table);
1483 X86Opcode = &X86Opcode->Table[OpcodeExtension];
1484 if (X86_INVALID(X86Opcode))
1485 {
1486 Instruction->Length++;
1487 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, Opcode, OpcodeExtension);
1488 goto abort;
1489 }
1490
1491 Group = X86_Groups_1[Opcode];
1492 X86Instruction->Group = (U8)Group;
1493 DISASM_OUTPUT(("[0x%08I64X] Group %d (byte 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, Opcode, OpcodeExtension, X86Opcode->Mnemonic));
1494 assert(Group > 0 && Group <= 17);
1495 assert(X86Opcode->Mnemonic);
1496 }
1497 else
1498 {
1499 if (X86_SPECIAL_EXTENSION(X86Opcode))
1500 {
1501 DISASM_OUTPUT(("[0x%08I64X] Special opcode extension 0x%02X\n", VIRTUAL_ADDRESS, Opcode));
1502 SpecialExtension = TRUE;
1503 goto HasSpecialExtension;
1504 }
1505
1506 DISASM_OUTPUT(("[0x%08I64X] One byte opcode 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Opcode, X86Opcode->Mnemonic));
1507 }
1508 }
1509
1510 HasSpecialExtension:
1511 if (SpecialExtension)
1512 {
1513 if (X86Opcode->MnemonicFlags & ITYPE_EXT_MODRM)
1514 {
1515 assert(X86Opcode->Table);
1516 assert(Instruction->OpcodeLength == 2);
1517 assert(X86Instruction->HasModRM);
1518 X86Opcode = &X86Opcode->Table[*Address];
1519 if (X86_INVALID(X86Opcode))
1520 {
1521 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal opcode 0x%02X 0x%02X + modrm 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], *Address);
1522 goto abort;
1523 }
1524 else if (X86_EXTENDED_OPCODE(X86Opcode))
1525 {
1526 assert(!X86Opcode->MnemonicFlags);
1527 OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b);
1528
1529 assert(X86Opcode->Table);
1530 X86Opcode = &X86Opcode->Table[OpcodeExtension];
1531 if (X86_INVALID(X86Opcode))
1532 {
1533 Instruction->Length++;
1534 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid group opcode 0x%02X 0x%02X extension 0x%02X\n", VIRTUAL_ADDRESS, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension);
1535 goto abort;
1536 }
1537
1538 assert(!X86_SPECIAL_EXTENSION(X86Opcode));
1539 Group = X86_Groups_2[Opcode];
1540 X86Instruction->Group = (U8)Group;
1541 assert(Group > 0 && Group <= 19);
1542 assert(X86Opcode->Mnemonic);
1543 DISASM_OUTPUT(("[0x%08I64X] Group %d (bytes 0x%02X 0x%02X) extension 0x%02X (\"%s\")\n", VIRTUAL_ADDRESS, Group, X86_TWO_BYTE_OPCODE, Opcode, OpcodeExtension, X86Opcode->Mnemonic));
1544 }
1545 else if (!X86_OPERAND_COUNT(X86Opcode))
1546 {
1547 INSTR_INC(1); // increment Instruction->Length and address
1548 }
1549 }
1550 else if (X86Opcode->MnemonicFlags & ITYPE_EXT_FPU)
1551 {
1552 assert(X86Opcode->Table);
1553 if (X86Instruction->modrm_b < 0xC0)
1554 {
1555 // It is an opcode extension, use the X86Opcode->Table
1556 OpcodeExtension = GET_MODRM_EXT(X86Instruction->modrm_b);
1557 X86Opcode = &X86Opcode->Table[OpcodeExtension];
1558 }
1559 else
1560 {
1561 // The whole ModRM byte is used, these start at index 0x08 in X86Opcode->Table
1562 OpcodeExtension = (X86Instruction->modrm_b & 0x3F);
1563 X86Opcode = &X86Opcode->Table[0x08 + OpcodeExtension];
1564 }
1565
1566 if (X86_INVALID(X86Opcode))
1567 {
1568 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Invalid FPU opcode 0x%02X + modrm extension 0x%02X (index 0x%02X)\n", VIRTUAL_ADDRESS, Opcode, X86Instruction->modrm_b, 0x08 + OpcodeExtension);
1569 goto abort;
1570 }
1571
1572 DISASM_OUTPUT(("[0x%08I64X] FPU instruction is (\"%s\"): 0x%02X + modrm 0x%02X (index 0x%02X)\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Opcode, X86Instruction->modrm_b, 0x08 + OpcodeExtension));
1573 if (!X86_OPERAND_COUNT(X86Opcode)) INSTR_INC(1); // increment Instruction->Length and address
1574 }
1575 else if (X86Opcode->MnemonicFlags & ITYPE_EXT_SUFFIX)
1576 {
1577 if (X86Instruction->HasOperandSizePrefix)
1578 {
1579 if (!Instruction->AnomalyOccurred && X86Opcode->Table == X86_3DNOW_0F)
1580 {
1581 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: operand size prefix used with 3DNOW instruction\n", VIRTUAL_ADDRESS);
1582 Instruction->AnomalyOccurred = TRUE;
1583 }
1584 X86Instruction->HasOperandSizePrefix = FALSE;
1585 X86Instruction->OperandSize = 4;
1586 }
1587 Instruction->OperandCount = X86_OPERAND_COUNT(X86Opcode);
1588 assert(Instruction->OpcodeLength == 2 && X86Instruction->HasModRM && Instruction->OperandCount == 2);
1589 memcpy(&X86Instruction->Opcode, X86Opcode, sizeof(X86_OPCODE));
1590 Instruction->Operands[0].Flags = X86Opcode->OperandFlags[0] & X86_OPFLAGS_MASK;
1591 Instruction->Operands[1].Flags = X86Opcode->OperandFlags[1] & X86_OPFLAGS_MASK;
1592 Instruction->Operands[2].Flags = X86Opcode->OperandFlags[2] & X86_OPFLAGS_MASK;
1593 assert(Address == Instruction->Address + Instruction->Length);
1594 if (!SetOperands(Instruction, Address, Flags & DISASM_SUPPRESSERRORS)) goto abort;
1595 Suffix = Instruction->Address[Instruction->Length++];
1596 Instruction->OpcodeBytes[2] = Suffix;
1597 Instruction->OpcodeLength = 3;
1598 X86Opcode = &X86Opcode->Table[Suffix];
1599
1600 if (X86_INVALID(X86Opcode))
1601 {
1602 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal opcode 0x%02X 0x%02X + suffix 0x%02X\n", VIRTUAL_ADDRESS, Instruction->OpcodeBytes[0], Instruction->OpcodeBytes[1], Suffix);
1603 goto abort;
1604 }
1605 assert(Instruction->Length >= 4 + Instruction->PrefixCount);
1606 }
1607 else if (X86Opcode->MnemonicFlags & ITYPE_EXT_64)
1608 {
1609 assert(X86Opcode->Table);
1610 if (IS_AMD64()) X86Opcode = &X86Opcode->Table[1];
1611 else X86Opcode = &X86Opcode->Table[0];
1612 assert(!X86_INVALID(X86Opcode));
1613 }
1614 }
1615
1616 // Detect incompatibilities
1617 if (IS_X86_16() && X86Opcode->CPU > CPU_I386)
1618 {
1619 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Instruction \"%s\" (opcode 0x%02X) can't be used in 16-bit X86\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->LastOpcode);
1620 goto abort;
1621 }
1622 if (!IS_AMD64() && X86Opcode->CPU >= CPU_AMD64)
1623 {
1624 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Instruction \"%s\" (opcode 0x%02X) can only be used in X86-64\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->LastOpcode);
1625 goto abort;
1626 }
1627
1628 // Copy the opcode into the local structure and set the fields
1629 assert(Instruction->OpcodeLength && !X86_INVALID(X86Opcode));
1630 memcpy(&X86Instruction->Opcode, X86Opcode, sizeof(X86_OPCODE));
1631 Instruction->Groups |= X86_GET_CATEGORY(X86Opcode);
1632 assert(Instruction->Groups);
1633 Instruction->Type |= X86_GET_TYPE(X86Opcode);
1634 assert((U32)Instruction->Type >= Instruction->Groups);
1635 Instruction->OperandCount = X86_OPERAND_COUNT(X86Opcode);
1636
1637 //
1638 // Sanity check prefixes now that opcode is known and prefixes are resolved
1639 //
1640
1641 // Instructions that implicitly reference the CS/DS can't have segment override prefixes
1642 switch (Instruction->Type)
1643 {
1644 case ITYPE_PUSHF: case ITYPE_POPF:
1645 case ITYPE_ENTER: case ITYPE_LEAVE:
1646 SANITY_CHECK_SEGMENT_OVERRIDE();
1647 X86Instruction->HasSegmentOverridePrefix = FALSE;
1648 X86Instruction->Segment = SEG_SS;
1649 break;
1650 case ITYPE_RET: case ITYPE_DEBUG:
1651 case ITYPE_OFLOW: case ITYPE_TRAP:
1652 case ITYPE_TRAPRET:
1653 SANITY_CHECK_SEGMENT_OVERRIDE();
1654 X86Instruction->HasSegmentOverridePrefix = FALSE;
1655 X86Instruction->Segment = SEG_CS;
1656 break;
1657 }
1658
1659 // Check illegal prefixes used with FPU/MMX/SSEx
1660 if (Instruction->Groups & (ITYPE_FPU|ITYPE_MMX|ITYPE_SSE|ITYPE_SSE2|ITYPE_SSE3))
1661 {
1662 // Check for prefixes that produce unpredictable results
1663 for (i = 0; i < Instruction->PrefixCount; i++)
1664 {
1665 switch (Instruction->Prefixes[i])
1666 {
1667 case PREFIX_OPERAND_SIZE:
1668 switch (Instruction->Type)
1669 {
1670 case ITYPE_FSTOREENV: case ITYPE_FLOADENV: case ITYPE_FSAVE: case ITYPE_FRESTORE: continue;
1671 default: break;
1672 }
1673
1674 if (!Instruction->AnomalyOccurred)
1675 {
1676 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: operand size prefix used with FPU/MMX/SSEx\n", VIRTUAL_ADDRESS);
1677 goto abort;
1678 }
1679 X86Instruction->HasOperandSizePrefix = FALSE;
1680 if (X86Instruction->OperandSize == 2) X86Instruction->OperandSize = 2;
1681 break;
1682
1683 case PREFIX_REPNE:
1684 case PREFIX_REP:
1685 if (Instruction->Groups & ITYPE_FPU) { assert(Instruction->Repeat); continue; }
1686 // The Intel manual says this results in unpredictable behavior -- it's not even
1687 // clear which SSE prefix is used as the third opcode byte in this case
1688 // (e.g., is it the first or last SSE prefix?)
1689 if (!SuppressErrors) printf("[0x%08I64X] ERROR: rep/repne used with MMX/SSEx\n", VIRTUAL_ADDRESS);
1690 goto abort;
1691
1692 default:
1693 break;
1694 }
1695 }
1696 }
1697
1698 // Check for conflicts involving operand size
1699 if (IS_AMD64())
1700 {
1701 // Check for use of rex.w=1 with an operand size prefix
1702 if (X86Instruction->rex.w)
1703 {
1704 assert(X86Instruction->OperandSize == 8);
1705 for (i = 0; i < Instruction->PrefixCount; i++)
1706 {
1707 if (Instruction->Prefixes[i] == PREFIX_OPERAND_SIZE)
1708 {
1709 X86Instruction->HasOperandSizePrefix = FALSE;
1710 if (!Instruction->AnomalyOccurred)
1711 {
1712 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of operand size prefix meaningless when REX.w=1\n", VIRTUAL_ADDRESS);
1713 Instruction->AnomalyOccurred = TRUE;
1714 }
1715 }
1716 }
1717 }
1718
1719 // Set default operand size to 64 instead of 32 for some instructions
1720 switch (Instruction->Type)
1721 {
1722 case ITYPE_PUSH: case ITYPE_POP:
1723 case ITYPE_PUSHF: case ITYPE_POPF:
1724 case ITYPE_ENTER: case ITYPE_LEAVE:
1725 case ITYPE_CALL: case ITYPE_BRANCH:
1726 case ITYPE_LOOPCC: case ITYPE_RET:
1727 X86Instruction->HasDefault64Operand = TRUE;
1728 break;
1729
1730 case ITYPE_SYSTEM:
1731 if (Instruction->OpcodeLength != 2) break;
1732
1733 // lgdt/lidt/lldt/ltr
1734 if ((Instruction->LastOpcode == 0x00 || Instruction->LastOpcode == 0x01) &&
1735 (OpcodeExtension == 0x02 || OpcodeExtension == 0x03))
1736 {
1737 X86Instruction->HasDefault64Operand = TRUE;
1738 }
1739 break;
1740
1741 default:
1742 break;
1743 }
1744
1745 if (X86Instruction->HasDefault64Operand)
1746 {
1747 if (X86Instruction->rex.w)
1748 {
1749 if (!Instruction->AnomalyOccurred)
1750 {
1751 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of REX.w is meaningless (default operand size is 64)\n", VIRTUAL_ADDRESS);
1752 Instruction->AnomalyOccurred = TRUE;
1753 }
1754 X86Instruction->rex_b &= ~8;
1755 X86Instruction->rex.w = 0;
1756 }
1757
1758 if (X86Instruction->HasOperandSizePrefix)
1759 {
1760 assert(X86Instruction->OperandSize == 2);
1761 X86Instruction->HasDefault64Operand = FALSE;
1762 }
1763 else
1764 {
1765 assert(X86Instruction->OperandSize >= 4);
1766 X86Instruction->OperandSize = 8;
1767 }
1768 }
1769 }
1770
1771 // Make sure rep/repe/repne is set correctly based on instruction
1772 if (Instruction->Repeat)
1773 {
1774 switch (Instruction->Type)
1775 {
1776 case ITYPE_IN:
1777 case ITYPE_OUT:
1778 case ITYPE_STRMOV:
1779 case ITYPE_STRSTOR:
1780 case ITYPE_STRLOAD:
1781 if (X86Instruction->HasRepeatWhileNotEqualPrefix)
1782 {
1783 if (!Instruction->AnomalyOccurred)
1784 {
1785 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: REPNE should only be used with cmps/scas\n", VIRTUAL_ADDRESS);
1786 Instruction->AnomalyOccurred = TRUE;
1787 }
1788 // Treat it as just a "rep"
1789 X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE;
1790 X86Instruction->HasRepeatWhileEqualPrefix = TRUE;
1791 }
1792 break;
1793 case ITYPE_STRCMP:
1794 break;
1795 default:
1796 if (!Instruction->AnomalyOccurred)
1797 {
1798 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Repeat prefix used with non-string instruction\n", VIRTUAL_ADDRESS);
1799 Instruction->AnomalyOccurred = TRUE;
1800 }
1801 Instruction->Repeat = FALSE;
1802 X86Instruction->HasRepeatWhileEqualPrefix = FALSE;
1803 X86Instruction->HasRepeatWhileNotEqualPrefix = FALSE;
1804 break;
1805 }
1806 }
1807
1808 if (Disassemble)
1809 {
1810 assert(!Instruction->StringIndex);
1811 if (X86Instruction->HasRepeatWhileEqualPrefix)
1812 {
1813 if (Instruction->Type == ITYPE_STRCMP) { APPENDS("repe "); }
1814 else { APPENDS("rep "); }
1815 }
1816 if (X86Instruction->HasRepeatWhileNotEqualPrefix) APPENDS("repne ");
1817 if (X86Instruction->HasLockPrefix) APPENDS("lock ");
1818 if (X86Instruction->HasBranchTakenPrefix) APPENDS("hinttake ");
1819 if (X86Instruction->HasBranchNotTakenPrefix) APPENDS("hintskip ");
1820 APPENDPAD(12);
1821 APPEND(OPCSTR, SIZE_LEFT, "%s", X86Opcode->Mnemonic);
1822 APPENDPAD(24);
1823 }
1824
1825 if (Instruction->OperandCount)
1826 {
1827 Instruction->Operands[0].Flags = X86Opcode->OperandFlags[0] & X86_OPFLAGS_MASK;
1828 Instruction->Operands[1].Flags = X86Opcode->OperandFlags[1] & X86_OPFLAGS_MASK;
1829 Instruction->Operands[2].Flags = X86Opcode->OperandFlags[2] & X86_OPFLAGS_MASK;
1830 Address = SetOperands(Instruction, Address, Flags);
1831 if (!Address) goto abort;
1832 assert(!(Instruction->Operands[0].Flags & 0x7F));
1833 assert(!(Instruction->Operands[1].Flags & 0x7F));
1834 assert(!(Instruction->Operands[2].Flags & 0x7F));
1835 }
1836
1837 Disassembler->Stage2Count++;
1838
1839 #ifdef TEST_DISASM
1840 //////////////////////////////////////////////////////////////////////
1841 // Test against other disassemblers
1842 //////////////////////////////////////////////////////////////////////
1843
1844 if (IS_X86_32())
1845 {
1846 InstructionLength = X86_GetLength(Instruction, Instruction->Address);
1847 if (InstructionLength && Instruction->Length != InstructionLength)
1848 {
1849 printf("[0x%08I64X] WARNING: instruction lengths differ (%d vs %d)\n", VIRTUAL_ADDRESS, Instruction->Length, InstructionLength);
1850 DumpInstruction(Instruction, TRUE, TRUE);
1851 assert(0);
1852 }
1853 }
1854 else if (IS_AMD64())
1855 {
1856 // TODO: need other amd64 (x86-64) disassembler to test against
1857 }
1858 else if (IS_X86_16())
1859 {
1860 // TODO: need other x86 16-bit disassembler to test against
1861 }
1862 #endif
1863
1864 //////////////////////////////////////////////////////////////////////
1865 // Post-operand sanity checks
1866 //////////////////////////////////////////////////////////////////////
1867
1868 if (!X86Instruction->HasDstAddressing && !X86Instruction->HasSrcAddressing)
1869 {
1870 if (X86Instruction->HasAddressSizePrefix)
1871 {
1872 if (!Instruction->AnomalyOccurred)
1873 {
1874 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: address size prefix used with no addressing\n", VIRTUAL_ADDRESS);
1875 Instruction->AnomalyOccurred = TRUE;
1876 }
1877 X86Instruction->HasAddressSizePrefix = FALSE;
1878 }
1879
1880 if (X86Instruction->HasSegmentOverridePrefix)
1881 {
1882 if (!Instruction->AnomalyOccurred)
1883 {
1884 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: segment override used with no addressing\n", VIRTUAL_ADDRESS);
1885 Instruction->AnomalyOccurred = TRUE;
1886 }
1887 X86Instruction->HasSegmentOverridePrefix = FALSE;
1888 }
1889 }
1890
1891 // Detect use of unusual segments
1892 if (!Instruction->AnomalyOccurred && !IS_X86_16())
1893 {
1894 switch (X86Instruction->Segment)
1895 {
1896 case SEG_CS: case SEG_DS: case SEG_SS:
1897 break;
1898 case SEG_ES:
1899 switch (Instruction->Type)
1900 {
1901 case ITYPE_IN: case ITYPE_STRMOV: case ITYPE_STRCMP: case ITYPE_STRSTOR:
1902 break;
1903 default:
1904 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment ES\n", VIRTUAL_ADDRESS);
1905 Instruction->AnomalyOccurred = TRUE;
1906 break;
1907 }
1908 break;
1909 case SEG_FS:
1910 if (IS_X86_32() && !(Instruction->Groups & ITYPE_EXEC)) break;
1911 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment FS\n", VIRTUAL_ADDRESS);
1912 Instruction->AnomalyOccurred = TRUE;
1913 break;
1914 case SEG_GS:
1915 if (IS_AMD64() && !(Instruction->Groups & ITYPE_EXEC)) break;
1916 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: use of unexpected segment GS\n", VIRTUAL_ADDRESS);
1917 Instruction->AnomalyOccurred = TRUE;
1918 break;
1919 default:
1920 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: unexpected segment 0x%02lX\n", VIRTUAL_ADDRESS, X86Instruction->Selector);
1921 Instruction->AnomalyOccurred = TRUE;
1922 break;
1923 }
1924 }
1925
1926 if ((X86Opcode->OperandFlags[0] & OP_COND_EXEC) == OP_COND_EXEC)
1927 {
1928 assert(Instruction->Type == ITYPE_BRANCHCC || Instruction->Type == ITYPE_LOOPCC);
1929 for (i = 0; i < Instruction->PrefixCount; i++)
1930 {
1931 switch (Instruction->Prefixes[i])
1932 {
1933 case PREFIX_BRANCH_NOT_TAKEN:
1934 if (!Instruction->AnomalyOccurred && X86Instruction->Segment != SEG_CS)
1935 {
1936 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used with conditional branch\n", VIRTUAL_ADDRESS);
1937 Instruction->AnomalyOccurred = TRUE;
1938 }
1939 X86Instruction->HasSegmentOverridePrefix = FALSE;
1940 X86Instruction->Segment = SEG_CS;
1941 X86Instruction->HasBranchNotTakenPrefix = TRUE;
1942 break;
1943 case PREFIX_BRANCH_TAKEN:
1944 if (!Instruction->AnomalyOccurred && X86Instruction->Segment != SEG_DS)
1945 {
1946 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used with conditional branch\n", VIRTUAL_ADDRESS);
1947 Instruction->AnomalyOccurred = TRUE;
1948 }
1949 X86Instruction->HasSegmentOverridePrefix = FALSE;
1950 X86Instruction->Segment = SEG_CS;
1951 X86Instruction->HasBranchTakenPrefix = TRUE;
1952 break;
1953 }
1954 }
1955 }
1956
1957 //
1958 // If lock prefix is enabled, verify it is valid
1959 //
1960 if (X86Instruction->HasLockPrefix &&
1961 !IsValidLockPrefix(X86Instruction, Opcode, Instruction->OpcodeLength, Group, OpcodeExtension))
1962 {
1963 if (!SuppressErrors) printf("[0x%08I64X] ERROR: Illegal use of lock prefix for instruction \"%s\"\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic);
1964 goto abort;
1965 }
1966
1967 //////////////////////////////////////////////////////////////////////
1968 // Generate disassembly output
1969 //////////////////////////////////////////////////////////////////////
1970
1971 if (Disassemble)
1972 {
1973 if ((Flags & DISASM_SHOWFLAGS) &&
1974 (X86Instruction->Opcode.Preconditions || X86Instruction->Opcode.FlagsChanged || X86Instruction->Opcode.ResultsIfTrue))
1975 {
1976 APPENDPAD(124);
1977 if (X86Instruction->Opcode.Preconditions)
1978 {
1979 Result = X86Instruction->Opcode.Preconditions;
1980 APPENDS("COND:{ ");
1981 if (Result & COND_L) APPENDS("L ");
1982 if (Result & COND_NL) APPENDS("NL ");
1983 if (Result & COND_LE) APPENDS("LE ");
1984 if (Result & COND_NLE) APPENDS("NLE ");
1985 if (Result & COND_G) APPENDS("G ");
1986 if (Result & COND_NG) APPENDS("NG ");
1987 if (Result & COND_GE) APPENDS("GE ");
1988 if (Result & COND_NGE) APPENDS("NGE ");
1989 if (Result & COND_A) APPENDS("A ");
1990 if (Result & COND_NA) APPENDS("NA ");
1991 if (Result & COND_AE) APPENDS("AE ");
1992 if (Result & COND_NAE) APPENDS("NAE ");
1993 if (Result & COND_B) APPENDS("B ");
1994 if (Result & COND_NB) APPENDS("NB ");
1995 if (Result & COND_BE) APPENDS("BE ");
1996 if (Result & COND_NBE) APPENDS("NBE ");
1997 if (Result & COND_E) APPENDS("E ");
1998 if (Result & COND_NE) APPENDS("NE ");
1999 if (Result & COND_C) APPENDS("C ");
2000 if (Result & COND_NC) APPENDS("NC ");
2001 if (Result & COND_Z) APPENDS("Z ");
2002 if (Result & COND_NZ) APPENDS("NZ ");
2003 if (Result & COND_P) APPENDS("P ");
2004 if (Result & COND_NP) APPENDS("NP ");
2005 if (Result & COND_PE) APPENDS("PE ");
2006 if (Result & COND_PO) APPENDS("PO ");
2007 if (Result & COND_O) APPENDS("O ");
2008 if (Result & COND_NO) APPENDS("NO ");
2009 if (Result & COND_U) APPENDS("U ");
2010 if (Result & COND_NU) APPENDS("NU ");
2011 if (Result & COND_S) APPENDS("S ");
2012 if (Result & COND_NS) APPENDS("NS ");
2013 if (Result & COND_D) APPENDS("D ");
2014 APPENDB('}');
2015 }
2016
2017 if (X86Instruction->Opcode.FlagsChanged)
2018 {
2019 Result = X86Instruction->Opcode.FlagsChanged;
2020
2021 if (Result & FLAG_SET_MASK)
2022 {
2023 APPENDS("SET:{ ");
2024 if (Result & FLAG_CF_SET) APPENDS("C ");
2025 if (Result & FLAG_DF_SET) APPENDS("D ");
2026 if (Result & FLAG_IF_SET) APPENDS("I ");
2027 APPENDB('}');
2028 }
2029
2030 if (Result & FLAG_CLR_MASK)
2031 {
2032 APPENDS("CLR:{ ");
2033 if (Result & FLAG_SF_CLR) APPENDS("S ");
2034 if (Result & FLAG_ZF_CLR) APPENDS("Z ");
2035 if (Result & FLAG_AF_CLR) APPENDS("A ");
2036 if (Result & FLAG_CF_CLR) APPENDS("C ");
2037 if (Result & FLAG_DF_CLR) APPENDS("D ");
2038 if (Result & FLAG_IF_CLR) APPENDS("I ");
2039 if (Result & FLAG_OF_CLR) APPENDS("O ");
2040 if ((Result & FPU_ALL_CLR) == FPU_ALL_CLR)
2041 {
2042 APPENDS("FPU_ALL ");
2043 }
2044 else
2045 {
2046 if (Result & FPU_C0_CLR) APPENDS("FPU_C0 ");
2047 if (Result & FPU_C1_CLR) APPENDS("FPU_C1 ");
2048 if (Result & FPU_C2_CLR) APPENDS("FPU_C2 ");
2049 if (Result & FPU_C3_CLR) APPENDS("FPU_C3 ");
2050 }
2051 APPENDB('}');
2052 }
2053
2054 if ((Result & FLAG_MOD_MASK) == FLAG_MOD_MASK)
2055 {
2056 APPENDS("MOD:{ ");
2057 if ((Result & FLAG_ALL_MOD) == FLAG_ALL_MOD)
2058 {
2059 APPENDS("FLAGS_ALL ");
2060 }
2061 else if ((Result & FLAG_COMMON_MOD) == FLAG_COMMON_MOD)
2062 {
2063 APPENDS("FLAGS_COMMON ");
2064 }
2065 else
2066 {
2067 if (Result & FLAG_OF_MOD) APPENDS("O ");
2068 if (Result & FLAG_SF_MOD) APPENDS("S ");
2069 if (Result & FLAG_ZF_MOD) APPENDS("Z ");
2070 if (Result & FLAG_AF_MOD) APPENDS("A ");
2071 if (Result & FLAG_PF_MOD) APPENDS("P ");
2072 if (Result & FLAG_CF_MOD) APPENDS("C ");
2073 if (Result & FLAG_DF_MOD) APPENDS("D ");
2074 if (Result & FLAG_IF_MOD) APPENDS("I ");
2075 }
2076 if ((Result & FPU_ALL_MOD) == FPU_ALL_MOD)
2077 {
2078 APPENDS("FPU_ALL ");
2079 }
2080 else
2081 {
2082 if (Result & FPU_C0_MOD) APPENDS("FPU_C0 ");
2083 if (Result & FPU_C1_MOD) APPENDS("FPU_C1 ");
2084 if (Result & FPU_C2_MOD) APPENDS("FPU_C2 ");
2085 if (Result & FPU_C3_MOD) APPENDS("FPU_C3 ");
2086 }
2087 APPENDB('}');
2088 }
2089
2090 if (Result & FLAG_TOG_MASK)
2091 {
2092 APPENDS("TOG:{ ");
2093 if (Result & FLAG_CF_TOG) APPENDS("C ");
2094 APPENDB('}');
2095 }
2096 }
2097 }
2098
2099 APPENDS("\n");
2100 }
2101 else
2102 {
2103 Instruction->String[0] = '\0';
2104 }
2105
2106 if (!Instruction->Length || Instruction->Length > X86_MAX_INSTRUCTION_LEN)
2107 {
2108 if (!SuppressErrors) printf("[0x%08I64X] ERROR: maximum instruction length reached (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
2109 goto abort;
2110 }
2111
2112 if (!Decode)
2113 {
2114 Disassembler->Stage3CountNoDecode++;
2115 return TRUE; // all work is done
2116 }
2117
2118 //////////////////////////////////////////////////////////////////////
2119 // Detect particularly interesting intructions
2120 //////////////////////////////////////////////////////////////////////
2121
2122 Operand1 = &Instruction->Operands[0];
2123 if (Instruction->Groups & ITYPE_EXEC)
2124 {
2125 // If it is a negative offset with a 1-byte or 2-byte offset, assume it is a loop
2126 if (Operand1->Type == OPTYPE_OFFSET &&
2127 Operand1->Length <= 2 && X86Instruction->Displacement < 0)
2128 {
2129 Instruction->CodeBranch.IsLoop = TRUE;
2130 Instruction->CodeBranch.Operand = Operand1;
2131 }
2132
2133 if (!Instruction->AnomalyOccurred &&
2134 Operand1->TargetAddress >= (U64)Instruction->Address &&
2135 Operand1->TargetAddress < (U64)Instruction->Address + Instruction->Length)
2136 {
2137 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: branch into the middle of an instruction\n", VIRTUAL_ADDRESS);
2138 Instruction->AnomalyOccurred = TRUE;
2139 }
2140
2141 switch (Instruction->Type)
2142 {
2143 case ITYPE_BRANCH:
2144 Operand1->Flags |= OP_ADDRESS;
2145 assert(Instruction->OperandCount == 1);
2146 if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR)))
2147 {
2148 assert(!X86Instruction->HasSelector);
2149 X86Instruction->Segment = SEG_CS;
2150 }
2151
2152 if (Operand1->TargetAddress)
2153 {
2154 assert(!Instruction->CodeBranch.AddressOffset);
2155 Instruction->CodeBranch.Count = 1;
2156 Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress;
2157 Instruction->CodeBranch.Operand = Operand1;
2158 }
2159 // If there is both a base and index register, the Result will probably be too wrong
2160 // to even guess
2161 else if (X86Instruction->HasFullDisplacement &&
2162 ((X86Instruction->HasBaseRegister && !X86Instruction->HasIndexRegister) ||
2163 (!X86Instruction->HasBaseRegister && X86Instruction->HasIndexRegister)))
2164 {
2165 assert(Operand1->Length <= 0xFF);
2166 if (!X86Instruction->Scale)
2167 {
2168 if (Operand1->Length) X86Instruction->Scale = (U8)Operand1->Length;
2169 else X86Instruction->Scale = X86Instruction->OperandSize;
2170 }
2171 assert(Operand1->Length <= 0xFF);
2172 tmpScale = MAX(X86Instruction->Scale, Operand1->Length);
2173
2174 assert(tmpScale <= 16);
2175 Instruction->CodeBranch.AddressOffset = (U8)tmpScale;
2176 for (i = 0; i < MAX_CODE_REFERENCE_COUNT; i++) Instruction->CodeBranch.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale);
2177 Instruction->CodeBranch.Count = i;
2178 Instruction->CodeBranch.IsIndirect = TRUE;
2179 Instruction->CodeBranch.Operand = Operand1;
2180 }
2181 break;
2182
2183 case ITYPE_CALL:
2184 Instruction->Groups |= ITYPE_STACK;
2185 Instruction->CodeBranch.IsCall = TRUE;
2186 Operand1->Flags |= OP_ADDRESS;
2187 assert(Instruction->OperandCount == 1);
2188 if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR)))
2189 {
2190 assert(!X86Instruction->HasSelector);
2191 X86Instruction->Segment = SEG_CS;
2192 }
2193
2194 if (Operand1->TargetAddress)
2195 {
2196 assert(!Instruction->CodeBranch.AddressOffset);
2197 Instruction->CodeBranch.Count = 1;
2198 Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress;
2199 Instruction->CodeBranch.Operand = Operand1;
2200 }
2201 // If there is both a base and index register, the Result will probably be too wrong
2202 // to even guess
2203 else if (X86Instruction->HasFullDisplacement &&
2204 ((X86Instruction->HasBaseRegister && !X86Instruction->HasIndexRegister) ||
2205 (!X86Instruction->HasBaseRegister && X86Instruction->HasIndexRegister)))
2206 {
2207 //DISASM_OUTPUT(("[0x%08I64X] Scale %d, displacement 0x%08I64x\n", VIRTUAL_ADDRESS, X86Instruction->Scale, X86Instruction->Displacement));
2208 if (!X86Instruction->Scale)
2209 {
2210 assert(Operand1->Length <= 0xFF);
2211 if (Operand1->Length) X86Instruction->Scale = (U8)Operand1->Length;
2212 else X86Instruction->Scale = X86Instruction->OperandSize;
2213 }
2214 tmpScale = MAX(X86Instruction->Scale, Operand1->Length);
2215
2216 assert(tmpScale <= 16);
2217 Instruction->CodeBranch.AddressOffset = (U8)tmpScale;
2218 assert(X86Instruction->Scale > 1);
2219 for (i = 0; i < MAX_CODE_REFERENCE_COUNT; i++) Instruction->CodeBranch.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale);
2220 Instruction->CodeBranch.Count = i;
2221 Instruction->CodeBranch.IsIndirect = TRUE;
2222 Instruction->CodeBranch.Operand = Operand1;
2223 }
2224 break;
2225
2226 case ITYPE_BRANCHCC:
2227 assert(Instruction->OperandCount == 1);
2228 assert(Operand1->Flags & OP_ADDRESS);
2229 assert(Operand1->Type == OPTYPE_OFFSET);
2230 if (!(Operand1->Flags & (OP_GLOBAL|OP_FAR)))
2231 {
2232 assert(!X86Instruction->HasSelector);
2233 X86Instruction->Segment = SEG_CS;
2234 }
2235
2236 if (Operand1->TargetAddress)
2237 {
2238 assert(!Instruction->CodeBranch.AddressOffset);
2239 Instruction->CodeBranch.Count = 2;
2240 Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress;
2241 Instruction->CodeBranch.Addresses[1] = (U64)Instruction->Address + Instruction->Length;
2242 Instruction->CodeBranch.Operand = Operand1;
2243 }
2244 break;
2245
2246 case ITYPE_LOOPCC:
2247 Instruction->CodeBranch.IsLoop = TRUE;
2248 assert(Instruction->OperandCount == 1);
2249 assert(Operand1->Flags & OP_ADDRESS);
2250 assert(Operand1->Type == OPTYPE_OFFSET);
2251 assert(!(Operand1->Flags & (OP_GLOBAL|OP_FAR)));
2252 if (Operand1->TargetAddress)
2253 {
2254 assert(!Instruction->CodeBranch.AddressOffset);
2255 Instruction->CodeBranch.Count = 2;
2256 Instruction->CodeBranch.Addresses[0] = Operand1->TargetAddress;
2257 Instruction->CodeBranch.Addresses[1] = (U64)Instruction->Address + Instruction->Length;
2258 Instruction->CodeBranch.Operand = Operand1;
2259 }
2260 break;
2261
2262 case ITYPE_RET:
2263 Instruction->Groups |= ITYPE_STACK;
2264 break;
2265
2266 default:
2267 break; // do nothing
2268 }
2269 }
2270 else // possible data instruction
2271 {
2272 for (i = 0, Operand = Instruction->Operands; i < Instruction->OperandCount; i++, Operand++)
2273 {
2274 if (Operand->TargetAddress)
2275 {
2276 if (Operand->Flags & OP_DST)
2277 {
2278 assert(!Instruction->DataDst.Count);
2279 Instruction->DataDst.Count = 1;
2280 Instruction->DataDst.Addresses[0] = Operand->TargetAddress;
2281 Instruction->DataDst.DataSize = Operand->Length;
2282 Instruction->DataDst.Operand = Operand;
2283 DISASM_OUTPUT(("[0x%08I64X] Write of size %d to 0x%04I64X\n", VIRTUAL_ADDRESS, Operand->Length, Operand->TargetAddress));
2284 }
2285 if (Operand->Flags & OP_SRC)
2286 {
2287 assert(!Instruction->DataSrc.Count);
2288 Instruction->DataSrc.Count = 1;
2289 Instruction->DataSrc.Addresses[0] = Operand->TargetAddress;
2290 Instruction->DataSrc.DataSize = Operand->Length;
2291 Instruction->DataSrc.Operand = Operand;
2292 DISASM_OUTPUT(("[0x%08I64X] Read of size %d to 0x%04I64X\n", VIRTUAL_ADDRESS, Operand->Length, Operand->TargetAddress));
2293 }
2294 }
2295
2296 // If there is both a base and index register, the Result will probably be too wrong
2297 // to even guess
2298 else if (Operand->Flags & OP_GLOBAL &&
2299 ((X86Instruction->HasBaseRegister && !X86Instruction->HasIndexRegister) ||
2300 (!X86Instruction->HasBaseRegister && X86Instruction->HasIndexRegister)))
2301 {
2302 DISASM_OUTPUT(("[0x%08I64X] Data reference (scale %d, size %d, displacement 0x%08I64x)\n", VIRTUAL_ADDRESS, X86Instruction->Scale, Operand->Length, X86Instruction->Displacement));
2303 if (!X86Instruction->Scale)
2304 {
2305 assert(Operand->Length <= 0xFF);
2306 if (Operand->Length) X86Instruction->Scale = (U8)Operand->Length;
2307 else X86Instruction->Scale = X86Instruction->OperandSize;
2308 }
2309 tmpScale = MAX(X86Instruction->Scale, Operand->Length);
2310
2311 assert(X86Instruction->HasFullDisplacement);
2312 if (Operand->Flags & OP_DST)
2313 {
2314 assert(!Instruction->DataDst.Count);
2315 assert(tmpScale <= 16);
2316 Instruction->CodeBranch.AddressOffset = (U8)tmpScale;
2317 for (i = 0; i < MAX_DATA_REFERENCE_COUNT; i++) Instruction->DataDst.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale);
2318 Instruction->DataDst.Count = i;
2319 Instruction->DataDst.DataSize = Operand->Length;
2320 Instruction->DataDst.Operand = Operand;
2321 }
2322 if (Operand->Flags & OP_SRC)
2323 {
2324 assert(!Instruction->DataSrc.Count);
2325 assert(tmpScale <= 16);
2326 Instruction->CodeBranch.AddressOffset = (U8)tmpScale;
2327 for (i = 0; i < MAX_DATA_REFERENCE_COUNT; i++) Instruction->DataSrc.Addresses[i] = (U64)X86Instruction->Displacement + (i * tmpScale);
2328 Instruction->DataSrc.Count = i;
2329 Instruction->DataSrc.DataSize = Operand->Length;
2330 Instruction->DataSrc.Operand = Operand;
2331 }
2332 }
2333 }
2334 }
2335
2336 if (Instruction->Groups & ITYPE_STACK)
2337 {
2338 switch (Instruction->Type)
2339 {
2340 case ITYPE_PUSH:
2341 assert(Instruction->OperandCount == 1 && Operand1->Length);
2342 Instruction->StackChange = -Operand1->Length;
2343 SANITY_CHECK_ADDRESS_SIZE();
2344 break;
2345
2346 case ITYPE_POP:
2347 assert(Instruction->OperandCount == 1 && Operand1->Length);
2348 Instruction->StackChange = Operand1->Length;
2349 SANITY_CHECK_ADDRESS_SIZE();
2350 break;
2351
2352 case ITYPE_PUSHA:
2353 Instruction->StackChange = -(X86Instruction->OperandSize * 8); // xAX, xCX, xDX, xBX, xBP, xSP, xSI, xDI
2354 SANITY_CHECK_ADDRESS_SIZE();
2355 break;
2356
2357 case ITYPE_POPA:
2358 Instruction->StackChange = X86Instruction->OperandSize * 8; // xDI, xSI, xSP, xBP, xBX, xDX, xCX, xAX
2359 SANITY_CHECK_ADDRESS_SIZE();
2360 break;
2361
2362 case ITYPE_PUSHF:
2363 Instruction->StackChange = -Operand1->Length;
2364 Instruction->NeedsEmulation = TRUE;
2365 SANITY_CHECK_ADDRESS_SIZE();
2366 break;
2367
2368 case ITYPE_POPF:
2369 Instruction->StackChange = Operand1->Length;
2370 Instruction->NeedsEmulation = TRUE;
2371 SANITY_CHECK_ADDRESS_SIZE();
2372 break;
2373
2374 case ITYPE_ENTER:
2375 if (!Instruction->AnomalyOccurred)
2376 {
2377 if (Instruction->Operands[1].Value_U64 & 3)
2378 {
2379 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ENTER has invalid operand 2\n", VIRTUAL_ADDRESS);
2380 Instruction->AnomalyOccurred = TRUE;
2381 }
2382 if (Instruction->Operands[2].Value_U64 & ~0x1F)
2383 {
2384 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ENTER has invalid operand 3\n", VIRTUAL_ADDRESS);
2385 Instruction->AnomalyOccurred = TRUE;
2386 }
2387 }
2388 SANITY_CHECK_ADDRESS_SIZE();
2389 Instruction->Operands[2].Value_U64 &= 0x1F;
2390
2391 // frame pointer + stack space
2392 i = Operand1->Length + (U32)Instruction->Operands[1].Value_U64;
2393 Instruction->StackChange = -((LONG)i);
2394 i = (U32)Instruction->Operands[2].Value_U64 * Operand1->Length;
2395 Instruction->StackChange -= i;
2396 break;
2397
2398 case ITYPE_LEAVE:
2399 // This will do "mov esp, ebp; pop ebp" so the StackChange size is dynamic
2400 SANITY_CHECK_ADDRESS_SIZE();
2401 break;
2402
2403 case ITYPE_CALL:
2404 Instruction->StackChange = -X86Instruction->OperandSize;
2405 SANITY_CHECK_ADDRESS_SIZE();
2406 break;
2407
2408 case ITYPE_RET:
2409 Instruction->StackChange = X86Instruction->OperandSize;
2410
2411 switch (Opcode)
2412 {
2413 case 0xC3: // ret with no args
2414 break;
2415
2416 case 0xC2: // ret with 1 arg
2417 if (!Instruction->AnomalyOccurred && (Operand1->Value_U64 & 3))
2418 {
2419 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: ret has invalid operand 1\n", VIRTUAL_ADDRESS);
2420 Instruction->AnomalyOccurred = TRUE;
2421 }
2422 Instruction->StackChange += (LONG)Operand1->Value_U64;
2423 break;
2424
2425 case 0xCB: // far ret with no args
2426 Instruction->StackChange *= 2; // account for segment
2427 Instruction->StackChange += (LONG)Operand1->Value_U64;
2428 break;
2429
2430 case 0xCA: // far ret with 1 arg
2431 if (!Instruction->AnomalyOccurred && (Operand1->Value_U64 & 3))
2432 {
2433 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: retf has invalid operand 1\n", VIRTUAL_ADDRESS);
2434 Instruction->AnomalyOccurred = TRUE;
2435 }
2436 Instruction->StackChange *= 2; // account for segment
2437 Instruction->StackChange += (LONG)Operand1->Value_U64;
2438 break;
2439 }
2440 SANITY_CHECK_ADDRESS_SIZE();
2441 break;
2442
2443 case ITYPE_ADD:
2444 case ITYPE_XCHGADD:
2445 if (Instruction->Operands[1].Value_S64) Instruction->StackChange = (LONG)(Instruction->Operands[1].Value_S64);
2446 break;
2447 case ITYPE_SUB:
2448 if (Instruction->Operands[1].Value_S64) Instruction->StackChange = (LONG)(-Instruction->Operands[1].Value_S64);
2449 break;
2450 case ITYPE_MOV:
2451 case ITYPE_AND:
2452 break;
2453
2454 default:
2455 if (!Instruction->AnomalyOccurred)
2456 {
2457 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Instruction \"%s\" is modifying the stack\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic);
2458 Instruction->AnomalyOccurred = TRUE;
2459 }
2460 break;
2461 }
2462
2463 if (!Instruction->AnomalyOccurred &&
2464 ((X86Instruction->OperandSize != 2 && (Instruction->StackChange & 3)) || (Instruction->StackChange & 1)))
2465 {
2466 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: \"%s\" has invalid stack change 0x%02lX\n", VIRTUAL_ADDRESS, X86Opcode->Mnemonic, Instruction->StackChange);
2467 Instruction->AnomalyOccurred = TRUE;
2468 }
2469 }
2470
2471 if (Instruction->Groups & ITYPE_TRAPS)
2472 {
2473 switch (Instruction->Type)
2474 {
2475 case ITYPE_TRAP:
2476 case ITYPE_TRAPCC:
2477 case ITYPE_TRAPRET:
2478 case ITYPE_BOUNDS:
2479 case ITYPE_DEBUG:
2480 case ITYPE_TRACE:
2481 case ITYPE_INVALID:
2482 case ITYPE_OFLOW:
2483 Instruction->NeedsEmulation = TRUE;
2484 break;
2485 default:
2486 assert(0);
2487 break;
2488 }
2489 }
2490
2491 if (Instruction->Groups & ITYPE_SYSTEM)
2492 {
2493 switch (Instruction->Type)
2494 {
2495 case ITYPE_CPUID:
2496 case ITYPE_SYSCALL:
2497 case ITYPE_SYSCALLRET:
2498 // This doesn't require privileges
2499 break;
2500
2501 case ITYPE_HALT:
2502 case ITYPE_IN:
2503 case ITYPE_OUT:
2504 default:
2505 Instruction->NeedsEmulation = TRUE;
2506 break;
2507 }
2508 }
2509
2510 Disassembler->Stage3CountWithDecode++;
2511 return TRUE;
2512
2513 abort:
2514 if (!SuppressErrors)
2515 {
2516 #ifdef TEST_DISASM
2517 printf("Dump of 0x%04I64X:\n", VIRTUAL_ADDRESS);
2518 __try { DumpAsBytes(stdout, Instruction->Address, (ULONG_PTR)VIRTUAL_ADDRESS, 16, TRUE); }
2519 __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {}
2520 #endif
2521 fflush(stdout);
2522 }
2523 return FALSE;
2524 }
2525
2526 // Address = address to first byte after the opcode (e.g., first byte of ModR/M byte or
2527 // immediate value
2528 //
2529 // Returns the address immediately following the operand (e.g., the next operand or the
2530 // start of the next instruction
SetOperands(INSTRUCTION * Instruction,U8 * Address,U32 Flags)2531 INTERNAL U8 *SetOperands(INSTRUCTION *Instruction, U8 *Address, U32 Flags)
2532 {
2533 INSTRUCTION_OPERAND *Operand;
2534 U32 Index, OperandIndex;
2535 S64 Displacement = 0;
2536 U8 Register;
2537 U32 OperandFlags, OperandType, AddressMode, Segment;
2538 U8 Opcode;
2539 MODRM modrm;
2540 REX rex;
2541 REX_MODRM rex_modrm;
2542 X86_OPCODE *X86Opcode;
2543 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
2544 BOOL Decode = Flags & DISASM_DECODE;
2545 BOOL Disassemble = Flags & DISASM_DISASSEMBLE;
2546 BOOL SuppressErrors = Flags & DISASM_SUPPRESSERRORS;
2547
2548 Opcode = Instruction->LastOpcode;
2549 X86Opcode = &X86Instruction->Opcode;
2550
2551 // Setup Mod R/M byte
2552 if (X86Instruction->HasModRM)
2553 {
2554 SET_MODRM(X86Instruction->modrm, X86Instruction->modrm_b);
2555 modrm = X86Instruction->modrm;
2556 rex = X86Instruction->rex;
2557 SET_REX_MODRM(X86Instruction->rex_modrm, rex, modrm);
2558 rex_modrm = X86Instruction->rex_modrm;
2559 //DISASM_OUTPUT(("[0x%08I64X] ModRM = 0x%02X (mod=%d, reg=%d, rm=%d)\n", VIRTUAL_ADDRESS, X86Instruction->modrm_b, modrm.mod, rex_modrm.reg, rex_modrm.rm));
2560 INSTR_INC(1); // increment Instruction->Length and address
2561 }
2562 else
2563 {
2564 // initialize them to 0
2565 modrm = X86Instruction->modrm;
2566 rex = X86Instruction->rex;
2567 rex_modrm = X86Instruction->rex_modrm;
2568 }
2569
2570 for (OperandIndex = 0; OperandIndex < Instruction->OperandCount; OperandIndex++)
2571 {
2572 Operand = &Instruction->Operands[OperandIndex];
2573 assert(!(Operand->Flags & 0x7F));
2574
2575 OperandFlags = X86Opcode->OperandFlags[OperandIndex] & X86_OPFLAGS_MASK;
2576 OperandType = X86Opcode->OperandFlags[OperandIndex] & X86_OPTYPE_MASK;
2577 AddressMode = X86Opcode->OperandFlags[OperandIndex] & X86_AMODE_MASK;
2578 if (Decode && OperandIndex != 0) APPENDS(", ");
2579
2580 switch (OperandType)
2581 {
2582 ////////////////////////////////////////////////////////////
2583 // Special operand types with no associated addressing mode
2584 ////////////////////////////////////////////////////////////
2585
2586 case OPTYPE_0:
2587 if (!Decode) continue;
2588 Operand->Value_U64 = 0;
2589 Operand->Type = OPTYPE_IMM;
2590 //DISASM_OUTPUT(("[SetOperand] const 0\n"));
2591 if (Disassemble)
2592 {
2593 APPENDS("<0>");
2594 X86_WRITE_OPFLAGS();
2595 }
2596 continue;
2597 case OPTYPE_1:
2598 if (!Decode) continue;
2599 Operand->Value_U64 = 1;
2600 Operand->Type = OPTYPE_IMM;
2601 //DISASM_OUTPUT(("[SetOperand] const 1\n"));
2602 if (Disassemble)
2603 {
2604 APPENDS("<1>");
2605 X86_WRITE_OPFLAGS();
2606 }
2607 continue;
2608 case OPTYPE_FF:
2609 if (!Decode) continue;
2610 Operand->Value_U64 = 0xFF;
2611 Operand->Type = OPTYPE_IMM;
2612 //DISASM_OUTPUT(("[SetOperand] const 0xff\n"));
2613 if (Disassemble)
2614 {
2615 APPENDS("<0xFF>");
2616 X86_WRITE_OPFLAGS();
2617 }
2618 continue;
2619
2620 case OPTYPE_TSC:
2621 if (!Decode) continue;
2622 Operand->Length = 8;
2623 Operand->Type = OPTYPE_SPECIAL;
2624 //DISASM_OUTPUT(("[SetOperand] TSC\n"));
2625 if (Disassemble)
2626 {
2627 APPENDS("<TSC_MSR>");
2628 X86_WRITE_OPFLAGS();
2629 }
2630 continue;
2631
2632 case OPTYPE_CS_MSR:
2633 if (!Decode) continue;
2634 Operand->Length = 8;
2635 Operand->Type = OPTYPE_SPECIAL;
2636 //DISASM_OUTPUT(("[SetOperand] CS MSR\n"));
2637 if (Disassemble)
2638 {
2639 APPENDS("<CS_MSR>");
2640 X86_WRITE_OPFLAGS();
2641 }
2642 continue;
2643 case OPTYPE_EIP_MSR:
2644 if (!Decode) continue;
2645 Operand->Length = 8;
2646 Operand->Type = OPTYPE_SPECIAL;
2647 //DISASM_OUTPUT(("[SetOperand] EIP MSR\n"));
2648 if (Disassemble)
2649 {
2650 APPENDS("<EIP_MSR>");
2651 X86_WRITE_OPFLAGS();
2652 }
2653 continue;
2654 case OPTYPE_ESP_MSR:
2655 if (!Decode) continue;
2656 Operand->Length = 8;
2657 Operand->Type = OPTYPE_SPECIAL;
2658 //DISASM_OUTPUT(("[SetOperand] ESP MSR\n"));
2659 if (Disassemble)
2660 {
2661 APPENDS("<ESP_MSR>");
2662 X86_WRITE_OPFLAGS();
2663 }
2664 continue;
2665 case OPTYPE_KERNELBASE_MSR:
2666 if (!Decode) continue;
2667 Operand->Length = 8;
2668 Operand->Type = OPTYPE_SPECIAL;
2669 //DISASM_OUTPUT(("[SetOperand] KernelBase MSR\n"));
2670 if (Disassemble)
2671 {
2672 APPENDS("<KRNLBASE_MSR>");
2673 X86_WRITE_OPFLAGS();
2674 }
2675 continue;
2676
2677 case OPTYPE_STAR_MSR:
2678 if (!Decode) continue;
2679 Operand->Length = 8;
2680 Operand->Type = OPTYPE_SPECIAL;
2681 //DISASM_OUTPUT(("[SetOperand] KernelBase MSR\n"));
2682 if (Disassemble)
2683 {
2684 APPENDS("<STAR_MSR>");
2685 X86_WRITE_OPFLAGS();
2686 }
2687 continue;
2688 case OPTYPE_CSTAR_MSR:
2689 assert(!IS_AMD64());
2690 if (!Decode) continue;
2691 Operand->Length = 8;
2692 Operand->Type = OPTYPE_SPECIAL;
2693 //DISASM_OUTPUT(("[SetOperand] CSTAR MSR\n"));
2694 if (Disassemble)
2695 {
2696 APPENDS("<CSTAR_MSR>");
2697 X86_WRITE_OPFLAGS();
2698 }
2699 continue;
2700 case OPTYPE_LSTAR_MSR:
2701 assert(IS_AMD64());
2702 if (!Decode) continue;
2703 Operand->Length = 8;
2704 Operand->Type = OPTYPE_SPECIAL;
2705 //DISASM_OUTPUT(("[SetOperand] LSTAR MSR\n"));
2706 if (Disassemble)
2707 {
2708 APPENDS("<LSTAR_MSR>");
2709 X86_WRITE_OPFLAGS();
2710 }
2711 continue;
2712 case OPTYPE_FMASK_MSR:
2713 if (!Decode) continue;
2714 Operand->Length = 8;
2715 Operand->Type = OPTYPE_SPECIAL;
2716 //DISASM_OUTPUT(("[SetOperand] FMASK MSR\n"));
2717 if (Disassemble)
2718 {
2719 APPENDS("<FMASK_MSR>");
2720 X86_WRITE_OPFLAGS();
2721 }
2722 continue;
2723
2724 case OP_REG:
2725 if (!Decode) continue;
2726 // The reg field is included in the opcode
2727 Operand->Length = X86Instruction->OperandSize;
2728 Register = X86_GET_REG64(Opcode);
2729 switch (X86Instruction->OperandSize)
2730 {
2731 case 8:
2732 Operand->Register = AMD64_64BIT_OFFSET + Register;
2733 break;
2734 case 4:
2735 Operand->Register = X86_32BIT_OFFSET + Register;
2736 CHECK_AMD64_REG();
2737 break;
2738 case 2:
2739 Operand->Register = X86_16BIT_OFFSET + Register;
2740 CHECK_AMD64_REG();
2741 break;
2742 case 1:
2743 Operand->Register = X86_8BIT_OFFSET + Register;
2744 if (X86Instruction->rex_b) CHECK_AMD64_REG();
2745 break;
2746 default:
2747 assert(0);
2748 return NULL;
2749 }
2750 X86_SET_REG(Register);
2751
2752 //DISASM_OUTPUT(("[SetOperand] OP_REG %s\n", X86_Registers[Operand->Register]));
2753 if (Disassemble)
2754 {
2755 APPENDB('<'); APPENDS(X86_Registers[Operand->Register]); APPENDB('>');
2756 X86_WRITE_OPFLAGS();
2757 }
2758 continue;
2759
2760 case OPTYPE_REG8:
2761 if (!Decode) continue;
2762 // The reg field is included in the opcode
2763 Operand->Length = 1;
2764 Register = X86_GET_REG64(Opcode);
2765 Operand->Register = X86_8BIT_OFFSET + Register;
2766 CHECK_AMD64_REG();
2767 X86_SET_REG(Register);
2768
2769 //DISASM_OUTPUT(("[SetOperand] OP_REG %s\n", X86_Registers[Operand->Register]));
2770 if (Disassemble)
2771 {
2772 APPENDB('<'); APPENDS(X86_Registers[Operand->Register]); APPENDB('>');
2773 X86_WRITE_OPFLAGS();
2774 }
2775 continue;
2776
2777 case OPTYPE_REG_AL:
2778 if (!Decode) continue;
2779 Operand->Length = 1;
2780 Operand->Register = X86_REG_AL;
2781 X86_SET_REG(0);
2782 //DISASM_OUTPUT(("[SetOperand] reg AL\n"));
2783 if (Disassemble)
2784 {
2785 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2786 X86_WRITE_OPFLAGS();
2787 }
2788 continue;
2789 case OPTYPE_REG_CL:
2790 if (!Decode) continue;
2791 Operand->Length = 1;
2792 Operand->Register = X86_REG_CL;
2793 X86_SET_REG(0);
2794 //DISASM_OUTPUT(("[SetOperand] reg CL\n"));
2795 if (Disassemble)
2796 {
2797 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2798 X86_WRITE_OPFLAGS();
2799 }
2800 continue;
2801 case OPTYPE_REG_AH:
2802 if (!Decode) continue;
2803 Operand->Length = 1;
2804 Operand->Register = X86_REG_AH;
2805 X86_SET_REG(0);
2806 //DISASM_OUTPUT(("[SetOperand] reg AH\n"));
2807 if (Disassemble)
2808 {
2809 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2810 X86_WRITE_OPFLAGS();
2811 }
2812 continue;
2813 case OPTYPE_REG_AX:
2814 if (!Decode) continue;
2815 Operand->Length = 2;
2816 Operand->Register = X86_REG_AX;
2817 X86_SET_REG(0);
2818 //DISASM_OUTPUT(("[SetOperand] reg AX\n"));
2819 if (Disassemble)
2820 {
2821 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2822 X86_WRITE_OPFLAGS();
2823 }
2824 continue;
2825 case OPTYPE_REG_DX:
2826 if (!Decode) continue;
2827 Operand->Length = 2;
2828 Operand->Register = X86_REG_DX;
2829 X86_SET_REG(0);
2830 //DISASM_OUTPUT(("[SetOperand] reg DX\n"));
2831 if (Disassemble)
2832 {
2833 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2834 X86_WRITE_OPFLAGS();
2835 }
2836 continue;
2837 case OPTYPE_REG_ECX:
2838 if (!Decode) continue;
2839 Operand->Length = 4;
2840 Operand->Register = X86_REG_ECX;
2841 X86_SET_REG(0);
2842 //DISASM_OUTPUT(("[SetOperand] reg ECX\n"));
2843 if (Disassemble)
2844 {
2845 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2846 X86_WRITE_OPFLAGS();
2847 }
2848 continue;
2849
2850 case OPTYPE_REG_xBP:
2851 if (!Decode) continue;
2852 Operand->Length = X86Instruction->OperandSize;
2853 switch (X86Instruction->OperandSize)
2854 {
2855 case 8: Operand->Register = AMD64_REG_RBP; break;
2856 case 4: Operand->Register = X86_REG_EBP; break;
2857 case 2: Operand->Register = X86_REG_BP; break;
2858 default: assert(0); return NULL;
2859 }
2860 X86_SET_REG(0);
2861 //DISASM_OUTPUT(("[SetOperand] xAX_BIG (size = %d)\n", Operand->Length));
2862 if (Disassemble)
2863 {
2864 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2865 X86_WRITE_OPFLAGS();
2866 }
2867 continue;
2868
2869 case OPTYPE_REG_xAX_BIG:
2870 if (!Decode) continue;
2871 Operand->Length = X86Instruction->OperandSize;
2872 switch (X86Instruction->OperandSize)
2873 {
2874 case 8: Operand->Register = AMD64_REG_RAX; break;
2875 case 4: Operand->Register = X86_REG_EAX; break;
2876 case 2: Operand->Register = X86_REG_AX; break;
2877 default: assert(0); return NULL;
2878 }
2879 X86_SET_REG(0);
2880 //DISASM_OUTPUT(("[SetOperand] xAX_BIG (size = %d)\n", Operand->Length));
2881 if (Disassemble)
2882 {
2883 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2884 X86_WRITE_OPFLAGS();
2885 }
2886 continue;
2887 case OPTYPE_REG_xAX_SMALL:
2888 if (!Decode) continue;
2889 Operand->Length = X86Instruction->OperandSize >> 1;
2890 switch (X86Instruction->OperandSize)
2891 {
2892 case 8: Operand->Register = X86_REG_EAX; break;
2893 case 4: Operand->Register = X86_REG_AX; break;
2894 case 2: Operand->Register = X86_REG_AL; break;
2895 default: assert(0); return NULL;
2896 }
2897 X86_SET_REG(0);
2898 //DISASM_OUTPUT(("[SetOperand] xAX_SMALL (size = %d)\n", Operand->Length));
2899 if (Disassemble)
2900 {
2901 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2902 X86_WRITE_OPFLAGS();
2903 }
2904 continue;
2905
2906 case OPTYPE_xCX_HI_xBX_LO:
2907 if (!Decode) continue;
2908 Operand->Length = X86Instruction->OperandSize << 1;
2909 if (Disassemble)
2910 {
2911 switch (X86Instruction->OperandSize)
2912 {
2913 case 8: APPENDS("<RCX:RBX>"); break;
2914 case 4: APPENDS("<ECX:EBX>"); break;
2915 case 2: APPENDS("<CX:BX>"); break;
2916 default: assert(0); return NULL;
2917 }
2918 X86_WRITE_OPFLAGS();
2919 }
2920 //DISASM_OUTPUT(("[SetOperand] xCX_BIG:xBX_BIG (size = %d)\n", Operand->Length));
2921 continue;
2922 case OPTYPE_xDX_HI_xAX_LO:
2923 if (!Decode) continue;
2924 Operand->Length = X86Instruction->OperandSize << 1;
2925 if (Disassemble)
2926 {
2927 switch (X86Instruction->OperandSize)
2928 {
2929 case 8: APPENDS("<RDX:RAX>"); break;
2930 case 4: APPENDS("<EDX:EAX>"); break;
2931 case 2: APPENDS("<DX:AX>"); break;
2932 default: assert(0); return NULL;
2933 }
2934 X86_WRITE_OPFLAGS();
2935 }
2936 //DISASM_OUTPUT(("[SetOperand] xDX_BIG:xAX_BIG (size = %d)\n", Operand->Length));
2937 continue;
2938
2939 case OPTYPE_EDX_HI_EAX_LO:
2940 if (!Decode) continue;
2941 Operand->Length = 8;
2942 //DISASM_OUTPUT(("[SetOperand] EDX:EAX\n"));
2943 if (Disassemble)
2944 {
2945 APPENDS("<EDX:EAX>");
2946 X86_WRITE_OPFLAGS();
2947 }
2948 continue;
2949
2950 case OPTYPE_EDX_ECX_EBX_EAX:
2951 Operand->Length = 32;
2952 //DISASM_OUTPUT(("[SetOperand] EDX:ECX:EBX:EAX\n"));
2953 if (Disassemble)
2954 {
2955 APPENDS("<EDX:ECX:EBX:EAX>");
2956 X86_WRITE_OPFLAGS();
2957 }
2958 continue;
2959
2960 case OPTYPE_FLAGS:
2961 if (!Decode) continue;
2962 Operand->Length = 2;
2963 Operand->Flags |= OP_REG;
2964 Operand->Register = X86_REG_FLAGS;
2965 //DISASM_OUTPUT(("[SetOperand] reg FLAGS\n"));
2966 if (Disassemble)
2967 {
2968 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2969 X86_WRITE_OPFLAGS();
2970 }
2971 continue;
2972
2973 case OPTYPE_xFLAGS:
2974 if (!Decode) continue;
2975 Operand->Length = X86Instruction->OperandSize;
2976 Operand->Flags |= OP_REG;
2977 switch (X86Instruction->OperandSize)
2978 {
2979 case 8: Operand->Register = AMD64_REG_RFLAGS; break;
2980 case 4: Operand->Register = X86_REG_EFLAGS; break;
2981 case 2: Operand->Register = X86_REG_FLAGS; break;
2982 default: assert(0); return NULL;
2983 }
2984 //DISASM_OUTPUT(("[SetOperand] reg xFLAGS (size = %d)\n", Operand->Length));
2985 if (Disassemble)
2986 {
2987 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
2988 X86_WRITE_OPFLAGS();
2989 }
2990 continue;
2991
2992 case OPTYPE_CS:
2993 if (!Decode) continue;
2994 if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
2995 else Operand->Length = X86Instruction->OperandSize;
2996 Operand->Register = X86_SEG_CS;
2997 Operand->Flags |= OP_REG;
2998 //DISASM_OUTPUT(("[SetOperand] seg CS\n"));
2999 if (Disassemble)
3000 {
3001 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
3002 X86_WRITE_OPFLAGS();
3003 }
3004 continue;
3005 case OPTYPE_DS:
3006 if (!Decode) continue;
3007 if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
3008 else Operand->Length = X86Instruction->OperandSize;
3009 Operand->Register = X86_SEG_DS;
3010 Operand->Flags |= OP_REG;
3011 //DISASM_OUTPUT(("[SetOperand] seg DS\n"));
3012 if (Disassemble)
3013 {
3014 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
3015 X86_WRITE_OPFLAGS();
3016 }
3017 continue;
3018 case OPTYPE_ES:
3019 if (!Decode) continue;
3020 if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
3021 else Operand->Length = X86Instruction->OperandSize;
3022 Operand->Register = X86_SEG_ES;
3023 Operand->Flags |= OP_REG;
3024 //DISASM_OUTPUT(("[SetOperand] seg ES\n"));
3025 if (Disassemble)
3026 {
3027 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
3028 X86_WRITE_OPFLAGS();
3029 }
3030 continue;
3031 case OPTYPE_FS:
3032 if (!Decode) continue;
3033 if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
3034 else Operand->Length = X86Instruction->OperandSize;
3035 Operand->Register = X86_SEG_FS;
3036 Operand->Flags |= OP_REG;
3037 //DISASM_OUTPUT(("[SetOperand] seg FS\n"));
3038 if (Disassemble)
3039 {
3040 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
3041 X86_WRITE_OPFLAGS();
3042 }
3043 continue;
3044 case OPTYPE_GS:
3045 if (!Decode) continue;
3046 if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
3047 else Operand->Length = X86Instruction->OperandSize;
3048 Operand->Register = X86_SEG_GS;
3049 Operand->Flags |= OP_REG;
3050 //DISASM_OUTPUT(("[SetOperand] seg GS\n"));
3051 if (Disassemble)
3052 {
3053 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
3054 X86_WRITE_OPFLAGS();
3055 }
3056 continue;
3057 case OPTYPE_SS:
3058 if (!Decode) continue;
3059 if (Instruction->Type != ITYPE_PUSH && Instruction->Type != ITYPE_POP) Operand->Length = 2;
3060 else Operand->Length = X86Instruction->OperandSize;
3061 Operand->Register = X86_SEG_SS;
3062 Operand->Flags |= OP_REG;
3063 //DISASM_OUTPUT(("[SetOperand] seg SS\n"));
3064 if (Disassemble)
3065 {
3066 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
3067 X86_WRITE_OPFLAGS();
3068 }
3069 continue;
3070
3071 case OPTYPE_CR0:
3072 if (!Decode) continue;
3073 Operand->Length = X86Instruction->OperandSize;
3074 Operand->Register = X86_REG_CR0;
3075 Operand->Flags |= OP_REG;
3076 //DISASM_OUTPUT(("[SetOperand] reg CR0\n"));
3077 if (Disassemble)
3078 {
3079 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
3080 X86_WRITE_OPFLAGS();
3081 }
3082 continue;
3083
3084 case OPTYPE_STx:
3085 if (!Decode) continue;
3086 Operand->Length = 10;
3087 Operand->Type = OPTYPE_FLOAT;
3088 Operand->Flags |= OP_REG;
3089 Register = X86_GET_REG(X86Instruction->modrm_b);
3090 Operand->Register = X86_FPU_OFFSET + Register;
3091 //DISASM_OUTPUT(("[SetOperand] OPTYPE_STx: reg st(%d)\n", Register));
3092 if (Disassemble)
3093 {
3094 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
3095 X86_WRITE_OPFLAGS();
3096 }
3097 continue;
3098
3099 case OPTYPE_ST0:
3100 if (!Decode) continue;
3101 Operand->Length = 10;
3102 Operand->Type = OPTYPE_FLOAT;
3103 Operand->Flags |= OP_REG;
3104 Operand->Register = X86_REG_ST0;
3105 if (Disassemble)
3106 {
3107 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
3108 X86_WRITE_OPFLAGS();
3109 }
3110 continue;
3111
3112 case OPTYPE_ST1:
3113 if (!Decode) continue;
3114 Operand->Length = 10;
3115 Operand->Type = OPTYPE_FLOAT;
3116 Operand->Flags |= OP_REG;
3117 Operand->Register = X86_REG_ST1;
3118 if (Disassemble)
3119 {
3120 APPEND(OPCSTR, SIZE_LEFT, "<%s>", X86_Registers[Operand->Register]);
3121 X86_WRITE_OPFLAGS();
3122 }
3123 continue;
3124
3125 case OPTYPE_FPU_STATUS:
3126 if (!Decode) continue;
3127 Operand->Length = 2;
3128 if (Disassemble)
3129 {
3130 APPENDS("<FPUSTAT>");
3131 X86_WRITE_OPFLAGS();
3132 }
3133 continue;
3134
3135 case OPTYPE_FPU_CONTROL:
3136 if (!Decode) continue;
3137 Operand->Length = 2;
3138 if (Disassemble)
3139 {
3140 APPENDS("<FPUCTRL>");
3141 X86_WRITE_OPFLAGS();
3142 }
3143 continue;
3144
3145 case OPTYPE_FPU_TAG:
3146 if (!Decode) continue;
3147 Operand->Length = 2;
3148 if (Disassemble)
3149 {
3150 APPENDS("<FPUTAG>");
3151 X86_WRITE_OPFLAGS();
3152 }
3153 continue;
3154
3155 case OPTYPE_FLDZ:
3156 if (!Decode) continue;
3157 Operand->Type = OPTYPE_FLOAT;
3158 Operand->Length = 10;
3159 if (Disassemble)
3160 {
3161 APPENDS("<0.0>");
3162 X86_WRITE_OPFLAGS();
3163 }
3164 continue;
3165 case OPTYPE_FLD1:
3166 if (!Decode) continue;
3167 Operand->Type = OPTYPE_FLOAT;
3168 Operand->Length = 10;
3169 if (Disassemble)
3170 {
3171 APPENDS("<1.0>");
3172 X86_WRITE_OPFLAGS();
3173 }
3174 continue;
3175 case OPTYPE_FLDPI:
3176 if (!Decode) continue;
3177 Operand->Type = OPTYPE_FLOAT;
3178 Operand->Length = 10;
3179 if (Disassemble)
3180 {
3181 APPENDS("<pi>");
3182 X86_WRITE_OPFLAGS();
3183 }
3184 continue;
3185 case OPTYPE_FLDL2T:
3186 if (!Decode) continue;
3187 Operand->Type = OPTYPE_FLOAT;
3188 Operand->Length = 10;
3189 if (Disassemble)
3190 {
3191 APPENDS("<log_2 10>");
3192 X86_WRITE_OPFLAGS();
3193 }
3194 continue;
3195 case OPTYPE_FLDL2E:
3196 if (!Decode) continue;
3197 Operand->Type = OPTYPE_FLOAT;
3198 Operand->Length = 10;
3199 if (Disassemble)
3200 {
3201 APPENDS("<log_2 e>");
3202 X86_WRITE_OPFLAGS();
3203 }
3204 continue;
3205 case OPTYPE_FLDLG2:
3206 if (!Decode) continue;
3207 Operand->Type = OPTYPE_FLOAT;
3208 Operand->Length = 10;
3209 if (Disassemble)
3210 {
3211 APPENDS("<log_10 2>");
3212 X86_WRITE_OPFLAGS();
3213 }
3214 continue;
3215 case OPTYPE_FLDLN2:
3216 if (!Decode) continue;
3217 Operand->Type = OPTYPE_FLOAT;
3218 Operand->Length = 10;
3219 if (Disassemble)
3220 {
3221 APPENDS("<ln 2>");
3222 X86_WRITE_OPFLAGS();
3223 }
3224 continue;
3225
3226 ////////////////////////////////////////////////////////////
3227 // Fixed sizes regardless of operand size
3228 ////////////////////////////////////////////////////////////
3229
3230 case OPTYPE_b: // byte regardless of operand size
3231 Operand->Length = 1;
3232 //DISASM_OUTPUT(("[SetOperand] OPTYPE_b (size 1, signed %d)\n", ((OperandFlags & OP_SIGNED) != 0)));
3233 break;
3234
3235 case OPTYPE_w: // word regardless of operand size
3236 Operand->Length = 2;
3237 //DISASM_OUTPUT(("[SetOperand] OPTYPE_w (size 2)\n"));
3238 break;
3239
3240 case OPTYPE_d: // dword regardless of operand size
3241 Operand->Length = 4;
3242 //DISASM_OUTPUT(("[SetOperand] OPTYPE_d (size 4)\n"));
3243 break;
3244
3245 case OPTYPE_q: // qword regardless of operand size
3246 Operand->Length = 8;
3247 //DISASM_OUTPUT(("[SetOperand] OPTYPE_q (size 8)\n"));
3248 break;
3249
3250 case OPTYPE_o: // oword regardless of operand size
3251 Operand->Length = 16;
3252 //DISASM_OUTPUT(("[SetOperand] OPTYPE_o (size 16)\n"));
3253 break;
3254
3255 case OPTYPE_dt: // 6-byte or 10-byte pseudo descriptor (sgdt, lgdt, sidt, lidt)
3256 if (IS_AMD64()) Operand->Length = 10;
3257 else Operand->Length = 6;
3258 //DISASM_OUTPUT(("[SetOperand] OPTYPE_dt (%d bytes)\n", Operand->Length));
3259 break;
3260
3261 case OPTYPE_cpu:
3262 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Undocumented loadall instruction?\n", VIRTUAL_ADDRESS);
3263 Instruction->AnomalyOccurred = TRUE;
3264 Operand->Length = 204;
3265 //DISASM_OUTPUT(("[SetOperand] OPTYPE_cpu (size 204)\n"));
3266 break;
3267
3268 ////////////////////////////////////////////////////////////
3269 // Sizes depending on the operand size
3270 ////////////////////////////////////////////////////////////
3271
3272 case OPTYPE_z: // word if operand size is 16 bits and dword otherwise
3273 switch (X86Instruction->OperandSize)
3274 {
3275 case 8: case 4: Operand->Length = 4; break;
3276 case 2: Operand->Length = 2; break;
3277 default: assert(0); return NULL;
3278 }
3279 //DISASM_OUTPUT(("[SetOperand] OPTYPE_z (length %d)\n", Operand->Length));
3280 break;
3281
3282 case OPTYPE_v: // word, dword, or qword
3283 Operand->Length = X86Instruction->OperandSize;
3284 //DISASM_OUTPUT(("[SetOperand] OPTYPE_v (size %d, signed = %d)\n", Operand->Length, ((OperandFlags & OP_SIGNED) != 0)));
3285 break;
3286
3287 case OPTYPE_a: // two word or dword operands in memory (used only by bound)
3288 assert(Instruction->OpcodeBytes[0] == X86_BOUND);
3289 switch (X86Instruction->OperandSize)
3290 {
3291 case 8: case 4: Operand->Length = 8; break;
3292 case 2: Operand->Length = 4; break;
3293 default: assert(0); return NULL;
3294 }
3295 //DISASM_OUTPUT(("[SetOperand] OPTYPE_a (size %d)\n", Operand->Length));
3296 break;
3297
3298 case OPTYPE_p: // 32-bit or 48-bit pointer depending on operand size
3299 if (!Instruction->AnomalyOccurred && X86Instruction->HasSegmentOverridePrefix)
3300 {
3301 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Segment override used when segment is explicit\n", VIRTUAL_ADDRESS);
3302 Instruction->AnomalyOccurred = TRUE;
3303 }
3304 switch (X86Instruction->OperandSize)
3305 {
3306 case 8: case 4: Operand->Length = 6; break;
3307 case 2: Operand->Length = 4; break;
3308 default: assert(0); return NULL;
3309 }
3310 //DISASM_OUTPUT(("[SetOperand] OPTYPE_p (length %d)\n", Operand->Length));
3311 break;
3312
3313 case OPTYPE_dq: // dword or qword
3314 //DISASM_OUTPUT(("[SetOperand] OPTYPE_dq (size 4 or 8)\n"));
3315 switch (X86Instruction->OperandSize)
3316 {
3317 case 8: Operand->Length = 8; break;
3318 case 4: case 2: Operand->Length = 4; break;
3319 default: assert(0); return NULL;
3320 }
3321 break;
3322
3323 case OPTYPE_mw: // a word if the destination operand is memory
3324 //DISASM_OUTPUT(("[SetOperand] OPTYPE_mw (size 0)\n"));
3325 assert(X86Instruction->HasModRM);
3326 if (modrm.mod == 3) Operand->Length = X86Instruction->OperandSize; // using register
3327 else Operand->Length = 2; // using memory
3328 break;
3329
3330 case OPTYPE_lea:
3331 //DISASM_OUTPUT(("[SetOperand] OPTYPE_lea (size 0)\n"));
3332 assert(OperandIndex == 1);
3333 Operand->Length = Instruction->Operands[0].Length;
3334 break;
3335
3336 ////////////////////////////////////////////////////////////
3337 // FPU types
3338 ////////////////////////////////////////////////////////////
3339
3340 case OPTYPE_ps: // packed single real
3341 Operand->Length = 4;
3342 Operand->Type = OPTYPE_FLOAT;
3343 //DISASM_OUTPUT(("[SetOperand] OPTYPE_ps (packed single real)\n"));
3344 break;
3345 case OPTYPE_pd: // packed double real
3346 Operand->Length = 8;
3347 Operand->Type = OPTYPE_FLOAT;
3348 //DISASM_OUTPUT(("[SetOperand] OPTYPE_pd (packed double real)\n"));
3349 break;
3350 case OPTYPE_pb: // packed BCD
3351 Operand->Length = 10;
3352 Operand->Type = OPTYPE_BCD;
3353 //DISASM_OUTPUT(("[SetOperand] OPTYPE_pb (packed BCD)\n"));
3354 break;
3355 case OPTYPE_ss: // scalar single real
3356 Operand->Length = 4;
3357 Operand->Type = OPTYPE_FLOAT;
3358 //DISASM_OUTPUT(("[SetOperand] OPTYPE_ss (single real)\n"));
3359 break;
3360 case OPTYPE_sd: // scalar double real
3361 Operand->Length = 8;
3362 Operand->Type = OPTYPE_FLOAT;
3363 //DISASM_OUTPUT(("[SetOperand] OPTYPE_sd (double real)\n"));
3364 break;
3365 case OPTYPE_se: // extended real
3366 Operand->Length = 10;
3367 Operand->Type = OPTYPE_FLOAT;
3368 //DISASM_OUTPUT(("[SetOperand] OPTYPE_se (extended real)\n"));
3369 break;
3370
3371 case OPTYPE_fev: // FPU environment (28 bytes in 32-bit modes, 14 bytes in 16-bit real mode)
3372 switch (X86Instruction->OperandSize)
3373 {
3374 case 8: case 4: Operand->Length = 28; break;
3375 case 2: Operand->Length = 14; break;
3376 default: assert(0); return NULL;
3377 }
3378 //DISASM_OUTPUT(("[SetOperand] OPTYPE_fev (FPU environment, length %d)\n", Operand->Length));
3379 break;
3380
3381 case OPTYPE_fst1: // FPU state (108 bytes in 32-bit modes, 94 bytes in 16-bit real mode)
3382 switch (X86Instruction->OperandSize)
3383 {
3384 case 8: case 4: Operand->Length = 108; break;
3385 case 2: Operand->Length = 94; break;
3386 default: assert(0); return NULL;
3387 }
3388 //DISASM_OUTPUT(("[SetOperand] OPTYPE_fst1 (FPU state, length %d)\n", Operand->Length));
3389 break;
3390
3391 case OPTYPE_fst2: // 512 bytes for FPU state (FPU + MMX + XXM + MXCSR)
3392 Operand->Length = 512;
3393 //DISASM_OUTPUT(("[SetOperand] OPTYPE_fst2 (FPU + MMX + XXM + MXCSR state, length 512)\n"));
3394 break;
3395
3396 case OPTYPE_sso:
3397 if (modrm.mod == 3) // from register
3398 {
3399 Operand->Length = 16;
3400 }
3401 else // from memory
3402 {
3403 Operand->Length = 4;
3404 Operand->Type = OPTYPE_FLOAT;
3405 }
3406 //DISASM_OUTPUT(("[SetOperand] OPTYPE_sso (single real or oword)\n"));
3407 break;
3408
3409 case OPTYPE_sdo:
3410 if (modrm.mod == 3) // from register
3411 {
3412 Operand->Length = 16;
3413 }
3414 else // from memory
3415 {
3416 Operand->Length = 8;
3417 Operand->Type = OPTYPE_FLOAT;
3418 }
3419 //DISASM_OUTPUT(("[SetOperand] OPTYPE_sso (double real or oword)\n"));
3420 break;
3421
3422 default:
3423 assert(0);
3424 return NULL;
3425 }
3426
3427 switch (AddressMode)
3428 {
3429 ////////////////////////////////////////////////////////////
3430 // Special types
3431 ////////////////////////////////////////////////////////////
3432
3433 case AMODE_xlat: // DS:[EBX+AL]
3434 if (!Decode) continue;
3435 assert(Operand->Length == 1);
3436 Operand->Flags |= OP_ADDRESS | OP_REG;
3437 Operand->Type = OPTYPE_STRING;
3438
3439 switch (X86Instruction->AddressSize)
3440 {
3441 case 8: Operand->Register = AMD64_REG_RBX; break;
3442 case 4: Operand->Register = X86_REG_EBX; break;
3443 case 2: Operand->Register = X86_REG_BX; break;
3444 default: assert(0); return NULL;
3445 }
3446 X86_SET_ADDR();
3447 X86Instruction->Scale = 1;
3448 X86Instruction->BaseRegister = Operand->Register;
3449 X86Instruction->HasBaseRegister = TRUE;
3450 X86Instruction->IndexRegister = X86_REG_AL;
3451 X86Instruction->HasIndexRegister = TRUE;
3452
3453 //DISASM_OUTPUT(("[SetOperand] AMODE_xlat (DS:[EBX+AL])\n"));
3454 if (Disassemble)
3455 {
3456 APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]",
3457 Segments[X86Instruction->Segment], X86_Registers[Operand->Register]);
3458 X86_WRITE_OPFLAGS();
3459 }
3460 continue;
3461
3462 ////////////////////////////////////////////////////////////
3463 // Without mod R/M byte
3464 ////////////////////////////////////////////////////////////
3465
3466 case AMODE_I: // immediate value
3467 if (Decode)
3468 {
3469 Operand->Type = OPTYPE_IMM;
3470 switch (Operand->Length)
3471 {
3472 case 8:
3473 if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S64 *)Address);
3474 else Operand->Value_U64 = (U64)*((U64 *)Address);
3475 break;
3476 case 4:
3477 if (!(OperandFlags & OP_SIGNED) && OperandIndex == 1 &&
3478 (Instruction->Operands[0].Flags & (OP_REG|OP_ADDRESS)) &&
3479 Instruction->Operands[0].Length == 8)
3480 {
3481 // For some opcodes the second operand is a sign-extended imm32 value
3482 assert(X86Instruction->OperandSize == 8);
3483 switch (Instruction->Type)
3484 {
3485 case ITYPE_AND:
3486 case ITYPE_ADD:
3487 case ITYPE_XCHGADD:
3488 case ITYPE_CMP:
3489 case ITYPE_MOV:
3490 case ITYPE_SUB:
3491 case ITYPE_TEST:
3492 case ITYPE_OR:
3493 case ITYPE_XOR:
3494 assert(OperandIndex == 1);
3495 Operand->Value_S64 = (S64)*((S32 *)Address);
3496 break;
3497 default:
3498 assert(0);
3499 if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S32 *)Address);
3500 else Operand->Value_U64 = (U64)*((U32 *)Address);
3501 break;
3502 }
3503 }
3504 else
3505 {
3506 if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S32 *)Address);
3507 else Operand->Value_U64 = (U64)*((U32 *)Address);
3508 }
3509 break;
3510 case 2:
3511 if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S16 *)Address);
3512 else Operand->Value_U64 = (U64)*((U16 *)Address);
3513 break;
3514 case 1:
3515 if (OperandFlags & OP_SIGNED) Operand->Value_S64 = (S64)*((S8 *)Address);
3516 else Operand->Value_U64 = (U64)*((U8 *)Address);
3517 break;
3518 default:
3519 assert(0);
3520 return NULL;
3521 }
3522 }
3523 INSTR_INC(Operand->Length); // increment Instruction->Length and address
3524 assert(X86Instruction->OperandSize >= Operand->Length);
3525 if (Instruction->Type == ITYPE_PUSH) Operand->Length = X86Instruction->OperandSize;
3526
3527 //DISASM_OUTPUT(("[SetOperand] AMODE_I (immediate data)\n"));
3528 if (Disassemble)
3529 {
3530 X86_WRITE_IMMEDIATE();
3531 X86_WRITE_OPFLAGS();
3532 }
3533 continue;
3534
3535 case AMODE_J: // IP-relative jump offset
3536 SANITY_CHECK_ADDRESS_SIZE();
3537 if (Decode)
3538 {
3539 Operand->Flags |= OP_IPREL | OP_SIGNED | OP_REG | OP_ADDRESS;
3540 Operand->Type = OPTYPE_OFFSET;
3541 switch (X86Instruction->OperandSize)
3542 {
3543 case 8: Operand->Register = AMD64_REG_RIP; break;
3544 case 4: Operand->Register = X86_REG_EIP; break;
3545 case 2: Operand->Register = X86_REG_IP; break;
3546 default: assert(0); return NULL;
3547 }
3548 switch (Operand->Length)
3549 {
3550 case 8: X86Instruction->Displacement = *((S64 *)Address); break;
3551 case 4: X86Instruction->Displacement = (S64)*((S32 *)Address); break;
3552 case 2: X86Instruction->Displacement = (S64)*((S16 *)Address); break;
3553 case 1: X86Instruction->Displacement = (S64)*((S8 *)Address); break;
3554 default: assert(0); return NULL;
3555 }
3556
3557 Operand->Value_S64 = X86Instruction->Displacement;
3558 X86Instruction->Relative = TRUE;
3559
3560 if ((Operand->Flags & OP_COND) && !X86Instruction->Displacement)
3561 {
3562 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: Both conditions of branch go to same address\n", VIRTUAL_ADDRESS);
3563 Instruction->AnomalyOccurred = TRUE;
3564 }
3565 }
3566
3567 INSTR_INC(Operand->Length); // increment Instruction->Length and address
3568 if (!Decode) continue;
3569
3570 assert((Operand->Flags & OP_EXEC) && (Instruction->Groups & ITYPE_EXEC));
3571 Operand->TargetAddress = ApplyDisplacement((U64)Address, Instruction);
3572 X86Instruction->Relative = TRUE;
3573 X86_SET_ADDR();
3574 SANITY_CHECK_SEGMENT_OVERRIDE();
3575 X86Instruction->HasSegmentOverridePrefix = FALSE;
3576 X86Instruction->Segment = SEG_CS;
3577 X86Instruction->BaseRegister = Operand->Register;
3578 X86Instruction->HasBaseRegister = TRUE;
3579 assert(Instruction->OperandCount == 1);
3580 //DISASM_OUTPUT(("[SetOperand] AMODE_J (branch with relative offset)\n"));
3581 if (Disassemble)
3582 {
3583 X86_WRITE_IP_OFFSET(Operand);
3584 X86_WRITE_OPFLAGS();
3585 }
3586 continue;
3587
3588 case AMODE_O: // word/dword offset
3589 Operand->Type = OPTYPE_OFFSET;
3590 Operand->Flags |= OP_ADDRESS;
3591 SANITY_CHECK_OPERAND_SIZE();
3592 switch (X86Instruction->AddressSize)
3593 {
3594 case 8:
3595 if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = *((S64 *)Address);
3596 else X86Instruction->Displacement = (S64)*((U64 *)Address);
3597 break;
3598 case 4:
3599 if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = (S64)*((S32 *)Address);
3600 else X86Instruction->Displacement = (S64)*((U32 *)Address);
3601 break;
3602 case 2:
3603 if (Operand->Flags & OP_SIGNED) X86Instruction->Displacement = (S64)*((S16 *)Address);
3604 else X86Instruction->Displacement = (S64)*((U16 *)Address);
3605 break;
3606 default:
3607 assert(0);
3608 return FALSE;
3609 }
3610
3611 INSTR_INC(X86Instruction->AddressSize); // increment Instruction->Length and address
3612 if (!Decode) continue;
3613
3614 X86Instruction->HasFullDisplacement = TRUE;
3615 X86_SET_ADDR();
3616 X86_SET_TARGET();
3617 assert(X86Instruction->Segment == SEG_DS || X86Instruction->HasSegmentOverridePrefix);
3618 //DISASM_OUTPUT(("[SetOperand] AMODE_O (offset)\n"));
3619 if (Disassemble)
3620 {
3621 X86_WRITE_OFFSET(Operand);
3622 X86_WRITE_OPFLAGS();
3623 }
3624 continue;
3625
3626 case AMODE_A: // absolute address
3627 Operand->Flags |= OP_ADDRESS | OP_FAR;
3628 SANITY_CHECK_ADDRESS_SIZE();
3629 SANITY_CHECK_SEGMENT_OVERRIDE();
3630 X86Instruction->HasSelector = TRUE;
3631 X86Instruction->HasSegmentOverridePrefix = FALSE;
3632 switch (Operand->Length)
3633 {
3634 case 6:
3635 X86Instruction->Segment = *((U16 *)Address); INSTR_INC(2);
3636 X86Instruction->Displacement = (S64)*((S32 *)Address); INSTR_INC(4);
3637 break;
3638 case 4:
3639 X86Instruction->Segment = *((U16 *)Address); INSTR_INC(2);
3640 X86Instruction->Displacement = (S64)*((S16 *)Address); INSTR_INC(2);
3641 break;
3642 default:
3643 assert(0);
3644 return FALSE;
3645 }
3646 if (!Decode) continue;
3647 X86Instruction->HasFullDisplacement = TRUE;
3648 X86_SET_ADDR();
3649 X86_SET_TARGET();
3650 //DISASM_OUTPUT(("[SetOperand] AMODE_A (absolute address)\n"));
3651 if (Disassemble)
3652 {
3653 X86_WRITE_OFFSET(Operand);
3654 X86_WRITE_OPFLAGS();
3655 }
3656 continue;
3657
3658 case AMODE_X: // DS:[ESI]
3659 if (!Decode) continue;
3660 Operand->Flags |= OP_ADDRESS | OP_REG;
3661 Operand->Type = OPTYPE_STRING;
3662 switch (X86Instruction->AddressSize)
3663 {
3664 case 8: Operand->Register = AMD64_REG_RSI; break;
3665 case 4: Operand->Register = X86_REG_ESI; break;
3666 case 2: Operand->Register = X86_REG_SI; break;
3667 default: assert(0); return NULL;
3668 }
3669
3670 X86Instruction->BaseRegister = Operand->Register;
3671 X86Instruction->HasBaseRegister = TRUE;
3672 X86_SET_ADDR();
3673 if (!X86Instruction->HasSegmentOverridePrefix) X86Instruction->Segment = SEG_DS;
3674
3675 //DISASM_OUTPUT(("[SetOperand] AMODE_X (addressing via DS:[ESI])\n"));
3676 if (Disassemble)
3677 {
3678 APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]",
3679 Segments[X86Instruction->Segment], X86_Registers[Operand->Register]);
3680 X86_WRITE_OPFLAGS();
3681 }
3682 continue;
3683
3684 case AMODE_Y: // ES:[EDI]
3685 if (!Decode) continue;
3686 Operand->Flags |= OP_ADDRESS | OP_REG;
3687 Operand->Type = OPTYPE_STRING;
3688 switch (X86Instruction->AddressSize)
3689 {
3690 case 8: Operand->Register = AMD64_REG_RDI; break;
3691 case 4: Operand->Register = X86_REG_EDI; break;
3692 case 2: Operand->Register = X86_REG_DI; break;
3693 default: assert(0); return NULL;
3694 }
3695
3696 X86Instruction->BaseRegister = Operand->Register;
3697 X86Instruction->HasBaseRegister = TRUE;
3698 X86_SET_ADDR();
3699 if (X86Instruction->HasSegmentOverridePrefix)
3700 {
3701 if (!Instruction->AnomalyOccurred)
3702 {
3703 if (!SuppressErrors) printf("[0x%08I64X] ANOMALY: segment override used with AMODE_Y\n", VIRTUAL_ADDRESS);
3704 Instruction->AnomalyOccurred = TRUE;
3705 }
3706 Segment = X86Instruction->DstSegment = SEG_ES;
3707 X86Instruction->HasDstSegment = TRUE;
3708 }
3709 else
3710 {
3711 Segment = X86Instruction->Segment = SEG_ES;
3712 }
3713
3714 //DISASM_OUTPUT(("[SetOperand] AMODE_Y (addressing via ES:[EDI])\n"));
3715 if (Disassemble)
3716 {
3717 APPEND(OPCSTR, SIZE_LEFT, "%s:[%s]",
3718 Segments[Segment], X86_Registers[Operand->Register]);
3719 X86_WRITE_OPFLAGS();
3720 }
3721 continue;
3722
3723 ////////////////////////////////////////////////////////////
3724 // Mod R/M byte with only registers
3725 // Handle that case here since it is straightforward
3726 ////////////////////////////////////////////////////////////
3727
3728 case AMODE_PR: // modrm.rm = mmx register and modrm.mod = 11
3729 assert(X86Instruction->HasModRM);
3730 if (modrm.mod != 3)
3731 {
3732 if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_PR (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
3733 goto abort;
3734 }
3735 else if (rex_modrm.rm > 7)
3736 {
3737 if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_PR (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic);
3738 goto abort;
3739 }
3740 else if (X86Instruction->OperandSize == 2)
3741 {
3742 if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_PR illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
3743 goto abort;
3744 }
3745 if (!Decode) continue;
3746
3747 Operand->Flags |= OP_REG;
3748 Operand->Register = X86_MMX_OFFSET + rex_modrm.rm;
3749 X86_SET_REG(0);
3750
3751 if (Disassemble)
3752 {
3753 assert(X86_Registers[Operand->Register]);
3754 APPENDS(X86_Registers[Operand->Register]);
3755 X86_WRITE_OPFLAGS();
3756 }
3757 //DISASM_OUTPUT(("[SetOperand] AMODE_PR (MMX register)\n"));
3758 continue;
3759
3760 case AMODE_VR: // modrm.rm = xmm register and modrm.mod = 11
3761 assert(X86Instruction->HasModRM);
3762 if (modrm.mod != 3)
3763 {
3764 if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_VR (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
3765 goto abort;
3766 }
3767 else if (X86Instruction->OperandSize == 2)
3768 {
3769 if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_VR illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
3770 goto abort;
3771 }
3772 if (!Decode) continue;
3773
3774 Operand->Flags |= OP_REG;
3775 Operand->Register = X86_XMM_OFFSET + rex_modrm.rm;
3776 X86_SET_REG(0);
3777
3778 if (Disassemble)
3779 {
3780 APPENDS(X86_Registers[Operand->Register]);
3781 X86_WRITE_OPFLAGS();
3782 }
3783 //DISASM_OUTPUT(("[SetOperand] AMODE_VR (XMM register)\n"));
3784 continue;
3785
3786 case AMODE_P: // modrm.reg = mmx register
3787 assert(X86Instruction->HasModRM);
3788 if (rex_modrm.reg > 7)
3789 {
3790 if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_P (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.reg, X86Instruction->Opcode.Mnemonic);
3791 goto abort;
3792 }
3793 else if (X86Instruction->OperandSize == 2)
3794 {
3795 if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_P illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
3796 goto abort;
3797 }
3798 if (!Decode) continue;
3799
3800 Operand->Flags |= OP_REG;
3801 Operand->Register = X86_MMX_OFFSET + rex_modrm.reg;
3802 X86_SET_REG(0);
3803
3804 if (Disassemble)
3805 {
3806 APPENDS(X86_Registers[Operand->Register]);
3807 X86_WRITE_OPFLAGS();
3808 }
3809 //DISASM_OUTPUT(("[SetOperand] AMODE_P (MMX register)\n"));
3810 continue;
3811
3812 case AMODE_V: // modrm.reg = xmm register
3813 assert(X86Instruction->HasModRM);
3814 if (X86Instruction->OperandSize == 2)
3815 {
3816 if (!SuppressErrors) printf("[0x%08I64X] ERROR: AMODE_P illegal in 16-bit mode (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
3817 goto abort;
3818 }
3819 if (!Decode) continue;
3820
3821 Operand->Flags |= OP_REG;
3822 Operand->Register = X86_XMM_OFFSET + rex_modrm.reg; break;
3823 X86_SET_REG(0);
3824
3825 if (Disassemble)
3826 {
3827 APPENDS(X86_Registers[Operand->Register]);
3828 X86_WRITE_OPFLAGS();
3829 }
3830 //DISASM_OUTPUT(("[SetOperand] AMODE_V (XMM register)\n"));
3831 continue;
3832
3833 case AMODE_R: // modrm.rm is general register and modrm.mod = 11
3834 assert(X86Instruction->HasModRM);
3835 if (modrm.mod != 3)
3836 {
3837 if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod != 3 for AMODE_R (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
3838 goto abort;
3839 }
3840 if (!Decode) continue;
3841 Operand->Flags |= OP_REG;
3842 switch (Operand->Length)
3843 {
3844 case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break;
3845 case 4: Operand->Register = X86_32BIT_OFFSET, rex_modrm.rm; CHECK_AMD64_REG(); break;
3846 case 2: Operand->Register = X86_16BIT_OFFSET, rex_modrm.rm; CHECK_AMD64_REG(); break;
3847 case 1: Operand->Register = X86_8BIT_OFFSET, rex_modrm.rm; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break;
3848 default: assert(0); return NULL;
3849 }
3850 X86_SET_REG(rex_modrm.rm);
3851 if (Disassemble)
3852 {
3853 APPENDS(X86_Registers[Operand->Register]);
3854 X86_WRITE_OPFLAGS();
3855 }
3856 //DISASM_OUTPUT(("[SetOperand] AMODE_R (general register)\n"));
3857 continue;
3858
3859 case AMODE_G: // modrm.reg = general register
3860 assert(X86Instruction->HasModRM);
3861 if (!Decode) continue;
3862 Operand->Flags |= OP_REG;
3863 switch (Operand->Length)
3864 {
3865 case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.reg; break;
3866 case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.reg; CHECK_AMD64_REG(); break;
3867 case 2: Operand->Register = X86_16BIT_OFFSET + rex_modrm.reg; CHECK_AMD64_REG(); break;
3868 case 1: Operand->Register = X86_8BIT_OFFSET + rex_modrm.reg; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break;
3869 default: assert(0); return NULL;
3870 }
3871 X86_SET_REG(rex_modrm.reg);
3872 if (Disassemble)
3873 {
3874 APPENDS(X86_Registers[Operand->Register]);
3875 X86_WRITE_OPFLAGS();
3876 }
3877 //DISASM_OUTPUT(("[SetOperand] AMODE_G (general register)\n"));
3878 continue;
3879
3880 case AMODE_S: // modrm.reg = segment register
3881 assert(X86Instruction->HasModRM);
3882 if (!Decode) continue;
3883 Operand->Flags |= OP_REG;
3884 switch (X86Instruction->OperandSize)
3885 {
3886 case 8:
3887 case 4:
3888 case 2:
3889 if (rex_modrm.reg <= 5) Operand->Register = X86_SEGMENT_OFFSET + rex_modrm.reg;
3890 break;
3891 default:
3892 assert(0);
3893 return NULL;
3894 }
3895
3896 X86_SET_REG(0);
3897 if (Disassemble)
3898 {
3899 if (rex_modrm.reg > 5) APPEND(OPCSTR, SIZE_LEFT, "seg_%02X", rex_modrm.reg);
3900 else APPENDS(X86_Registers[Operand->Register]);
3901 X86_WRITE_OPFLAGS();
3902 }
3903 //DISASM_OUTPUT(("[SetOperand] AMODE_S (segment register)\n"));
3904 continue;
3905
3906 case AMODE_T: // modrm.reg = test register
3907 assert(X86Instruction->HasModRM);
3908 if (!Decode) continue;
3909 Instruction->Groups |= ITYPE_SYSTEM;
3910 Instruction->NeedsEmulation = TRUE;
3911 Operand->Flags |= OP_REG;
3912 switch (X86Instruction->OperandSize)
3913 {
3914 case 8:
3915 case 4:
3916 case 2:
3917 Operand->Register = X86_TEST_OFFSET + rex_modrm.reg;
3918 break;
3919 default:
3920 assert(0);
3921 return NULL;
3922 }
3923
3924 X86_SET_REG(0);
3925 if (Disassemble)
3926 {
3927 APPENDS(X86_Registers[Operand->Register]);
3928 X86_WRITE_OPFLAGS();
3929 }
3930 //DISASM_OUTPUT(("[SetOperand] AMODE_T (test register)\n"));
3931 continue;
3932
3933 case AMODE_C: // modrm.reg = control register
3934 assert(X86Instruction->HasModRM);
3935 assert(Instruction->Type == ITYPE_MOV);
3936 if (!Decode) continue;
3937 Instruction->Groups |= ITYPE_SYSTEM;
3938 Instruction->NeedsEmulation = TRUE;
3939 Operand->Flags |= OP_REG;
3940 if (IS_AMD64()) X86Instruction->OperandSize = 8;
3941 switch (X86Instruction->OperandSize)
3942 {
3943 case 8:
3944 case 4:
3945 case 2:
3946 Operand->Register = X86_CONTROL_OFFSET + rex_modrm.reg;
3947 break;
3948 default:
3949 assert(0);
3950 return NULL;
3951 }
3952
3953 X86_SET_REG(0);
3954 if (Disassemble)
3955 {
3956 APPENDS(X86_Registers[Operand->Register]);
3957 X86_WRITE_OPFLAGS();
3958 }
3959 //DISASM_OUTPUT(("[SetOperand] AMODE_C (control register)\n"));
3960 continue;
3961
3962 case AMODE_D: // modrm.reg = debug register
3963 assert(X86Instruction->HasModRM);
3964 assert(Instruction->Type == ITYPE_MOV);
3965 if (!Decode) continue;
3966 Instruction->NeedsEmulation = TRUE;
3967 Operand->Flags |= OP_REG;
3968 Instruction->Groups |= ITYPE_SYSTEM;
3969 Instruction->NeedsEmulation = TRUE;
3970 if (IS_AMD64()) X86Instruction->OperandSize = 8;
3971 switch (X86Instruction->OperandSize)
3972 {
3973 case 8:
3974 case 4:
3975 case 2:
3976 Operand->Register = X86_DEBUG_OFFSET + rex_modrm.reg;
3977 break;
3978 default:
3979 assert(0);
3980 return NULL;
3981 }
3982
3983 X86_SET_REG(0);
3984 if (Disassemble)
3985 {
3986 APPENDS(X86_Registers[Operand->Register]);
3987 X86_WRITE_OPFLAGS();
3988 }
3989 //DISASM_OUTPUT(("[SetOperand] AMODE_D (debug register)\n"));
3990 continue;
3991
3992 ////////////////////////////////////////////////////////////
3993 // Mod R/M byte with memory or register
3994 ////////////////////////////////////////////////////////////
3995
3996 case AMODE_M: // memory only
3997 assert(X86Instruction->HasModRM);
3998 if (modrm.mod == 3)
3999 {
4000 if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod = 3 for AMODE_M (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
4001 goto abort;
4002 }
4003 assert(X86Instruction->Segment == SEG_DS || X86Instruction->HasSegmentOverridePrefix);
4004 //DISASM_OUTPUT(("[SetOperand] AMODE_M (memory only)\n"));
4005 Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors);
4006 if (!Address) return NULL;
4007 break;
4008
4009 case AMODE_E: // general register or memory
4010 assert(X86Instruction->HasModRM);
4011 if (OperandType == OPTYPE_p && modrm.mod == 3)
4012 {
4013 if (!SuppressErrors) printf("[0x%08I64X] ERROR: mod = 3 for AMODE_E with OPTYPE_p (\"%s\")\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic);
4014 goto abort;
4015 }
4016
4017 //DISASM_OUTPUT(("[SetOperand] AMODE_E (general register or memory)\n"));
4018 Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors);
4019 if (!Address) return NULL;
4020 if (Decode && (Instruction->Type == ITYPE_PUSH || Instruction->Type == ITYPE_POP))
4021 {
4022 assert(X86Instruction->OperandSize >= Operand->Length);
4023 Operand->Length = X86Instruction->OperandSize;
4024 }
4025 break;
4026
4027 case AMODE_Q: // mmx register or memory address
4028 assert(X86Instruction->HasModRM);
4029 //DISASM_OUTPUT(("[SetOperand] AMODE_Q (MMX register or memory address)\n"));
4030 if (modrm.mod == 3) // it is a register
4031 {
4032 if (rex_modrm.rm > 7)
4033 {
4034 if (!SuppressErrors) printf("[0x%08I64X] ERROR: invalid mmx register %d for AMODE_P (\"%s\")\n", VIRTUAL_ADDRESS, rex_modrm.rm, X86Instruction->Opcode.Mnemonic);
4035 goto abort;
4036 }
4037 Operand->Register = X86_MMX_OFFSET + rex_modrm.rm;
4038 Operand->Flags |= OP_REG;
4039 X86_SET_REG(0);
4040 }
4041 else
4042 {
4043 Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors);
4044 if (!Address) return NULL;
4045 }
4046 break;
4047
4048 case AMODE_W: // xmm register or memory address
4049 assert(X86Instruction->HasModRM);
4050 //DISASM_OUTPUT(("[SetOperand] AMODE_W (XMM register or memory address)\n"));
4051 if (modrm.mod == 3) // it is a register
4052 {
4053 Operand->Register = X86_XMM_OFFSET + rex_modrm.rm;
4054 Operand->Flags |= OP_REG;
4055 X86_SET_REG(0);
4056 }
4057 else
4058 {
4059 Address = SetModRM32(Instruction, Address, Operand, OperandIndex, SuppressErrors);
4060 if (!Address) return NULL;
4061 }
4062 break;
4063
4064 default:
4065 assert(0);
4066 return NULL;
4067 }
4068
4069 if (!Decode) continue;
4070
4071 // If this is reached then SetModRM32 was called
4072 if ((Operand->Flags & OP_ADDRESS))
4073 {
4074 assert(Operand->Length);
4075 switch (Operand->Register)
4076 {
4077 case X86_REG_BP:
4078 case X86_REG_EBP:
4079 case AMD64_REG_RBP:
4080 if (X86Instruction->Displacement > 0) Operand->Flags |= OP_PARAM;
4081 else Operand->Flags |= OP_LOCAL;
4082 break;
4083 default:
4084 break;
4085 }
4086 }
4087
4088 if (Disassemble)
4089 {
4090 Index = OperandType >> OPTYPE_SHIFT;
4091 assert(Index > 0 && Index < MAX_OPTYPE_INDEX && OptypeHandlers[Index]);
4092 OptypeHandlers[Index](Instruction, Operand, OperandIndex);
4093 X86_WRITE_OPFLAGS();
4094 }
4095 }
4096
4097 return Address;
4098
4099 abort:
4100 if (!SuppressErrors)
4101 {
4102 #ifdef TEST_DISASM
4103 printf("Dump of 0x%04I64X:\n", VIRTUAL_ADDRESS);
4104 __try { DumpAsBytes(stdout, Instruction->Address, (ULONG_PTR)VIRTUAL_ADDRESS, 16, TRUE); }
4105 __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {}
4106 #endif
4107 fflush(stdout);
4108 }
4109 return NULL;
4110 }
4111
4112 // NOTE: Address points one byte after ModRM
SetModRM16(INSTRUCTION * Instruction,U8 * Address,INSTRUCTION_OPERAND * Operand,U32 OperandIndex,BOOL SuppressErrors)4113 INTERNAL U8 *SetModRM16(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors)
4114 {
4115 MODRM modrm;
4116 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
4117
4118 DISASM_OUTPUT(("[SetModRM16] Current instruction length = %d\n", Instruction->Length));
4119 modrm = X86Instruction->modrm;
4120 assert(!X86Instruction->rex_b);
4121
4122 //
4123 // Both operands are registers
4124 // Condition: mod = 3
4125 //
4126 if (modrm.mod == 3)
4127 {
4128 //DISASM_OUTPUT(("[SetModRM16] Both regs (rm_reg %d)\n", modrm.rm));
4129 switch (Operand->Length)
4130 {
4131 case 4: Operand->Register = X86_32BIT_OFFSET + modrm.rm; break;
4132 case 2: Operand->Register = X86_16BIT_OFFSET + modrm.rm; break;
4133 case 1: Operand->Register = X86_8BIT_OFFSET + modrm.rm; break;
4134 default: assert(0); return NULL;
4135 }
4136 Operand->Flags |= OP_REG;
4137 }
4138
4139 //
4140 // Address is an absolute address (technically a 16-bit offset from DS:0)
4141 // Condition: mod = 0 and rm = 6
4142 //
4143 else if (modrm.mod == 0 && modrm.rm == 6)
4144 {
4145 //DISASM_OUTPUT(("[SetModRM16] Absolute addressing (displacement 0x%04X)\n", *(S16 *)Address));
4146 X86Instruction->Displacement = (S64)(*((S16 *)Address));
4147 if (IS_VALID_ADDRESS(X86Instruction->Displacement))
4148 {
4149 X86Instruction->HasFullDisplacement = TRUE;
4150 X86_SET_TARGET();
4151 Operand->Flags |= OP_GLOBAL;
4152 }
4153 X86_SET_ADDR();
4154 Operand->Flags |= OP_ADDRESS;
4155 INSTR_INC(2);
4156 }
4157
4158 // Conditions:
4159 // (1) mod = 0 and rm != 6
4160 // (2) mod = 1-2 and rm = 0-7
4161 else
4162 {
4163 switch (modrm.mod)
4164 {
4165 case 0: // no displacement
4166 //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (no displacement)\n"));
4167 break;
4168 case 1: // 8-bit signed displacement
4169 //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (displacement = 0x%02X, reg_rm = %d)\n", *(S8 *)Address, modrm.rm));
4170 X86Instruction->Displacement = (S64)(*((S8 *)Address));
4171 INSTR_INC(1); // increment Instruction->Length and address
4172 break;
4173 case 2: // 16-bit displacement
4174 //DISASM_OUTPUT(("[SetModRM16] Indirect addressing (displacement = 0x%04X, reg_rm = %d)\n", *(S16 *)Address, modrm.rm));
4175 X86Instruction->Displacement = (S64)(*((S16 *)Address));
4176 if (IS_VALID_ADDRESS(X86Instruction->Displacement))
4177 {
4178 Operand->Flags |= OP_GLOBAL;
4179 X86Instruction->HasFullDisplacement = TRUE;
4180 }
4181 INSTR_INC(2);
4182 break;
4183 }
4184
4185 switch (modrm.rm)
4186 {
4187 case 0:
4188 //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX+SI]\n"));
4189 X86Instruction->BaseRegister = X86_REG_BX;
4190 X86Instruction->IndexRegister = X86_REG_SI;
4191 X86Instruction->HasIndexRegister = TRUE;
4192 break;
4193 case 1:
4194 //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX+DI]\n"));
4195 X86Instruction->BaseRegister = X86_REG_BX;
4196 X86Instruction->IndexRegister = X86_REG_DI;
4197 X86Instruction->HasIndexRegister = TRUE;
4198 break;
4199 case 2:
4200 //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP+SI]\n"));
4201 X86Instruction->BaseRegister = X86_REG_BP;
4202 X86Instruction->IndexRegister = X86_REG_SI;
4203 X86Instruction->HasIndexRegister = TRUE;
4204 X86_SET_SEG(REG_BP);
4205 break;
4206 case 3:
4207 //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP+DI]\n"));
4208 X86Instruction->BaseRegister = X86_REG_BP;
4209 X86Instruction->IndexRegister = X86_REG_DI;
4210 X86Instruction->HasIndexRegister = TRUE;
4211 X86_SET_SEG(REG_BP);
4212 break;
4213 case 4:
4214 //DISASM_OUTPUT(("[SetModRM16] Addressing mode [SI]\n"));
4215 X86Instruction->BaseRegister = X86_REG_SI;
4216 break;
4217 case 5:
4218 //DISASM_OUTPUT(("[SetModRM16] Addressing mode [DI]\n"));
4219 X86Instruction->BaseRegister = X86_REG_DI;
4220 break;
4221 case 6:
4222 //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BP]\n"));
4223 X86Instruction->BaseRegister = X86_REG_BP;
4224 break;
4225 case 7:
4226 //DISASM_OUTPUT(("[SetModRM16] Addressing mode [BX]\n"));
4227 X86Instruction->BaseRegister = X86_REG_BX;
4228 break;
4229 }
4230
4231 X86Instruction->HasBaseRegister = TRUE;
4232 Operand->Flags |= OP_ADDRESS | OP_REG;
4233 X86_SET_ADDR();
4234 }
4235
4236 return Address;
4237 }
4238
4239 // NOTE: Address points one byte after ModRM
SetModRM32(INSTRUCTION * Instruction,U8 * Address,INSTRUCTION_OPERAND * Operand,U32 OperandIndex,BOOL SuppressErrors)4240 INTERNAL U8 *SetModRM32(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors)
4241 {
4242 MODRM modrm;
4243 REX_MODRM rex_modrm;
4244 U32 i, ImmediateSize = 0;
4245 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
4246
4247 if (X86Instruction->AddressSize == 2)
4248 {
4249 return SetModRM16(Instruction, Address, Operand, OperandIndex, SuppressErrors);
4250 }
4251
4252 //DISASM_OUTPUT(("[SetModRM32] Length %d, modrm = 0x%02X\n", Instruction->Length, X86Instruction->modrm_b));
4253 modrm = X86Instruction->modrm;
4254 rex_modrm = X86Instruction->rex_modrm;
4255
4256 //
4257 // Both operands are registers
4258 // Condition: mod = 3
4259 //
4260 if (modrm.mod == 3)
4261 {
4262 switch (Operand->Length)
4263 {
4264 case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break;
4265 case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break;
4266 case 2: Operand->Register = X86_16BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break;
4267 case 1: Operand->Register = X86_8BIT_OFFSET + rex_modrm.rm; if (X86Instruction->rex_b) CHECK_AMD64_REG(); break;
4268 default: assert(0); return NULL;
4269 }
4270 X86_SET_REG(rex_modrm.rm);
4271 Operand->Flags |= OP_REG;
4272 }
4273
4274 //
4275 // Address is an absolute address (technically a 32-bit offset from DS:0)
4276 // mod = 0 and rm = 5
4277 //
4278 else if (modrm.mod == 0 && modrm.rm == 5)
4279 {
4280 //DISASM_OUTPUT(("[SetModRM32] Absolute addressing (displacement 0x%08lX)\n", *(S32 *)Address));
4281 Operand->Flags |= OP_ADDRESS;
4282 X86Instruction->Displacement = (S64)*((S32 *)Address);
4283 INSTR_INC(4); // increment Instruction->Length and address
4284
4285 if (IS_AMD64())
4286 {
4287 // RIP-relative addressing always replaced Disp32, even when using a 32-bit address space
4288 // (via address size override prefix)
4289 switch (X86Instruction->OperandSize)
4290 {
4291 case 8: Operand->Register = AMD64_REG_RIP; break;
4292 case 4: Operand->Register = X86_REG_EIP; break;
4293 case 2: Operand->Register = X86_REG_IP; break;
4294 default: assert(0); return NULL;
4295 }
4296 X86Instruction->BaseRegister = Operand->Register;
4297 X86Instruction->HasBaseRegister = TRUE;
4298 X86Instruction->Relative = TRUE;
4299 Operand->Flags |= OP_IPREL | OP_SIGNED | OP_REG;
4300 SANITY_CHECK_SEGMENT_OVERRIDE();
4301 if (!X86Instruction->HasSegmentOverridePrefix) X86Instruction->Segment = SEG_CS;
4302 X86Instruction->HasFullDisplacement = TRUE;
4303
4304 // Since there may be an immediate value to follow, it is necessary
4305 // to determine the length in order get the proper offset
4306 //
4307 // Maybe there is a better way to do this, since this is wasteful
4308 // (the size of the immediate value will have to be decoded again later
4309 // in SetOperands)
4310
4311 for (ImmediateSize = 0, i = OperandIndex+1; i < Instruction->OperandCount; i++)
4312 {
4313 if ((X86Instruction->Opcode.OperandFlags[i] & X86_AMODE_MASK) != AMODE_I) continue;
4314 else assert(!ImmediateSize);
4315 switch (X86Instruction->Opcode.OperandFlags[i] & X86_OPTYPE_MASK)
4316 {
4317 case OPTYPE_v:
4318 ImmediateSize = X86Instruction->OperandSize;
4319 break;
4320 case OPTYPE_z:
4321 switch (X86Instruction->OperandSize)
4322 {
4323 case 8: case 4: ImmediateSize = 4; break;
4324 case 2: ImmediateSize = 2; break;
4325 default: assert(0); return NULL;
4326 }
4327 break;
4328 case OPTYPE_b:
4329 ImmediateSize = 1;
4330 break;
4331 case OPTYPE_w:
4332 ImmediateSize = 2;
4333 break;
4334 case OPTYPE_1:
4335 break;
4336 default:
4337 assert(0);
4338 break;
4339 }
4340 }
4341
4342 Operand->TargetAddress = ApplyDisplacement((U64)Address + ImmediateSize, Instruction);
4343 }
4344 else if (IS_VALID_ADDRESS(X86Instruction->Displacement))
4345 {
4346 X86_SET_TARGET();
4347 Operand->Flags |= OP_GLOBAL;
4348 X86Instruction->HasFullDisplacement = TRUE;
4349 }
4350
4351 X86_SET_ADDR();
4352 }
4353
4354 //
4355 // Addressing mode indicated by SIB byte
4356 // Condition: mod = 0-2 and rm = 4
4357 //
4358 else if (modrm.rm == 4)
4359 {
4360 // The X86_SET_*() is called from within SetSIB()
4361 Address = SetSIB(Instruction, Address, Operand, OperandIndex, SuppressErrors);
4362 if (!Address)
4363 {
4364 assert(0);
4365 return NULL;
4366 }
4367
4368 if (X86Instruction->sib.base != 5) // if base == 5, the displacement is handled in SetSIB
4369 {
4370 switch (modrm.mod)
4371 {
4372 case 1: // 8-bit displacement
4373 //DISASM_OUTPUT(("[SetModRM32] After SIB: displacement 0x%02X\n", *((S8 *)Address)));
4374 X86Instruction->Displacement = (S64)(*((S8 *)Address));
4375 INSTR_INC(1); // increment Instruction->Length and address
4376 break;
4377 case 2: // 32-bit displacement
4378 //DISASM_OUTPUT(("[SetModRM32] After SIB: displacement 0x%08lX\n", *((S32 *)Address)));
4379 X86Instruction->Displacement = (S64)*((S32 *)Address);
4380 if (IS_VALID_ADDRESS(X86Instruction->Displacement))
4381 {
4382 Operand->Flags |= OP_GLOBAL;
4383 X86Instruction->HasFullDisplacement = TRUE;
4384 }
4385 INSTR_INC(4); // increment Instruction->Length and address
4386 break;
4387 }
4388 }
4389 }
4390
4391 // Indirect addressing
4392 // Conditions:
4393 // (1) mod = 0 and (rm = 0-3 or 6-7)
4394 // (2) mod = 1-2 and rm != 4
4395 else
4396 {
4397 switch (X86Instruction->AddressSize)
4398 {
4399 case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_modrm.rm; break;
4400 case 4: Operand->Register = X86_32BIT_OFFSET + rex_modrm.rm; CHECK_AMD64_REG(); break;
4401 default: assert(0); return NULL;
4402 }
4403 X86Instruction->BaseRegister = Operand->Register;
4404 X86Instruction->HasBaseRegister = TRUE;
4405 Operand->Flags |= OP_ADDRESS | OP_REG;
4406 X86_SET_SEG(rex_modrm.rm);
4407 X86_SET_ADDR();
4408
4409 switch (modrm.mod)
4410 {
4411 case 0: // no displacement
4412 //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (no displacement, reg_rm = %d)\n", rex_modrm.rm));
4413 break;
4414 case 1: // 8-bit signed displacement
4415 //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (displacement = 0x%02X, reg_rm = %d)\n", *(S8 *)Address, rex_modrm.rm));
4416 X86Instruction->Displacement = (S64)(*((S8 *)Address));
4417 INSTR_INC(1); // increment Instruction->Length and address
4418 break;
4419 case 2: // 32-bit displacement
4420 //DISASM_OUTPUT(("[SetModRM32] Indirect addressing (displacement = 0x%08lX, reg_rm = %d)\n", *(S32 *)Address, rex_modrm.rm));
4421 X86Instruction->Displacement = (S64)*((S32 *)Address);
4422 if (IS_VALID_ADDRESS(X86Instruction->Displacement))
4423 {
4424 Operand->Flags |= OP_GLOBAL;
4425 X86Instruction->HasFullDisplacement = TRUE;
4426 }
4427 INSTR_INC(4); // increment Instruction->Length and address
4428 break;
4429 }
4430 }
4431
4432 return Address;
4433 }
4434
4435 // NOTE: Address points at SIB
SetSIB(INSTRUCTION * Instruction,U8 * Address,INSTRUCTION_OPERAND * Operand,U32 OperandIndex,BOOL SuppressErrors)4436 INTERNAL U8 *SetSIB(INSTRUCTION *Instruction, U8 *Address, INSTRUCTION_OPERAND *Operand, U32 OperandIndex, BOOL SuppressErrors)
4437 {
4438 REX rex;
4439 SIB sib;
4440 REX_SIB rex_sib;
4441 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
4442
4443 X86Instruction->sib_b = *Address;
4444 SET_SIB(X86Instruction->sib, *Address);
4445 sib = X86Instruction->sib;
4446 rex = X86Instruction->rex;
4447 SET_REX_SIB(X86Instruction->rex_sib, rex, sib);
4448 rex_sib = X86Instruction->rex_sib;
4449
4450 //if (!X86Instruction->rex_b) DISASM_OUTPUT(("[0x%08I64X] SIB = 0x%02X (scale=%d, index=%d, base=%d)\n", VIRTUAL_ADDRESS, *Address, sib.scale, sib.index, sib.base)); \
4451 //else DISASM_OUTPUT(("[0x%08I64X] SIB = 0x%02X (scale=%d, index=%d, base=%d)\n", VIRTUAL_ADDRESS, *Address, sib.scale, rex_sib.index, rex_sib.base)); \
4452 //DISASM_OUTPUT(("[SetSIB] Current instruction length = %d\n", Instruction->Length));
4453
4454 Operand->Flags |= OP_ADDRESS;
4455 X86_SET_ADDR();
4456 INSTR_INC(1); // increment Instruction->Length and address
4457
4458 if (sib.base == 5)
4459 {
4460 switch (X86Instruction->modrm.mod)
4461 {
4462 case 0:
4463 X86Instruction->Displacement = (S64)*((S32 *)Address);
4464 if (IS_VALID_ADDRESS(X86Instruction->Displacement))
4465 {
4466 X86Instruction->HasFullDisplacement = TRUE;
4467 X86_SET_TARGET();
4468 Operand->Flags |= OP_GLOBAL;
4469 }
4470 INSTR_INC(4);
4471 break;
4472 case 1:
4473 X86Instruction->Displacement = (S64)(*((S8 *)Address));
4474 if (rex_sib.base == 5)
4475 {
4476 switch (X86Instruction->AddressSize)
4477 {
4478 case 8: Operand->Register = AMD64_REG_RBP; break;
4479 case 4: Operand->Register = X86_REG_EBP; break;
4480 default: assert(0); return NULL;
4481 }
4482 X86_SET_SEG(REG_EBP);
4483 }
4484 else
4485 {
4486 Operand->Register = AMD64_REG_R13;
4487 }
4488
4489 X86Instruction->BaseRegister = Operand->Register;
4490 X86Instruction->HasBaseRegister = TRUE;
4491 Operand->Flags |= OP_REG;
4492 INSTR_INC(1);
4493 break;
4494 case 2:
4495 X86Instruction->Displacement = (S64)*((S32 *)Address);
4496 if (rex_sib.base == 5)
4497 {
4498 switch (X86Instruction->AddressSize)
4499 {
4500 case 8: Operand->Register = AMD64_REG_RBP; break;
4501 case 4: Operand->Register = X86_REG_EBP; break;
4502 default: assert(0); return NULL;
4503 }
4504 X86_SET_SEG(REG_EBP);
4505 }
4506 else
4507 {
4508 Operand->Register = AMD64_REG_R13;
4509 }
4510
4511 if (IS_VALID_ADDRESS(X86Instruction->Displacement))
4512 {
4513 Operand->Flags |= OP_GLOBAL;
4514 X86Instruction->HasFullDisplacement = TRUE;
4515 }
4516 X86Instruction->BaseRegister = Operand->Register;
4517 X86Instruction->HasBaseRegister = TRUE;
4518 Operand->Flags |= OP_REG;
4519 INSTR_INC(4);
4520 break;
4521 }
4522 }
4523 else
4524 {
4525 switch (X86Instruction->AddressSize)
4526 {
4527 case 8: Operand->Register = AMD64_64BIT_OFFSET + rex_sib.base; break;
4528 case 4: Operand->Register = X86_32BIT_OFFSET + rex_sib.base; CHECK_AMD64_REG(); break;
4529 default: assert(0); return NULL;
4530 }
4531 X86Instruction->BaseRegister = Operand->Register;
4532 X86Instruction->HasBaseRegister = TRUE;
4533 X86_SET_SEG(rex_sib.base);
4534 Operand->Flags |= OP_REG;
4535 }
4536
4537 if (rex_sib.index != 4)
4538 {
4539 switch (X86Instruction->AddressSize)
4540 {
4541 case 8:
4542 X86Instruction->IndexRegister = AMD64_64BIT_OFFSET + rex_sib.index;
4543 break;
4544 case 4:
4545 X86Instruction->IndexRegister = X86_32BIT_OFFSET + rex_sib.index;
4546 break;
4547 default:
4548 fflush(stdout);
4549 assert(0);
4550 return NULL;
4551 }
4552
4553 Operand->TargetAddress = 0;
4554 X86Instruction->HasIndexRegister = TRUE;
4555 //DISASM_OUTPUT(("[SetSIB] Index register = %s\n", X86_Registers[X86_32BIT_OFFSET + rex_sib.index]));
4556
4557 switch (sib.scale)
4558 {
4559 case 0: X86Instruction->Scale = 1; break;
4560 case 1: X86Instruction->Scale = 2; break;
4561 case 2: X86Instruction->Scale = 4; break;
4562 case 3: X86Instruction->Scale = 8; break;
4563 }
4564 //DISASM_OUTPUT(("[SetSIB] Scale = %d\n", X86Instruction->Scale));
4565 }
4566
4567 return Address;
4568 }
4569
ApplyDisplacement(U64 Address,INSTRUCTION * Instruction)4570 INTERNAL U64 ApplyDisplacement(U64 Address, INSTRUCTION *Instruction)
4571 {
4572 X86_INSTRUCTION *X86Instruction = &Instruction->X86;
4573
4574 #ifdef SUPPORT_WRAPAROUND
4575 U64 VirtualAddress = Address + Instruction->VirtualAddressDelta;
4576 switch (X86Instruction->OperandSize)
4577 {
4578 case 8:
4579 {
4580 U64 PreAddr = VirtualAddress;
4581 U64 PostAddr = PreAddr + X86Instruction->Displacement;
4582 return Address + (PostAddr - PreAddr);
4583 }
4584 case 4:
4585 {
4586 // We have to do this carefully...
4587 // If EIP = FFFFF000 and Displacement=2000 then the final IP should be 1000
4588 // due to wraparound
4589 U32 PreAddr = (U32)VirtualAddress;
4590 U32 PostAddr = PreAddr + (S32)X86Instruction->Displacement;
4591 return Address + (PostAddr - PreAddr);
4592 }
4593 case 2:
4594 {
4595 // We have to do this carefully...
4596 // If IP = F000 and Displacement=2000 then the final IP should be 1000
4597 // due to wraparound
4598 U16 PreAddr = (U16)VirtualAddress;
4599 U16 PostAddr = PreAddr + (S16)X86Instruction->Displacement;
4600 return Address + (PostAddr - PreAddr);
4601 }
4602 default:
4603 assert(0);
4604 return 0;
4605 }
4606 #else
4607 return (Address + X86Instruction->Displacement);
4608 #endif
4609 }
4610
4611
4612
IsValidLockPrefix(X86_INSTRUCTION * X86Instruction,U8 Opcode,U32 OpcodeLength,U8 Group,U8 OpcodeExtension)4613 INTERNAL BOOL IsValidLockPrefix(X86_INSTRUCTION *X86Instruction, U8 Opcode, U32 OpcodeLength, U8 Group, U8 OpcodeExtension)
4614 {
4615 switch (OpcodeLength)
4616 {
4617 case 1:
4618 switch (X86_LockPrefix_1[Opcode])
4619 {
4620 case 0: // instruction can't be locked
4621 return FALSE;
4622 case 1: // instruction can be locked
4623 break;
4624 case GR:
4625 assert(Group);
4626 if (!X86_LockPrefix_Groups[Group-1][OpcodeExtension]) return FALSE;
4627 break;
4628 default:
4629 assert(0);
4630 return FALSE;
4631 }
4632 break;
4633
4634 case 2:
4635 case 3:
4636 switch (X86_LockPrefix_2[Opcode])
4637 {
4638 case 0: // lock prefix is not acceptable
4639 return FALSE;
4640 case 1: // lock prefix allowed
4641 break;
4642 case GR:
4643 assert(Group);
4644 if (!X86_LockPrefix_Groups[Group-1][OpcodeExtension]) return FALSE;
4645 break;
4646 default:
4647 assert(0);
4648 return FALSE;
4649 }
4650 break;
4651
4652 default:
4653 assert(0);
4654 return FALSE;
4655 }
4656
4657 if (!X86Instruction->HasModRM || X86Instruction->modrm.mod == 3 || !X86Instruction->HasDstAddressing)
4658 {
4659 DISASM_OUTPUT(("[0x%08I64X] ERROR: Instruction \"%s\" with LOCK prefix has invalid ModRM addressing\n", VIRTUAL_ADDRESS, X86Instruction->Opcode.Mnemonic, X86Instruction->Instruction->Address));
4660 return FALSE;
4661 }
4662
4663 return TRUE;
4664 }
4665