OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
325 | 325 |
326 virtual ~DisassemblerX64() { | 326 virtual ~DisassemblerX64() { |
327 } | 327 } |
328 | 328 |
329 // Writes one disassembled instruction into 'buffer' (0-terminated). | 329 // Writes one disassembled instruction into 'buffer' (0-terminated). |
330 // Returns the length of the disassembled machine instruction in bytes. | 330 // Returns the length of the disassembled machine instruction in bytes. |
331 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); | 331 int InstructionDecode(v8::internal::Vector<char> buffer, byte* instruction); |
332 | 332 |
333 private: | 333 private: |
334 enum OperandSize { | 334 enum OperandSize { |
335 BYTE_SIZE = 0, | 335 kByteSize = 0, |
336 WORD_SIZE = 1, | 336 kWordSize = 1, |
Michael Starzinger
2013/09/02 19:12:43
nit: This makes it look like these are constants t
Benedikt Meurer
2013/09/03 07:27:39
Done.
| |
337 DOUBLEWORD_SIZE = 2, | 337 kDoublewordSize = 2, |
338 QUADWORD_SIZE = 3 | 338 kQuadwordSize = 3 |
339 }; | 339 }; |
340 | 340 |
341 const NameConverter& converter_; | 341 const NameConverter& converter_; |
342 v8::internal::EmbeddedVector<char, 128> tmp_buffer_; | 342 v8::internal::EmbeddedVector<char, 128> tmp_buffer_; |
343 unsigned int tmp_buffer_pos_; | 343 unsigned int tmp_buffer_pos_; |
344 bool abort_on_unimplemented_; | 344 bool abort_on_unimplemented_; |
345 // Prefixes parsed | 345 // Prefixes parsed |
346 byte rex_; | 346 byte rex_; |
347 byte operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. | 347 byte operand_size_; // 0x66 or (if no group 3 prefix is present) 0x0. |
348 byte group_1_prefix_; // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. | 348 byte group_1_prefix_; // 0xF2, 0xF3, or (if no group 1 prefix is present) 0. |
(...skipping 13 matching lines...) Expand all Loading... | |
362 // Actual number of base register given the low bits and the rex.b state. | 362 // Actual number of base register given the low bits and the rex.b state. |
363 int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); } | 363 int base_reg(int low_bits) { return low_bits | ((rex_ & 0x01) << 3); } |
364 | 364 |
365 bool rex_x() { return (rex_ & 0x02) != 0; } | 365 bool rex_x() { return (rex_ & 0x02) != 0; } |
366 | 366 |
367 bool rex_r() { return (rex_ & 0x04) != 0; } | 367 bool rex_r() { return (rex_ & 0x04) != 0; } |
368 | 368 |
369 bool rex_w() { return (rex_ & 0x08) != 0; } | 369 bool rex_w() { return (rex_ & 0x08) != 0; } |
370 | 370 |
371 OperandSize operand_size() { | 371 OperandSize operand_size() { |
372 if (byte_size_operand_) return BYTE_SIZE; | 372 if (byte_size_operand_) return kByteSize; |
373 if (rex_w()) return QUADWORD_SIZE; | 373 if (rex_w()) return kQuadwordSize; |
374 if (operand_size_ != 0) return WORD_SIZE; | 374 if (operand_size_ != 0) return kWordSize; |
375 return DOUBLEWORD_SIZE; | 375 return kDoublewordSize; |
376 } | 376 } |
377 | 377 |
378 char operand_size_code() { | 378 char operand_size_code() { |
379 return "bwlq"[operand_size()]; | 379 return "bwlq"[operand_size()]; |
380 } | 380 } |
381 | 381 |
382 const char* NameOfCPURegister(int reg) const { | 382 const char* NameOfCPURegister(int reg) const { |
383 return converter_.NameOfCPURegister(reg); | 383 return converter_.NameOfCPURegister(reg); |
384 } | 384 } |
385 | 385 |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
555 return 1; | 555 return 1; |
556 } | 556 } |
557 UNREACHABLE(); | 557 UNREACHABLE(); |
558 } | 558 } |
559 | 559 |
560 | 560 |
561 int DisassemblerX64::PrintImmediate(byte* data, OperandSize size) { | 561 int DisassemblerX64::PrintImmediate(byte* data, OperandSize size) { |
562 int64_t value; | 562 int64_t value; |
563 int count; | 563 int count; |
564 switch (size) { | 564 switch (size) { |
565 case BYTE_SIZE: | 565 case kByteSize: |
566 value = *data; | 566 value = *data; |
567 count = 1; | 567 count = 1; |
568 break; | 568 break; |
569 case WORD_SIZE: | 569 case kWordSize: |
570 value = *reinterpret_cast<int16_t*>(data); | 570 value = *reinterpret_cast<int16_t*>(data); |
571 count = 2; | 571 count = 2; |
572 break; | 572 break; |
573 case DOUBLEWORD_SIZE: | 573 case kDoublewordSize: |
574 value = *reinterpret_cast<uint32_t*>(data); | 574 value = *reinterpret_cast<uint32_t*>(data); |
575 count = 4; | 575 count = 4; |
576 break; | 576 break; |
577 case QUADWORD_SIZE: | 577 case kQuadwordSize: |
578 value = *reinterpret_cast<int32_t*>(data); | 578 value = *reinterpret_cast<int32_t*>(data); |
579 count = 4; | 579 count = 4; |
580 break; | 580 break; |
581 default: | 581 default: |
582 UNREACHABLE(); | 582 UNREACHABLE(); |
583 value = 0; // Initialize variables on all paths to satisfy the compiler. | 583 value = 0; // Initialize variables on all paths to satisfy the compiler. |
584 count = 0; | 584 count = 0; |
585 } | 585 } |
586 AppendToBuffer("%" V8_PTR_PREFIX "x", value); | 586 AppendToBuffer("%" V8_PTR_PREFIX "x", value); |
587 return count; | 587 return count; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
675 break; | 675 break; |
676 case 7: | 676 case 7: |
677 mnem = "cmp"; | 677 mnem = "cmp"; |
678 break; | 678 break; |
679 default: | 679 default: |
680 UnimplementedInstruction(); | 680 UnimplementedInstruction(); |
681 } | 681 } |
682 AppendToBuffer("%s%c ", mnem, operand_size_code()); | 682 AppendToBuffer("%s%c ", mnem, operand_size_code()); |
683 int count = PrintRightOperand(data + 1); | 683 int count = PrintRightOperand(data + 1); |
684 AppendToBuffer(",0x"); | 684 AppendToBuffer(",0x"); |
685 OperandSize immediate_size = byte_size_immediate ? BYTE_SIZE : operand_size(); | 685 OperandSize immediate_size = byte_size_immediate ? kByteSize : operand_size(); |
686 count += PrintImmediate(data + 1 + count, immediate_size); | 686 count += PrintImmediate(data + 1 + count, immediate_size); |
687 return 1 + count; | 687 return 1 + count; |
688 } | 688 } |
689 | 689 |
690 | 690 |
691 // Returns number of bytes used, including *data. | 691 // Returns number of bytes used, including *data. |
692 int DisassemblerX64::F6F7Instruction(byte* data) { | 692 int DisassemblerX64::F6F7Instruction(byte* data) { |
693 ASSERT(*data == 0xF7 || *data == 0xF6); | 693 ASSERT(*data == 0xF7 || *data == 0xF6); |
694 byte modrm = *(data + 1); | 694 byte modrm = *(data + 1); |
695 int mod, regop, rm; | 695 int mod, regop, rm; |
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1408 break; | 1408 break; |
1409 case PUSHPOP_INSTR: | 1409 case PUSHPOP_INSTR: |
1410 AppendToBuffer("%s %s", | 1410 AppendToBuffer("%s %s", |
1411 idesc.mnem, | 1411 idesc.mnem, |
1412 NameOfCPURegister(base_reg(current & 0x07))); | 1412 NameOfCPURegister(base_reg(current & 0x07))); |
1413 data++; | 1413 data++; |
1414 break; | 1414 break; |
1415 case MOVE_REG_INSTR: { | 1415 case MOVE_REG_INSTR: { |
1416 byte* addr = NULL; | 1416 byte* addr = NULL; |
1417 switch (operand_size()) { | 1417 switch (operand_size()) { |
1418 case WORD_SIZE: | 1418 case kWordSize: |
1419 addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1)); | 1419 addr = reinterpret_cast<byte*>(*reinterpret_cast<int16_t*>(data + 1)); |
1420 data += 3; | 1420 data += 3; |
1421 break; | 1421 break; |
1422 case DOUBLEWORD_SIZE: | 1422 case kDoublewordSize: |
1423 addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); | 1423 addr = reinterpret_cast<byte*>(*reinterpret_cast<int32_t*>(data + 1)); |
1424 data += 5; | 1424 data += 5; |
1425 break; | 1425 break; |
1426 case QUADWORD_SIZE: | 1426 case kQuadwordSize: |
1427 addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1)); | 1427 addr = reinterpret_cast<byte*>(*reinterpret_cast<int64_t*>(data + 1)); |
1428 data += 9; | 1428 data += 9; |
1429 break; | 1429 break; |
1430 default: | 1430 default: |
1431 UNREACHABLE(); | 1431 UNREACHABLE(); |
1432 } | 1432 } |
1433 AppendToBuffer("mov%c %s,%s", | 1433 AppendToBuffer("mov%c %s,%s", |
1434 operand_size_code(), | 1434 operand_size_code(), |
1435 NameOfCPURegister(base_reg(current & 0x07)), | 1435 NameOfCPURegister(base_reg(current & 0x07)), |
1436 NameOfAddress(addr)); | 1436 NameOfAddress(addr)); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1621 case 0xBF: { | 1621 case 0xBF: { |
1622 // mov reg8,imm8 or mov reg32,imm32 | 1622 // mov reg8,imm8 or mov reg32,imm32 |
1623 byte opcode = *data; | 1623 byte opcode = *data; |
1624 data++; | 1624 data++; |
1625 bool is_32bit = (opcode >= 0xB8); | 1625 bool is_32bit = (opcode >= 0xB8); |
1626 int reg = (opcode & 0x7) | (rex_b() ? 8 : 0); | 1626 int reg = (opcode & 0x7) | (rex_b() ? 8 : 0); |
1627 if (is_32bit) { | 1627 if (is_32bit) { |
1628 AppendToBuffer("mov%c %s, ", | 1628 AppendToBuffer("mov%c %s, ", |
1629 operand_size_code(), | 1629 operand_size_code(), |
1630 NameOfCPURegister(reg)); | 1630 NameOfCPURegister(reg)); |
1631 data += PrintImmediate(data, DOUBLEWORD_SIZE); | 1631 data += PrintImmediate(data, kDoublewordSize); |
1632 } else { | 1632 } else { |
1633 AppendToBuffer("movb %s, ", | 1633 AppendToBuffer("movb %s, ", |
1634 NameOfByteCPURegister(reg)); | 1634 NameOfByteCPURegister(reg)); |
1635 data += PrintImmediate(data, BYTE_SIZE); | 1635 data += PrintImmediate(data, kByteSize); |
1636 } | 1636 } |
1637 break; | 1637 break; |
1638 } | 1638 } |
1639 case 0xFE: { | 1639 case 0xFE: { |
1640 data++; | 1640 data++; |
1641 int mod, regop, rm; | 1641 int mod, regop, rm; |
1642 get_modrm(*data, &mod, ®op, &rm); | 1642 get_modrm(*data, &mod, ®op, &rm); |
1643 if (regop == 1) { | 1643 if (regop == 1) { |
1644 AppendToBuffer("decb "); | 1644 AppendToBuffer("decb "); |
1645 data += PrintRightByteOperand(data); | 1645 data += PrintRightByteOperand(data); |
1646 } else { | 1646 } else { |
1647 UnimplementedInstruction(); | 1647 UnimplementedInstruction(); |
1648 } | 1648 } |
1649 break; | 1649 break; |
1650 } | 1650 } |
1651 case 0x68: | 1651 case 0x68: |
1652 AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1)); | 1652 AppendToBuffer("push 0x%x", *reinterpret_cast<int32_t*>(data + 1)); |
1653 data += 5; | 1653 data += 5; |
1654 break; | 1654 break; |
1655 | 1655 |
1656 case 0x6A: | 1656 case 0x6A: |
1657 AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); | 1657 AppendToBuffer("push 0x%x", *reinterpret_cast<int8_t*>(data + 1)); |
1658 data += 2; | 1658 data += 2; |
1659 break; | 1659 break; |
1660 | 1660 |
1661 case 0xA1: // Fall through. | 1661 case 0xA1: // Fall through. |
1662 case 0xA3: | 1662 case 0xA3: |
1663 switch (operand_size()) { | 1663 switch (operand_size()) { |
1664 case DOUBLEWORD_SIZE: { | 1664 case kDoublewordSize: { |
1665 const char* memory_location = NameOfAddress( | 1665 const char* memory_location = NameOfAddress( |
1666 reinterpret_cast<byte*>( | 1666 reinterpret_cast<byte*>( |
1667 *reinterpret_cast<int32_t*>(data + 1))); | 1667 *reinterpret_cast<int32_t*>(data + 1))); |
1668 if (*data == 0xA1) { // Opcode 0xA1 | 1668 if (*data == 0xA1) { // Opcode 0xA1 |
1669 AppendToBuffer("movzxlq rax,(%s)", memory_location); | 1669 AppendToBuffer("movzxlq rax,(%s)", memory_location); |
1670 } else { // Opcode 0xA3 | 1670 } else { // Opcode 0xA3 |
1671 AppendToBuffer("movzxlq (%s),rax", memory_location); | 1671 AppendToBuffer("movzxlq (%s),rax", memory_location); |
1672 } | 1672 } |
1673 data += 5; | 1673 data += 5; |
1674 break; | 1674 break; |
1675 } | 1675 } |
1676 case QUADWORD_SIZE: { | 1676 case kQuadwordSize: { |
1677 // New x64 instruction mov rax,(imm_64). | 1677 // New x64 instruction mov rax,(imm_64). |
1678 const char* memory_location = NameOfAddress( | 1678 const char* memory_location = NameOfAddress( |
1679 *reinterpret_cast<byte**>(data + 1)); | 1679 *reinterpret_cast<byte**>(data + 1)); |
1680 if (*data == 0xA1) { // Opcode 0xA1 | 1680 if (*data == 0xA1) { // Opcode 0xA1 |
1681 AppendToBuffer("movq rax,(%s)", memory_location); | 1681 AppendToBuffer("movq rax,(%s)", memory_location); |
1682 } else { // Opcode 0xA3 | 1682 } else { // Opcode 0xA3 |
1683 AppendToBuffer("movq (%s),rax", memory_location); | 1683 AppendToBuffer("movq (%s),rax", memory_location); |
1684 } | 1684 } |
1685 data += 9; | 1685 data += 9; |
1686 break; | 1686 break; |
1687 } | 1687 } |
1688 default: | 1688 default: |
1689 UnimplementedInstruction(); | 1689 UnimplementedInstruction(); |
1690 data += 2; | 1690 data += 2; |
1691 } | 1691 } |
1692 break; | 1692 break; |
1693 | 1693 |
1694 case 0xA8: | 1694 case 0xA8: |
1695 AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1)); | 1695 AppendToBuffer("test al,0x%x", *reinterpret_cast<uint8_t*>(data + 1)); |
1696 data += 2; | 1696 data += 2; |
1697 break; | 1697 break; |
1698 | 1698 |
1699 case 0xA9: { | 1699 case 0xA9: { |
1700 int64_t value = 0; | 1700 int64_t value = 0; |
1701 switch (operand_size()) { | 1701 switch (operand_size()) { |
1702 case WORD_SIZE: | 1702 case kWordSize: |
1703 value = *reinterpret_cast<uint16_t*>(data + 1); | 1703 value = *reinterpret_cast<uint16_t*>(data + 1); |
1704 data += 3; | 1704 data += 3; |
1705 break; | 1705 break; |
1706 case DOUBLEWORD_SIZE: | 1706 case kDoublewordSize: |
1707 value = *reinterpret_cast<uint32_t*>(data + 1); | 1707 value = *reinterpret_cast<uint32_t*>(data + 1); |
1708 data += 5; | 1708 data += 5; |
1709 break; | 1709 break; |
1710 case QUADWORD_SIZE: | 1710 case kQuadwordSize: |
1711 value = *reinterpret_cast<int32_t*>(data + 1); | 1711 value = *reinterpret_cast<int32_t*>(data + 1); |
1712 data += 5; | 1712 data += 5; |
1713 break; | 1713 break; |
1714 default: | 1714 default: |
1715 UNREACHABLE(); | 1715 UNREACHABLE(); |
1716 } | 1716 } |
1717 AppendToBuffer("test%c rax,0x%" V8_PTR_PREFIX "x", | 1717 AppendToBuffer("test%c rax,0x%" V8_PTR_PREFIX "x", |
1718 operand_size_code(), | 1718 operand_size_code(), |
1719 value); | 1719 value); |
1720 break; | 1720 break; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1882 for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) { | 1882 for (int i = 6 - static_cast<int>(pc - prev_pc); i >= 0; i--) { |
1883 fprintf(f, " "); | 1883 fprintf(f, " "); |
1884 } | 1884 } |
1885 fprintf(f, " %s\n", buffer.start()); | 1885 fprintf(f, " %s\n", buffer.start()); |
1886 } | 1886 } |
1887 } | 1887 } |
1888 | 1888 |
1889 } // namespace disasm | 1889 } // namespace disasm |
1890 | 1890 |
1891 #endif // V8_TARGET_ARCH_X64 | 1891 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |