| 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 |