| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 // A Disassembler object is used to disassemble a block of code instruction by | 5 // A Disassembler object is used to disassemble a block of code instruction by |
| 6 // instruction. The default implementation of the NameConverter object can be | 6 // instruction. The default implementation of the NameConverter object can be |
| 7 // overriden to modify register names or to do symbol lookup on addresses. | 7 // overriden to modify register names or to do symbol lookup on addresses. |
| 8 // | 8 // |
| 9 // The example below will disassemble a block of code and print it to stdout. | 9 // The example below will disassemble a block of code and print it to stdout. |
| 10 // | 10 // |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 // achieved by just calling Disassembler::Disassemble(stdout, begin, end); | 23 // achieved by just calling Disassembler::Disassemble(stdout, begin, end); |
| 24 | 24 |
| 25 | 25 |
| 26 #include <assert.h> | 26 #include <assert.h> |
| 27 #include <stdarg.h> | 27 #include <stdarg.h> |
| 28 #include <stdio.h> | 28 #include <stdio.h> |
| 29 #include <string.h> | 29 #include <string.h> |
| 30 | 30 |
| 31 #include "src/v8.h" | 31 #include "src/v8.h" |
| 32 | 32 |
| 33 #if V8_TARGET_ARCH_MIPS | 33 #if V8_TARGET_ARCH_MIPS64 |
| 34 | 34 |
| 35 #include "src/base/platform/platform.h" | 35 #include "src/base/platform/platform.h" |
| 36 #include "src/disasm.h" | 36 #include "src/disasm.h" |
| 37 #include "src/macro-assembler.h" | 37 #include "src/macro-assembler.h" |
| 38 #include "src/mips/constants-mips.h" | 38 #include "src/mips64/constants-mips64.h" |
| 39 | 39 |
| 40 namespace v8 { | 40 namespace v8 { |
| 41 namespace internal { | 41 namespace internal { |
| 42 | 42 |
| 43 //------------------------------------------------------------------------------ | 43 //------------------------------------------------------------------------------ |
| 44 | 44 |
| 45 // Decoder decodes and disassembles instructions into an output buffer. | 45 // Decoder decodes and disassembles instructions into an output buffer. |
| 46 // It uses the converter to convert register names and call destinations into | 46 // It uses the converter to convert register names and call destinations into |
| 47 // more informative description. | 47 // more informative description. |
| 48 class Decoder { | 48 class Decoder { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 void PrintCode(Instruction* instr); // For break and trap instructions. | 90 void PrintCode(Instruction* instr); // For break and trap instructions. |
| 91 // Printing of instruction name. | 91 // Printing of instruction name. |
| 92 void PrintInstructionName(Instruction* instr); | 92 void PrintInstructionName(Instruction* instr); |
| 93 | 93 |
| 94 // Handle formatting of instructions and their options. | 94 // Handle formatting of instructions and their options. |
| 95 int FormatRegister(Instruction* instr, const char* option); | 95 int FormatRegister(Instruction* instr, const char* option); |
| 96 int FormatFPURegister(Instruction* instr, const char* option); | 96 int FormatFPURegister(Instruction* instr, const char* option); |
| 97 int FormatOption(Instruction* instr, const char* option); | 97 int FormatOption(Instruction* instr, const char* option); |
| 98 void Format(Instruction* instr, const char* format); | 98 void Format(Instruction* instr, const char* format); |
| 99 void Unknown(Instruction* instr); | 99 void Unknown(Instruction* instr); |
| 100 int DecodeBreakInstr(Instruction* instr); |
| 100 | 101 |
| 101 // Each of these functions decodes one particular instruction type. | 102 // Each of these functions decodes one particular instruction type. |
| 102 void DecodeTypeRegister(Instruction* instr); | 103 int DecodeTypeRegister(Instruction* instr); |
| 103 void DecodeTypeImmediate(Instruction* instr); | 104 void DecodeTypeImmediate(Instruction* instr); |
| 104 void DecodeTypeJump(Instruction* instr); | 105 void DecodeTypeJump(Instruction* instr); |
| 105 | 106 |
| 106 const disasm::NameConverter& converter_; | 107 const disasm::NameConverter& converter_; |
| 107 v8::internal::Vector<char> out_buffer_; | 108 v8::internal::Vector<char> out_buffer_; |
| 108 int out_buffer_pos_; | 109 int out_buffer_pos_; |
| 109 | 110 |
| 110 DISALLOW_COPY_AND_ASSIGN(Decoder); | 111 DISALLOW_COPY_AND_ASSIGN(Decoder); |
| 111 }; | 112 }; |
| 112 | 113 |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 } | 431 } |
| 431 | 432 |
| 432 | 433 |
| 433 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 434 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
| 434 // which will just print "unknown" of the instruction bits. | 435 // which will just print "unknown" of the instruction bits. |
| 435 void Decoder::Unknown(Instruction* instr) { | 436 void Decoder::Unknown(Instruction* instr) { |
| 436 Format(instr, "unknown"); | 437 Format(instr, "unknown"); |
| 437 } | 438 } |
| 438 | 439 |
| 439 | 440 |
| 440 void Decoder::DecodeTypeRegister(Instruction* instr) { | 441 int Decoder::DecodeBreakInstr(Instruction* instr) { |
| 442 // This is already known to be BREAK instr, just extract the code. |
| 443 if (instr->Bits(25, 6) == static_cast<int>(kMaxStopCode)) { |
| 444 // This is stop(msg). |
| 445 Format(instr, "break, code: 'code"); |
| 446 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 447 "\n%p %08lx stop msg: %s", |
| 448 static_cast<void*> |
| 449 (reinterpret_cast<int32_t*>(instr |
| 450 + Instruction::kInstrSize)), |
| 451 reinterpret_cast<uint64_t> |
| 452 (*reinterpret_cast<char**>(instr |
| 453 + Instruction::kInstrSize)), |
| 454 *reinterpret_cast<char**>(instr |
| 455 + Instruction::kInstrSize)); |
| 456 // Size 3: the break_ instr, plus embedded 64-bit char pointer. |
| 457 return 3 * Instruction::kInstrSize; |
| 458 } else { |
| 459 Format(instr, "break, code: 'code"); |
| 460 return Instruction::kInstrSize; |
| 461 } |
| 462 } |
| 463 |
| 464 |
| 465 int Decoder::DecodeTypeRegister(Instruction* instr) { |
| 441 switch (instr->OpcodeFieldRaw()) { | 466 switch (instr->OpcodeFieldRaw()) { |
| 442 case COP1: // Coprocessor instructions. | 467 case COP1: // Coprocessor instructions. |
| 443 switch (instr->RsFieldRaw()) { | 468 switch (instr->RsFieldRaw()) { |
| 444 case BC1: // bc1 handled in DecodeTypeImmediate. | 469 case BC1: // bc1 handled in DecodeTypeImmediate. |
| 445 UNREACHABLE(); | 470 UNREACHABLE(); |
| 446 break; | 471 break; |
| 447 case MFC1: | 472 case MFC1: |
| 448 Format(instr, "mfc1 'rt, 'fs"); | 473 Format(instr, "mfc1 'rt, 'fs"); |
| 449 break; | 474 break; |
| 475 case DMFC1: |
| 476 Format(instr, "dmfc1 'rt, 'fs"); |
| 477 break; |
| 450 case MFHC1: | 478 case MFHC1: |
| 451 Format(instr, "mfhc1 'rt, 'fs"); | 479 Format(instr, "mfhc1 'rt, 'fs"); |
| 452 break; | 480 break; |
| 453 case MTC1: | 481 case MTC1: |
| 454 Format(instr, "mtc1 'rt, 'fs"); | 482 Format(instr, "mtc1 'rt, 'fs"); |
| 455 break; | 483 break; |
| 484 case DMTC1: |
| 485 Format(instr, "dmtc1 'rt, 'fs"); |
| 486 break; |
| 456 // These are called "fs" too, although they are not FPU registers. | 487 // These are called "fs" too, although they are not FPU registers. |
| 457 case CTC1: | 488 case CTC1: |
| 458 Format(instr, "ctc1 'rt, 'fs"); | 489 Format(instr, "ctc1 'rt, 'fs"); |
| 459 break; | 490 break; |
| 460 case CFC1: | 491 case CFC1: |
| 461 Format(instr, "cfc1 'rt, 'fs"); | 492 Format(instr, "cfc1 'rt, 'fs"); |
| 462 break; | 493 break; |
| 463 case MTHC1: | 494 case MTHC1: |
| 464 Format(instr, "mthc1 'rt, 'fs"); | 495 Format(instr, "mthc1 'rt, 'fs"); |
| 465 break; | 496 break; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 485 break; | 516 break; |
| 486 case NEG_D: | 517 case NEG_D: |
| 487 Format(instr, "neg.d 'fd, 'fs"); | 518 Format(instr, "neg.d 'fd, 'fs"); |
| 488 break; | 519 break; |
| 489 case SQRT_D: | 520 case SQRT_D: |
| 490 Format(instr, "sqrt.d 'fd, 'fs"); | 521 Format(instr, "sqrt.d 'fd, 'fs"); |
| 491 break; | 522 break; |
| 492 case CVT_W_D: | 523 case CVT_W_D: |
| 493 Format(instr, "cvt.w.d 'fd, 'fs"); | 524 Format(instr, "cvt.w.d 'fd, 'fs"); |
| 494 break; | 525 break; |
| 495 case CVT_L_D: { | 526 case CVT_L_D: |
| 496 if (kArchVariant == kMips32r2) { | 527 Format(instr, "cvt.l.d 'fd, 'fs"); |
| 497 Format(instr, "cvt.l.d 'fd, 'fs"); | |
| 498 } else { | |
| 499 Unknown(instr); | |
| 500 } | |
| 501 break; | 528 break; |
| 502 } | |
| 503 case TRUNC_W_D: | 529 case TRUNC_W_D: |
| 504 Format(instr, "trunc.w.d 'fd, 'fs"); | 530 Format(instr, "trunc.w.d 'fd, 'fs"); |
| 505 break; | 531 break; |
| 506 case TRUNC_L_D: { | 532 case TRUNC_L_D: |
| 507 if (kArchVariant == kMips32r2) { | 533 Format(instr, "trunc.l.d 'fd, 'fs"); |
| 508 Format(instr, "trunc.l.d 'fd, 'fs"); | |
| 509 } else { | |
| 510 Unknown(instr); | |
| 511 } | |
| 512 break; | 534 break; |
| 513 } | |
| 514 case ROUND_W_D: | 535 case ROUND_W_D: |
| 515 Format(instr, "round.w.d 'fd, 'fs"); | 536 Format(instr, "round.w.d 'fd, 'fs"); |
| 516 break; | 537 break; |
| 538 case ROUND_L_D: |
| 539 Format(instr, "round.l.d 'fd, 'fs"); |
| 540 break; |
| 517 case FLOOR_W_D: | 541 case FLOOR_W_D: |
| 518 Format(instr, "floor.w.d 'fd, 'fs"); | 542 Format(instr, "floor.w.d 'fd, 'fs"); |
| 519 break; | 543 break; |
| 544 case FLOOR_L_D: |
| 545 Format(instr, "floor.l.d 'fd, 'fs"); |
| 546 break; |
| 520 case CEIL_W_D: | 547 case CEIL_W_D: |
| 521 Format(instr, "ceil.w.d 'fd, 'fs"); | 548 Format(instr, "ceil.w.d 'fd, 'fs"); |
| 522 break; | 549 break; |
| 550 case CEIL_L_D: |
| 551 Format(instr, "ceil.l.d 'fd, 'fs"); |
| 552 break; |
| 523 case CVT_S_D: | 553 case CVT_S_D: |
| 524 Format(instr, "cvt.s.d 'fd, 'fs"); | 554 Format(instr, "cvt.s.d 'fd, 'fs"); |
| 525 break; | 555 break; |
| 526 case C_F_D: | 556 case C_F_D: |
| 527 Format(instr, "c.f.d 'fs, 'ft, 'Cc"); | 557 Format(instr, "c.f.d 'fs, 'ft, 'Cc"); |
| 528 break; | 558 break; |
| 529 case C_UN_D: | 559 case C_UN_D: |
| 530 Format(instr, "c.un.d 'fs, 'ft, 'Cc"); | 560 Format(instr, "c.un.d 'fs, 'ft, 'Cc"); |
| 531 break; | 561 break; |
| 532 case C_EQ_D: | 562 case C_EQ_D: |
| (...skipping 29 matching lines...) Expand all Loading... |
| 562 break; | 592 break; |
| 563 case CVT_D_W: // Convert word to double. | 593 case CVT_D_W: // Convert word to double. |
| 564 Format(instr, "cvt.d.w 'fd, 'fs"); | 594 Format(instr, "cvt.d.w 'fd, 'fs"); |
| 565 break; | 595 break; |
| 566 default: | 596 default: |
| 567 UNREACHABLE(); | 597 UNREACHABLE(); |
| 568 } | 598 } |
| 569 break; | 599 break; |
| 570 case L: | 600 case L: |
| 571 switch (instr->FunctionFieldRaw()) { | 601 switch (instr->FunctionFieldRaw()) { |
| 572 case CVT_D_L: { | 602 case CVT_D_L: |
| 573 if (kArchVariant == kMips32r2) { | 603 Format(instr, "cvt.d.l 'fd, 'fs"); |
| 574 Format(instr, "cvt.d.l 'fd, 'fs"); | |
| 575 } else { | |
| 576 Unknown(instr); | |
| 577 } | |
| 578 break; | 604 break; |
| 579 } | 605 case CVT_S_L: |
| 580 case CVT_S_L: { | 606 Format(instr, "cvt.s.l 'fd, 'fs"); |
| 581 if (kArchVariant == kMips32r2) { | |
| 582 Format(instr, "cvt.s.l 'fd, 'fs"); | |
| 583 } else { | |
| 584 Unknown(instr); | |
| 585 } | |
| 586 break; | 607 break; |
| 587 } | |
| 588 default: | 608 default: |
| 589 UNREACHABLE(); | 609 UNREACHABLE(); |
| 590 } | 610 } |
| 591 break; | 611 break; |
| 592 case PS: | 612 case PS: |
| 593 UNIMPLEMENTED_MIPS(); | 613 UNIMPLEMENTED_MIPS(); |
| 594 break; | 614 break; |
| 595 default: | 615 default: |
| 596 UNREACHABLE(); | 616 UNREACHABLE(); |
| 597 } | 617 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 612 break; | 632 break; |
| 613 case JALR: | 633 case JALR: |
| 614 Format(instr, "jalr 'rs"); | 634 Format(instr, "jalr 'rs"); |
| 615 break; | 635 break; |
| 616 case SLL: | 636 case SLL: |
| 617 if ( 0x0 == static_cast<int>(instr->InstructionBits())) | 637 if ( 0x0 == static_cast<int>(instr->InstructionBits())) |
| 618 Format(instr, "nop"); | 638 Format(instr, "nop"); |
| 619 else | 639 else |
| 620 Format(instr, "sll 'rd, 'rt, 'sa"); | 640 Format(instr, "sll 'rd, 'rt, 'sa"); |
| 621 break; | 641 break; |
| 642 case DSLL: |
| 643 Format(instr, "dsll 'rd, 'rt, 'sa"); |
| 644 break; |
| 645 case DSLL32: |
| 646 Format(instr, "dsll32 'rd, 'rt, 'sa"); |
| 647 break; |
| 622 case SRL: | 648 case SRL: |
| 623 if (instr->RsValue() == 0) { | 649 if (instr->RsValue() == 0) { |
| 624 Format(instr, "srl 'rd, 'rt, 'sa"); | 650 Format(instr, "srl 'rd, 'rt, 'sa"); |
| 625 } else { | 651 } else { |
| 626 if (kArchVariant == kMips32r2) { | 652 if (kArchVariant == kMips64r2) { |
| 627 Format(instr, "rotr 'rd, 'rt, 'sa"); | 653 Format(instr, "rotr 'rd, 'rt, 'sa"); |
| 628 } else { | 654 } else { |
| 629 Unknown(instr); | 655 Unknown(instr); |
| 630 } | 656 } |
| 631 } | 657 } |
| 632 break; | 658 break; |
| 659 case DSRL: |
| 660 if (instr->RsValue() == 0) { |
| 661 Format(instr, "dsrl 'rd, 'rt, 'sa"); |
| 662 } else { |
| 663 if (kArchVariant == kMips64r2) { |
| 664 Format(instr, "drotr 'rd, 'rt, 'sa"); |
| 665 } else { |
| 666 Unknown(instr); |
| 667 } |
| 668 } |
| 669 break; |
| 670 case DSRL32: |
| 671 Format(instr, "dsrl32 'rd, 'rt, 'sa"); |
| 672 break; |
| 633 case SRA: | 673 case SRA: |
| 634 Format(instr, "sra 'rd, 'rt, 'sa"); | 674 Format(instr, "sra 'rd, 'rt, 'sa"); |
| 635 break; | 675 break; |
| 676 case DSRA: |
| 677 Format(instr, "dsra 'rd, 'rt, 'sa"); |
| 678 break; |
| 679 case DSRA32: |
| 680 Format(instr, "dsra32 'rd, 'rt, 'sa"); |
| 681 break; |
| 636 case SLLV: | 682 case SLLV: |
| 637 Format(instr, "sllv 'rd, 'rt, 'rs"); | 683 Format(instr, "sllv 'rd, 'rt, 'rs"); |
| 638 break; | 684 break; |
| 685 case DSLLV: |
| 686 Format(instr, "dsllv 'rd, 'rt, 'rs"); |
| 687 break; |
| 639 case SRLV: | 688 case SRLV: |
| 640 if (instr->SaValue() == 0) { | 689 if (instr->SaValue() == 0) { |
| 641 Format(instr, "srlv 'rd, 'rt, 'rs"); | 690 Format(instr, "srlv 'rd, 'rt, 'rs"); |
| 642 } else { | 691 } else { |
| 643 if (kArchVariant == kMips32r2) { | 692 if (kArchVariant == kMips64r2) { |
| 644 Format(instr, "rotrv 'rd, 'rt, 'rs"); | 693 Format(instr, "rotrv 'rd, 'rt, 'rs"); |
| 645 } else { | 694 } else { |
| 646 Unknown(instr); | 695 Unknown(instr); |
| 647 } | 696 } |
| 648 } | 697 } |
| 649 break; | 698 break; |
| 699 case DSRLV: |
| 700 if (instr->SaValue() == 0) { |
| 701 Format(instr, "dsrlv 'rd, 'rt, 'rs"); |
| 702 } else { |
| 703 if (kArchVariant == kMips64r2) { |
| 704 Format(instr, "drotrv 'rd, 'rt, 'rs"); |
| 705 } else { |
| 706 Unknown(instr); |
| 707 } |
| 708 } |
| 709 break; |
| 650 case SRAV: | 710 case SRAV: |
| 651 Format(instr, "srav 'rd, 'rt, 'rs"); | 711 Format(instr, "srav 'rd, 'rt, 'rs"); |
| 652 break; | 712 break; |
| 713 case DSRAV: |
| 714 Format(instr, "dsrav 'rd, 'rt, 'rs"); |
| 715 break; |
| 653 case MFHI: | 716 case MFHI: |
| 654 Format(instr, "mfhi 'rd"); | 717 Format(instr, "mfhi 'rd"); |
| 655 break; | 718 break; |
| 656 case MFLO: | 719 case MFLO: |
| 657 Format(instr, "mflo 'rd"); | 720 Format(instr, "mflo 'rd"); |
| 658 break; | 721 break; |
| 659 case MULT: | 722 case MULT: |
| 660 Format(instr, "mult 'rs, 'rt"); | 723 Format(instr, "mult 'rs, 'rt"); |
| 661 break; | 724 break; |
| 725 case DMULT: |
| 726 Format(instr, "dmult 'rs, 'rt"); |
| 727 break; |
| 662 case MULTU: | 728 case MULTU: |
| 663 Format(instr, "multu 'rs, 'rt"); | 729 Format(instr, "multu 'rs, 'rt"); |
| 664 break; | 730 break; |
| 731 case DMULTU: |
| 732 Format(instr, "dmultu 'rs, 'rt"); |
| 733 break; |
| 665 case DIV: | 734 case DIV: |
| 666 Format(instr, "div 'rs, 'rt"); | 735 Format(instr, "div 'rs, 'rt"); |
| 667 break; | 736 break; |
| 737 case DDIV: |
| 738 Format(instr, "ddiv 'rs, 'rt"); |
| 739 break; |
| 668 case DIVU: | 740 case DIVU: |
| 669 Format(instr, "divu 'rs, 'rt"); | 741 Format(instr, "divu 'rs, 'rt"); |
| 670 break; | 742 break; |
| 743 case DDIVU: |
| 744 Format(instr, "ddivu 'rs, 'rt"); |
| 745 break; |
| 671 case ADD: | 746 case ADD: |
| 672 Format(instr, "add 'rd, 'rs, 'rt"); | 747 Format(instr, "add 'rd, 'rs, 'rt"); |
| 673 break; | 748 break; |
| 749 case DADD: |
| 750 Format(instr, "dadd 'rd, 'rs, 'rt"); |
| 751 break; |
| 674 case ADDU: | 752 case ADDU: |
| 675 Format(instr, "addu 'rd, 'rs, 'rt"); | 753 Format(instr, "addu 'rd, 'rs, 'rt"); |
| 676 break; | 754 break; |
| 755 case DADDU: |
| 756 Format(instr, "daddu 'rd, 'rs, 'rt"); |
| 757 break; |
| 677 case SUB: | 758 case SUB: |
| 678 Format(instr, "sub 'rd, 'rs, 'rt"); | 759 Format(instr, "sub 'rd, 'rs, 'rt"); |
| 679 break; | 760 break; |
| 761 case DSUB: |
| 762 Format(instr, "dsub 'rd, 'rs, 'rt"); |
| 763 break; |
| 680 case SUBU: | 764 case SUBU: |
| 681 Format(instr, "subu 'rd, 'rs, 'rt"); | 765 Format(instr, "subu 'rd, 'rs, 'rt"); |
| 682 break; | 766 break; |
| 767 case DSUBU: |
| 768 Format(instr, "dsubu 'rd, 'rs, 'rt"); |
| 769 break; |
| 683 case AND: | 770 case AND: |
| 684 Format(instr, "and 'rd, 'rs, 'rt"); | 771 Format(instr, "and 'rd, 'rs, 'rt"); |
| 685 break; | 772 break; |
| 686 case OR: | 773 case OR: |
| 687 if (0 == instr->RsValue()) { | 774 if (0 == instr->RsValue()) { |
| 688 Format(instr, "mov 'rd, 'rt"); | 775 Format(instr, "mov 'rd, 'rt"); |
| 689 } else if (0 == instr->RtValue()) { | 776 } else if (0 == instr->RtValue()) { |
| 690 Format(instr, "mov 'rd, 'rs"); | 777 Format(instr, "mov 'rd, 'rs"); |
| 691 } else { | 778 } else { |
| 692 Format(instr, "or 'rd, 'rs, 'rt"); | 779 Format(instr, "or 'rd, 'rs, 'rt"); |
| 693 } | 780 } |
| 694 break; | 781 break; |
| 695 case XOR: | 782 case XOR: |
| 696 Format(instr, "xor 'rd, 'rs, 'rt"); | 783 Format(instr, "xor 'rd, 'rs, 'rt"); |
| 697 break; | 784 break; |
| 698 case NOR: | 785 case NOR: |
| 699 Format(instr, "nor 'rd, 'rs, 'rt"); | 786 Format(instr, "nor 'rd, 'rs, 'rt"); |
| 700 break; | 787 break; |
| 701 case SLT: | 788 case SLT: |
| 702 Format(instr, "slt 'rd, 'rs, 'rt"); | 789 Format(instr, "slt 'rd, 'rs, 'rt"); |
| 703 break; | 790 break; |
| 704 case SLTU: | 791 case SLTU: |
| 705 Format(instr, "sltu 'rd, 'rs, 'rt"); | 792 Format(instr, "sltu 'rd, 'rs, 'rt"); |
| 706 break; | 793 break; |
| 707 case BREAK: | 794 case BREAK: |
| 708 Format(instr, "break, code: 'code"); | 795 return DecodeBreakInstr(instr); |
| 709 break; | |
| 710 case TGE: | 796 case TGE: |
| 711 Format(instr, "tge 'rs, 'rt, code: 'code"); | 797 Format(instr, "tge 'rs, 'rt, code: 'code"); |
| 712 break; | 798 break; |
| 713 case TGEU: | 799 case TGEU: |
| 714 Format(instr, "tgeu 'rs, 'rt, code: 'code"); | 800 Format(instr, "tgeu 'rs, 'rt, code: 'code"); |
| 715 break; | 801 break; |
| 716 case TLT: | 802 case TLT: |
| 717 Format(instr, "tlt 'rs, 'rt, code: 'code"); | 803 Format(instr, "tlt 'rs, 'rt, code: 'code"); |
| 718 break; | 804 break; |
| 719 case TLTU: | 805 case TLTU: |
| (...skipping 30 matching lines...) Expand all Loading... |
| 750 case CLZ: | 836 case CLZ: |
| 751 Format(instr, "clz 'rd, 'rs"); | 837 Format(instr, "clz 'rd, 'rs"); |
| 752 break; | 838 break; |
| 753 default: | 839 default: |
| 754 UNREACHABLE(); | 840 UNREACHABLE(); |
| 755 } | 841 } |
| 756 break; | 842 break; |
| 757 case SPECIAL3: | 843 case SPECIAL3: |
| 758 switch (instr->FunctionFieldRaw()) { | 844 switch (instr->FunctionFieldRaw()) { |
| 759 case INS: { | 845 case INS: { |
| 760 if (kArchVariant == kMips32r2) { | 846 if (kArchVariant == kMips64r2) { |
| 761 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); | 847 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); |
| 762 } else { | 848 } else { |
| 763 Unknown(instr); | 849 Unknown(instr); |
| 764 } | 850 } |
| 765 break; | 851 break; |
| 766 } | 852 } |
| 767 case EXT: { | 853 case EXT: { |
| 768 if (kArchVariant == kMips32r2) { | 854 if (kArchVariant == kMips64r2) { |
| 769 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); | 855 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); |
| 770 } else { | 856 } else { |
| 771 Unknown(instr); | 857 Unknown(instr); |
| 772 } | 858 } |
| 773 break; | 859 break; |
| 774 } | 860 } |
| 775 default: | 861 default: |
| 776 UNREACHABLE(); | 862 UNREACHABLE(); |
| 777 } | 863 } |
| 778 break; | 864 break; |
| 779 default: | 865 default: |
| 780 UNREACHABLE(); | 866 UNREACHABLE(); |
| 781 } | 867 } |
| 868 return Instruction::kInstrSize; |
| 782 } | 869 } |
| 783 | 870 |
| 784 | 871 |
| 785 void Decoder::DecodeTypeImmediate(Instruction* instr) { | 872 void Decoder::DecodeTypeImmediate(Instruction* instr) { |
| 786 switch (instr->OpcodeFieldRaw()) { | 873 switch (instr->OpcodeFieldRaw()) { |
| 787 // ------------- REGIMM class. | 874 // ------------- REGIMM class. |
| 788 case COP1: | 875 case COP1: |
| 789 switch (instr->RsFieldRaw()) { | 876 switch (instr->RsFieldRaw()) { |
| 790 case BC1: | 877 case BC1: |
| 791 if (instr->FBtrueValue()) { | 878 if (instr->FBtrueValue()) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 case BLEZ: | 913 case BLEZ: |
| 827 Format(instr, "blez 'rs, 'imm16u"); | 914 Format(instr, "blez 'rs, 'imm16u"); |
| 828 break; | 915 break; |
| 829 case BGTZ: | 916 case BGTZ: |
| 830 Format(instr, "bgtz 'rs, 'imm16u"); | 917 Format(instr, "bgtz 'rs, 'imm16u"); |
| 831 break; | 918 break; |
| 832 // ------------- Arithmetic instructions. | 919 // ------------- Arithmetic instructions. |
| 833 case ADDI: | 920 case ADDI: |
| 834 Format(instr, "addi 'rt, 'rs, 'imm16s"); | 921 Format(instr, "addi 'rt, 'rs, 'imm16s"); |
| 835 break; | 922 break; |
| 923 case DADDI: |
| 924 Format(instr, "daddi 'rt, 'rs, 'imm16s"); |
| 925 break; |
| 836 case ADDIU: | 926 case ADDIU: |
| 837 Format(instr, "addiu 'rt, 'rs, 'imm16s"); | 927 Format(instr, "addiu 'rt, 'rs, 'imm16s"); |
| 838 break; | 928 break; |
| 929 case DADDIU: |
| 930 Format(instr, "daddiu 'rt, 'rs, 'imm16s"); |
| 931 break; |
| 839 case SLTI: | 932 case SLTI: |
| 840 Format(instr, "slti 'rt, 'rs, 'imm16s"); | 933 Format(instr, "slti 'rt, 'rs, 'imm16s"); |
| 841 break; | 934 break; |
| 842 case SLTIU: | 935 case SLTIU: |
| 843 Format(instr, "sltiu 'rt, 'rs, 'imm16u"); | 936 Format(instr, "sltiu 'rt, 'rs, 'imm16u"); |
| 844 break; | 937 break; |
| 845 case ANDI: | 938 case ANDI: |
| 846 Format(instr, "andi 'rt, 'rs, 'imm16x"); | 939 Format(instr, "andi 'rt, 'rs, 'imm16x"); |
| 847 break; | 940 break; |
| 848 case ORI: | 941 case ORI: |
| 849 Format(instr, "ori 'rt, 'rs, 'imm16x"); | 942 Format(instr, "ori 'rt, 'rs, 'imm16x"); |
| 850 break; | 943 break; |
| 851 case XORI: | 944 case XORI: |
| 852 Format(instr, "xori 'rt, 'rs, 'imm16x"); | 945 Format(instr, "xori 'rt, 'rs, 'imm16x"); |
| 853 break; | 946 break; |
| 854 case LUI: | 947 case LUI: |
| 855 Format(instr, "lui 'rt, 'imm16x"); | 948 Format(instr, "lui 'rt, 'imm16x"); |
| 856 break; | 949 break; |
| 857 // ------------- Memory instructions. | 950 // ------------- Memory instructions. |
| 858 case LB: | 951 case LB: |
| 859 Format(instr, "lb 'rt, 'imm16s('rs)"); | 952 Format(instr, "lb 'rt, 'imm16s('rs)"); |
| 860 break; | 953 break; |
| 861 case LH: | 954 case LH: |
| 862 Format(instr, "lh 'rt, 'imm16s('rs)"); | 955 Format(instr, "lh 'rt, 'imm16s('rs)"); |
| 863 break; | 956 break; |
| 864 case LWL: | 957 case LWL: |
| 865 Format(instr, "lwl 'rt, 'imm16s('rs)"); | 958 Format(instr, "lwl 'rt, 'imm16s('rs)"); |
| 866 break; | 959 break; |
| 960 case LDL: |
| 961 Format(instr, "ldl 'rt, 'imm16s('rs)"); |
| 962 break; |
| 867 case LW: | 963 case LW: |
| 868 Format(instr, "lw 'rt, 'imm16s('rs)"); | 964 Format(instr, "lw 'rt, 'imm16s('rs)"); |
| 869 break; | 965 break; |
| 966 case LWU: |
| 967 Format(instr, "lwu 'rt, 'imm16s('rs)"); |
| 968 break; |
| 969 case LD: |
| 970 Format(instr, "ld 'rt, 'imm16s('rs)"); |
| 971 break; |
| 870 case LBU: | 972 case LBU: |
| 871 Format(instr, "lbu 'rt, 'imm16s('rs)"); | 973 Format(instr, "lbu 'rt, 'imm16s('rs)"); |
| 872 break; | 974 break; |
| 873 case LHU: | 975 case LHU: |
| 874 Format(instr, "lhu 'rt, 'imm16s('rs)"); | 976 Format(instr, "lhu 'rt, 'imm16s('rs)"); |
| 875 break; | 977 break; |
| 876 case LWR: | 978 case LWR: |
| 877 Format(instr, "lwr 'rt, 'imm16s('rs)"); | 979 Format(instr, "lwr 'rt, 'imm16s('rs)"); |
| 878 break; | 980 break; |
| 981 case LDR: |
| 982 Format(instr, "ldr 'rt, 'imm16s('rs)"); |
| 983 break; |
| 879 case PREF: | 984 case PREF: |
| 880 Format(instr, "pref 'rt, 'imm16s('rs)"); | 985 Format(instr, "pref 'rt, 'imm16s('rs)"); |
| 881 break; | 986 break; |
| 882 case SB: | 987 case SB: |
| 883 Format(instr, "sb 'rt, 'imm16s('rs)"); | 988 Format(instr, "sb 'rt, 'imm16s('rs)"); |
| 884 break; | 989 break; |
| 885 case SH: | 990 case SH: |
| 886 Format(instr, "sh 'rt, 'imm16s('rs)"); | 991 Format(instr, "sh 'rt, 'imm16s('rs)"); |
| 887 break; | 992 break; |
| 888 case SWL: | 993 case SWL: |
| 889 Format(instr, "swl 'rt, 'imm16s('rs)"); | 994 Format(instr, "swl 'rt, 'imm16s('rs)"); |
| 890 break; | 995 break; |
| 891 case SW: | 996 case SW: |
| 892 Format(instr, "sw 'rt, 'imm16s('rs)"); | 997 Format(instr, "sw 'rt, 'imm16s('rs)"); |
| 893 break; | 998 break; |
| 999 case SD: |
| 1000 Format(instr, "sd 'rt, 'imm16s('rs)"); |
| 1001 break; |
| 894 case SWR: | 1002 case SWR: |
| 895 Format(instr, "swr 'rt, 'imm16s('rs)"); | 1003 Format(instr, "swr 'rt, 'imm16s('rs)"); |
| 896 break; | 1004 break; |
| 897 case LWC1: | 1005 case LWC1: |
| 898 Format(instr, "lwc1 'ft, 'imm16s('rs)"); | 1006 Format(instr, "lwc1 'ft, 'imm16s('rs)"); |
| 899 break; | 1007 break; |
| 900 case LDC1: | 1008 case LDC1: |
| 901 Format(instr, "ldc1 'ft, 'imm16s('rs)"); | 1009 Format(instr, "ldc1 'ft, 'imm16s('rs)"); |
| 902 break; | 1010 break; |
| 903 case SWC1: | 1011 case SWC1: |
| 904 Format(instr, "swc1 'ft, 'imm16s('rs)"); | 1012 Format(instr, "swc1 'ft, 'imm16s('rs)"); |
| 905 break; | 1013 break; |
| 906 case SDC1: | 1014 case SDC1: |
| 907 Format(instr, "sdc1 'ft, 'imm16s('rs)"); | 1015 Format(instr, "sdc1 'ft, 'imm16s('rs)"); |
| 908 break; | 1016 break; |
| 909 default: | 1017 default: |
| 910 UNREACHABLE(); | 1018 printf("a 0x%x \n", instr->OpcodeFieldRaw()); |
| 1019 UNREACHABLE(); |
| 911 break; | 1020 break; |
| 912 } | 1021 } |
| 913 } | 1022 } |
| 914 | 1023 |
| 915 | 1024 |
| 916 void Decoder::DecodeTypeJump(Instruction* instr) { | 1025 void Decoder::DecodeTypeJump(Instruction* instr) { |
| 917 switch (instr->OpcodeFieldRaw()) { | 1026 switch (instr->OpcodeFieldRaw()) { |
| 918 case J: | 1027 case J: |
| 919 Format(instr, "j 'imm26x"); | 1028 Format(instr, "j 'imm26x"); |
| 920 break; | 1029 break; |
| 921 case JAL: | 1030 case JAL: |
| 922 Format(instr, "jal 'imm26x"); | 1031 Format(instr, "jal 'imm26x"); |
| 923 break; | 1032 break; |
| 924 default: | 1033 default: |
| 925 UNREACHABLE(); | 1034 UNREACHABLE(); |
| 926 } | 1035 } |
| 927 } | 1036 } |
| 928 | 1037 |
| 929 | 1038 |
| 930 // Disassemble the instruction at *instr_ptr into the output buffer. | 1039 // Disassemble the instruction at *instr_ptr into the output buffer. |
| 1040 // All instructions are one word long, except for the simulator |
| 1041 // psuedo-instruction stop(msg). For that one special case, we return |
| 1042 // size larger than one kInstrSize. |
| 931 int Decoder::InstructionDecode(byte* instr_ptr) { | 1043 int Decoder::InstructionDecode(byte* instr_ptr) { |
| 932 Instruction* instr = Instruction::At(instr_ptr); | 1044 Instruction* instr = Instruction::At(instr_ptr); |
| 933 // Print raw instruction bytes. | 1045 // Print raw instruction bytes. |
| 934 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, | 1046 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, |
| 935 "%08x ", | 1047 "%08x ", |
| 936 instr->InstructionBits()); | 1048 instr->InstructionBits()); |
| 937 switch (instr->InstructionType()) { | 1049 switch (instr->InstructionType()) { |
| 938 case Instruction::kRegisterType: { | 1050 case Instruction::kRegisterType: { |
| 939 DecodeTypeRegister(instr); | 1051 return DecodeTypeRegister(instr); |
| 940 break; | |
| 941 } | 1052 } |
| 942 case Instruction::kImmediateType: { | 1053 case Instruction::kImmediateType: { |
| 943 DecodeTypeImmediate(instr); | 1054 DecodeTypeImmediate(instr); |
| 944 break; | 1055 break; |
| 945 } | 1056 } |
| 946 case Instruction::kJumpType: { | 1057 case Instruction::kJumpType: { |
| 947 DecodeTypeJump(instr); | 1058 DecodeTypeJump(instr); |
| 948 break; | 1059 break; |
| 949 } | 1060 } |
| 950 default: { | 1061 default: { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 v8::internal::PrintF(f, "%p %08x %s\n", | 1142 v8::internal::PrintF(f, "%p %08x %s\n", |
| 1032 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1143 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1033 } | 1144 } |
| 1034 } | 1145 } |
| 1035 | 1146 |
| 1036 | 1147 |
| 1037 #undef UNSUPPORTED | 1148 #undef UNSUPPORTED |
| 1038 | 1149 |
| 1039 } // namespace disasm | 1150 } // namespace disasm |
| 1040 | 1151 |
| 1041 #endif // V8_TARGET_ARCH_MIPS | 1152 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |