| 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_X64) | 8 #if defined(TARGET_ARCH_X64) |
| 9 #include "platform/utils.h" | 9 #include "platform/utils.h" |
| 10 #include "vm/allocation.h" | 10 #include "vm/allocation.h" |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 static const char* xmm_regs[kMaxXmmRegisters] = { | 284 static const char* xmm_regs[kMaxXmmRegisters] = { |
| 285 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", | 285 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", |
| 286 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" | 286 "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" |
| 287 }; | 287 }; |
| 288 | 288 |
| 289 class DisassemblerX64 : public ValueObject { | 289 class DisassemblerX64 : public ValueObject { |
| 290 public: | 290 public: |
| 291 DisassemblerX64(char* buffer, intptr_t buffer_size) | 291 DisassemblerX64(char* buffer, intptr_t buffer_size) |
| 292 : buffer_(buffer), | 292 : buffer_(buffer), |
| 293 buffer_size_(buffer_size), | 293 buffer_size_(buffer_size), |
| 294 buffer_pos_(0) { | 294 buffer_pos_(0), |
| 295 rex_(0), |
| 296 operand_size_(0), |
| 297 group_1_prefix_(0), |
| 298 byte_size_operand_(false) { |
| 295 buffer_[buffer_pos_] = '\0'; | 299 buffer_[buffer_pos_] = '\0'; |
| 296 } | 300 } |
| 297 | 301 |
| 298 virtual ~DisassemblerX64() { | 302 virtual ~DisassemblerX64() { |
| 299 } | 303 } |
| 300 | 304 |
| 301 int InstructionDecode(uword pc); | 305 int InstructionDecode(uword pc); |
| 302 | 306 |
| 303 private: | 307 private: |
| 304 enum OperandSize { | 308 enum OperandSize { |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 int F6F7Instruction(uint8_t* data); | 395 int F6F7Instruction(uint8_t* data); |
| 392 int ShiftInstruction(uint8_t* data); | 396 int ShiftInstruction(uint8_t* data); |
| 393 int JumpShort(uint8_t* data); | 397 int JumpShort(uint8_t* data); |
| 394 int JumpConditional(uint8_t* data); | 398 int JumpConditional(uint8_t* data); |
| 395 int JumpConditionalShort(uint8_t* data); | 399 int JumpConditionalShort(uint8_t* data); |
| 396 int SetCC(uint8_t* data); | 400 int SetCC(uint8_t* data); |
| 397 int FPUInstruction(uint8_t* data); | 401 int FPUInstruction(uint8_t* data); |
| 398 int MemoryFPUInstruction(int escape_opcode, int regop, uint8_t* modrm_start); | 402 int MemoryFPUInstruction(int escape_opcode, int regop, uint8_t* modrm_start); |
| 399 int RegisterFPUInstruction(int escape_opcode, uint8_t modrm_byte); | 403 int RegisterFPUInstruction(int escape_opcode, uint8_t modrm_byte); |
| 400 | 404 |
| 401 bool DecodeInstructionType(const InstructionDesc& idesc, uint8_t** data); | 405 bool DecodeInstructionType(uint8_t** data); |
| 402 | 406 |
| 403 void UnimplementedInstruction() { | 407 void UnimplementedInstruction() { |
| 404 AppendToBuffer("'Unimplemented Instruction'"); | 408 AppendToBuffer("'Unimplemented Instruction'"); |
| 405 } | 409 } |
| 406 | 410 |
| 407 char* buffer_; // Decode instructions into this buffer. | 411 char* buffer_; // Decode instructions into this buffer. |
| 408 intptr_t buffer_size_; // The size of the buffer_. | 412 intptr_t buffer_size_; // The size of the buffer_. |
| 409 intptr_t buffer_pos_; // Current character position in the buffer_. | 413 intptr_t buffer_pos_; // Current character position in the buffer_. |
| 410 | 414 |
| 411 // Prefixes parsed | 415 // Prefixes parsed |
| (...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1030 if (has_register) { | 1034 if (has_register) { |
| 1031 AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7); | 1035 AppendToBuffer("%s st%d", mnem, modrm_byte & 0x7); |
| 1032 } else { | 1036 } else { |
| 1033 AppendToBuffer("%s", mnem); | 1037 AppendToBuffer("%s", mnem); |
| 1034 } | 1038 } |
| 1035 return 2; | 1039 return 2; |
| 1036 } | 1040 } |
| 1037 | 1041 |
| 1038 | 1042 |
| 1039 // TODO(srdjan): Should we add a branch hint argument? | 1043 // TODO(srdjan): Should we add a branch hint argument? |
| 1040 bool DisassemblerX64::DecodeInstructionType(const InstructionDesc& idesc, | 1044 bool DisassemblerX64::DecodeInstructionType(uint8_t** data) { |
| 1041 uint8_t** data) { | 1045 uint8_t current; |
| 1042 uint8_t current = **data; | 1046 |
| 1047 // Scan for prefixes. |
| 1048 while (true) { |
| 1049 current = **data; |
| 1050 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) { // Group 3 prefix. |
| 1051 operand_size_ = current; |
| 1052 } else if ((current & 0xF0) == 0x40) { // REX prefix. |
| 1053 setRex(current); |
| 1054 // TODO(srdjan): Should we enable printing of REX.W? |
| 1055 // if (rex_w()) AppendToBuffer("REX.W "); |
| 1056 } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3). |
| 1057 group_1_prefix_ = current; |
| 1058 } else { // Not a prefix - an opcode. |
| 1059 break; |
| 1060 } |
| 1061 (*data)++; |
| 1062 } |
| 1063 |
| 1064 const InstructionDesc& idesc = instruction_table.Get(current); |
| 1065 byte_size_operand_ = idesc.byte_size_operation; |
| 1066 |
| 1043 switch (idesc.type) { | 1067 switch (idesc.type) { |
| 1044 case ZERO_OPERANDS_INSTR: | 1068 case ZERO_OPERANDS_INSTR: |
| 1045 if (current >= 0xA4 && current <= 0xA7) { | 1069 if (current >= 0xA4 && current <= 0xA7) { |
| 1046 // String move or compare operations. | 1070 // String move or compare operations. |
| 1047 if (group_1_prefix_ == REP_PREFIX) { | 1071 if (group_1_prefix_ == REP_PREFIX) { |
| 1048 // REP. | 1072 // REP. |
| 1049 AppendToBuffer("rep "); | 1073 AppendToBuffer("rep "); |
| 1050 } | 1074 } |
| 1051 // TODO(srdjan): Should we enable printing of REX.W? | 1075 // TODO(srdjan): Should we enable printing of REX.W? |
| 1052 // if (rex_w()) AppendToBuffer("REX.W "); | 1076 // if (rex_w()) AppendToBuffer("REX.W "); |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1435 case 0xBF: | 1459 case 0xBF: |
| 1436 return "movsxw"; | 1460 return "movsxw"; |
| 1437 default: | 1461 default: |
| 1438 return NULL; | 1462 return NULL; |
| 1439 } | 1463 } |
| 1440 } | 1464 } |
| 1441 | 1465 |
| 1442 | 1466 |
| 1443 int DisassemblerX64::InstructionDecode(uword pc) { | 1467 int DisassemblerX64::InstructionDecode(uword pc) { |
| 1444 uint8_t* data = reinterpret_cast<uint8_t*>(pc); | 1468 uint8_t* data = reinterpret_cast<uint8_t*>(pc); |
| 1445 uint8_t current; | |
| 1446 | 1469 |
| 1447 // Scan for prefixes. | 1470 const bool processed = DecodeInstructionType(&data); |
| 1448 while (true) { | |
| 1449 current = *data; | |
| 1450 if (current == OPERAND_SIZE_OVERRIDE_PREFIX) { // Group 3 prefix. | |
| 1451 operand_size_ = current; | |
| 1452 } else if ((current & 0xF0) == 0x40) { // REX prefix. | |
| 1453 setRex(current); | |
| 1454 // TODO(srdjan): Should we enable printing of REX.W? | |
| 1455 // if (rex_w()) AppendToBuffer("REX.W "); | |
| 1456 } else if ((current & 0xFE) == 0xF2) { // Group 1 prefix (0xF2 or 0xF3). | |
| 1457 group_1_prefix_ = current; | |
| 1458 } else { // Not a prefix - an opcode. | |
| 1459 break; | |
| 1460 } | |
| 1461 data++; | |
| 1462 } | |
| 1463 | |
| 1464 const InstructionDesc& idesc = instruction_table.Get(current); | |
| 1465 byte_size_operand_ = idesc.byte_size_operation; | |
| 1466 bool processed = DecodeInstructionType(idesc, &data); | |
| 1467 | 1471 |
| 1468 if (!processed) { | 1472 if (!processed) { |
| 1469 switch (*data) { | 1473 switch (*data) { |
| 1470 case 0xC2: | 1474 case 0xC2: |
| 1471 AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1)); | 1475 AppendToBuffer("ret 0x%x", *reinterpret_cast<uint16_t*>(data + 1)); |
| 1472 data += 3; | 1476 data += 3; |
| 1473 break; | 1477 break; |
| 1474 | 1478 |
| 1475 case 0x69: // fall through | 1479 case 0x69: // fall through |
| 1476 case 0x6B: { | 1480 case 0x6B: { |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1828 human_buffer, | 1832 human_buffer, |
| 1829 sizeof(human_buffer), | 1833 sizeof(human_buffer), |
| 1830 pc); | 1834 pc); |
| 1831 pc += instruction_length; | 1835 pc += instruction_length; |
| 1832 } | 1836 } |
| 1833 } | 1837 } |
| 1834 | 1838 |
| 1835 } // namespace dart | 1839 } // namespace dart |
| 1836 | 1840 |
| 1837 #endif // defined TARGET_ARCH_X64 | 1841 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |