Chromium Code Reviews| 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 void PrintSd(Instruction* instr); | 79 void PrintSd(Instruction* instr); |
| 80 void PrintSs1(Instruction* instr); | 80 void PrintSs1(Instruction* instr); |
| 81 void PrintSs2(Instruction* instr); | 81 void PrintSs2(Instruction* instr); |
| 82 void PrintBc(Instruction* instr); | 82 void PrintBc(Instruction* instr); |
| 83 void PrintCc(Instruction* instr); | 83 void PrintCc(Instruction* instr); |
| 84 void PrintFunction(Instruction* instr); | 84 void PrintFunction(Instruction* instr); |
| 85 void PrintSecondaryField(Instruction* instr); | 85 void PrintSecondaryField(Instruction* instr); |
| 86 void PrintUImm16(Instruction* instr); | 86 void PrintUImm16(Instruction* instr); |
| 87 void PrintSImm16(Instruction* instr); | 87 void PrintSImm16(Instruction* instr); |
| 88 void PrintXImm16(Instruction* instr); | 88 void PrintXImm16(Instruction* instr); |
| 89 void PrintXImm21(Instruction* instr); | |
| 89 void PrintXImm26(Instruction* instr); | 90 void PrintXImm26(Instruction* instr); |
| 90 void PrintCode(Instruction* instr); // For break and trap instructions. | 91 void PrintCode(Instruction* instr); // For break and trap instructions. |
| 91 // Printing of instruction name. | 92 // Printing of instruction name. |
| 92 void PrintInstructionName(Instruction* instr); | 93 void PrintInstructionName(Instruction* instr); |
| 93 | 94 |
| 94 // Handle formatting of instructions and their options. | 95 // Handle formatting of instructions and their options. |
| 95 int FormatRegister(Instruction* instr, const char* option); | 96 int FormatRegister(Instruction* instr, const char* option); |
| 96 int FormatFPURegister(Instruction* instr, const char* option); | 97 int FormatFPURegister(Instruction* instr, const char* option); |
| 97 int FormatOption(Instruction* instr, const char* option); | 98 int FormatOption(Instruction* instr, const char* option); |
| 98 void Format(Instruction* instr, const char* format); | 99 void Format(Instruction* instr, const char* format); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 } | 241 } |
| 241 | 242 |
| 242 | 243 |
| 243 // Print 16-bit hexa immediate value. | 244 // Print 16-bit hexa immediate value. |
| 244 void Decoder::PrintXImm16(Instruction* instr) { | 245 void Decoder::PrintXImm16(Instruction* instr) { |
| 245 int32_t imm = instr->Imm16Value(); | 246 int32_t imm = instr->Imm16Value(); |
| 246 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); | 247 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
| 247 } | 248 } |
| 248 | 249 |
| 249 | 250 |
| 251 // Print 21-bit immediate value. | |
| 252 void Decoder::PrintXImm21(Instruction* instr) { | |
| 253 uint32_t imm = instr->Imm21Value(); | |
| 254 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); | |
| 255 } | |
| 256 | |
| 257 | |
| 250 // Print 26-bit immediate value. | 258 // Print 26-bit immediate value. |
| 251 void Decoder::PrintXImm26(Instruction* instr) { | 259 void Decoder::PrintXImm26(Instruction* instr) { |
| 252 uint32_t imm = instr->Imm26Value() << kImmFieldShift; | 260 uint32_t imm = instr->Imm26Value() << kImmFieldShift; |
| 253 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); | 261 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
| 254 } | 262 } |
| 255 | 263 |
| 256 | 264 |
| 257 // Print 26-bit immediate value. | 265 // Print 26-bit immediate value. |
| 258 void Decoder::PrintCode(Instruction* instr) { | 266 void Decoder::PrintCode(Instruction* instr) { |
| 259 if (instr->OpcodeFieldRaw() != SPECIAL) | 267 if (instr->OpcodeFieldRaw() != SPECIAL) |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 354 ASSERT(STRING_STARTS_WITH(format, "imm16s")); | 362 ASSERT(STRING_STARTS_WITH(format, "imm16s")); |
| 355 PrintSImm16(instr); | 363 PrintSImm16(instr); |
| 356 } else if (format[5] == 'u') { | 364 } else if (format[5] == 'u') { |
| 357 ASSERT(STRING_STARTS_WITH(format, "imm16u")); | 365 ASSERT(STRING_STARTS_WITH(format, "imm16u")); |
| 358 PrintSImm16(instr); | 366 PrintSImm16(instr); |
| 359 } else { | 367 } else { |
| 360 ASSERT(STRING_STARTS_WITH(format, "imm16x")); | 368 ASSERT(STRING_STARTS_WITH(format, "imm16x")); |
| 361 PrintXImm16(instr); | 369 PrintXImm16(instr); |
| 362 } | 370 } |
| 363 return 6; | 371 return 6; |
| 364 } else { | 372 } else if (format[3] == '2' && format[4] == '1') { |
| 373 ASSERT(STRING_STARTS_WITH(format, "imm21x")); | |
| 374 PrintXImm21(instr); | |
| 375 return 6; | |
| 376 } else if (format[3] == '2' && format[4] == '6') { | |
| 365 ASSERT(STRING_STARTS_WITH(format, "imm26x")); | 377 ASSERT(STRING_STARTS_WITH(format, "imm26x")); |
| 366 PrintXImm26(instr); | 378 PrintXImm26(instr); |
| 367 return 6; | 379 return 6; |
| 368 } | 380 } |
| 369 } | 381 } |
| 370 case 'r': { // 'r: registers. | 382 case 'r': { // 'r: registers. |
| 371 return FormatRegister(instr, format); | 383 return FormatRegister(instr, format); |
| 372 } | 384 } |
| 373 case 'f': { // 'f: FPUregisters. | 385 case 'f': { // 'f: FPUregisters. |
| 374 return FormatFPURegister(instr, format); | 386 return FormatFPURegister(instr, format); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 Format(instr, "break, code: 'code"); | 471 Format(instr, "break, code: 'code"); |
| 460 return Instruction::kInstrSize; | 472 return Instruction::kInstrSize; |
| 461 } | 473 } |
| 462 } | 474 } |
| 463 | 475 |
| 464 | 476 |
| 465 int Decoder::DecodeTypeRegister(Instruction* instr) { | 477 int Decoder::DecodeTypeRegister(Instruction* instr) { |
| 466 switch (instr->OpcodeFieldRaw()) { | 478 switch (instr->OpcodeFieldRaw()) { |
| 467 case COP1: // Coprocessor instructions. | 479 case COP1: // Coprocessor instructions. |
| 468 switch (instr->RsFieldRaw()) { | 480 switch (instr->RsFieldRaw()) { |
| 469 case BC1: // bc1 handled in DecodeTypeImmediate. | |
| 470 UNREACHABLE(); | |
| 471 break; | |
| 472 case MFC1: | 481 case MFC1: |
| 473 Format(instr, "mfc1 'rt, 'fs"); | 482 Format(instr, "mfc1 'rt, 'fs"); |
| 474 break; | 483 break; |
| 475 case DMFC1: | 484 case DMFC1: |
| 476 Format(instr, "dmfc1 'rt, 'fs"); | 485 Format(instr, "dmfc1 'rt, 'fs"); |
| 477 break; | 486 break; |
| 478 case MFHC1: | 487 case MFHC1: |
| 479 Format(instr, "mfhc1 'rt, 'fs"); | 488 Format(instr, "mfhc1 'rt, 'fs"); |
| 480 break; | 489 break; |
| 481 case MTC1: | 490 case MTC1: |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 575 Format(instr, "c.ole.d 'fs, 'ft, 'Cc"); | 584 Format(instr, "c.ole.d 'fs, 'ft, 'Cc"); |
| 576 break; | 585 break; |
| 577 case C_ULE_D: | 586 case C_ULE_D: |
| 578 Format(instr, "c.ule.d 'fs, 'ft, 'Cc"); | 587 Format(instr, "c.ule.d 'fs, 'ft, 'Cc"); |
| 579 break; | 588 break; |
| 580 default: | 589 default: |
| 581 Format(instr, "unknown.cop1.d"); | 590 Format(instr, "unknown.cop1.d"); |
| 582 break; | 591 break; |
| 583 } | 592 } |
| 584 break; | 593 break; |
| 585 case S: | |
| 586 UNIMPLEMENTED_MIPS(); | |
| 587 break; | |
| 588 case W: | 594 case W: |
| 589 switch (instr->FunctionFieldRaw()) { | 595 switch (instr->FunctionFieldRaw()) { |
| 590 case CVT_S_W: // Convert word to float (single). | |
| 591 Format(instr, "cvt.s.w 'fd, 'fs"); | |
| 592 break; | |
| 593 case CVT_D_W: // Convert word to double. | 596 case CVT_D_W: // Convert word to double. |
| 594 Format(instr, "cvt.d.w 'fd, 'fs"); | 597 Format(instr, "cvt.d.w 'fd, 'fs"); |
| 595 break; | 598 break; |
| 596 default: | 599 default: |
| 597 UNREACHABLE(); | 600 UNREACHABLE(); |
| 598 } | 601 } |
| 599 break; | 602 break; |
| 600 case L: | 603 case L: |
| 601 switch (instr->FunctionFieldRaw()) { | 604 switch (instr->FunctionFieldRaw()) { |
| 602 case CVT_D_L: | 605 case CVT_D_L: |
| 603 Format(instr, "cvt.d.l 'fd, 'fs"); | 606 Format(instr, "cvt.d.l 'fd, 'fs"); |
| 604 break; | 607 break; |
| 605 case CVT_S_L: | 608 case CVT_S_L: |
| 606 Format(instr, "cvt.s.l 'fd, 'fs"); | 609 Format(instr, "cvt.s.l 'fd, 'fs"); |
| 607 break; | 610 break; |
| 611 case CMP_UN: | |
| 612 Format(instr, "cmp.un.d 'fd, 'fs, 'ft"); | |
| 613 break; | |
| 614 case CMP_EQ: | |
| 615 Format(instr, "cmp.eq.d 'fd, 'fs, 'ft"); | |
| 616 break; | |
| 617 case CMP_UEQ: | |
| 618 Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft"); | |
| 619 break; | |
| 620 case CMP_LT: | |
| 621 Format(instr, "cmp.lt.d 'fd, 'fs, 'ft"); | |
| 622 break; | |
| 623 case CMP_ULT: | |
| 624 Format(instr, "cmp.ult.d 'fd, 'fs, 'ft"); | |
| 625 break; | |
| 626 case CMP_LE: | |
| 627 Format(instr, "cmp.le.d 'fd, 'fs, 'ft"); | |
| 628 break; | |
| 629 case CMP_ULE: | |
| 630 Format(instr, "cmp.ule.d 'fd, 'fs, 'ft"); | |
| 631 break; | |
| 632 case CMP_OR: | |
| 633 Format(instr, "cmp.or.d 'fd, 'fs, 'ft"); | |
| 634 break; | |
| 635 case CMP_UNE: | |
| 636 Format(instr, "cmp.une.d 'fd, 'fs, 'ft"); | |
| 637 break; | |
| 638 case CMP_NE: | |
| 639 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); | |
| 640 break; | |
| 608 default: | 641 default: |
| 609 UNREACHABLE(); | 642 UNREACHABLE(); |
| 610 } | 643 } |
| 611 break; | 644 break; |
| 612 case PS: | |
| 613 UNIMPLEMENTED_MIPS(); | |
| 614 break; | |
| 615 default: | 645 default: |
| 616 UNREACHABLE(); | 646 UNREACHABLE(); |
| 617 } | 647 } |
| 618 break; | 648 break; |
| 619 case COP1X: | 649 case COP1X: |
| 620 switch (instr->FunctionFieldRaw()) { | 650 switch (instr->FunctionFieldRaw()) { |
| 621 case MADD_D: | 651 case MADD_D: |
| 622 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); | 652 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); |
| 623 break; | 653 break; |
| 624 default: | 654 default: |
| 625 UNREACHABLE(); | 655 UNREACHABLE(); |
| 626 } | 656 } |
| 627 break; | 657 break; |
| 628 case SPECIAL: | 658 case SPECIAL: |
| 629 switch (instr->FunctionFieldRaw()) { | 659 switch (instr->FunctionFieldRaw()) { |
| 630 case JR: | 660 case JR: |
| 631 Format(instr, "jr 'rs"); | 661 Format(instr, "jr 'rs"); |
| 632 break; | 662 break; |
| 633 case JALR: | 663 case JALR: |
| 634 Format(instr, "jalr 'rs"); | 664 Format(instr, "jalr 'rs"); |
| 635 break; | 665 break; |
| 636 case SLL: | 666 case SLL: |
| 637 if ( 0x0 == static_cast<int>(instr->InstructionBits())) | 667 if (0x0 == static_cast<int>(instr->InstructionBits())) |
| 638 Format(instr, "nop"); | 668 Format(instr, "nop"); |
| 639 else | 669 else |
| 640 Format(instr, "sll 'rd, 'rt, 'sa"); | 670 Format(instr, "sll 'rd, 'rt, 'sa"); |
| 641 break; | 671 break; |
| 642 case DSLL: | 672 case DSLL: |
| 643 Format(instr, "dsll 'rd, 'rt, 'sa"); | 673 Format(instr, "dsll 'rd, 'rt, 'sa"); |
| 674 break; | |
| 675 case D_MUL_MUH: // Eqauls to DMUL. | |
|
paul.l...
2014/07/29 14:58:04
nit: Eqauls -> Equals
dusmil.imgtec
2014/07/29 17:39:12
Done.
| |
| 676 if (kArchVariant != kMips64r6) { | |
| 677 Format(instr, "dmult 'rs, 'rt"); | |
| 678 } else { | |
| 679 if (instr->SaValue() == MUL_OP) { | |
| 680 Format(instr, "dmul 'rd, 'rs, 'rt"); | |
| 681 } else { | |
| 682 Format(instr, "dmuh 'rd, 'rs, 'rt"); | |
| 683 } | |
| 684 } | |
| 644 break; | 685 break; |
| 645 case DSLL32: | 686 case DSLL32: |
| 646 Format(instr, "dsll32 'rd, 'rt, 'sa"); | 687 Format(instr, "dsll32 'rd, 'rt, 'sa"); |
| 647 break; | 688 break; |
| 648 case SRL: | 689 case SRL: |
| 649 if (instr->RsValue() == 0) { | 690 if (instr->RsValue() == 0) { |
| 650 Format(instr, "srl 'rd, 'rt, 'sa"); | 691 Format(instr, "srl 'rd, 'rt, 'sa"); |
| 651 } else { | 692 } else { |
| 652 if (kArchVariant == kMips64r2) { | 693 if (kArchVariant == kMips64r2) { |
| 653 Format(instr, "rotr 'rd, 'rt, 'sa"); | 694 Format(instr, "rotr 'rd, 'rt, 'sa"); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 707 } | 748 } |
| 708 } | 749 } |
| 709 break; | 750 break; |
| 710 case SRAV: | 751 case SRAV: |
| 711 Format(instr, "srav 'rd, 'rt, 'rs"); | 752 Format(instr, "srav 'rd, 'rt, 'rs"); |
| 712 break; | 753 break; |
| 713 case DSRAV: | 754 case DSRAV: |
| 714 Format(instr, "dsrav 'rd, 'rt, 'rs"); | 755 Format(instr, "dsrav 'rd, 'rt, 'rs"); |
| 715 break; | 756 break; |
| 716 case MFHI: | 757 case MFHI: |
| 717 Format(instr, "mfhi 'rd"); | 758 if (instr->Bits(25, 16) == 0) { |
| 759 Format(instr, "mfhi 'rd"); | |
| 760 } else { | |
| 761 if ((instr->FunctionFieldRaw() == CLZ_R6) | |
| 762 && (instr->FdValue() == 1)) { | |
| 763 Format(instr, "clz 'rd, 'rs"); | |
| 764 } else if ((instr->FunctionFieldRaw() == CLO_R6) | |
| 765 && (instr->FdValue() == 1)) { | |
| 766 Format(instr, "clo 'rd, 'rs"); | |
| 767 } | |
| 768 } | |
| 718 break; | 769 break; |
| 719 case MFLO: | 770 case MFLO: |
| 720 Format(instr, "mflo 'rd"); | 771 Format(instr, "mflo 'rd"); |
| 721 break; | 772 break; |
| 722 case MULT: | 773 case D_MUL_MUH_U: // Equals to DMULTU. |
| 723 Format(instr, "mult 'rs, 'rt"); | 774 if (kArchVariant != kMips64r6) { |
| 775 Format(instr, "dmultu 'rs, 'rt"); | |
| 776 } else { | |
| 777 if (instr->SaValue() == MUL_OP) { | |
| 778 Format(instr, "dmulu 'rd, 'rs, 'rt"); | |
| 779 } else { | |
| 780 Format(instr, "dmuhu 'rd, 'rs, 'rt"); | |
| 781 } | |
| 782 } | |
| 724 break; | 783 break; |
| 725 case DMULT: | 784 case MULT: // @Mips64r6 == MUL_MUH. |
| 726 Format(instr, "dmult 'rs, 'rt"); | 785 if (kArchVariant != kMips64r6) { |
| 786 Format(instr, "mult 'rs, 'rt"); | |
| 787 } else { | |
| 788 if (instr->SaValue() == MUL_OP) { | |
| 789 Format(instr, "mul 'rd, 'rs, 'rt"); | |
| 790 } else { | |
| 791 Format(instr, "muh 'rd, 'rs, 'rt"); | |
| 792 } | |
| 793 } | |
| 727 break; | 794 break; |
| 728 case MULTU: | 795 case MULTU: // @Mips64r6 == MUL_MUH_U. |
| 729 Format(instr, "multu 'rs, 'rt"); | 796 if (kArchVariant != kMips64r6) { |
| 797 Format(instr, "multu 'rs, 'rt"); | |
| 798 } else { | |
| 799 if (instr->SaValue() == MUL_OP) { | |
| 800 Format(instr, "mulu 'rd, 'rs, 'rt"); | |
| 801 } else { | |
| 802 Format(instr, "muhu 'rd, 'rs, 'rt"); | |
| 803 } | |
| 804 } | |
| 805 | |
| 730 break; | 806 break; |
| 731 case DMULTU: | 807 case DIV: // @Mips64r6 == DIV_MOD. |
| 732 Format(instr, "dmultu 'rs, 'rt"); | 808 if (kArchVariant != kMips64r6) { |
| 809 Format(instr, "div 'rs, 'rt"); | |
| 810 } else { | |
| 811 if (instr->SaValue() == DIV_OP) { | |
| 812 Format(instr, "div 'rd, 'rs, 'rt"); | |
| 813 } else { | |
| 814 Format(instr, "mod 'rd, 'rs, 'rt"); | |
| 815 } | |
| 816 } | |
| 733 break; | 817 break; |
| 734 case DIV: | 818 case DDIV: // @Mips64r6 == D_DIV_MOD. |
| 735 Format(instr, "div 'rs, 'rt"); | 819 if (kArchVariant != kMips64r6) { |
| 820 Format(instr, "ddiv 'rs, 'rt"); | |
| 821 } else { | |
| 822 if (instr->SaValue() == DIV_OP) { | |
| 823 Format(instr, "ddiv 'rd, 'rs, 'rt"); | |
| 824 } else { | |
| 825 Format(instr, "dmod 'rd, 'rs, 'rt"); | |
| 826 } | |
| 827 } | |
| 736 break; | 828 break; |
| 737 case DDIV: | 829 case DIVU: // @Mips64r6 == DIV_MOD_U. |
| 738 Format(instr, "ddiv 'rs, 'rt"); | 830 if (kArchVariant != kMips64r6) { |
| 831 Format(instr, "divu 'rs, 'rt"); | |
| 832 } else { | |
| 833 if (instr->SaValue() == DIV_OP) { | |
| 834 Format(instr, "divu 'rd, 'rs, 'rt"); | |
| 835 } else { | |
| 836 Format(instr, "modu 'rd, 'rs, 'rt"); | |
| 837 } | |
| 838 } | |
| 739 break; | 839 break; |
| 740 case DIVU: | 840 case DDIVU: // @Mips64r6 == D_DIV_MOD_U. |
| 741 Format(instr, "divu 'rs, 'rt"); | 841 if (kArchVariant != kMips64r6) { |
| 742 break; | 842 Format(instr, "ddivu 'rs, 'rt"); |
| 743 case DDIVU: | 843 } else { |
| 744 Format(instr, "ddivu 'rs, 'rt"); | 844 if (instr->SaValue() == DIV_OP) { |
| 845 Format(instr, "ddivu 'rd, 'rs, 'rt"); | |
| 846 } else { | |
| 847 Format(instr, "dmodu 'rd, 'rs, 'rt"); | |
| 848 } | |
| 849 } | |
| 745 break; | 850 break; |
| 746 case ADD: | 851 case ADD: |
| 747 Format(instr, "add 'rd, 'rs, 'rt"); | 852 Format(instr, "add 'rd, 'rs, 'rt"); |
| 748 break; | 853 break; |
| 749 case DADD: | 854 case DADD: |
| 750 Format(instr, "dadd 'rd, 'rs, 'rt"); | 855 Format(instr, "dadd 'rd, 'rs, 'rt"); |
| 751 break; | 856 break; |
| 752 case ADDU: | 857 case ADDU: |
| 753 Format(instr, "addu 'rd, 'rs, 'rt"); | 858 Format(instr, "addu 'rd, 'rs, 'rt"); |
| 754 break; | 859 break; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 817 case MOVN: | 922 case MOVN: |
| 818 Format(instr, "movn 'rd, 'rs, 'rt"); | 923 Format(instr, "movn 'rd, 'rs, 'rt"); |
| 819 break; | 924 break; |
| 820 case MOVCI: | 925 case MOVCI: |
| 821 if (instr->Bit(16)) { | 926 if (instr->Bit(16)) { |
| 822 Format(instr, "movt 'rd, 'rs, 'bc"); | 927 Format(instr, "movt 'rd, 'rs, 'bc"); |
| 823 } else { | 928 } else { |
| 824 Format(instr, "movf 'rd, 'rs, 'bc"); | 929 Format(instr, "movf 'rd, 'rs, 'bc"); |
| 825 } | 930 } |
| 826 break; | 931 break; |
| 932 case SELEQZ_S: | |
| 933 Format(instr, "seleqz 'rd, 'rs, 'rt"); | |
| 934 break; | |
| 935 case SELNEZ_S: | |
| 936 Format(instr, "selnez 'rd, 'rs, 'rt"); | |
| 937 break; | |
| 827 default: | 938 default: |
| 828 UNREACHABLE(); | 939 UNREACHABLE(); |
| 829 } | 940 } |
| 830 break; | 941 break; |
| 831 case SPECIAL2: | 942 case SPECIAL2: |
| 832 switch (instr->FunctionFieldRaw()) { | 943 switch (instr->FunctionFieldRaw()) { |
| 833 case MUL: | 944 case MUL: |
| 834 Format(instr, "mul 'rd, 'rs, 'rt"); | 945 Format(instr, "mul 'rd, 'rs, 'rt"); |
| 835 break; | 946 break; |
| 836 case CLZ: | 947 case CLZ: |
| 837 Format(instr, "clz 'rd, 'rs"); | 948 if (kArchVariant != kMips64r6) { |
| 949 Format(instr, "clz 'rd, 'rs"); | |
| 950 } | |
| 838 break; | 951 break; |
| 839 default: | 952 default: |
| 840 UNREACHABLE(); | 953 UNREACHABLE(); |
| 841 } | 954 } |
| 842 break; | 955 break; |
| 843 case SPECIAL3: | 956 case SPECIAL3: |
| 844 switch (instr->FunctionFieldRaw()) { | 957 switch (instr->FunctionFieldRaw()) { |
| 845 case INS: { | 958 case INS: { |
| 846 if (kArchVariant == kMips64r2) { | 959 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); |
| 847 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); | |
| 848 } else { | |
| 849 Unknown(instr); | |
| 850 } | |
| 851 break; | 960 break; |
| 852 } | 961 } |
| 853 case EXT: { | 962 case EXT: { |
| 854 if (kArchVariant == kMips64r2) { | 963 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); |
| 855 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); | |
| 856 } else { | |
| 857 Unknown(instr); | |
| 858 } | |
| 859 break; | 964 break; |
| 860 } | 965 } |
| 861 default: | 966 default: |
| 862 UNREACHABLE(); | 967 UNREACHABLE(); |
| 863 } | 968 } |
| 864 break; | 969 break; |
| 865 default: | 970 default: |
| 866 UNREACHABLE(); | 971 UNREACHABLE(); |
| 867 } | 972 } |
| 868 return Instruction::kInstrSize; | 973 return Instruction::kInstrSize; |
| 869 } | 974 } |
| 870 | 975 |
| 871 | 976 |
| 872 void Decoder::DecodeTypeImmediate(Instruction* instr) { | 977 void Decoder::DecodeTypeImmediate(Instruction* instr) { |
| 873 switch (instr->OpcodeFieldRaw()) { | 978 switch (instr->OpcodeFieldRaw()) { |
| 874 // ------------- REGIMM class. | |
| 875 case COP1: | 979 case COP1: |
| 876 switch (instr->RsFieldRaw()) { | 980 switch (instr->RsFieldRaw()) { |
| 877 case BC1: | 981 case BC1: |
| 878 if (instr->FBtrueValue()) { | 982 if (instr->FBtrueValue()) { |
| 879 Format(instr, "bc1t 'bc, 'imm16u"); | 983 Format(instr, "bc1t 'bc, 'imm16u"); |
| 880 } else { | 984 } else { |
| 881 Format(instr, "bc1f 'bc, 'imm16u"); | 985 Format(instr, "bc1f 'bc, 'imm16u"); |
| 882 } | 986 } |
| 883 break; | 987 break; |
| 988 case BC1EQZ: | |
| 989 Format(instr, "bc1eqz 'ft, 'imm16u"); | |
| 990 break; | |
| 991 case BC1NEZ: | |
| 992 Format(instr, "bc1nez 'ft, 'imm16u"); | |
| 993 break; | |
| 994 case W: // CMP.S instruction. | |
| 995 switch (instr->FunctionValue()) { | |
| 996 case CMP_AF: | |
| 997 Format(instr, "cmp.af.S 'ft, 'fs, 'fd"); | |
| 998 break; | |
| 999 case CMP_UN: | |
| 1000 Format(instr, "cmp.un.S 'ft, 'fs, 'fd"); | |
| 1001 break; | |
| 1002 case CMP_EQ: | |
| 1003 Format(instr, "cmp.eq.S 'ft, 'fs, 'fd"); | |
| 1004 break; | |
| 1005 case CMP_UEQ: | |
| 1006 Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd"); | |
| 1007 break; | |
| 1008 case CMP_LT: | |
| 1009 Format(instr, "cmp.lt.S 'ft, 'fs, 'fd"); | |
| 1010 break; | |
| 1011 case CMP_ULT: | |
| 1012 Format(instr, "cmp.ult.S 'ft, 'fs, 'fd"); | |
| 1013 break; | |
| 1014 case CMP_LE: | |
| 1015 Format(instr, "cmp.le.S 'ft, 'fs, 'fd"); | |
| 1016 break; | |
| 1017 case CMP_ULE: | |
| 1018 Format(instr, "cmp.ule.S 'ft, 'fs, 'fd"); | |
| 1019 break; | |
| 1020 case CMP_OR: | |
| 1021 Format(instr, "cmp.or.S 'ft, 'fs, 'fd"); | |
| 1022 break; | |
| 1023 case CMP_UNE: | |
| 1024 Format(instr, "cmp.une.S 'ft, 'fs, 'fd"); | |
| 1025 break; | |
| 1026 case CMP_NE: | |
| 1027 Format(instr, "cmp.ne.S 'ft, 'fs, 'fd"); | |
| 1028 break; | |
| 1029 default: | |
| 1030 UNREACHABLE(); | |
| 1031 } | |
| 1032 break; | |
| 1033 case L: // CMP.D instruction. | |
| 1034 switch (instr->FunctionValue()) { | |
| 1035 case CMP_AF: | |
| 1036 Format(instr, "cmp.af.D 'ft, 'fs, 'fd"); | |
| 1037 break; | |
| 1038 case CMP_UN: | |
| 1039 Format(instr, "cmp.un.D 'ft, 'fs, 'fd"); | |
| 1040 break; | |
| 1041 case CMP_EQ: | |
| 1042 Format(instr, "cmp.eq.D 'ft, 'fs, 'fd"); | |
| 1043 break; | |
| 1044 case CMP_UEQ: | |
| 1045 Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd"); | |
| 1046 break; | |
| 1047 case CMP_LT: | |
| 1048 Format(instr, "cmp.lt.D 'ft, 'fs, 'fd"); | |
| 1049 break; | |
| 1050 case CMP_ULT: | |
| 1051 Format(instr, "cmp.ult.D 'ft, 'fs, 'fd"); | |
| 1052 break; | |
| 1053 case CMP_LE: | |
| 1054 Format(instr, "cmp.le.D 'ft, 'fs, 'fd"); | |
| 1055 break; | |
| 1056 case CMP_ULE: | |
| 1057 Format(instr, "cmp.ule.D 'ft, 'fs, 'fd"); | |
| 1058 break; | |
| 1059 case CMP_OR: | |
| 1060 Format(instr, "cmp.or.D 'ft, 'fs, 'fd"); | |
| 1061 break; | |
| 1062 case CMP_UNE: | |
| 1063 Format(instr, "cmp.une.D 'ft, 'fs, 'fd"); | |
| 1064 break; | |
| 1065 case CMP_NE: | |
| 1066 Format(instr, "cmp.ne.D 'ft, 'fs, 'fd"); | |
| 1067 break; | |
| 1068 default: | |
| 1069 UNREACHABLE(); | |
| 1070 } | |
| 1071 break; | |
| 1072 case S: | |
| 1073 switch (instr->FunctionValue()) { | |
| 1074 case SEL: | |
| 1075 Format(instr, "sel.S 'ft, 'fs, 'fd"); | |
| 1076 break; | |
| 1077 case SELEQZ_C: | |
| 1078 Format(instr, "seleqz.S 'ft, 'fs, 'fd"); | |
| 1079 break; | |
| 1080 case SELNEZ_C: | |
| 1081 Format(instr, "selnez.S 'ft, 'fs, 'fd"); | |
| 1082 break; | |
| 1083 case MIN: | |
| 1084 Format(instr, "min.S 'ft, 'fs, 'fd"); | |
| 1085 break; | |
| 1086 case MINA: | |
| 1087 Format(instr, "mina.S 'ft, 'fs, 'fd"); | |
| 1088 break; | |
| 1089 case MAX: | |
| 1090 Format(instr, "max.S 'ft, 'fs, 'fd"); | |
| 1091 break; | |
| 1092 case MAXA: | |
| 1093 Format(instr, "maxa.S 'ft, 'fs, 'fd"); | |
| 1094 break; | |
| 1095 default: | |
| 1096 UNREACHABLE(); | |
| 1097 } | |
| 1098 break; | |
| 1099 case D: | |
| 1100 switch (instr->FunctionValue()) { | |
| 1101 case SEL: | |
| 1102 Format(instr, "sel.D 'ft, 'fs, 'fd"); | |
| 1103 break; | |
| 1104 case SELEQZ_C: | |
| 1105 Format(instr, "seleqz.D 'ft, 'fs, 'fd"); | |
| 1106 break; | |
| 1107 case SELNEZ_C: | |
| 1108 Format(instr, "selnez.D 'ft, 'fs, 'fd"); | |
| 1109 break; | |
| 1110 case MIN: | |
| 1111 Format(instr, "min.D 'ft, 'fs, 'fd"); | |
| 1112 break; | |
| 1113 case MINA: | |
| 1114 Format(instr, "mina.D 'ft, 'fs, 'fd"); | |
| 1115 break; | |
| 1116 case MAX: | |
| 1117 Format(instr, "max.D 'ft, 'fs, 'fd"); | |
| 1118 break; | |
| 1119 case MAXA: | |
| 1120 Format(instr, "maxa.D 'ft, 'fs, 'fd"); | |
| 1121 break; | |
| 1122 default: | |
| 1123 UNREACHABLE(); | |
| 1124 } | |
| 1125 break; | |
| 884 default: | 1126 default: |
| 885 UNREACHABLE(); | 1127 UNREACHABLE(); |
| 886 } | 1128 } |
| 1129 | |
| 887 break; // Case COP1. | 1130 break; // Case COP1. |
| 1131 // ------------- REGIMM class. | |
| 888 case REGIMM: | 1132 case REGIMM: |
| 889 switch (instr->RtFieldRaw()) { | 1133 switch (instr->RtFieldRaw()) { |
| 890 case BLTZ: | 1134 case BLTZ: |
| 891 Format(instr, "bltz 'rs, 'imm16u"); | 1135 Format(instr, "bltz 'rs, 'imm16u"); |
| 892 break; | 1136 break; |
| 893 case BLTZAL: | 1137 case BLTZAL: |
| 894 Format(instr, "bltzal 'rs, 'imm16u"); | 1138 Format(instr, "bltzal 'rs, 'imm16u"); |
| 895 break; | 1139 break; |
| 896 case BGEZ: | 1140 case BGEZ: |
| 897 Format(instr, "bgez 'rs, 'imm16u"); | 1141 Format(instr, "bgez 'rs, 'imm16u"); |
| 898 break; | 1142 break; |
| 899 case BGEZAL: | 1143 case BGEZAL: |
| 900 Format(instr, "bgezal 'rs, 'imm16u"); | 1144 Format(instr, "bgezal 'rs, 'imm16u"); |
| 901 break; | 1145 break; |
| 1146 case BGEZALL: | |
| 1147 Format(instr, "bgezall 'rs, 'imm16u"); | |
| 1148 break; | |
| 1149 case DAHI: | |
| 1150 Format(instr, "dahi 'rs, 'imm16u"); | |
| 1151 break; | |
| 1152 case DATI: | |
| 1153 Format(instr, "dati 'rs, 'imm16u"); | |
| 1154 break; | |
| 902 default: | 1155 default: |
| 903 UNREACHABLE(); | 1156 UNREACHABLE(); |
| 904 } | 1157 } |
| 905 break; // Case REGIMM. | 1158 break; // Case REGIMM. |
| 906 // ------------- Branch instructions. | 1159 // ------------- Branch instructions. |
| 907 case BEQ: | 1160 case BEQ: |
| 908 Format(instr, "beq 'rs, 'rt, 'imm16u"); | 1161 Format(instr, "beq 'rs, 'rt, 'imm16u"); |
| 909 break; | 1162 break; |
| 910 case BNE: | 1163 case BNE: |
| 911 Format(instr, "bne 'rs, 'rt, 'imm16u"); | 1164 Format(instr, "bne 'rs, 'rt, 'imm16u"); |
| 912 break; | 1165 break; |
| 913 case BLEZ: | 1166 case BLEZ: |
| 914 Format(instr, "blez 'rs, 'imm16u"); | 1167 if ((instr->RtFieldRaw() == 0) |
| 1168 && (instr->RsFieldRaw() != 0)) { | |
| 1169 Format(instr, "blez 'rs, 'imm16u"); | |
| 1170 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) | |
| 1171 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { | |
| 1172 Format(instr, "bgeuc 'rs, 'rt, 'imm16u"); | |
| 1173 } else if ((instr->RtFieldRaw() == instr->RsFieldRaw()) | |
| 1174 && (instr->RtFieldRaw() != 0)) { | |
| 1175 Format(instr, "bgezalc 'rs, 'imm16u"); | |
| 1176 } else if ((instr->RsFieldRaw() == 0) | |
| 1177 && (instr->RtFieldRaw() != 0)) { | |
| 1178 Format(instr, "blezalc 'rs, 'imm16u"); | |
| 1179 } else { | |
| 1180 UNREACHABLE(); | |
| 1181 } | |
| 915 break; | 1182 break; |
| 916 case BGTZ: | 1183 case BGTZ: |
| 917 Format(instr, "bgtz 'rs, 'imm16u"); | 1184 if ((instr->RtFieldRaw() == 0) |
| 1185 && (instr->RsFieldRaw() != 0)) { | |
| 1186 Format(instr, "bgtz 'rs, 'imm16u"); | |
| 1187 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) | |
| 1188 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { | |
| 1189 Format(instr, "bltuc 'rs, 'rt, 'imm16u"); | |
| 1190 } else if ((instr->RtFieldRaw() == instr->RsFieldRaw()) | |
| 1191 && (instr->RtFieldRaw() != 0)) { | |
| 1192 Format(instr, "bltzalc 'rt, 'imm16u"); | |
| 1193 } else if ((instr->RsFieldRaw() == 0) | |
| 1194 && (instr->RtFieldRaw() != 0)) { | |
| 1195 Format(instr, "bgtzalc 'rt, 'imm16u"); | |
| 1196 } else { | |
| 1197 UNREACHABLE(); | |
| 1198 } | |
| 1199 break; | |
| 1200 case BLEZL: | |
| 1201 if ((instr->RtFieldRaw() == instr->RsFieldRaw()) | |
| 1202 && (instr->RtFieldRaw() != 0)) { | |
| 1203 Format(instr, "bgezc 'rt, 'imm16u"); | |
| 1204 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) | |
| 1205 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { | |
| 1206 Format(instr, "bgec 'rs, 'rt, 'imm16u"); | |
| 1207 } else if ((instr->RsFieldRaw() == 0) | |
| 1208 && (instr->RtFieldRaw() != 0)) { | |
| 1209 Format(instr, "blezc 'rt, 'imm16u"); | |
| 1210 } else { | |
| 1211 UNREACHABLE(); | |
| 1212 } | |
| 1213 break; | |
| 1214 case BGTZL: | |
| 1215 if ((instr->RtFieldRaw() == instr->RsFieldRaw()) | |
| 1216 && (instr->RtFieldRaw() != 0)) { | |
| 1217 Format(instr, "bltzc 'rt, 'imm16u"); | |
| 1218 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) | |
| 1219 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { | |
| 1220 Format(instr, "bltc 'rs, 'rt, 'imm16u"); | |
| 1221 } else if ((instr->RsFieldRaw() == 0) | |
| 1222 && (instr->RtFieldRaw() != 0)) { | |
| 1223 Format(instr, "bgtzc 'rt, 'imm16u"); | |
| 1224 } else { | |
| 1225 UNREACHABLE(); | |
| 1226 } | |
| 1227 break; | |
| 1228 case BEQZC: | |
| 1229 if (instr->RsFieldRaw() != 0) { | |
| 1230 Format(instr, "beqzc 'rs, 'imm21x"); | |
| 1231 } | |
| 1232 break; | |
| 1233 case BNEZC: | |
| 1234 if (instr->RsFieldRaw() != 0) { | |
| 1235 Format(instr, "bnezc 'rs, 'imm21x"); | |
| 1236 } | |
| 918 break; | 1237 break; |
| 919 // ------------- Arithmetic instructions. | 1238 // ------------- Arithmetic instructions. |
| 920 case ADDI: | 1239 case ADDI: |
| 921 Format(instr, "addi 'rt, 'rs, 'imm16s"); | 1240 if (kArchVariant != kMips64r6) { |
| 1241 Format(instr, "addi 'rt, 'rs, 'imm16s"); | |
| 1242 } else { | |
| 1243 // Check if BOVC or BEQC instruction. | |
| 1244 if (instr->RsFieldRaw() >= instr->RtFieldRaw()) { | |
| 1245 Format(instr, "bovc 'rs, 'rt, 'imm16s"); | |
| 1246 } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) { | |
| 1247 Format(instr, "beqc 'rs, 'rt, 'imm16s"); | |
| 1248 } else { | |
| 1249 UNREACHABLE(); | |
| 1250 } | |
| 1251 } | |
| 922 break; | 1252 break; |
| 923 case DADDI: | 1253 case DADDI: |
| 924 Format(instr, "daddi 'rt, 'rs, 'imm16s"); | 1254 if (kArchVariant != kMips64r6) { |
| 1255 Format(instr, "daddi 'rt, 'rs, 'imm16s"); | |
| 1256 } else { | |
| 1257 // Check if BNVC or BNEC instruction. | |
| 1258 if (instr->RsFieldRaw() >= instr->RtFieldRaw()) { | |
| 1259 Format(instr, "bnvc 'rs, 'rt, 'imm16s"); | |
| 1260 } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) { | |
| 1261 Format(instr, "bnec 'rs, 'rt, 'imm16s"); | |
| 1262 } else { | |
| 1263 UNREACHABLE(); | |
| 1264 } | |
| 1265 } | |
| 925 break; | 1266 break; |
| 926 case ADDIU: | 1267 case ADDIU: |
| 927 Format(instr, "addiu 'rt, 'rs, 'imm16s"); | 1268 Format(instr, "addiu 'rt, 'rs, 'imm16s"); |
| 928 break; | 1269 break; |
| 929 case DADDIU: | 1270 case DADDIU: |
| 930 Format(instr, "daddiu 'rt, 'rs, 'imm16s"); | 1271 Format(instr, "daddiu 'rt, 'rs, 'imm16s"); |
| 931 break; | 1272 break; |
| 932 case SLTI: | 1273 case SLTI: |
| 933 Format(instr, "slti 'rt, 'rs, 'imm16s"); | 1274 Format(instr, "slti 'rt, 'rs, 'imm16s"); |
| 934 break; | 1275 break; |
| 935 case SLTIU: | 1276 case SLTIU: |
| 936 Format(instr, "sltiu 'rt, 'rs, 'imm16u"); | 1277 Format(instr, "sltiu 'rt, 'rs, 'imm16u"); |
| 937 break; | 1278 break; |
| 938 case ANDI: | 1279 case ANDI: |
| 939 Format(instr, "andi 'rt, 'rs, 'imm16x"); | 1280 Format(instr, "andi 'rt, 'rs, 'imm16x"); |
| 940 break; | 1281 break; |
| 941 case ORI: | 1282 case ORI: |
| 942 Format(instr, "ori 'rt, 'rs, 'imm16x"); | 1283 Format(instr, "ori 'rt, 'rs, 'imm16x"); |
| 943 break; | 1284 break; |
| 944 case XORI: | 1285 case XORI: |
| 945 Format(instr, "xori 'rt, 'rs, 'imm16x"); | 1286 Format(instr, "xori 'rt, 'rs, 'imm16x"); |
| 946 break; | 1287 break; |
| 947 case LUI: | 1288 case LUI: |
| 948 Format(instr, "lui 'rt, 'imm16x"); | 1289 if (kArchVariant != kMips64r6) { |
| 1290 Format(instr, "lui 'rt, 'imm16x"); | |
| 1291 } else { | |
| 1292 if (instr->RsValue() != 0) { | |
| 1293 Format(instr, "aui 'rt, 'imm16x"); | |
| 1294 } else { | |
| 1295 Format(instr, "lui 'rt, 'imm16x"); | |
| 1296 } | |
| 1297 } | |
| 1298 break; | |
| 1299 case DAUI: | |
| 1300 Format(instr, "daui 'rt, 'imm16x"); | |
| 949 break; | 1301 break; |
| 950 // ------------- Memory instructions. | 1302 // ------------- Memory instructions. |
| 951 case LB: | 1303 case LB: |
| 952 Format(instr, "lb 'rt, 'imm16s('rs)"); | 1304 Format(instr, "lb 'rt, 'imm16s('rs)"); |
| 953 break; | 1305 break; |
| 954 case LH: | 1306 case LH: |
| 955 Format(instr, "lh 'rt, 'imm16s('rs)"); | 1307 Format(instr, "lh 'rt, 'imm16s('rs)"); |
| 956 break; | 1308 break; |
| 957 case LWL: | 1309 case LWL: |
| 958 Format(instr, "lwl 'rt, 'imm16s('rs)"); | 1310 Format(instr, "lwl 'rt, 'imm16s('rs)"); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1143 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1495 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1144 } | 1496 } |
| 1145 } | 1497 } |
| 1146 | 1498 |
| 1147 | 1499 |
| 1148 #undef UNSUPPORTED | 1500 #undef UNSUPPORTED |
| 1149 | 1501 |
| 1150 } // namespace disasm | 1502 } // namespace disasm |
| 1151 | 1503 |
| 1152 #endif // V8_TARGET_ARCH_MIPS64 | 1504 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |