OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/disassembler.h" | 5 #include "vm/disassembler.h" |
6 | 6 |
7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. | 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
8 #if defined(TARGET_ARCH_IA32) | 8 #if defined(TARGET_ARCH_IA32) |
9 #include "platform/utils.h" | 9 #include "platform/utils.h" |
10 #include "vm/allocation.h" | 10 #include "vm/allocation.h" |
11 #include "vm/heap.h" | 11 #include "vm/heap.h" |
12 #include "vm/os.h" | 12 #include "vm/os.h" |
13 #include "vm/stack_frame.h" | 13 #include "vm/stack_frame.h" |
14 #include "vm/stub_code.h" | 14 #include "vm/stub_code.h" |
15 | 15 |
16 namespace dart { | 16 namespace dart { |
17 | 17 |
18 #ifndef PRODUCT | 18 #ifndef PRODUCT |
19 | 19 |
20 // Tables used for decoding of x86 instructions. | 20 // Tables used for decoding of x86 instructions. |
21 enum OperandOrder { | 21 enum OperandOrder { UNSET_OP_ORDER = 0, REG_OPER_OP_ORDER, OPER_REG_OP_ORDER }; |
22 UNSET_OP_ORDER = 0, | |
23 REG_OPER_OP_ORDER, | |
24 OPER_REG_OP_ORDER | |
25 }; | |
26 | 22 |
27 | 23 |
28 struct ByteMnemonic { | 24 struct ByteMnemonic { |
29 int b; // -1 terminates, otherwise must be in range (0..255) | 25 int b; // -1 terminates, otherwise must be in range (0..255) |
30 const char* mnem; | 26 const char* mnem; |
31 OperandOrder op_order_; | 27 OperandOrder op_order_; |
32 }; | 28 }; |
33 | 29 |
34 | 30 |
35 static ByteMnemonic two_operands_instr[] = { | 31 static ByteMnemonic two_operands_instr[] = { |
36 {0x01, "add", OPER_REG_OP_ORDER}, | 32 {0x01, "add", OPER_REG_OP_ORDER}, {0x03, "add", REG_OPER_OP_ORDER}, |
37 {0x03, "add", REG_OPER_OP_ORDER}, | 33 {0x09, "or", OPER_REG_OP_ORDER}, {0x0B, "or", REG_OPER_OP_ORDER}, |
38 {0x09, "or", OPER_REG_OP_ORDER}, | 34 {0x11, "adc", OPER_REG_OP_ORDER}, {0x13, "adc", REG_OPER_OP_ORDER}, |
39 {0x0B, "or", REG_OPER_OP_ORDER}, | 35 {0x19, "sbb", OPER_REG_OP_ORDER}, {0x1B, "sbb", REG_OPER_OP_ORDER}, |
40 {0x11, "adc", OPER_REG_OP_ORDER}, | 36 {0x21, "and", OPER_REG_OP_ORDER}, {0x23, "and", REG_OPER_OP_ORDER}, |
41 {0x13, "adc", REG_OPER_OP_ORDER}, | 37 {0x29, "sub", OPER_REG_OP_ORDER}, {0x2B, "sub", REG_OPER_OP_ORDER}, |
42 {0x19, "sbb", OPER_REG_OP_ORDER}, | 38 {0x31, "xor", OPER_REG_OP_ORDER}, {0x33, "xor", REG_OPER_OP_ORDER}, |
43 {0x1B, "sbb", REG_OPER_OP_ORDER}, | 39 {0x39, "cmp", OPER_REG_OP_ORDER}, {0x3B, "cmp", REG_OPER_OP_ORDER}, |
44 {0x21, "and", OPER_REG_OP_ORDER}, | 40 {0x85, "test", REG_OPER_OP_ORDER}, {0x87, "xchg", REG_OPER_OP_ORDER}, |
45 {0x23, "and", REG_OPER_OP_ORDER}, | 41 {0x8A, "mov_b", REG_OPER_OP_ORDER}, {0x8B, "mov", REG_OPER_OP_ORDER}, |
46 {0x29, "sub", OPER_REG_OP_ORDER}, | 42 {0x8D, "lea", REG_OPER_OP_ORDER}, {-1, "", UNSET_OP_ORDER}}; |
47 {0x2B, "sub", REG_OPER_OP_ORDER}, | |
48 {0x31, "xor", OPER_REG_OP_ORDER}, | |
49 {0x33, "xor", REG_OPER_OP_ORDER}, | |
50 {0x39, "cmp", OPER_REG_OP_ORDER}, | |
51 {0x3B, "cmp", REG_OPER_OP_ORDER}, | |
52 {0x85, "test", REG_OPER_OP_ORDER}, | |
53 {0x87, "xchg", REG_OPER_OP_ORDER}, | |
54 {0x8A, "mov_b", REG_OPER_OP_ORDER}, | |
55 {0x8B, "mov", REG_OPER_OP_ORDER}, | |
56 {0x8D, "lea", REG_OPER_OP_ORDER}, | |
57 {-1, "", UNSET_OP_ORDER} | |
58 }; | |
59 | 43 |
60 | 44 |
61 static ByteMnemonic zero_operands_instr[] = { | 45 static ByteMnemonic zero_operands_instr[] = { |
62 {0xC3, "ret", UNSET_OP_ORDER}, | 46 {0xC3, "ret", UNSET_OP_ORDER}, {0xC9, "leave", UNSET_OP_ORDER}, |
63 {0xC9, "leave", UNSET_OP_ORDER}, | 47 {0x90, "nop", UNSET_OP_ORDER}, {0xF4, "hlt", UNSET_OP_ORDER}, |
64 {0x90, "nop", UNSET_OP_ORDER}, | 48 {0xCC, "int3", UNSET_OP_ORDER}, {0x60, "pushad", UNSET_OP_ORDER}, |
65 {0xF4, "hlt", UNSET_OP_ORDER}, | 49 {0x61, "popad", UNSET_OP_ORDER}, {0x9C, "pushfd", UNSET_OP_ORDER}, |
66 {0xCC, "int3", UNSET_OP_ORDER}, | 50 {0x9D, "popfd", UNSET_OP_ORDER}, {0x9E, "sahf", UNSET_OP_ORDER}, |
67 {0x60, "pushad", UNSET_OP_ORDER}, | 51 {0x99, "cdq", UNSET_OP_ORDER}, {0x9B, "fwait", UNSET_OP_ORDER}, |
68 {0x61, "popad", UNSET_OP_ORDER}, | 52 {-1, "", UNSET_OP_ORDER}}; |
69 {0x9C, "pushfd", UNSET_OP_ORDER}, | |
70 {0x9D, "popfd", UNSET_OP_ORDER}, | |
71 {0x9E, "sahf", UNSET_OP_ORDER}, | |
72 {0x99, "cdq", UNSET_OP_ORDER}, | |
73 {0x9B, "fwait", UNSET_OP_ORDER}, | |
74 {-1, "", UNSET_OP_ORDER} | |
75 }; | |
76 | 53 |
77 | 54 |
78 static ByteMnemonic call_jump_instr[] = { | 55 static ByteMnemonic call_jump_instr[] = {{0xE8, "call", UNSET_OP_ORDER}, |
79 {0xE8, "call", UNSET_OP_ORDER}, | 56 {0xE9, "jmp", UNSET_OP_ORDER}, |
80 {0xE9, "jmp", UNSET_OP_ORDER}, | 57 {-1, "", UNSET_OP_ORDER}}; |
81 {-1, "", UNSET_OP_ORDER} | |
82 }; | |
83 | 58 |
84 | 59 |
85 static ByteMnemonic short_immediate_instr[] = { | 60 static ByteMnemonic short_immediate_instr[] = { |
86 {0x05, "add", UNSET_OP_ORDER}, | 61 {0x05, "add", UNSET_OP_ORDER}, {0x0D, "or", UNSET_OP_ORDER}, |
87 {0x0D, "or", UNSET_OP_ORDER}, | 62 {0x15, "adc", UNSET_OP_ORDER}, {0x25, "and", UNSET_OP_ORDER}, |
88 {0x15, "adc", UNSET_OP_ORDER}, | 63 {0x2D, "sub", UNSET_OP_ORDER}, {0x35, "xor", UNSET_OP_ORDER}, |
89 {0x25, "and", UNSET_OP_ORDER}, | 64 {0x3D, "cmp", UNSET_OP_ORDER}, {-1, "", UNSET_OP_ORDER}}; |
90 {0x2D, "sub", UNSET_OP_ORDER}, | |
91 {0x35, "xor", UNSET_OP_ORDER}, | |
92 {0x3D, "cmp", UNSET_OP_ORDER}, | |
93 {-1, "", UNSET_OP_ORDER} | |
94 }; | |
95 | 65 |
96 | 66 |
97 static const char* jump_conditional_mnem[] = { | 67 static const char* jump_conditional_mnem[] = { |
98 /*0*/ "jo", "jno", "jc", "jnc", | 68 /*0*/ "jo", "jno", "jc", "jnc", |
99 /*4*/ "jz", "jnz", "jna", "ja", | 69 /*4*/ "jz", "jnz", "jna", "ja", |
100 /*8*/ "js", "jns", "jpe", "jpo", | 70 /*8*/ "js", "jns", "jpe", "jpo", |
101 /*12*/ "jl", "jnl", "jng", "jg" | 71 /*12*/ "jl", "jnl", "jng", "jg"}; |
102 }; | |
103 | 72 |
104 | 73 |
105 static const char* set_conditional_mnem[] = { | 74 static const char* set_conditional_mnem[] = { |
106 /*0*/ "seto", "setno", "setc", "setnc", | 75 /*0*/ "seto", "setno", "setc", "setnc", |
107 /*4*/ "setz", "setnz", "setna", "seta", | 76 /*4*/ "setz", "setnz", "setna", "seta", |
108 /*8*/ "sets", "setns", "setpe", "setpo", | 77 /*8*/ "sets", "setns", "setpe", "setpo", |
109 /*12*/ "setl", "setnl", "setng", "setg" | 78 /*12*/ "setl", "setnl", "setng", "setg"}; |
110 }; | |
111 | 79 |
112 | 80 |
113 static const char* conditional_move_mnem[] = { | 81 static const char* conditional_move_mnem[] = { |
114 /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", | 82 /*0*/ "cmovo", "cmovno", "cmovc", "cmovnc", |
115 /*4*/ "cmovz", "cmovnz", "cmovna", "cmova", | 83 /*4*/ "cmovz", "cmovnz", "cmovna", "cmova", |
116 /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", | 84 /*8*/ "cmovs", "cmovns", "cmovpe", "cmovpo", |
117 /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg" | 85 /*12*/ "cmovl", "cmovnl", "cmovng", "cmovg"}; |
118 }; | |
119 | 86 |
120 | 87 |
121 enum InstructionType { | 88 enum InstructionType { |
122 NO_INSTR, | 89 NO_INSTR, |
123 ZERO_OPERANDS_INSTR, | 90 ZERO_OPERANDS_INSTR, |
124 TWO_OPERANDS_INSTR, | 91 TWO_OPERANDS_INSTR, |
125 JUMP_CONDITIONAL_SHORT_INSTR, | 92 JUMP_CONDITIONAL_SHORT_INSTR, |
126 REGISTER_INSTR, | 93 REGISTER_INSTR, |
127 MOVE_REG_INSTR, | 94 MOVE_REG_INSTR, |
128 CALL_JUMP_INSTR, | 95 CALL_JUMP_INSTR, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 } | 188 } |
222 | 189 |
223 | 190 |
224 static InstructionTable instruction_table; | 191 static InstructionTable instruction_table; |
225 | 192 |
226 | 193 |
227 // Mnemonics for instructions 0xF0 byte. | 194 // Mnemonics for instructions 0xF0 byte. |
228 // Returns NULL if the instruction is not handled here. | 195 // Returns NULL if the instruction is not handled here. |
229 static const char* F0Mnem(uint8_t f0byte) { | 196 static const char* F0Mnem(uint8_t f0byte) { |
230 switch (f0byte) { | 197 switch (f0byte) { |
231 case 0x12: return "movhlps"; | 198 case 0x12: |
232 case 0x14: return "unpcklps"; | 199 return "movhlps"; |
233 case 0x15: return "unpckhps"; | 200 case 0x14: |
234 case 0x16: return "movlhps"; | 201 return "unpcklps"; |
235 case 0xA2: return "cpuid"; | 202 case 0x15: |
236 case 0x31: return "rdtsc"; | 203 return "unpckhps"; |
237 case 0xBE: return "movsx_b"; | 204 case 0x16: |
238 case 0xBF: return "movsx_w"; | 205 return "movlhps"; |
239 case 0xB6: return "movzx_b"; | 206 case 0xA2: |
240 case 0xB7: return "movzx_w"; | 207 return "cpuid"; |
241 case 0xAF: return "imul"; | 208 case 0x31: |
| 209 return "rdtsc"; |
| 210 case 0xBE: |
| 211 return "movsx_b"; |
| 212 case 0xBF: |
| 213 return "movsx_w"; |
| 214 case 0xB6: |
| 215 return "movzx_b"; |
| 216 case 0xB7: |
| 217 return "movzx_w"; |
| 218 case 0xAF: |
| 219 return "imul"; |
242 case 0xA4: // Fall through. | 220 case 0xA4: // Fall through. |
243 case 0xA5: return "shld"; | 221 case 0xA5: |
| 222 return "shld"; |
244 case 0xAC: // Fall through. | 223 case 0xAC: // Fall through. |
245 case 0xAD: return "shrd"; | 224 case 0xAD: |
246 case 0xA3: return "bt"; | 225 return "shrd"; |
247 case 0xAB: return "bts"; | 226 case 0xA3: |
248 case 0xBD: return "bsr"; | 227 return "bt"; |
249 case 0xB1: return "cmpxchg"; | 228 case 0xAB: |
250 case 0x50: return "movmskps"; | 229 return "bts"; |
251 case 0x51: return "sqrtps"; | 230 case 0xBD: |
252 case 0x52: return "rqstps"; | 231 return "bsr"; |
253 case 0x53: return "rcpps"; | 232 case 0xB1: |
254 case 0x54: return "andps"; | 233 return "cmpxchg"; |
255 case 0x56: return "orps"; | 234 case 0x50: |
256 case 0x57: return "xorps"; | 235 return "movmskps"; |
257 case 0x58: return "addps"; | 236 case 0x51: |
258 case 0x59: return "mulps"; | 237 return "sqrtps"; |
259 case 0x5A: return "cvtps2pd"; | 238 case 0x52: |
260 case 0x5C: return "subps"; | 239 return "rqstps"; |
261 case 0x5D: return "minps"; | 240 case 0x53: |
262 case 0x5E: return "divps"; | 241 return "rcpps"; |
263 case 0x5F: return "maxps"; | 242 case 0x54: |
264 case 0x28: return "movaps"; | 243 return "andps"; |
265 case 0x10: return "movups"; | 244 case 0x56: |
266 case 0x11: return "movups"; | 245 return "orps"; |
267 default: return NULL; | 246 case 0x57: |
| 247 return "xorps"; |
| 248 case 0x58: |
| 249 return "addps"; |
| 250 case 0x59: |
| 251 return "mulps"; |
| 252 case 0x5A: |
| 253 return "cvtps2pd"; |
| 254 case 0x5C: |
| 255 return "subps"; |
| 256 case 0x5D: |
| 257 return "minps"; |
| 258 case 0x5E: |
| 259 return "divps"; |
| 260 case 0x5F: |
| 261 return "maxps"; |
| 262 case 0x28: |
| 263 return "movaps"; |
| 264 case 0x10: |
| 265 return "movups"; |
| 266 case 0x11: |
| 267 return "movups"; |
| 268 default: |
| 269 return NULL; |
268 } | 270 } |
269 } | 271 } |
270 | 272 |
271 static const char* PackedDoubleMnemonic(uint8_t data) { | 273 static const char* PackedDoubleMnemonic(uint8_t data) { |
272 const char* mnemonic = NULL; | 274 const char* mnemonic = NULL; |
273 if (data == 0xFE) mnemonic = "paddd "; | 275 if (data == 0xFE) mnemonic = "paddd "; |
274 if (data == 0xFA) mnemonic = "psubd "; | 276 if (data == 0xFA) mnemonic = "psubd "; |
275 if (data == 0x2F) mnemonic = "comisd "; | 277 if (data == 0x2F) mnemonic = "comisd "; |
276 if (data == 0x58) mnemonic = "addpd "; | 278 if (data == 0x58) mnemonic = "addpd "; |
277 if (data == 0x5C) mnemonic = "subpd "; | 279 if (data == 0x5C) mnemonic = "subpd "; |
278 if (data == 0x59) mnemonic = "mulpd "; | 280 if (data == 0x59) mnemonic = "mulpd "; |
279 if (data == 0x5E) mnemonic = "divpd "; | 281 if (data == 0x5E) mnemonic = "divpd "; |
280 if (data == 0x5D) mnemonic = "minpd "; | 282 if (data == 0x5D) mnemonic = "minpd "; |
281 if (data == 0x5F) mnemonic = "maxpd "; | 283 if (data == 0x5F) mnemonic = "maxpd "; |
282 if (data == 0x51) mnemonic = "sqrtpd "; | 284 if (data == 0x51) mnemonic = "sqrtpd "; |
283 if (data == 0x5A) mnemonic = "cvtpd2ps "; | 285 if (data == 0x5A) mnemonic = "cvtpd2ps "; |
284 ASSERT(mnemonic != NULL); | 286 ASSERT(mnemonic != NULL); |
285 return mnemonic; | 287 return mnemonic; |
286 } | 288 } |
287 | 289 |
288 | 290 |
289 static bool IsTwoXmmRegInstruction(uint8_t f0byte) { | 291 static bool IsTwoXmmRegInstruction(uint8_t f0byte) { |
290 return f0byte == 0x28 || f0byte == 0x11 || f0byte == 0x12 || | 292 return f0byte == 0x28 || f0byte == 0x11 || f0byte == 0x12 || f0byte == 0x14 || |
291 f0byte == 0x14 || f0byte == 0x15 || f0byte == 0x16 || | 293 f0byte == 0x15 || f0byte == 0x16 || f0byte == 0x51 || f0byte == 0x52 || |
292 f0byte == 0x51 || f0byte == 0x52 || f0byte == 0x53 || | 294 f0byte == 0x53 || f0byte == 0x54 || f0byte == 0x56 || f0byte == 0x58 || |
293 f0byte == 0x54 || f0byte == 0x56 || f0byte == 0x58 || | 295 f0byte == 0x59 || f0byte == 0x5C || f0byte == 0x5D || f0byte == 0x5E || |
294 f0byte == 0x59 || f0byte == 0x5C || f0byte == 0x5D || | 296 f0byte == 0x5F || f0byte == 0x5A; |
295 f0byte == 0x5E || f0byte == 0x5F || f0byte == 0x5A; | |
296 } | 297 } |
297 | 298 |
298 | 299 |
299 // The implementation of x86 decoding based on the above tables. | 300 // The implementation of x86 decoding based on the above tables. |
300 class X86Decoder : public ValueObject { | 301 class X86Decoder : public ValueObject { |
301 public: | 302 public: |
302 X86Decoder(char* buffer, intptr_t buffer_size) | 303 X86Decoder(char* buffer, intptr_t buffer_size) |
303 : buffer_(buffer), | 304 : buffer_(buffer), buffer_size_(buffer_size), buffer_pos_(0) { |
304 buffer_size_(buffer_size), | |
305 buffer_pos_(0) { | |
306 buffer_[buffer_pos_] = '\0'; | 305 buffer_[buffer_pos_] = '\0'; |
307 } | 306 } |
308 | 307 |
309 ~X86Decoder() {} | 308 ~X86Decoder() {} |
310 | 309 |
311 // Writes one disassembled instruction into the buffer (0-terminated). | 310 // Writes one disassembled instruction into the buffer (0-terminated). |
312 // Returns the length of the disassembled machine instruction in bytes. | 311 // Returns the length of the disassembled machine instruction in bytes. |
313 int InstructionDecode(uword pc); | 312 int InstructionDecode(uword pc); |
314 | 313 |
315 private: | 314 private: |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 *index = (data >> 3) & 7; | 378 *index = (data >> 3) & 7; |
380 *base = data & 7; | 379 *base = data & 7; |
381 } | 380 } |
382 | 381 |
383 | 382 |
384 // Convenience functions. | 383 // Convenience functions. |
385 char* get_buffer() const { return buffer_; } | 384 char* get_buffer() const { return buffer_; } |
386 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } | 385 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } |
387 intptr_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } | 386 intptr_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } |
388 | 387 |
389 char* buffer_; // Decode instructions into this buffer. | 388 char* buffer_; // Decode instructions into this buffer. |
390 intptr_t buffer_size_; // The size of the buffer_. | 389 intptr_t buffer_size_; // The size of the buffer_. |
391 intptr_t buffer_pos_; // Current character position in the buffer_. | 390 intptr_t buffer_pos_; // Current character position in the buffer_. |
392 | 391 |
393 DISALLOW_COPY_AND_ASSIGN(X86Decoder); | 392 DISALLOW_COPY_AND_ASSIGN(X86Decoder); |
394 }; | 393 }; |
395 | 394 |
396 | 395 |
397 void X86Decoder::PrintInt(int value) { | 396 void X86Decoder::PrintInt(int value) { |
398 char int_buffer[16]; | 397 char int_buffer[16]; |
399 OS::SNPrint(int_buffer, sizeof(int_buffer), "%#x", value); | 398 OS::SNPrint(int_buffer, sizeof(int_buffer), "%#x", value); |
400 Print(int_buffer); | 399 Print(int_buffer); |
401 } | 400 } |
(...skipping 12 matching lines...) Expand all Loading... |
414 char cur = *str++; | 413 char cur = *str++; |
415 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) { | 414 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) { |
416 buffer_[buffer_pos_++] = cur; | 415 buffer_[buffer_pos_++] = cur; |
417 cur = *str++; | 416 cur = *str++; |
418 } | 417 } |
419 buffer_[buffer_pos_] = '\0'; | 418 buffer_[buffer_pos_] = '\0'; |
420 } | 419 } |
421 | 420 |
422 | 421 |
423 static const int kMaxCPURegisters = 8; | 422 static const int kMaxCPURegisters = 8; |
424 static const char* cpu_regs[kMaxCPURegisters] = { | 423 static const char* cpu_regs[kMaxCPURegisters] = {"eax", "ecx", "edx", "ebx", |
425 "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" | 424 "esp", "ebp", "esi", "edi"}; |
426 }; | |
427 | 425 |
428 static const int kMaxByteCPURegisters = 8; | 426 static const int kMaxByteCPURegisters = 8; |
429 static const char* byte_cpu_regs[kMaxByteCPURegisters] = { | 427 static const char* byte_cpu_regs[kMaxByteCPURegisters] = { |
430 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh" | 428 "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh"}; |
431 }; | |
432 | 429 |
433 static const int kMaxXmmRegisters = 8; | 430 static const int kMaxXmmRegisters = 8; |
434 static const char* xmm_regs[kMaxXmmRegisters] = { | 431 static const char* xmm_regs[kMaxXmmRegisters] = { |
435 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7" | 432 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7"}; |
436 }; | |
437 | 433 |
438 void X86Decoder::PrintCPURegister(int reg) { | 434 void X86Decoder::PrintCPURegister(int reg) { |
439 ASSERT(0 <= reg); | 435 ASSERT(0 <= reg); |
440 ASSERT(reg < kMaxCPURegisters); | 436 ASSERT(reg < kMaxCPURegisters); |
441 Print(cpu_regs[reg]); | 437 Print(cpu_regs[reg]); |
442 } | 438 } |
443 | 439 |
444 | 440 |
445 void X86Decoder::PrintCPUByteRegister(int reg) { | 441 void X86Decoder::PrintCPUByteRegister(int reg) { |
446 ASSERT(0 <= reg); | 442 ASSERT(0 <= reg); |
447 ASSERT(reg < kMaxByteCPURegisters); | 443 ASSERT(reg < kMaxByteCPURegisters); |
448 Print(byte_cpu_regs[reg]); | 444 Print(byte_cpu_regs[reg]); |
449 } | 445 } |
450 | 446 |
451 | 447 |
452 void X86Decoder::PrintXmmRegister(int reg) { | 448 void X86Decoder::PrintXmmRegister(int reg) { |
453 ASSERT(0 <= reg); | 449 ASSERT(0 <= reg); |
454 ASSERT(reg < kMaxXmmRegisters); | 450 ASSERT(reg < kMaxXmmRegisters); |
455 Print(xmm_regs[reg]); | 451 Print(xmm_regs[reg]); |
456 } | 452 } |
457 | 453 |
458 void X86Decoder::PrintXmmComparison(int comparison) { | 454 void X86Decoder::PrintXmmComparison(int comparison) { |
459 ASSERT(0 <= comparison); | 455 ASSERT(0 <= comparison); |
460 ASSERT(comparison < 8); | 456 ASSERT(comparison < 8); |
461 static const char* comparisons[8] = { | 457 static const char* comparisons[8] = { |
462 "eq", "lt", "le", "unordered", "not eq", "not lt", "not le", "ordered" | 458 "eq", "lt", "le", "unordered", "not eq", "not lt", "not le", "ordered"}; |
463 }; | |
464 Print(comparisons[comparison]); | 459 Print(comparisons[comparison]); |
465 } | 460 } |
466 | 461 |
467 | 462 |
468 void X86Decoder::PrintAddress(uword addr) { | 463 void X86Decoder::PrintAddress(uword addr) { |
469 char addr_buffer[32]; | 464 char addr_buffer[32]; |
470 OS::SNPrint(addr_buffer, sizeof(addr_buffer), "%#" Px "", addr); | 465 OS::SNPrint(addr_buffer, sizeof(addr_buffer), "%#" Px "", addr); |
471 Print(addr_buffer); | 466 Print(addr_buffer); |
472 | 467 |
473 // Try to print as stub name. | 468 // Try to print as stub name. |
474 const char* name_of_stub = StubCode::NameOfStub(addr); | 469 const char* name_of_stub = StubCode::NameOfStub(addr); |
475 if (name_of_stub != NULL) { | 470 if (name_of_stub != NULL) { |
476 Print(" [stub: "); | 471 Print(" [stub: "); |
477 Print(name_of_stub); | 472 Print(name_of_stub); |
478 Print("]"); | 473 Print("]"); |
479 } | 474 } |
480 } | 475 } |
481 | 476 |
482 | 477 |
483 int X86Decoder::PrintRightOperandHelper(uint8_t* modrmp, | 478 int X86Decoder::PrintRightOperandHelper(uint8_t* modrmp, |
484 RegisterNamePrinter register_printer) { | 479 RegisterNamePrinter register_printer) { |
485 int mod, regop, rm; | 480 int mod, regop, rm; |
486 GetModRm(*modrmp, &mod, ®op, &rm); | 481 GetModRm(*modrmp, &mod, ®op, &rm); |
487 switch (mod) { | 482 switch (mod) { |
488 case 0: | 483 case 0: |
489 if (rm == ebp) { | 484 if (rm == ebp) { |
490 int32_t disp = *reinterpret_cast<int32_t*>(modrmp+1); | 485 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 1); |
491 Print("["); | 486 Print("["); |
492 PrintHex(disp); | 487 PrintHex(disp); |
493 Print("]"); | 488 Print("]"); |
494 return 5; | 489 return 5; |
495 } else if (rm == esp) { | 490 } else if (rm == esp) { |
496 uint8_t sib = *(modrmp + 1); | 491 uint8_t sib = *(modrmp + 1); |
497 int scale, index, base; | 492 int scale, index, base; |
498 GetSib(sib, &scale, &index, &base); | 493 GetSib(sib, &scale, &index, &base); |
499 if (index == esp && base == esp && scale == 0 /*times_1*/) { | 494 if (index == esp && base == esp && scale == 0 /*times_1*/) { |
500 Print("["); | 495 Print("["); |
501 PrintCPURegister(rm); | 496 PrintCPURegister(rm); |
502 Print("]"); | 497 Print("]"); |
503 return 2; | 498 return 2; |
504 } else if (base == ebp) { | 499 } else if (base == ebp) { |
505 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); | 500 int32_t disp = *reinterpret_cast<int32_t*>(modrmp + 2); |
506 Print("["); | 501 Print("["); |
507 PrintCPURegister(index); | 502 PrintCPURegister(index); |
508 Print("*"); | 503 Print("*"); |
509 PrintInt(1 << scale); | 504 PrintInt(1 << scale); |
510 if (disp < 0) { | 505 if (disp < 0) { |
511 Print("-"); | 506 Print("-"); |
512 disp = -disp; | 507 disp = -disp; |
513 } else { | 508 } else { |
514 Print("+"); | 509 Print("+"); |
515 } | 510 } |
516 PrintHex(disp); | 511 PrintHex(disp); |
517 Print("]"); | 512 Print("]"); |
518 return 6; | 513 return 6; |
519 } else if (index != esp && base != ebp) { | 514 } else if (index != esp && base != ebp) { |
520 // [base+index*scale] | 515 // [base+index*scale] |
521 Print("["); | 516 Print("["); |
522 PrintCPURegister(base); | 517 PrintCPURegister(base); |
523 Print("+"); | 518 Print("+"); |
524 PrintCPURegister(index); | 519 PrintCPURegister(index); |
525 Print("*"); | 520 Print("*"); |
526 PrintInt(1 << scale); | 521 PrintInt(1 << scale); |
527 Print("]"); | 522 Print("]"); |
528 return 2; | 523 return 2; |
529 } else { | 524 } else { |
530 UNIMPLEMENTED(); | 525 UNIMPLEMENTED(); |
531 return 1; | 526 return 1; |
532 } | 527 } |
533 } else { | 528 } else { |
534 Print("["); | 529 Print("["); |
535 PrintCPURegister(rm); | 530 PrintCPURegister(rm); |
536 Print("]"); | 531 Print("]"); |
537 return 1; | 532 return 1; |
538 } | 533 } |
539 break; | 534 break; |
540 case 1: // fall through | 535 case 1: // fall through |
541 case 2: | 536 case 2: |
542 if (rm == esp) { | 537 if (rm == esp) { |
543 uint8_t sib = *(modrmp + 1); | 538 uint8_t sib = *(modrmp + 1); |
544 int scale, index, base; | 539 int scale, index, base; |
545 GetSib(sib, &scale, &index, &base); | 540 GetSib(sib, &scale, &index, &base); |
546 int disp = (mod == 2) ? | 541 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 2) |
547 *reinterpret_cast<int32_t*>(modrmp + 2) : | 542 : *reinterpret_cast<int8_t*>(modrmp + 2); |
548 *reinterpret_cast<int8_t*>(modrmp + 2); | |
549 if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) { | 543 if (index == base && index == rm /*esp*/ && scale == 0 /*times_1*/) { |
550 Print("["); | 544 Print("["); |
551 PrintCPURegister(rm); | 545 PrintCPURegister(rm); |
552 if (disp < 0) { | 546 if (disp < 0) { |
553 Print("-"); | 547 Print("-"); |
554 disp = -disp; | 548 disp = -disp; |
555 } else { | 549 } else { |
556 Print("+"); | 550 Print("+"); |
557 } | 551 } |
558 PrintHex(disp); | 552 PrintHex(disp); |
(...skipping 10 matching lines...) Expand all Loading... |
569 disp = -disp; | 563 disp = -disp; |
570 } else { | 564 } else { |
571 Print("+"); | 565 Print("+"); |
572 } | 566 } |
573 PrintHex(disp); | 567 PrintHex(disp); |
574 Print("]"); | 568 Print("]"); |
575 } | 569 } |
576 return mod == 2 ? 6 : 3; | 570 return mod == 2 ? 6 : 3; |
577 } else { | 571 } else { |
578 // No sib. | 572 // No sib. |
579 int disp = (mod == 2) ? | 573 int disp = (mod == 2) ? *reinterpret_cast<int32_t*>(modrmp + 1) |
580 *reinterpret_cast<int32_t*>(modrmp + 1) : | 574 : *reinterpret_cast<int8_t*>(modrmp + 1); |
581 *reinterpret_cast<int8_t*>(modrmp + 1); | |
582 Print("["); | 575 Print("["); |
583 PrintCPURegister(rm); | 576 PrintCPURegister(rm); |
584 if (disp < 0) { | 577 if (disp < 0) { |
585 Print("-"); | 578 Print("-"); |
586 disp = -disp; | 579 disp = -disp; |
587 } else { | 580 } else { |
588 Print("+"); | 581 Print("+"); |
589 } | 582 } |
590 PrintHex(disp); | 583 PrintHex(disp); |
591 Print("]"); | 584 Print("]"); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 default: | 638 default: |
646 UNREACHABLE(); | 639 UNREACHABLE(); |
647 break; | 640 break; |
648 } | 641 } |
649 return advance; | 642 return advance; |
650 } | 643 } |
651 | 644 |
652 | 645 |
653 int X86Decoder::PrintImmediateOp(uint8_t* data, bool size_override) { | 646 int X86Decoder::PrintImmediateOp(uint8_t* data, bool size_override) { |
654 bool sign_extension_bit = (*data & 0x02) != 0; | 647 bool sign_extension_bit = (*data & 0x02) != 0; |
655 uint8_t modrm = *(data+1); | 648 uint8_t modrm = *(data + 1); |
656 int mod, regop, rm; | 649 int mod, regop, rm; |
657 GetModRm(modrm, &mod, ®op, &rm); | 650 GetModRm(modrm, &mod, ®op, &rm); |
658 const char* mnem = "Imm???"; | 651 const char* mnem = "Imm???"; |
659 switch (regop) { | 652 switch (regop) { |
660 case 0: mnem = "add"; break; | 653 case 0: |
661 case 1: mnem = "or"; break; | 654 mnem = "add"; |
662 case 2: mnem = "adc"; break; | 655 break; |
663 case 3: mnem = "sbb"; break; | 656 case 1: |
664 case 4: mnem = "and"; break; | 657 mnem = "or"; |
665 case 5: mnem = "sub"; break; | 658 break; |
666 case 6: mnem = "xor"; break; | 659 case 2: |
667 case 7: mnem = "cmp"; break; | 660 mnem = "adc"; |
668 default: UNIMPLEMENTED(); | 661 break; |
| 662 case 3: |
| 663 mnem = "sbb"; |
| 664 break; |
| 665 case 4: |
| 666 mnem = "and"; |
| 667 break; |
| 668 case 5: |
| 669 mnem = "sub"; |
| 670 break; |
| 671 case 6: |
| 672 mnem = "xor"; |
| 673 break; |
| 674 case 7: |
| 675 mnem = "cmp"; |
| 676 break; |
| 677 default: |
| 678 UNIMPLEMENTED(); |
669 } | 679 } |
670 Print(mnem); | 680 Print(mnem); |
671 Print(" "); | 681 Print(" "); |
672 int count = PrintRightOperand(data+1); | 682 int count = PrintRightOperand(data + 1); |
673 Print(","); | 683 Print(","); |
674 if (size_override) { | 684 if (size_override) { |
675 PrintHex(*reinterpret_cast<int16_t*>(data + 1 + count)); | 685 PrintHex(*reinterpret_cast<int16_t*>(data + 1 + count)); |
676 return 1 + count + 2 /*int16_t*/; | 686 return 1 + count + 2 /*int16_t*/; |
677 } else if (sign_extension_bit) { | 687 } else if (sign_extension_bit) { |
678 PrintHex(*(data + 1 + count)); | 688 PrintHex(*(data + 1 + count)); |
679 return 1 + count + 1 /*int8_t*/; | 689 return 1 + count + 1 /*int8_t*/; |
680 } else { | 690 } else { |
681 PrintHex(*reinterpret_cast<int32_t*>(data + 1 + count)); | 691 PrintHex(*reinterpret_cast<int32_t*>(data + 1 + count)); |
682 return 1 + count + 4 /*int32_t*/; | 692 return 1 + count + 4 /*int32_t*/; |
683 } | 693 } |
684 } | 694 } |
685 | 695 |
686 | 696 |
687 int X86Decoder::DecodeEnter(uint8_t* data) { | 697 int X86Decoder::DecodeEnter(uint8_t* data) { |
688 uint16_t size = *reinterpret_cast<uint16_t*>(data + 1); | 698 uint16_t size = *reinterpret_cast<uint16_t*>(data + 1); |
689 uint8_t level = *reinterpret_cast<uint8_t*>(data + 3); | 699 uint8_t level = *reinterpret_cast<uint8_t*>(data + 3); |
690 Print("enter "); | 700 Print("enter "); |
691 PrintInt(size); | 701 PrintInt(size); |
692 Print(", "); | 702 Print(", "); |
693 PrintInt(level); | 703 PrintInt(level); |
694 return 4; | 704 return 4; |
695 } | 705 } |
696 | 706 |
697 | 707 |
698 // Returns number of bytes used, including *data. | 708 // Returns number of bytes used, including *data. |
699 int X86Decoder::JumpShort(uint8_t* data) { | 709 int X86Decoder::JumpShort(uint8_t* data) { |
700 ASSERT(*data == 0xEB); | 710 ASSERT(*data == 0xEB); |
701 uint8_t b = *(data+1); | 711 uint8_t b = *(data + 1); |
702 uword dest = reinterpret_cast<uword>(data) + static_cast<int8_t>(b) + 2; | 712 uword dest = reinterpret_cast<uword>(data) + static_cast<int8_t>(b) + 2; |
703 Print("jmp "); | 713 Print("jmp "); |
704 PrintAddress(dest); | 714 PrintAddress(dest); |
705 return 2; | 715 return 2; |
706 } | 716 } |
707 | 717 |
708 | 718 |
709 // Returns number of bytes used, including *data. | 719 // Returns number of bytes used, including *data. |
710 int X86Decoder::JumpConditional(uint8_t* data, const char* comment) { | 720 int X86Decoder::JumpConditional(uint8_t* data, const char* comment) { |
711 ASSERT(*data == 0x0F); | 721 ASSERT(*data == 0x0F); |
712 uint8_t cond = *(data+1) & 0x0F; | 722 uint8_t cond = *(data + 1) & 0x0F; |
713 uword dest = reinterpret_cast<uword>(data) + | 723 uword dest = |
714 *reinterpret_cast<int32_t*>(data+2) + 6; | 724 reinterpret_cast<uword>(data) + *reinterpret_cast<int32_t*>(data + 2) + 6; |
715 const char* mnem = jump_conditional_mnem[cond]; | 725 const char* mnem = jump_conditional_mnem[cond]; |
716 Print(mnem); | 726 Print(mnem); |
717 Print(" "); | 727 Print(" "); |
718 PrintAddress(dest); | 728 PrintAddress(dest); |
719 if (comment != NULL) { | 729 if (comment != NULL) { |
720 Print(", "); | 730 Print(", "); |
721 Print(comment); | 731 Print(comment); |
722 } | 732 } |
723 return 6; // includes 0x0F | 733 return 6; // includes 0x0F |
724 } | 734 } |
725 | 735 |
726 | 736 |
727 // Returns number of bytes used, including *data. | 737 // Returns number of bytes used, including *data. |
728 int X86Decoder::JumpConditionalShort(uint8_t* data, const char* comment) { | 738 int X86Decoder::JumpConditionalShort(uint8_t* data, const char* comment) { |
729 uint8_t cond = *data & 0x0F; | 739 uint8_t cond = *data & 0x0F; |
730 uint8_t b = *(data+1); | 740 uint8_t b = *(data + 1); |
731 uword dest = reinterpret_cast<uword>(data) + static_cast<int8_t>(b) + 2; | 741 uword dest = reinterpret_cast<uword>(data) + static_cast<int8_t>(b) + 2; |
732 const char* mnem = jump_conditional_mnem[cond]; | 742 const char* mnem = jump_conditional_mnem[cond]; |
733 Print(mnem); | 743 Print(mnem); |
734 Print(" "); | 744 Print(" "); |
735 PrintAddress(dest); | 745 PrintAddress(dest); |
736 if (comment != NULL) { | 746 if (comment != NULL) { |
737 Print(", "); | 747 Print(", "); |
738 Print(comment); | 748 Print(comment); |
739 } | 749 } |
740 return 2; | 750 return 2; |
741 } | 751 } |
742 | 752 |
743 | 753 |
744 // Returns number of bytes used, including *data. | 754 // Returns number of bytes used, including *data. |
745 int X86Decoder::SetCC(uint8_t* data) { | 755 int X86Decoder::SetCC(uint8_t* data) { |
746 ASSERT(*data == 0x0F); | 756 ASSERT(*data == 0x0F); |
747 uint8_t cond = *(data+1) & 0x0F; | 757 uint8_t cond = *(data + 1) & 0x0F; |
748 const char* mnem = set_conditional_mnem[cond]; | 758 const char* mnem = set_conditional_mnem[cond]; |
749 Print(mnem); | 759 Print(mnem); |
750 Print(" "); | 760 Print(" "); |
751 PrintRightByteOperand(data+2); | 761 PrintRightByteOperand(data + 2); |
752 return 3; // includes 0x0F | 762 return 3; // includes 0x0F |
753 } | 763 } |
754 | 764 |
755 | 765 |
756 // Returns number of bytes used, including *data. | 766 // Returns number of bytes used, including *data. |
757 int X86Decoder::CMov(uint8_t* data) { | 767 int X86Decoder::CMov(uint8_t* data) { |
758 ASSERT(*data == 0x0F); | 768 ASSERT(*data == 0x0F); |
759 uint8_t cond = *(data + 1) & 0x0F; | 769 uint8_t cond = *(data + 1) & 0x0F; |
760 const char* mnem = conditional_move_mnem[cond]; | 770 const char* mnem = conditional_move_mnem[cond]; |
761 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); | 771 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); |
762 return 2 + op_size; // includes 0x0F | 772 return 2 + op_size; // includes 0x0F |
763 } | 773 } |
764 | 774 |
765 | 775 |
766 int X86Decoder::D1D3C1Instruction(uint8_t* data) { | 776 int X86Decoder::D1D3C1Instruction(uint8_t* data) { |
767 uint8_t op = *data; | 777 uint8_t op = *data; |
768 ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1); | 778 ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1); |
769 int mod, regop, rm; | 779 int mod, regop, rm; |
770 GetModRm(*(data+1), &mod, ®op, &rm); | 780 GetModRm(*(data + 1), &mod, ®op, &rm); |
771 int num_bytes = 1; | 781 int num_bytes = 1; |
772 const char* mnem = NULL; | 782 const char* mnem = NULL; |
773 switch (regop) { | 783 switch (regop) { |
774 case 2: mnem = "rcl"; break; | 784 case 2: |
775 case 4: mnem = "shl"; break; | 785 mnem = "rcl"; |
776 case 5: mnem = "shr"; break; | 786 break; |
777 case 7: mnem = "sar"; break; | 787 case 4: |
778 default: UNIMPLEMENTED(); | 788 mnem = "shl"; |
| 789 break; |
| 790 case 5: |
| 791 mnem = "shr"; |
| 792 break; |
| 793 case 7: |
| 794 mnem = "sar"; |
| 795 break; |
| 796 default: |
| 797 UNIMPLEMENTED(); |
779 } | 798 } |
780 ASSERT(mnem != NULL); | 799 ASSERT(mnem != NULL); |
781 Print(mnem); | 800 Print(mnem); |
782 Print(" "); | 801 Print(" "); |
783 | 802 |
784 if (op == 0xD1) { | 803 if (op == 0xD1) { |
785 num_bytes += PrintRightOperand(data+1); | 804 num_bytes += PrintRightOperand(data + 1); |
786 Print(", 1"); | 805 Print(", 1"); |
787 } else if (op == 0xC1) { | 806 } else if (op == 0xC1) { |
788 num_bytes += PrintRightOperand(data+1); | 807 num_bytes += PrintRightOperand(data + 1); |
789 Print(", "); | 808 Print(", "); |
790 PrintInt(*(data+2)); | 809 PrintInt(*(data + 2)); |
791 num_bytes++; | 810 num_bytes++; |
792 } else { | 811 } else { |
793 ASSERT(op == 0xD3); | 812 ASSERT(op == 0xD3); |
794 num_bytes += PrintRightOperand(data+1); | 813 num_bytes += PrintRightOperand(data + 1); |
795 Print(", cl"); | 814 Print(", cl"); |
796 } | 815 } |
797 return num_bytes; | 816 return num_bytes; |
798 } | 817 } |
799 | 818 |
800 | 819 |
801 uint8_t* X86Decoder::F3Instruction(uint8_t* data) { | 820 uint8_t* X86Decoder::F3Instruction(uint8_t* data) { |
802 if (*(data+1) == 0x0F) { | 821 if (*(data + 1) == 0x0F) { |
803 uint8_t b2 = *(data+2); | 822 uint8_t b2 = *(data + 2); |
804 switch (b2) { | 823 switch (b2) { |
805 case 0x2C: { | 824 case 0x2C: { |
806 data += 3; | 825 data += 3; |
807 data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data); | 826 data += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, data); |
808 break; | 827 break; |
809 } | 828 } |
810 case 0x2A: { | 829 case 0x2A: { |
811 data += 3; | 830 data += 3; |
812 int mod, regop, rm; | 831 int mod, regop, rm; |
813 GetModRm(*data, &mod, ®op, &rm); | 832 GetModRm(*data, &mod, ®op, &rm); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
854 case 0x59: // Fall through. | 873 case 0x59: // Fall through. |
855 case 0x5A: // Fall through. | 874 case 0x5A: // Fall through. |
856 case 0x5C: // Fall through. | 875 case 0x5C: // Fall through. |
857 case 0x5E: // Fall through. | 876 case 0x5E: // Fall through. |
858 case 0xE6: { | 877 case 0xE6: { |
859 data += 3; | 878 data += 3; |
860 int mod, regop, rm; | 879 int mod, regop, rm; |
861 GetModRm(*data, &mod, ®op, &rm); | 880 GetModRm(*data, &mod, ®op, &rm); |
862 const char* mnem = "?? 0xF3"; | 881 const char* mnem = "?? 0xF3"; |
863 switch (b2) { | 882 switch (b2) { |
864 case 0x51: mnem = "sqrtss"; break; | 883 case 0x51: |
865 case 0x58: mnem = "addss"; break; | 884 mnem = "sqrtss"; |
866 case 0x59: mnem = "mulss"; break; | 885 break; |
867 case 0x5A: mnem = "cvtss2sd"; break; | 886 case 0x58: |
868 case 0x5C: mnem = "subss"; break; | 887 mnem = "addss"; |
869 case 0x5E: mnem = "divss"; break; | 888 break; |
870 case 0xE6: mnem = "cvtdq2pd"; break; | 889 case 0x59: |
871 default: UNIMPLEMENTED(); | 890 mnem = "mulss"; |
| 891 break; |
| 892 case 0x5A: |
| 893 mnem = "cvtss2sd"; |
| 894 break; |
| 895 case 0x5C: |
| 896 mnem = "subss"; |
| 897 break; |
| 898 case 0x5E: |
| 899 mnem = "divss"; |
| 900 break; |
| 901 case 0xE6: |
| 902 mnem = "cvtdq2pd"; |
| 903 break; |
| 904 default: |
| 905 UNIMPLEMENTED(); |
872 } | 906 } |
873 Print(mnem); | 907 Print(mnem); |
874 Print(" "); | 908 Print(" "); |
875 PrintXmmRegister(regop); | 909 PrintXmmRegister(regop); |
876 Print(","); | 910 Print(","); |
877 data += PrintRightXmmOperand(data); | 911 data += PrintRightXmmOperand(data); |
878 break; | 912 break; |
879 } | 913 } |
880 case 0x7E: { | 914 case 0x7E: { |
881 data += 3; | 915 data += 3; |
882 int mod, regop, rm; | 916 int mod, regop, rm; |
883 GetModRm(*data, &mod, ®op, &rm); | 917 GetModRm(*data, &mod, ®op, &rm); |
884 Print("movq "); | 918 Print("movq "); |
885 PrintXmmRegister(regop); | 919 PrintXmmRegister(regop); |
886 Print(","); | 920 Print(","); |
887 data += PrintRightOperand(data); | 921 data += PrintRightOperand(data); |
888 break; | 922 break; |
889 } | 923 } |
890 default: | 924 default: |
891 UNIMPLEMENTED(); | 925 UNIMPLEMENTED(); |
892 } | 926 } |
893 } else if (*(data+1) == 0xA4) { | 927 } else if (*(data + 1) == 0xA4) { |
894 Print("rep_movsb"); | 928 Print("rep_movsb"); |
895 data += 2; | 929 data += 2; |
896 } else { | 930 } else { |
897 UNIMPLEMENTED(); | 931 UNIMPLEMENTED(); |
898 } | 932 } |
899 return data; | 933 return data; |
900 } | 934 } |
901 | 935 |
902 | 936 |
903 // Returns number of bytes used, including *data. | 937 // Returns number of bytes used, including *data. |
904 int X86Decoder::F7Instruction(uint8_t* data) { | 938 int X86Decoder::F7Instruction(uint8_t* data) { |
905 ASSERT(*data == 0xF7); | 939 ASSERT(*data == 0xF7); |
906 uint8_t modrm = *(data+1); | 940 uint8_t modrm = *(data + 1); |
907 int mod, regop, rm; | 941 int mod, regop, rm; |
908 GetModRm(modrm, &mod, ®op, &rm); | 942 GetModRm(modrm, &mod, ®op, &rm); |
909 if (mod == 3 && regop != 0) { | 943 if (mod == 3 && regop != 0) { |
910 const char* mnem = NULL; | 944 const char* mnem = NULL; |
911 switch (regop) { | 945 switch (regop) { |
912 case 2: mnem = "not"; break; | 946 case 2: |
913 case 3: mnem = "neg"; break; | 947 mnem = "not"; |
914 case 4: mnem = "mul"; break; | 948 break; |
915 case 5: mnem = "imul"; break; | 949 case 3: |
916 case 6: mnem = "div"; break; | 950 mnem = "neg"; |
917 case 7: mnem = "idiv"; break; | 951 break; |
918 default: UNIMPLEMENTED(); | 952 case 4: |
| 953 mnem = "mul"; |
| 954 break; |
| 955 case 5: |
| 956 mnem = "imul"; |
| 957 break; |
| 958 case 6: |
| 959 mnem = "div"; |
| 960 break; |
| 961 case 7: |
| 962 mnem = "idiv"; |
| 963 break; |
| 964 default: |
| 965 UNIMPLEMENTED(); |
919 } | 966 } |
920 Print(mnem); | 967 Print(mnem); |
921 Print(" "); | 968 Print(" "); |
922 PrintCPURegister(rm); | 969 PrintCPURegister(rm); |
923 return 2; | 970 return 2; |
924 } else if (mod == 3 && regop == eax) { | 971 } else if (mod == 3 && regop == eax) { |
925 int32_t imm = *reinterpret_cast<int32_t*>(data+2); | 972 int32_t imm = *reinterpret_cast<int32_t*>(data + 2); |
926 Print("test "); | 973 Print("test "); |
927 PrintCPURegister(rm); | 974 PrintCPURegister(rm); |
928 Print(","); | 975 Print(","); |
929 PrintHex(imm); | 976 PrintHex(imm); |
930 return 6; | 977 return 6; |
931 } else if (regop == eax) { | 978 } else if (regop == eax) { |
932 Print("test "); | 979 Print("test "); |
933 int count = PrintRightOperand(data+1); | 980 int count = PrintRightOperand(data + 1); |
934 int32_t imm = *reinterpret_cast<int32_t*>(data+1+count); | 981 int32_t imm = *reinterpret_cast<int32_t*>(data + 1 + count); |
935 Print(","); | 982 Print(","); |
936 PrintHex(imm); | 983 PrintHex(imm); |
937 return 1+count+4 /*int32_t*/; | 984 return 1 + count + 4 /*int32_t*/; |
938 } else if (regop == 5) { | 985 } else if (regop == 5) { |
939 Print("imul "); | 986 Print("imul "); |
940 int count = PrintRightOperand(data + 1); | 987 int count = PrintRightOperand(data + 1); |
941 return 1 + count; | 988 return 1 + count; |
942 } else if (regop == 4) { | 989 } else if (regop == 4) { |
943 Print("mul "); | 990 Print("mul "); |
944 int count = PrintRightOperand(data + 1); | 991 int count = PrintRightOperand(data + 1); |
945 return 1 + count; | 992 return 1 + count; |
946 } else { | 993 } else { |
947 OS::Print("F7 Instr regop %d\n", regop); | 994 OS::Print("F7 Instr regop %d\n", regop); |
948 UNIMPLEMENTED(); | 995 UNIMPLEMENTED(); |
949 return 2; | 996 return 2; |
950 } | 997 } |
951 } | 998 } |
952 | 999 |
953 // Returns number of bytes used, including *data. | 1000 // Returns number of bytes used, including *data. |
954 int X86Decoder::FPUInstruction(uint8_t* data) { | 1001 int X86Decoder::FPUInstruction(uint8_t* data) { |
955 uint8_t b1 = *data; | 1002 uint8_t b1 = *data; |
956 uint8_t b2 = *(data + 1); | 1003 uint8_t b2 = *(data + 1); |
957 if (b1 == 0xD9) { | 1004 if (b1 == 0xD9) { |
958 const char* mnem = NULL; | 1005 const char* mnem = NULL; |
959 switch (b2) { | 1006 switch (b2) { |
960 case 0xE0: mnem = "fchs"; break; | 1007 case 0xE0: |
961 case 0xE1: mnem = "fabs"; break; | 1008 mnem = "fchs"; |
962 case 0xE4: mnem = "ftst"; break; | 1009 break; |
963 case 0xE8: mnem = "fld1"; break; | 1010 case 0xE1: |
964 case 0xEE: mnem = "fldz"; break; | 1011 mnem = "fabs"; |
965 case 0xF2: mnem = "fptan"; break; | 1012 break; |
966 case 0xF5: mnem = "fprem1"; break; | 1013 case 0xE4: |
967 case 0xF8: mnem = "fprem"; break; | 1014 mnem = "ftst"; |
968 case 0xF7: mnem = "fincstp"; break; | 1015 break; |
969 case 0xFB: mnem = "fsincos"; break; | 1016 case 0xE8: |
970 case 0xFE: mnem = "fsin"; break; | 1017 mnem = "fld1"; |
971 case 0xFF: mnem = "fcos"; break; | 1018 break; |
| 1019 case 0xEE: |
| 1020 mnem = "fldz"; |
| 1021 break; |
| 1022 case 0xF2: |
| 1023 mnem = "fptan"; |
| 1024 break; |
| 1025 case 0xF5: |
| 1026 mnem = "fprem1"; |
| 1027 break; |
| 1028 case 0xF8: |
| 1029 mnem = "fprem"; |
| 1030 break; |
| 1031 case 0xF7: |
| 1032 mnem = "fincstp"; |
| 1033 break; |
| 1034 case 0xFB: |
| 1035 mnem = "fsincos"; |
| 1036 break; |
| 1037 case 0xFE: |
| 1038 mnem = "fsin"; |
| 1039 break; |
| 1040 case 0xFF: |
| 1041 mnem = "fcos"; |
| 1042 break; |
972 } | 1043 } |
973 if (mnem != NULL) { | 1044 if (mnem != NULL) { |
974 Print(mnem); | 1045 Print(mnem); |
975 return 2; | 1046 return 2; |
976 } else if ((b2 & 0xF8) == 0xC8) { | 1047 } else if ((b2 & 0xF8) == 0xC8) { |
977 Print("fxch st"); | 1048 Print("fxch st"); |
978 PrintInt(b2 & 0x7); | 1049 PrintInt(b2 & 0x7); |
979 return 2; | 1050 return 2; |
980 } else { | 1051 } else { |
981 int mod, regop, rm; | 1052 int mod, regop, rm; |
982 GetModRm(*(data+1), &mod, ®op, &rm); | 1053 GetModRm(*(data + 1), &mod, ®op, &rm); |
983 const char* mnem = "? FPU 0xD9"; | 1054 const char* mnem = "? FPU 0xD9"; |
984 switch (regop) { | 1055 switch (regop) { |
985 case 0: mnem = "fld_s"; break; | 1056 case 0: |
986 case 3: mnem = "fstp_s"; break; | 1057 mnem = "fld_s"; |
987 case 5: mnem = "fldcw"; break; | 1058 break; |
988 case 7: mnem = "fnstcw"; break; | 1059 case 3: |
989 default: UNIMPLEMENTED(); | 1060 mnem = "fstp_s"; |
| 1061 break; |
| 1062 case 5: |
| 1063 mnem = "fldcw"; |
| 1064 break; |
| 1065 case 7: |
| 1066 mnem = "fnstcw"; |
| 1067 break; |
| 1068 default: |
| 1069 UNIMPLEMENTED(); |
990 } | 1070 } |
991 Print(mnem); | 1071 Print(mnem); |
992 Print(" "); | 1072 Print(" "); |
993 int count = PrintRightOperand(data + 1); | 1073 int count = PrintRightOperand(data + 1); |
994 return count + 1; | 1074 return count + 1; |
995 } | 1075 } |
996 } else if (b1 == 0xDD) { | 1076 } else if (b1 == 0xDD) { |
997 if ((b2 & 0xF8) == 0xC0) { | 1077 if ((b2 & 0xF8) == 0xC0) { |
998 Print("ffree st"); | 1078 Print("ffree st"); |
999 PrintInt(b2 & 0x7); | 1079 PrintInt(b2 & 0x7); |
1000 return 2; | 1080 return 2; |
1001 } else { | 1081 } else { |
1002 int mod, regop, rm; | 1082 int mod, regop, rm; |
1003 GetModRm(*(data+1), &mod, ®op, &rm); | 1083 GetModRm(*(data + 1), &mod, ®op, &rm); |
1004 const char* mnem = "? FPU 0xDD"; | 1084 const char* mnem = "? FPU 0xDD"; |
1005 switch (regop) { | 1085 switch (regop) { |
1006 case 0: mnem = "fld_d"; break; | 1086 case 0: |
1007 case 3: mnem = "fstp_d"; break; | 1087 mnem = "fld_d"; |
1008 default: UNIMPLEMENTED(); | 1088 break; |
| 1089 case 3: |
| 1090 mnem = "fstp_d"; |
| 1091 break; |
| 1092 default: |
| 1093 UNIMPLEMENTED(); |
1009 } | 1094 } |
1010 Print(mnem); | 1095 Print(mnem); |
1011 Print(" "); | 1096 Print(" "); |
1012 int count = PrintRightOperand(data + 1); | 1097 int count = PrintRightOperand(data + 1); |
1013 return count + 1; | 1098 return count + 1; |
1014 } | 1099 } |
1015 } else if (b1 == 0xDB) { | 1100 } else if (b1 == 0xDB) { |
1016 int mod, regop, rm; | 1101 int mod, regop, rm; |
1017 GetModRm(*(data+1), &mod, ®op, &rm); | 1102 GetModRm(*(data + 1), &mod, ®op, &rm); |
1018 const char* mnem = "? FPU 0xDB"; | 1103 const char* mnem = "? FPU 0xDB"; |
1019 switch (regop) { | 1104 switch (regop) { |
1020 case 0: mnem = "fild_s"; break; | 1105 case 0: |
1021 case 2: mnem = "fist_s"; break; | 1106 mnem = "fild_s"; |
1022 case 3: mnem = "fistp_s"; break; | 1107 break; |
1023 default: UNIMPLEMENTED(); | 1108 case 2: |
| 1109 mnem = "fist_s"; |
| 1110 break; |
| 1111 case 3: |
| 1112 mnem = "fistp_s"; |
| 1113 break; |
| 1114 default: |
| 1115 UNIMPLEMENTED(); |
1024 } | 1116 } |
1025 Print(mnem); | 1117 Print(mnem); |
1026 Print(" "); | 1118 Print(" "); |
1027 int count = PrintRightOperand(data + 1); | 1119 int count = PrintRightOperand(data + 1); |
1028 return count + 1; | 1120 return count + 1; |
1029 } else if (b1 == 0xDF) { | 1121 } else if (b1 == 0xDF) { |
1030 if (b2 == 0xE0) { | 1122 if (b2 == 0xE0) { |
1031 Print("fnstsw_ax"); | 1123 Print("fnstsw_ax"); |
1032 return 2; | 1124 return 2; |
1033 } | 1125 } |
1034 int mod, regop, rm; | 1126 int mod, regop, rm; |
1035 GetModRm(*(data+1), &mod, ®op, &rm); | 1127 GetModRm(*(data + 1), &mod, ®op, &rm); |
1036 const char* mnem = "? FPU 0xDF"; | 1128 const char* mnem = "? FPU 0xDF"; |
1037 switch (regop) { | 1129 switch (regop) { |
1038 case 5: mnem = "fild_d"; break; | 1130 case 5: |
1039 case 7: mnem = "fistp_d"; break; | 1131 mnem = "fild_d"; |
1040 default: UNIMPLEMENTED(); | 1132 break; |
| 1133 case 7: |
| 1134 mnem = "fistp_d"; |
| 1135 break; |
| 1136 default: |
| 1137 UNIMPLEMENTED(); |
1041 } | 1138 } |
1042 Print(mnem); | 1139 Print(mnem); |
1043 Print(" "); | 1140 Print(" "); |
1044 int count = PrintRightOperand(data + 1); | 1141 int count = PrintRightOperand(data + 1); |
1045 return count + 1; | 1142 return count + 1; |
1046 } else if (b1 == 0xDC || b1 == 0xDE) { | 1143 } else if (b1 == 0xDC || b1 == 0xDE) { |
1047 bool is_pop = (b1 == 0xDE); | 1144 bool is_pop = (b1 == 0xDE); |
1048 if (is_pop && b2 == 0xD9) { | 1145 if (is_pop && b2 == 0xD9) { |
1049 Print("fcompp"); | 1146 Print("fcompp"); |
1050 return 2; | 1147 return 2; |
1051 } | 1148 } |
1052 const char* mnem = "FP0xDC"; | 1149 const char* mnem = "FP0xDC"; |
1053 switch (b2 & 0xF8) { | 1150 switch (b2 & 0xF8) { |
1054 case 0xC0: mnem = "fadd"; break; | 1151 case 0xC0: |
1055 case 0xE8: mnem = "fsub"; break; | 1152 mnem = "fadd"; |
1056 case 0xC8: mnem = "fmul"; break; | 1153 break; |
1057 case 0xF8: mnem = "fdiv"; break; | 1154 case 0xE8: |
1058 default: UNIMPLEMENTED(); | 1155 mnem = "fsub"; |
| 1156 break; |
| 1157 case 0xC8: |
| 1158 mnem = "fmul"; |
| 1159 break; |
| 1160 case 0xF8: |
| 1161 mnem = "fdiv"; |
| 1162 break; |
| 1163 default: |
| 1164 UNIMPLEMENTED(); |
1059 } | 1165 } |
1060 Print(mnem); | 1166 Print(mnem); |
1061 Print(is_pop ? "p" : ""); | 1167 Print(is_pop ? "p" : ""); |
1062 Print(" st"); | 1168 Print(" st"); |
1063 PrintInt(b2 & 0x7); | 1169 PrintInt(b2 & 0x7); |
1064 return 2; | 1170 return 2; |
1065 } else if (b1 == 0xDA && b2 == 0xE9) { | 1171 } else if (b1 == 0xDA && b2 == 0xE9) { |
1066 const char* mnem = "fucompp"; | 1172 const char* mnem = "fucompp"; |
1067 Print(mnem); | 1173 Print(mnem); |
1068 return 2; | 1174 return 2; |
1069 } | 1175 } |
1070 Print("Unknown FP instruction"); | 1176 Print("Unknown FP instruction"); |
1071 return 2; | 1177 return 2; |
1072 } | 1178 } |
1073 | 1179 |
1074 | 1180 |
1075 uint8_t* X86Decoder::SSEInstruction(uint8_t prefix, uint8_t primary, | 1181 uint8_t* X86Decoder::SSEInstruction(uint8_t prefix, |
| 1182 uint8_t primary, |
1076 uint8_t* data) { | 1183 uint8_t* data) { |
1077 ASSERT(prefix == 0x0F); | 1184 ASSERT(prefix == 0x0F); |
1078 int mod, regop, rm; | 1185 int mod, regop, rm; |
1079 if (primary == 0x10) { | 1186 if (primary == 0x10) { |
1080 GetModRm(*data, &mod, ®op, &rm); | 1187 GetModRm(*data, &mod, ®op, &rm); |
1081 Print("movups "); | 1188 Print("movups "); |
1082 PrintXmmRegister(regop); | 1189 PrintXmmRegister(regop); |
1083 Print(","); | 1190 Print(","); |
1084 data += PrintRightOperand(data); | 1191 data += PrintRightOperand(data); |
1085 } else if (primary == 0x11) { | 1192 } else if (primary == 0x11) { |
(...skipping 11 matching lines...) Expand all Loading... |
1097 Print(" "); | 1204 Print(" "); |
1098 PrintXmmRegister(regop); | 1205 PrintXmmRegister(regop); |
1099 Print(","); | 1206 Print(","); |
1100 data += PrintRightXmmOperand(data); | 1207 data += PrintRightXmmOperand(data); |
1101 } | 1208 } |
1102 return data; | 1209 return data; |
1103 } | 1210 } |
1104 | 1211 |
1105 | 1212 |
1106 int X86Decoder::BitwisePDInstruction(uint8_t* data) { | 1213 int X86Decoder::BitwisePDInstruction(uint8_t* data) { |
1107 const char* mnem = (*data == 0x57) | 1214 const char* mnem = |
1108 ? "xorpd" | 1215 (*data == 0x57) ? "xorpd" : (*data == 0x56) ? "orpd" : "andpd"; |
1109 : (*data == 0x56) | |
1110 ? "orpd" | |
1111 : "andpd"; | |
1112 int mod, regop, rm; | 1216 int mod, regop, rm; |
1113 GetModRm(*(data+1), &mod, ®op, &rm); | 1217 GetModRm(*(data + 1), &mod, ®op, &rm); |
1114 Print(mnem); | 1218 Print(mnem); |
1115 Print(" "); | 1219 Print(" "); |
1116 PrintXmmRegister(regop); | 1220 PrintXmmRegister(regop); |
1117 Print(","); | 1221 Print(","); |
1118 return 1 + PrintRightXmmOperand(data+1); | 1222 return 1 + PrintRightXmmOperand(data + 1); |
1119 } | 1223 } |
1120 | 1224 |
1121 | 1225 |
1122 int X86Decoder::Packed660F38Instruction(uint8_t* data) { | 1226 int X86Decoder::Packed660F38Instruction(uint8_t* data) { |
1123 if (*(data+1) == 0x25) { | 1227 if (*(data + 1) == 0x25) { |
1124 Print("pmovsxdq "); | 1228 Print("pmovsxdq "); |
1125 int mod, regop, rm; | 1229 int mod, regop, rm; |
1126 GetModRm(*(data+2), &mod, ®op, &rm); | 1230 GetModRm(*(data + 2), &mod, ®op, &rm); |
1127 PrintXmmRegister(regop); | 1231 PrintXmmRegister(regop); |
1128 Print(","); | 1232 Print(","); |
1129 return 2 + PrintRightXmmOperand(data+2); | 1233 return 2 + PrintRightXmmOperand(data + 2); |
1130 } else if (*(data+1) == 0x29) { | 1234 } else if (*(data + 1) == 0x29) { |
1131 Print("pcmpeqq "); | 1235 Print("pcmpeqq "); |
1132 int mod, regop, rm; | 1236 int mod, regop, rm; |
1133 GetModRm(*(data+2), &mod, ®op, &rm); | 1237 GetModRm(*(data + 2), &mod, ®op, &rm); |
1134 PrintXmmRegister(regop); | 1238 PrintXmmRegister(regop); |
1135 Print(","); | 1239 Print(","); |
1136 return 2 + PrintRightXmmOperand(data+2); | 1240 return 2 + PrintRightXmmOperand(data + 2); |
1137 } | 1241 } |
1138 UNREACHABLE(); | 1242 UNREACHABLE(); |
1139 return 1; | 1243 return 1; |
1140 } | 1244 } |
1141 | 1245 |
1142 | 1246 |
1143 // Called when disassembling test eax, 0xXXXXX. | 1247 // Called when disassembling test eax, 0xXXXXX. |
1144 void X86Decoder::CheckPrintStop(uint8_t* data) { | 1248 void X86Decoder::CheckPrintStop(uint8_t* data) { |
1145 // Recognize stop pattern. | 1249 // Recognize stop pattern. |
1146 if (*reinterpret_cast<uint8_t*>(data + 5) == 0xCC) { | 1250 if (*reinterpret_cast<uint8_t*>(data + 5) == 0xCC) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 return true; | 1293 return true; |
1190 | 1294 |
1191 case REGISTER_INSTR: | 1295 case REGISTER_INSTR: |
1192 Print(idesc.mnem); | 1296 Print(idesc.mnem); |
1193 Print(" "); | 1297 Print(" "); |
1194 PrintCPURegister(**data & 0x07); | 1298 PrintCPURegister(**data & 0x07); |
1195 (*data)++; | 1299 (*data)++; |
1196 return true; | 1300 return true; |
1197 | 1301 |
1198 case MOVE_REG_INSTR: { | 1302 case MOVE_REG_INSTR: { |
1199 uword addr = *reinterpret_cast<uword*>(*data+1); | 1303 uword addr = *reinterpret_cast<uword*>(*data + 1); |
1200 Print("mov "); | 1304 Print("mov "); |
1201 PrintCPURegister(**data & 0x07), | 1305 PrintCPURegister(**data & 0x07), Print(","); |
1202 Print(","); | |
1203 PrintAddress(addr); | 1306 PrintAddress(addr); |
1204 (*data) += 5; | 1307 (*data) += 5; |
1205 return true; | 1308 return true; |
1206 } | 1309 } |
1207 | 1310 |
1208 case CALL_JUMP_INSTR: { | 1311 case CALL_JUMP_INSTR: { |
1209 uword addr = reinterpret_cast<uword>(*data) + | 1312 uword addr = reinterpret_cast<uword>(*data) + |
1210 *reinterpret_cast<uword*>(*data+1) + 5; | 1313 *reinterpret_cast<uword*>(*data + 1) + 5; |
1211 Print(idesc.mnem); | 1314 Print(idesc.mnem); |
1212 Print(" "); | 1315 Print(" "); |
1213 PrintAddress(addr); | 1316 PrintAddress(addr); |
1214 (*data) += 5; | 1317 (*data) += 5; |
1215 return true; | 1318 return true; |
1216 } | 1319 } |
1217 | 1320 |
1218 case SHORT_IMMEDIATE_INSTR: { | 1321 case SHORT_IMMEDIATE_INSTR: { |
1219 uword addr = *reinterpret_cast<uword*>(*data+1); | 1322 uword addr = *reinterpret_cast<uword*>(*data + 1); |
1220 Print(idesc.mnem); | 1323 Print(idesc.mnem); |
1221 Print(" eax, "); | 1324 Print(" eax, "); |
1222 PrintAddress(addr); | 1325 PrintAddress(addr); |
1223 (*data) += 5; | 1326 (*data) += 5; |
1224 return true; | 1327 return true; |
1225 } | 1328 } |
1226 | 1329 |
1227 case NO_INSTR: | 1330 case NO_INSTR: |
1228 return false; | 1331 return false; |
1229 | 1332 |
(...skipping 10 matching lines...) Expand all Loading... |
1240 const char* branch_hint = GetBranchPrefix(&data); | 1343 const char* branch_hint = GetBranchPrefix(&data); |
1241 const InstructionDesc& idesc = instruction_table.Get(*data); | 1344 const InstructionDesc& idesc = instruction_table.Get(*data); |
1242 // Will be set to false if the current instruction | 1345 // Will be set to false if the current instruction |
1243 // is not in 'instructions' table. | 1346 // is not in 'instructions' table. |
1244 bool processed = DecodeInstructionType(idesc, branch_hint, &data); | 1347 bool processed = DecodeInstructionType(idesc, branch_hint, &data); |
1245 //---------------------------- | 1348 //---------------------------- |
1246 if (!processed) { | 1349 if (!processed) { |
1247 switch (*data) { | 1350 switch (*data) { |
1248 case 0xC2: | 1351 case 0xC2: |
1249 Print("ret "); | 1352 Print("ret "); |
1250 PrintHex(*reinterpret_cast<uint16_t*>(data+1)); | 1353 PrintHex(*reinterpret_cast<uint16_t*>(data + 1)); |
1251 data += 3; | 1354 data += 3; |
1252 break; | 1355 break; |
1253 | 1356 |
1254 case 0x69: // fall through | 1357 case 0x69: // fall through |
1255 case 0x6B: | 1358 case 0x6B: { |
1256 { int mod, regop, rm; | 1359 int mod, regop, rm; |
1257 GetModRm(*(data+1), &mod, ®op, &rm); | 1360 GetModRm(*(data + 1), &mod, ®op, &rm); |
1258 int32_t imm = | 1361 int32_t imm = |
1259 *data == 0x6B ? *(data+2) : *reinterpret_cast<int32_t*>(data+2); | 1362 *data == 0x6B ? *(data + 2) : *reinterpret_cast<int32_t*>(data + 2); |
1260 Print("imul "); | 1363 Print("imul "); |
1261 PrintCPURegister(regop); | 1364 PrintCPURegister(regop); |
1262 Print(","); | 1365 Print(","); |
1263 PrintCPURegister(rm); | 1366 PrintCPURegister(rm); |
1264 Print(","); | 1367 Print(","); |
1265 PrintHex(imm); | 1368 PrintHex(imm); |
1266 data += 2 + (*data == 0x6B ? 1 : 4); | 1369 data += 2 + (*data == 0x6B ? 1 : 4); |
1267 } | 1370 } break; |
1268 break; | |
1269 | 1371 |
1270 case 0xF6: | 1372 case 0xF6: { |
1271 { int mod, regop, rm; | 1373 int mod, regop, rm; |
1272 GetModRm(*(data+1), &mod, ®op, &rm); | 1374 GetModRm(*(data + 1), &mod, ®op, &rm); |
1273 if ((mod == 3) && (regop == eax)) { | 1375 if ((mod == 3) && (regop == eax)) { |
1274 Print("test_b "); | 1376 Print("test_b "); |
1275 PrintCPURegister(rm); | 1377 PrintCPURegister(rm); |
1276 Print(","); | 1378 Print(","); |
1277 PrintHex(*(data+2)); | 1379 PrintHex(*(data + 2)); |
1278 data += 3; | 1380 data += 3; |
1279 } else { | 1381 } else { |
1280 data++; | 1382 data++; |
1281 Print("test_b "); | 1383 Print("test_b "); |
1282 data += PrintRightOperand(data); | 1384 data += PrintRightOperand(data); |
1283 int32_t imm = *data; | 1385 int32_t imm = *data; |
1284 Print(","); | 1386 Print(","); |
1285 PrintHex(imm); | 1387 PrintHex(imm); |
1286 data++; | 1388 data++; |
1287 } | 1389 } |
1288 } | 1390 } break; |
1289 break; | |
1290 | 1391 |
1291 case 0x81: // fall through | 1392 case 0x81: // fall through |
1292 case 0x83: // 0x81 with sign extension bit set | 1393 case 0x83: // 0x81 with sign extension bit set |
1293 data += PrintImmediateOp(data); | 1394 data += PrintImmediateOp(data); |
1294 break; | 1395 break; |
1295 | 1396 |
1296 case 0x0F: | 1397 case 0x0F: { |
1297 { uint8_t f0byte = *(data+1); | 1398 uint8_t f0byte = *(data + 1); |
1298 const char* f0mnem = F0Mnem(f0byte); | 1399 const char* f0mnem = F0Mnem(f0byte); |
1299 if (f0byte == 0xA2 || f0byte == 0x31) { | 1400 if (f0byte == 0xA2 || f0byte == 0x31) { |
1300 Print(f0mnem); | 1401 Print(f0mnem); |
1301 data += 2; | 1402 data += 2; |
1302 } else if ((f0byte & 0xF0) == 0x80) { | 1403 } else if ((f0byte & 0xF0) == 0x80) { |
1303 data += JumpConditional(data, branch_hint); | 1404 data += JumpConditional(data, branch_hint); |
1304 } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 || | 1405 } else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 || |
1305 f0byte == 0xB7 || f0byte == 0xAF || f0byte == 0xBD) { | 1406 f0byte == 0xB7 || f0byte == 0xAF || f0byte == 0xBD) { |
1306 data += 2; | 1407 data += 2; |
1307 data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data); | 1408 data += PrintOperands(f0mnem, REG_OPER_OP_ORDER, data); |
(...skipping 16 matching lines...) Expand all Loading... |
1324 } else if (f0byte == 0x2F) { | 1425 } else if (f0byte == 0x2F) { |
1325 data += 2; | 1426 data += 2; |
1326 int mod, regop, rm; | 1427 int mod, regop, rm; |
1327 GetModRm(*data, &mod, ®op, &rm); | 1428 GetModRm(*data, &mod, ®op, &rm); |
1328 Print("comiss "); | 1429 Print("comiss "); |
1329 PrintXmmRegister(regop); | 1430 PrintXmmRegister(regop); |
1330 Print(","); | 1431 Print(","); |
1331 PrintXmmRegister(rm); | 1432 PrintXmmRegister(rm); |
1332 data++; | 1433 data++; |
1333 } else if (f0byte == 0x1F) { | 1434 } else if (f0byte == 0x1F) { |
1334 if (*(data+2) == 0x00) { | 1435 if (*(data + 2) == 0x00) { |
1335 Print("nop"); | 1436 Print("nop"); |
1336 data += 3; | 1437 data += 3; |
1337 } else if (*(data+2) == 0x40 && *(data+3) == 0x00) { | 1438 } else if (*(data + 2) == 0x40 && *(data + 3) == 0x00) { |
1338 Print("nop"); | 1439 Print("nop"); |
1339 data += 4; | 1440 data += 4; |
1340 } else if (*(data+2) == 0x44 && | 1441 } else if (*(data + 2) == 0x44 && *(data + 3) == 0x00 && |
1341 *(data+3) == 0x00 && | 1442 *(data + 4) == 0x00) { |
1342 *(data+4) == 0x00) { | |
1343 Print("nop"); | 1443 Print("nop"); |
1344 data += 5; | 1444 data += 5; |
1345 } else if (*(data+2) == 0x80 && | 1445 } else if (*(data + 2) == 0x80 && *(data + 3) == 0x00 && |
1346 *(data+3) == 0x00 && | 1446 *(data + 4) == 0x00 && *(data + 5) == 0x00 && |
1347 *(data+4) == 0x00 && | 1447 *(data + 6) == 0x00) { |
1348 *(data+5) == 0x00 && | |
1349 *(data+6) == 0x00) { | |
1350 Print("nop"); | 1448 Print("nop"); |
1351 data += 7; | 1449 data += 7; |
1352 } else if (*(data+2) == 0x84 && | 1450 } else if (*(data + 2) == 0x84 && *(data + 3) == 0x00 && |
1353 *(data+3) == 0x00 && | 1451 *(data + 4) == 0x00 && *(data + 5) == 0x00 && |
1354 *(data+4) == 0x00 && | 1452 *(data + 6) == 0x00 && *(data + 7) == 0x00) { |
1355 *(data+5) == 0x00 && | |
1356 *(data+6) == 0x00 && | |
1357 *(data+7) == 0x00) { | |
1358 Print("nop"); | 1453 Print("nop"); |
1359 data += 8; | 1454 data += 8; |
1360 } else { | 1455 } else { |
1361 UNIMPLEMENTED(); | 1456 UNIMPLEMENTED(); |
1362 } | 1457 } |
1363 } else { | 1458 } else { |
1364 data += 2; | 1459 data += 2; |
1365 if (f0byte == 0xAB || f0byte == 0xA4 || f0byte == 0xA5 || | 1460 if (f0byte == 0xAB || f0byte == 0xA4 || f0byte == 0xA5 || |
1366 f0byte == 0xAC || f0byte == 0xAD || f0byte == 0xA3) { | 1461 f0byte == 0xAC || f0byte == 0xAD || f0byte == 0xA3) { |
1367 // shrd, shld, bts, bt | 1462 // shrd, shld, bts, bt |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1403 data += PrintRightXmmOperand(data); | 1498 data += PrintRightXmmOperand(data); |
1404 int comparison = *data; | 1499 int comparison = *data; |
1405 Print(" ["); | 1500 Print(" ["); |
1406 PrintHex(comparison); | 1501 PrintHex(comparison); |
1407 Print("]"); | 1502 Print("]"); |
1408 data++; | 1503 data++; |
1409 } else { | 1504 } else { |
1410 UNIMPLEMENTED(); | 1505 UNIMPLEMENTED(); |
1411 } | 1506 } |
1412 } | 1507 } |
1413 } | 1508 } break; |
1414 break; | |
1415 | 1509 |
1416 case 0x8F: | 1510 case 0x8F: { |
1417 { data++; | 1511 data++; |
1418 int mod, regop, rm; | 1512 int mod, regop, rm; |
1419 GetModRm(*data, &mod, ®op, &rm); | 1513 GetModRm(*data, &mod, ®op, &rm); |
1420 if (regop == eax) { | 1514 if (regop == eax) { |
1421 Print("pop "); | 1515 Print("pop "); |
1422 data += PrintRightOperand(data); | 1516 data += PrintRightOperand(data); |
1423 } | 1517 } |
1424 } | 1518 } break; |
1425 break; | |
1426 | 1519 |
1427 case 0xFF: | 1520 case 0xFF: { |
1428 { data++; | 1521 data++; |
1429 int mod, regop, rm; | 1522 int mod, regop, rm; |
1430 GetModRm(*data, &mod, ®op, &rm); | 1523 GetModRm(*data, &mod, ®op, &rm); |
1431 const char* mnem = NULL; | 1524 const char* mnem = NULL; |
1432 switch (regop) { | 1525 switch (regop) { |
1433 case esi: mnem = "push"; break; | 1526 case esi: |
1434 case eax: mnem = "inc"; break; | 1527 mnem = "push"; |
1435 case ecx: mnem = "dec"; break; | 1528 break; |
1436 case edx: mnem = "call"; break; | 1529 case eax: |
1437 case esp: mnem = "jmp"; break; | 1530 mnem = "inc"; |
1438 default: mnem = "??? 0xFF"; | 1531 break; |
| 1532 case ecx: |
| 1533 mnem = "dec"; |
| 1534 break; |
| 1535 case edx: |
| 1536 mnem = "call"; |
| 1537 break; |
| 1538 case esp: |
| 1539 mnem = "jmp"; |
| 1540 break; |
| 1541 default: |
| 1542 mnem = "??? 0xFF"; |
1439 } | 1543 } |
1440 Print(mnem); | 1544 Print(mnem); |
1441 Print(" "); | 1545 Print(" "); |
1442 data += PrintRightOperand(data); | 1546 data += PrintRightOperand(data); |
1443 } | 1547 } break; |
1444 break; | |
1445 | 1548 |
1446 case 0xC7: // imm32, fall through | 1549 case 0xC7: // imm32, fall through |
1447 case 0xC6: // imm8 | 1550 case 0xC6: // imm8 |
1448 { bool is_byte = *data == 0xC6; | 1551 { |
| 1552 bool is_byte = *data == 0xC6; |
1449 data++; | 1553 data++; |
1450 Print(is_byte ? "mov_b" : "mov"); | 1554 Print(is_byte ? "mov_b" : "mov"); |
1451 Print(" "); | 1555 Print(" "); |
1452 data += PrintRightOperand(data); | 1556 data += PrintRightOperand(data); |
1453 int32_t imm = is_byte ? *data : *reinterpret_cast<int32_t*>(data); | 1557 int32_t imm = is_byte ? *data : *reinterpret_cast<int32_t*>(data); |
1454 Print(","); | 1558 Print(","); |
1455 PrintHex(imm); | 1559 PrintHex(imm); |
1456 data += is_byte ? 1 : 4; | 1560 data += is_byte ? 1 : 4; |
1457 } | 1561 } break; |
1458 break; | |
1459 | 1562 |
1460 case 0x80: | 1563 case 0x80: { |
1461 { data++; | 1564 data++; |
1462 Print("cmpb "); | 1565 Print("cmpb "); |
1463 data += PrintRightOperand(data); | 1566 data += PrintRightOperand(data); |
1464 int32_t imm = *data; | 1567 int32_t imm = *data; |
1465 Print(","); | 1568 Print(","); |
1466 PrintHex(imm); | 1569 PrintHex(imm); |
1467 data++; | 1570 data++; |
1468 } | 1571 } break; |
1469 break; | |
1470 | 1572 |
1471 case 0x88: // 8bit, fall through | 1573 case 0x88: // 8bit, fall through |
1472 case 0x89: // 32bit | 1574 case 0x89: // 32bit |
1473 { bool is_byte = *data == 0x88; | 1575 { |
| 1576 bool is_byte = *data == 0x88; |
1474 int mod, regop, rm; | 1577 int mod, regop, rm; |
1475 data++; | 1578 data++; |
1476 GetModRm(*data, &mod, ®op, &rm); | 1579 GetModRm(*data, &mod, ®op, &rm); |
1477 Print(is_byte ? "mov_b" : "mov"); | 1580 Print(is_byte ? "mov_b" : "mov"); |
1478 Print(" "); | 1581 Print(" "); |
1479 data += PrintRightOperand(data); | 1582 data += PrintRightOperand(data); |
1480 Print(","); | 1583 Print(","); |
1481 PrintCPURegister(regop); | 1584 PrintCPURegister(regop); |
1482 } | 1585 } break; |
1483 break; | |
1484 | 1586 |
1485 case 0x66: // prefix | 1587 case 0x66: // prefix |
1486 data++; | 1588 data++; |
1487 if (*data == 0x8B) { | 1589 if (*data == 0x8B) { |
1488 data++; | 1590 data++; |
1489 data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data); | 1591 data += PrintOperands("mov_w", REG_OPER_OP_ORDER, data); |
1490 } else if (*data == 0x89) { | 1592 } else if (*data == 0x89) { |
1491 data++; | 1593 data++; |
1492 int mod, regop, rm; | 1594 int mod, regop, rm; |
1493 GetModRm(*data, &mod, ®op, &rm); | 1595 GetModRm(*data, &mod, ®op, &rm); |
(...skipping 24 matching lines...) Expand all Loading... |
1518 } else if (*data == 0xD6) { | 1620 } else if (*data == 0xD6) { |
1519 data++; | 1621 data++; |
1520 int mod, regop, rm; | 1622 int mod, regop, rm; |
1521 GetModRm(*data, &mod, ®op, &rm); | 1623 GetModRm(*data, &mod, ®op, &rm); |
1522 Print("movq "); | 1624 Print("movq "); |
1523 data += PrintRightOperand(data); | 1625 data += PrintRightOperand(data); |
1524 Print(","); | 1626 Print(","); |
1525 PrintXmmRegister(regop); | 1627 PrintXmmRegister(regop); |
1526 } else if (*data == 0x57 || *data == 0x56 || *data == 0x54) { | 1628 } else if (*data == 0x57 || *data == 0x56 || *data == 0x54) { |
1527 data += BitwisePDInstruction(data); | 1629 data += BitwisePDInstruction(data); |
1528 } else if (*data == 0x1F && | 1630 } else if (*data == 0x1F && *(data + 1) == 0x44 && |
1529 *(data+1) == 0x44 && | 1631 *(data + 2) == 0x00 && *(data + 3) == 0x00) { |
1530 *(data+2) == 0x00 && | |
1531 *(data+3) == 0x00) { | |
1532 data += 4; | 1632 data += 4; |
1533 Print("nop"); | 1633 Print("nop"); |
1534 } else if (*data == 0x50) { | 1634 } else if (*data == 0x50) { |
1535 Print("movmskpd "); | 1635 Print("movmskpd "); |
1536 data++; | 1636 data++; |
1537 int mod, regop, rm; | 1637 int mod, regop, rm; |
1538 GetModRm(*data, &mod, ®op, &rm); | 1638 GetModRm(*data, &mod, ®op, &rm); |
1539 PrintCPURegister(regop); | 1639 PrintCPURegister(regop); |
1540 Print(","); | 1640 Print(","); |
1541 data += PrintRightXmmOperand(data); | 1641 data += PrintRightXmmOperand(data); |
1542 } else if (*data == 0x3A && *(data+1) == 0x16) { | 1642 } else if (*data == 0x3A && *(data + 1) == 0x16) { |
1543 Print("pextrd "); | 1643 Print("pextrd "); |
1544 data += 2; | 1644 data += 2; |
1545 int mod, regop, rm; | 1645 int mod, regop, rm; |
1546 GetModRm(*data, &mod, ®op, &rm); | 1646 GetModRm(*data, &mod, ®op, &rm); |
1547 PrintCPURegister(rm); | 1647 PrintCPURegister(rm); |
1548 Print(","); | 1648 Print(","); |
1549 PrintXmmRegister(regop); | 1649 PrintXmmRegister(regop); |
1550 Print(","); | 1650 Print(","); |
1551 PrintHex(*(data+1)); | 1651 PrintHex(*(data + 1)); |
1552 data += 2; | 1652 data += 2; |
1553 } else if (*data == 0x38) { | 1653 } else if (*data == 0x38) { |
1554 data += Packed660F38Instruction(data); | 1654 data += Packed660F38Instruction(data); |
1555 } else if (*data == 0xEF) { | 1655 } else if (*data == 0xEF) { |
1556 int mod, regop, rm; | 1656 int mod, regop, rm; |
1557 GetModRm(*(data+1), &mod, ®op, &rm); | 1657 GetModRm(*(data + 1), &mod, ®op, &rm); |
1558 Print("pxor "); | 1658 Print("pxor "); |
1559 PrintXmmRegister(regop); | 1659 PrintXmmRegister(regop); |
1560 Print(","); | 1660 Print(","); |
1561 PrintXmmRegister(rm); | 1661 PrintXmmRegister(rm); |
1562 data += 2; | 1662 data += 2; |
1563 } else if (*data == 0x3A) { | 1663 } else if (*data == 0x3A) { |
1564 data++; | 1664 data++; |
1565 if (*data == 0x0B) { | 1665 if (*data == 0x0B) { |
1566 data++; | 1666 data++; |
1567 int mod, regop, rm; | 1667 int mod, regop, rm; |
1568 GetModRm(*data, &mod, ®op, &rm); | 1668 GetModRm(*data, &mod, ®op, &rm); |
1569 Print("roundsd "); | 1669 Print("roundsd "); |
1570 PrintXmmRegister(regop); | 1670 PrintXmmRegister(regop); |
1571 Print(", "); | 1671 Print(", "); |
1572 PrintXmmRegister(rm); | 1672 PrintXmmRegister(rm); |
1573 Print(", "); | 1673 Print(", "); |
1574 PrintInt(data[1] & 3); | 1674 PrintInt(data[1] & 3); |
1575 data += 2; | 1675 data += 2; |
1576 } else { | 1676 } else { |
1577 UNIMPLEMENTED(); | 1677 UNIMPLEMENTED(); |
1578 } | 1678 } |
1579 } else if (*data == 0x14) { | 1679 } else if (*data == 0x14) { |
1580 int mod, regop, rm; | 1680 int mod, regop, rm; |
1581 GetModRm(*(data+1), &mod, ®op, &rm); | 1681 GetModRm(*(data + 1), &mod, ®op, &rm); |
1582 Print("unpcklpd "); | 1682 Print("unpcklpd "); |
1583 PrintXmmRegister(regop); | 1683 PrintXmmRegister(regop); |
1584 Print(","); | 1684 Print(","); |
1585 PrintXmmRegister(rm); | 1685 PrintXmmRegister(rm); |
1586 data += 2; | 1686 data += 2; |
1587 } else if (*data == 0x15) { | 1687 } else if (*data == 0x15) { |
1588 int mod, regop, rm; | 1688 int mod, regop, rm; |
1589 GetModRm(*(data+1), &mod, ®op, &rm); | 1689 GetModRm(*(data + 1), &mod, ®op, &rm); |
1590 Print("unpckhpd "); | 1690 Print("unpckhpd "); |
1591 PrintXmmRegister(regop); | 1691 PrintXmmRegister(regop); |
1592 Print(","); | 1692 Print(","); |
1593 PrintXmmRegister(rm); | 1693 PrintXmmRegister(rm); |
1594 data += 2; | 1694 data += 2; |
1595 } else if ((*data == 0xFE) || (*data == 0xFA) || (*data == 0x2F) || | 1695 } else if ((*data == 0xFE) || (*data == 0xFA) || (*data == 0x2F) || |
1596 (*data == 0x58) || (*data == 0x5C) || (*data == 0x59) || | 1696 (*data == 0x58) || (*data == 0x5C) || (*data == 0x59) || |
1597 (*data == 0x5E) || (*data == 0x5D) || (*data == 0x5F) || | 1697 (*data == 0x5E) || (*data == 0x5D) || (*data == 0x5F) || |
1598 (*data == 0x51) || (*data == 0x5A)) { | 1698 (*data == 0x51) || (*data == 0x5A)) { |
1599 const char* mnemonic = PackedDoubleMnemonic(*data); | 1699 const char* mnemonic = PackedDoubleMnemonic(*data); |
1600 int mod, regop, rm; | 1700 int mod, regop, rm; |
1601 GetModRm(*(data+1), &mod, ®op, &rm); | 1701 GetModRm(*(data + 1), &mod, ®op, &rm); |
1602 Print(mnemonic); | 1702 Print(mnemonic); |
1603 PrintXmmRegister(regop); | 1703 PrintXmmRegister(regop); |
1604 Print(","); | 1704 Print(","); |
1605 PrintXmmRegister(rm); | 1705 PrintXmmRegister(rm); |
1606 data += 2; | 1706 data += 2; |
1607 } else if (*data == 0xC6) { | 1707 } else if (*data == 0xC6) { |
1608 int mod, regop, rm; | 1708 int mod, regop, rm; |
1609 data++; | 1709 data++; |
1610 GetModRm(*data, &mod, ®op, &rm); | 1710 GetModRm(*data, &mod, ®op, &rm); |
1611 Print("shufpd "); | 1711 Print("shufpd "); |
(...skipping 27 matching lines...) Expand all Loading... |
1639 PrintHex(imm); | 1739 PrintHex(imm); |
1640 data += 2; | 1740 data += 2; |
1641 } else if (*data == 0x90) { | 1741 } else if (*data == 0x90) { |
1642 data++; | 1742 data++; |
1643 Print("nop"); | 1743 Print("nop"); |
1644 } else { | 1744 } else { |
1645 UNIMPLEMENTED(); | 1745 UNIMPLEMENTED(); |
1646 } | 1746 } |
1647 break; | 1747 break; |
1648 | 1748 |
1649 case 0xFE: | 1749 case 0xFE: { |
1650 { data++; | 1750 data++; |
1651 int mod, regop, rm; | 1751 int mod, regop, rm; |
1652 GetModRm(*data, &mod, ®op, &rm); | 1752 GetModRm(*data, &mod, ®op, &rm); |
1653 if (mod == 3 && regop == ecx) { | 1753 if (mod == 3 && regop == ecx) { |
1654 Print("dec_b "); | 1754 Print("dec_b "); |
1655 PrintCPURegister(rm); | 1755 PrintCPURegister(rm); |
1656 } else { | 1756 } else { |
1657 UNIMPLEMENTED(); | 1757 UNIMPLEMENTED(); |
1658 } | 1758 } |
1659 data++; | 1759 data++; |
1660 } | 1760 } break; |
1661 break; | |
1662 | 1761 |
1663 case 0x68: | 1762 case 0x68: |
1664 Print("push "); | 1763 Print("push "); |
1665 PrintHex(*reinterpret_cast<int32_t*>(data+1)); | 1764 PrintHex(*reinterpret_cast<int32_t*>(data + 1)); |
1666 data += 5; | 1765 data += 5; |
1667 break; | 1766 break; |
1668 | 1767 |
1669 case 0x6A: | 1768 case 0x6A: |
1670 Print("push "); | 1769 Print("push "); |
1671 PrintHex(*reinterpret_cast<int8_t*>(data + 1)); | 1770 PrintHex(*reinterpret_cast<int8_t*>(data + 1)); |
1672 data += 2; | 1771 data += 2; |
1673 break; | 1772 break; |
1674 | 1773 |
1675 case 0xA8: | 1774 case 0xA8: |
1676 Print("test al,"); | 1775 Print("test al,"); |
1677 PrintHex(*reinterpret_cast<uint8_t*>(data+1)); | 1776 PrintHex(*reinterpret_cast<uint8_t*>(data + 1)); |
1678 data += 2; | 1777 data += 2; |
1679 break; | 1778 break; |
1680 | 1779 |
1681 case 0xA9: | 1780 case 0xA9: |
1682 Print("test eax,"); | 1781 Print("test eax,"); |
1683 PrintHex(*reinterpret_cast<int32_t*>(data+1)); | 1782 PrintHex(*reinterpret_cast<int32_t*>(data + 1)); |
1684 CheckPrintStop(data); | 1783 CheckPrintStop(data); |
1685 data += 5; | 1784 data += 5; |
1686 break; | 1785 break; |
1687 | 1786 |
1688 case 0xD1: // fall through | 1787 case 0xD1: // fall through |
1689 case 0xD3: // fall through | 1788 case 0xD3: // fall through |
1690 case 0xC1: | 1789 case 0xC1: |
1691 data += D1D3C1Instruction(data); | 1790 data += D1D3C1Instruction(data); |
1692 break; | 1791 break; |
1693 | 1792 |
1694 case 0xD9: // fall through | 1793 case 0xD9: // fall through |
1695 case 0xDA: // fall through | 1794 case 0xDA: // fall through |
1696 case 0xDB: // fall through | 1795 case 0xDB: // fall through |
1697 case 0xDC: // fall through | 1796 case 0xDC: // fall through |
1698 case 0xDD: // fall through | 1797 case 0xDD: // fall through |
1699 case 0xDE: // fall through | 1798 case 0xDE: // fall through |
1700 case 0xDF: | 1799 case 0xDF: |
1701 data += FPUInstruction(data); | 1800 data += FPUInstruction(data); |
1702 break; | 1801 break; |
1703 | 1802 |
1704 case 0xEB: | 1803 case 0xEB: |
1705 data += JumpShort(data); | 1804 data += JumpShort(data); |
1706 break; | 1805 break; |
1707 | 1806 |
1708 case 0xF3: | 1807 case 0xF3: |
1709 data = F3Instruction(data); | 1808 data = F3Instruction(data); |
1710 break; | 1809 break; |
1711 case 0xF2: { | 1810 case 0xF2: { |
1712 if (*(data+1) == 0x0F) { | 1811 if (*(data + 1) == 0x0F) { |
1713 uint8_t b2 = *(data+2); | 1812 uint8_t b2 = *(data + 2); |
1714 if (b2 == 0x11) { | 1813 if (b2 == 0x11) { |
1715 Print("movsd "); | 1814 Print("movsd "); |
1716 data += 3; | 1815 data += 3; |
1717 int mod, regop, rm; | 1816 int mod, regop, rm; |
1718 GetModRm(*data, &mod, ®op, &rm); | 1817 GetModRm(*data, &mod, ®op, &rm); |
1719 data += PrintRightXmmOperand(data); | 1818 data += PrintRightXmmOperand(data); |
1720 Print(","); | 1819 Print(","); |
1721 PrintXmmRegister(regop); | 1820 PrintXmmRegister(regop); |
1722 } else if (b2 == 0x10) { | 1821 } else if (b2 == 0x10) { |
1723 data += 3; | 1822 data += 3; |
1724 int mod, regop, rm; | 1823 int mod, regop, rm; |
1725 GetModRm(*data, &mod, ®op, &rm); | 1824 GetModRm(*data, &mod, ®op, &rm); |
1726 Print("movsd "); | 1825 Print("movsd "); |
1727 PrintXmmRegister(regop); | 1826 PrintXmmRegister(regop); |
1728 Print(","); | 1827 Print(","); |
1729 data += PrintRightOperand(data); | 1828 data += PrintRightOperand(data); |
1730 } else { | 1829 } else { |
1731 const char* mnem = "? 0xF2"; | 1830 const char* mnem = "? 0xF2"; |
1732 switch (b2) { | 1831 switch (b2) { |
1733 case 0x2A: mnem = "cvtsi2sd"; break; | 1832 case 0x2A: |
1734 case 0x2C: mnem = "cvttsd2si"; break; | 1833 mnem = "cvtsi2sd"; |
1735 case 0x2D: mnem = "cvtsd2i"; break; | 1834 break; |
1736 case 0x51: mnem = "sqrtsd"; break; | 1835 case 0x2C: |
1737 case 0x58: mnem = "addsd"; break; | 1836 mnem = "cvttsd2si"; |
1738 case 0x59: mnem = "mulsd"; break; | 1837 break; |
1739 case 0x5A: mnem = "cvtsd2ss"; break; | 1838 case 0x2D: |
1740 case 0x5C: mnem = "subsd"; break; | 1839 mnem = "cvtsd2i"; |
1741 case 0x5E: mnem = "divsd"; break; | 1840 break; |
1742 default: UNIMPLEMENTED(); | 1841 case 0x51: |
| 1842 mnem = "sqrtsd"; |
| 1843 break; |
| 1844 case 0x58: |
| 1845 mnem = "addsd"; |
| 1846 break; |
| 1847 case 0x59: |
| 1848 mnem = "mulsd"; |
| 1849 break; |
| 1850 case 0x5A: |
| 1851 mnem = "cvtsd2ss"; |
| 1852 break; |
| 1853 case 0x5C: |
| 1854 mnem = "subsd"; |
| 1855 break; |
| 1856 case 0x5E: |
| 1857 mnem = "divsd"; |
| 1858 break; |
| 1859 default: |
| 1860 UNIMPLEMENTED(); |
1743 } | 1861 } |
1744 data += 3; | 1862 data += 3; |
1745 int mod, regop, rm; | 1863 int mod, regop, rm; |
1746 GetModRm(*data, &mod, ®op, &rm); | 1864 GetModRm(*data, &mod, ®op, &rm); |
1747 if (b2 == 0x2A) { | 1865 if (b2 == 0x2A) { |
1748 Print(mnem); | 1866 Print(mnem); |
1749 Print(" "); | 1867 Print(" "); |
1750 PrintXmmRegister(regop); | 1868 PrintXmmRegister(regop); |
1751 Print(","); | 1869 Print(","); |
1752 data += PrintRightOperand(data); | 1870 data += PrintRightOperand(data); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1784 } | 1902 } |
1785 } | 1903 } |
1786 | 1904 |
1787 int instr_len = data - reinterpret_cast<uint8_t*>(pc); | 1905 int instr_len = data - reinterpret_cast<uint8_t*>(pc); |
1788 ASSERT(instr_len > 0); // Ensure progress. | 1906 ASSERT(instr_len > 0); // Ensure progress. |
1789 | 1907 |
1790 return instr_len; | 1908 return instr_len; |
1791 } // NOLINT | 1909 } // NOLINT |
1792 | 1910 |
1793 | 1911 |
1794 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, | 1912 void Disassembler::DecodeInstruction(char* hex_buffer, |
1795 char* human_buffer, intptr_t human_size, | 1913 intptr_t hex_size, |
1796 int* out_instr_len, const Code& code, | 1914 char* human_buffer, |
1797 Object** object, uword pc) { | 1915 intptr_t human_size, |
| 1916 int* out_instr_len, |
| 1917 const Code& code, |
| 1918 Object** object, |
| 1919 uword pc) { |
1798 ASSERT(hex_size > 0); | 1920 ASSERT(hex_size > 0); |
1799 ASSERT(human_size > 0); | 1921 ASSERT(human_size > 0); |
1800 X86Decoder decoder(human_buffer, human_size); | 1922 X86Decoder decoder(human_buffer, human_size); |
1801 int instruction_length = decoder.InstructionDecode(pc); | 1923 int instruction_length = decoder.InstructionDecode(pc); |
1802 uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc); | 1924 uint8_t* pc_ptr = reinterpret_cast<uint8_t*>(pc); |
1803 int hex_index = 0; | 1925 int hex_index = 0; |
1804 int remaining_size = hex_size - hex_index; | 1926 int remaining_size = hex_size - hex_index; |
1805 for (int i = 0; (i < instruction_length) && (remaining_size > 2); ++i) { | 1927 for (int i = 0; (i < instruction_length) && (remaining_size > 2); ++i) { |
1806 OS::SNPrint(&hex_buffer[hex_index], remaining_size, "%02x", pc_ptr[i]); | 1928 OS::SNPrint(&hex_buffer[hex_index], remaining_size, "%02x", pc_ptr[i]); |
1807 hex_index += 2; | 1929 hex_index += 2; |
(...skipping 15 matching lines...) Expand all Loading... |
1823 } | 1945 } |
1824 } | 1946 } |
1825 } | 1947 } |
1826 } | 1948 } |
1827 | 1949 |
1828 #endif // !PRODUCT | 1950 #endif // !PRODUCT |
1829 | 1951 |
1830 } // namespace dart | 1952 } // namespace dart |
1831 | 1953 |
1832 #endif // defined TARGET_ARCH_IA32 | 1954 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |