OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <assert.h> | 5 #include <assert.h> |
6 #include <stdarg.h> | 6 #include <stdarg.h> |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); | 204 SetTableRange(MOVE_REG_INSTR, 0xB8, 0xBF, "mov"); |
205 } | 205 } |
206 | 206 |
207 | 207 |
208 void InstructionTable::CopyTable(const ByteMnemonic bm[], | 208 void InstructionTable::CopyTable(const ByteMnemonic bm[], |
209 InstructionType type) { | 209 InstructionType type) { |
210 for (int i = 0; bm[i].b >= 0; i++) { | 210 for (int i = 0; bm[i].b >= 0; i++) { |
211 InstructionDesc* id = &instructions_[bm[i].b]; | 211 InstructionDesc* id = &instructions_[bm[i].b]; |
212 id->mnem = bm[i].mnem; | 212 id->mnem = bm[i].mnem; |
213 id->op_order_ = bm[i].op_order_; | 213 id->op_order_ = bm[i].op_order_; |
214 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. | 214 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered. |
215 id->type = type; | 215 id->type = type; |
216 } | 216 } |
217 } | 217 } |
218 | 218 |
219 | 219 |
220 void InstructionTable::SetTableRange(InstructionType type, | 220 void InstructionTable::SetTableRange(InstructionType type, |
221 byte start, | 221 byte start, |
222 byte end, | 222 byte end, |
223 const char* mnem) { | 223 const char* mnem) { |
224 for (byte b = start; b <= end; b++) { | 224 for (byte b = start; b <= end; b++) { |
225 InstructionDesc* id = &instructions_[b]; | 225 InstructionDesc* id = &instructions_[b]; |
226 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. | 226 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered. |
227 id->mnem = mnem; | 227 id->mnem = mnem; |
228 id->type = type; | 228 id->type = type; |
229 } | 229 } |
230 } | 230 } |
231 | 231 |
232 | 232 |
233 void InstructionTable::AddJumpConditionalShort() { | 233 void InstructionTable::AddJumpConditionalShort() { |
234 for (byte b = 0x70; b <= 0x7F; b++) { | 234 for (byte b = 0x70; b <= 0x7F; b++) { |
235 InstructionDesc* id = &instructions_[b]; | 235 InstructionDesc* id = &instructions_[b]; |
236 ASSERT_EQ(NO_INSTR, id->type); // Information not already entered. | 236 DCHECK_EQ(NO_INSTR, id->type); // Information not already entered. |
237 id->mnem = jump_conditional_mnem[b & 0x0F]; | 237 id->mnem = jump_conditional_mnem[b & 0x0F]; |
238 id->type = JUMP_CONDITIONAL_SHORT_INSTR; | 238 id->type = JUMP_CONDITIONAL_SHORT_INSTR; |
239 } | 239 } |
240 } | 240 } |
241 | 241 |
242 | 242 |
243 // The IA32 disassembler implementation. | 243 // The IA32 disassembler implementation. |
244 class DisassemblerIA32 { | 244 class DisassemblerIA32 { |
245 public: | 245 public: |
246 DisassemblerIA32(const NameConverter& converter, | 246 DisassemblerIA32(const NameConverter& converter, |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 return 1 + count + 1 /*int8*/; | 521 return 1 + count + 1 /*int8*/; |
522 } else { | 522 } else { |
523 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count)); | 523 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + 1 + count)); |
524 return 1 + count + 4 /*int32_t*/; | 524 return 1 + count + 4 /*int32_t*/; |
525 } | 525 } |
526 } | 526 } |
527 | 527 |
528 | 528 |
529 // Returns number of bytes used, including *data. | 529 // Returns number of bytes used, including *data. |
530 int DisassemblerIA32::F7Instruction(byte* data) { | 530 int DisassemblerIA32::F7Instruction(byte* data) { |
531 ASSERT_EQ(0xF7, *data); | 531 DCHECK_EQ(0xF7, *data); |
532 byte modrm = *++data; | 532 byte modrm = *++data; |
533 int mod, regop, rm; | 533 int mod, regop, rm; |
534 get_modrm(modrm, &mod, ®op, &rm); | 534 get_modrm(modrm, &mod, ®op, &rm); |
535 const char* mnem = NULL; | 535 const char* mnem = NULL; |
536 switch (regop) { | 536 switch (regop) { |
537 case 0: | 537 case 0: |
538 mnem = "test"; | 538 mnem = "test"; |
539 break; | 539 break; |
540 case 2: | 540 case 2: |
541 mnem = "not"; | 541 mnem = "not"; |
(...skipping 21 matching lines...) Expand all Loading... |
563 if (regop == 0) { | 563 if (regop == 0) { |
564 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + count)); | 564 AppendToBuffer(",0x%x", *reinterpret_cast<int32_t*>(data + count)); |
565 count += 4; | 565 count += 4; |
566 } | 566 } |
567 return 1 + count; | 567 return 1 + count; |
568 } | 568 } |
569 | 569 |
570 | 570 |
571 int DisassemblerIA32::D1D3C1Instruction(byte* data) { | 571 int DisassemblerIA32::D1D3C1Instruction(byte* data) { |
572 byte op = *data; | 572 byte op = *data; |
573 ASSERT(op == 0xD1 || op == 0xD3 || op == 0xC1); | 573 DCHECK(op == 0xD1 || op == 0xD3 || op == 0xC1); |
574 byte modrm = *++data; | 574 byte modrm = *++data; |
575 int mod, regop, rm; | 575 int mod, regop, rm; |
576 get_modrm(modrm, &mod, ®op, &rm); | 576 get_modrm(modrm, &mod, ®op, &rm); |
577 int imm8 = -1; | 577 int imm8 = -1; |
578 const char* mnem = NULL; | 578 const char* mnem = NULL; |
579 switch (regop) { | 579 switch (regop) { |
580 case kROL: | 580 case kROL: |
581 mnem = "rol"; | 581 mnem = "rol"; |
582 break; | 582 break; |
583 case kROR: | 583 case kROR: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 AppendToBuffer(",%d", imm8); | 615 AppendToBuffer(",%d", imm8); |
616 } else { | 616 } else { |
617 AppendToBuffer(",cl"); | 617 AppendToBuffer(",cl"); |
618 } | 618 } |
619 return 1 + count; | 619 return 1 + count; |
620 } | 620 } |
621 | 621 |
622 | 622 |
623 // Returns number of bytes used, including *data. | 623 // Returns number of bytes used, including *data. |
624 int DisassemblerIA32::JumpShort(byte* data) { | 624 int DisassemblerIA32::JumpShort(byte* data) { |
625 ASSERT_EQ(0xEB, *data); | 625 DCHECK_EQ(0xEB, *data); |
626 byte b = *(data+1); | 626 byte b = *(data+1); |
627 byte* dest = data + static_cast<int8_t>(b) + 2; | 627 byte* dest = data + static_cast<int8_t>(b) + 2; |
628 AppendToBuffer("jmp %s", NameOfAddress(dest)); | 628 AppendToBuffer("jmp %s", NameOfAddress(dest)); |
629 return 2; | 629 return 2; |
630 } | 630 } |
631 | 631 |
632 | 632 |
633 // Returns number of bytes used, including *data. | 633 // Returns number of bytes used, including *data. |
634 int DisassemblerIA32::JumpConditional(byte* data, const char* comment) { | 634 int DisassemblerIA32::JumpConditional(byte* data, const char* comment) { |
635 ASSERT_EQ(0x0F, *data); | 635 DCHECK_EQ(0x0F, *data); |
636 byte cond = *(data+1) & 0x0F; | 636 byte cond = *(data+1) & 0x0F; |
637 byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6; | 637 byte* dest = data + *reinterpret_cast<int32_t*>(data+2) + 6; |
638 const char* mnem = jump_conditional_mnem[cond]; | 638 const char* mnem = jump_conditional_mnem[cond]; |
639 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); | 639 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); |
640 if (comment != NULL) { | 640 if (comment != NULL) { |
641 AppendToBuffer(", %s", comment); | 641 AppendToBuffer(", %s", comment); |
642 } | 642 } |
643 return 6; // includes 0x0F | 643 return 6; // includes 0x0F |
644 } | 644 } |
645 | 645 |
646 | 646 |
647 // Returns number of bytes used, including *data. | 647 // Returns number of bytes used, including *data. |
648 int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) { | 648 int DisassemblerIA32::JumpConditionalShort(byte* data, const char* comment) { |
649 byte cond = *data & 0x0F; | 649 byte cond = *data & 0x0F; |
650 byte b = *(data+1); | 650 byte b = *(data+1); |
651 byte* dest = data + static_cast<int8_t>(b) + 2; | 651 byte* dest = data + static_cast<int8_t>(b) + 2; |
652 const char* mnem = jump_conditional_mnem[cond]; | 652 const char* mnem = jump_conditional_mnem[cond]; |
653 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); | 653 AppendToBuffer("%s %s", mnem, NameOfAddress(dest)); |
654 if (comment != NULL) { | 654 if (comment != NULL) { |
655 AppendToBuffer(", %s", comment); | 655 AppendToBuffer(", %s", comment); |
656 } | 656 } |
657 return 2; | 657 return 2; |
658 } | 658 } |
659 | 659 |
660 | 660 |
661 // Returns number of bytes used, including *data. | 661 // Returns number of bytes used, including *data. |
662 int DisassemblerIA32::SetCC(byte* data) { | 662 int DisassemblerIA32::SetCC(byte* data) { |
663 ASSERT_EQ(0x0F, *data); | 663 DCHECK_EQ(0x0F, *data); |
664 byte cond = *(data+1) & 0x0F; | 664 byte cond = *(data+1) & 0x0F; |
665 const char* mnem = set_conditional_mnem[cond]; | 665 const char* mnem = set_conditional_mnem[cond]; |
666 AppendToBuffer("%s ", mnem); | 666 AppendToBuffer("%s ", mnem); |
667 PrintRightByteOperand(data+2); | 667 PrintRightByteOperand(data+2); |
668 return 3; // Includes 0x0F. | 668 return 3; // Includes 0x0F. |
669 } | 669 } |
670 | 670 |
671 | 671 |
672 // Returns number of bytes used, including *data. | 672 // Returns number of bytes used, including *data. |
673 int DisassemblerIA32::CMov(byte* data) { | 673 int DisassemblerIA32::CMov(byte* data) { |
674 ASSERT_EQ(0x0F, *data); | 674 DCHECK_EQ(0x0F, *data); |
675 byte cond = *(data + 1) & 0x0F; | 675 byte cond = *(data + 1) & 0x0F; |
676 const char* mnem = conditional_move_mnem[cond]; | 676 const char* mnem = conditional_move_mnem[cond]; |
677 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); | 677 int op_size = PrintOperands(mnem, REG_OPER_OP_ORDER, data + 2); |
678 return 2 + op_size; // includes 0x0F | 678 return 2 + op_size; // includes 0x0F |
679 } | 679 } |
680 | 680 |
681 | 681 |
682 // Returns number of bytes used, including *data. | 682 // Returns number of bytes used, including *data. |
683 int DisassemblerIA32::FPUInstruction(byte* data) { | 683 int DisassemblerIA32::FPUInstruction(byte* data) { |
684 byte escape_opcode = *data; | 684 byte escape_opcode = *data; |
685 ASSERT_EQ(0xD8, escape_opcode & 0xF8); | 685 DCHECK_EQ(0xD8, escape_opcode & 0xF8); |
686 byte modrm_byte = *(data+1); | 686 byte modrm_byte = *(data+1); |
687 | 687 |
688 if (modrm_byte >= 0xC0) { | 688 if (modrm_byte >= 0xC0) { |
689 return RegisterFPUInstruction(escape_opcode, modrm_byte); | 689 return RegisterFPUInstruction(escape_opcode, modrm_byte); |
690 } else { | 690 } else { |
691 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); | 691 return MemoryFPUInstruction(escape_opcode, modrm_byte, data+1); |
692 } | 692 } |
693 } | 693 } |
694 | 694 |
695 int DisassemblerIA32::MemoryFPUInstruction(int escape_opcode, | 695 int DisassemblerIA32::MemoryFPUInstruction(int escape_opcode, |
(...skipping 688 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1384 get_modrm(*data, &mod, ®op, &rm); | 1384 get_modrm(*data, &mod, ®op, &rm); |
1385 AppendToBuffer("psllq %s,%s", | 1385 AppendToBuffer("psllq %s,%s", |
1386 NameOfXMMRegister(regop), | 1386 NameOfXMMRegister(regop), |
1387 NameOfXMMRegister(rm)); | 1387 NameOfXMMRegister(rm)); |
1388 data++; | 1388 data++; |
1389 } else if (*data == 0x73) { | 1389 } else if (*data == 0x73) { |
1390 data++; | 1390 data++; |
1391 int mod, regop, rm; | 1391 int mod, regop, rm; |
1392 get_modrm(*data, &mod, ®op, &rm); | 1392 get_modrm(*data, &mod, ®op, &rm); |
1393 int8_t imm8 = static_cast<int8_t>(data[1]); | 1393 int8_t imm8 = static_cast<int8_t>(data[1]); |
1394 ASSERT(regop == esi || regop == edx); | 1394 DCHECK(regop == esi || regop == edx); |
1395 AppendToBuffer("%s %s,%d", | 1395 AppendToBuffer("%s %s,%d", |
1396 (regop == esi) ? "psllq" : "psrlq", | 1396 (regop == esi) ? "psllq" : "psrlq", |
1397 NameOfXMMRegister(rm), | 1397 NameOfXMMRegister(rm), |
1398 static_cast<int>(imm8)); | 1398 static_cast<int>(imm8)); |
1399 data += 2; | 1399 data += 2; |
1400 } else if (*data == 0xD3) { | 1400 } else if (*data == 0xD3) { |
1401 data++; | 1401 data++; |
1402 int mod, regop, rm; | 1402 int mod, regop, rm; |
1403 get_modrm(*data, &mod, ®op, &rm); | 1403 get_modrm(*data, &mod, ®op, &rm); |
1404 AppendToBuffer("psrlq %s,%s", | 1404 AppendToBuffer("psrlq %s,%s", |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1651 } | 1651 } |
1652 | 1652 |
1653 if (tmp_buffer_pos_ < sizeof tmp_buffer_) { | 1653 if (tmp_buffer_pos_ < sizeof tmp_buffer_) { |
1654 tmp_buffer_[tmp_buffer_pos_] = '\0'; | 1654 tmp_buffer_[tmp_buffer_pos_] = '\0'; |
1655 } | 1655 } |
1656 | 1656 |
1657 int instr_len = data - instr; | 1657 int instr_len = data - instr; |
1658 if (instr_len == 0) { | 1658 if (instr_len == 0) { |
1659 printf("%02x", *data); | 1659 printf("%02x", *data); |
1660 } | 1660 } |
1661 ASSERT(instr_len > 0); // Ensure progress. | 1661 DCHECK(instr_len > 0); // Ensure progress. |
1662 | 1662 |
1663 int outp = 0; | 1663 int outp = 0; |
1664 // Instruction bytes. | 1664 // Instruction bytes. |
1665 for (byte* bp = instr; bp < data; bp++) { | 1665 for (byte* bp = instr; bp < data; bp++) { |
1666 outp += v8::internal::SNPrintF(out_buffer + outp, | 1666 outp += v8::internal::SNPrintF(out_buffer + outp, |
1667 "%02x", | 1667 "%02x", |
1668 *bp); | 1668 *bp); |
1669 } | 1669 } |
1670 for (int i = 6 - instr_len; i >= 0; i--) { | 1670 for (int i = 6 - instr_len; i >= 0; i--) { |
1671 outp += v8::internal::SNPrintF(out_buffer + outp, " "); | 1671 outp += v8::internal::SNPrintF(out_buffer + outp, " "); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1770 fprintf(f, " "); | 1770 fprintf(f, " "); |
1771 } | 1771 } |
1772 fprintf(f, " %s\n", buffer.start()); | 1772 fprintf(f, " %s\n", buffer.start()); |
1773 } | 1773 } |
1774 } | 1774 } |
1775 | 1775 |
1776 | 1776 |
1777 } // namespace disasm | 1777 } // namespace disasm |
1778 | 1778 |
1779 #endif // V8_TARGET_ARCH_IA32 | 1779 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |