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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 } | 240 } |
240 | 241 |
241 | 242 |
242 // Print 16-bit hexa immediate value. | 243 // Print 16-bit hexa immediate value. |
243 void Decoder::PrintXImm16(Instruction* instr) { | 244 void Decoder::PrintXImm16(Instruction* instr) { |
244 int32_t imm = instr->Imm16Value(); | 245 int32_t imm = instr->Imm16Value(); |
245 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); | 246 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
246 } | 247 } |
247 | 248 |
248 | 249 |
| 250 // Print 21-bit immediate value. |
| 251 void Decoder::PrintXImm21(Instruction* instr) { |
| 252 uint32_t imm = instr->Imm21Value(); |
| 253 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
| 254 } |
| 255 |
| 256 |
249 // Print 26-bit immediate value. | 257 // Print 26-bit immediate value. |
250 void Decoder::PrintXImm26(Instruction* instr) { | 258 void Decoder::PrintXImm26(Instruction* instr) { |
251 uint32_t imm = instr->Imm26Value() << kImmFieldShift; | 259 uint32_t imm = instr->Imm26Value() << kImmFieldShift; |
252 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); | 260 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
253 } | 261 } |
254 | 262 |
255 | 263 |
256 // Print 26-bit immediate value. | 264 // Print 26-bit immediate value. |
257 void Decoder::PrintCode(Instruction* instr) { | 265 void Decoder::PrintCode(Instruction* instr) { |
258 if (instr->OpcodeFieldRaw() != SPECIAL) | 266 if (instr->OpcodeFieldRaw() != SPECIAL) |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 DCHECK(STRING_STARTS_WITH(format, "imm16s")); | 361 DCHECK(STRING_STARTS_WITH(format, "imm16s")); |
354 PrintSImm16(instr); | 362 PrintSImm16(instr); |
355 } else if (format[5] == 'u') { | 363 } else if (format[5] == 'u') { |
356 DCHECK(STRING_STARTS_WITH(format, "imm16u")); | 364 DCHECK(STRING_STARTS_WITH(format, "imm16u")); |
357 PrintSImm16(instr); | 365 PrintSImm16(instr); |
358 } else { | 366 } else { |
359 DCHECK(STRING_STARTS_WITH(format, "imm16x")); | 367 DCHECK(STRING_STARTS_WITH(format, "imm16x")); |
360 PrintXImm16(instr); | 368 PrintXImm16(instr); |
361 } | 369 } |
362 return 6; | 370 return 6; |
363 } else { | 371 } else if (format[3] == '2' && format[4] == '1') { |
| 372 DCHECK(STRING_STARTS_WITH(format, "imm21x")); |
| 373 PrintXImm21(instr); |
| 374 return 6; |
| 375 } else if (format[3] == '2' && format[4] == '6') { |
364 DCHECK(STRING_STARTS_WITH(format, "imm26x")); | 376 DCHECK(STRING_STARTS_WITH(format, "imm26x")); |
365 PrintXImm26(instr); | 377 PrintXImm26(instr); |
366 return 6; | 378 return 6; |
367 } | 379 } |
368 } | 380 } |
369 case 'r': { // 'r: registers. | 381 case 'r': { // 'r: registers. |
370 return FormatRegister(instr, format); | 382 return FormatRegister(instr, format); |
371 } | 383 } |
372 case 'f': { // 'f: FPUregisters. | 384 case 'f': { // 'f: FPUregisters. |
373 return FormatFPURegister(instr, format); | 385 return FormatFPURegister(instr, format); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
485 break; | 497 break; |
486 case NEG_D: | 498 case NEG_D: |
487 Format(instr, "neg.d 'fd, 'fs"); | 499 Format(instr, "neg.d 'fd, 'fs"); |
488 break; | 500 break; |
489 case SQRT_D: | 501 case SQRT_D: |
490 Format(instr, "sqrt.d 'fd, 'fs"); | 502 Format(instr, "sqrt.d 'fd, 'fs"); |
491 break; | 503 break; |
492 case CVT_W_D: | 504 case CVT_W_D: |
493 Format(instr, "cvt.w.d 'fd, 'fs"); | 505 Format(instr, "cvt.w.d 'fd, 'fs"); |
494 break; | 506 break; |
495 case CVT_L_D: { | 507 case CVT_L_D: |
496 if (kArchVariant == kMips32r2) { | 508 Format(instr, "cvt.l.d 'fd, 'fs"); |
497 Format(instr, "cvt.l.d 'fd, 'fs"); | |
498 } else { | |
499 Unknown(instr); | |
500 } | |
501 break; | 509 break; |
502 } | |
503 case TRUNC_W_D: | 510 case TRUNC_W_D: |
504 Format(instr, "trunc.w.d 'fd, 'fs"); | 511 Format(instr, "trunc.w.d 'fd, 'fs"); |
505 break; | 512 break; |
506 case TRUNC_L_D: { | 513 case TRUNC_L_D: |
507 if (kArchVariant == kMips32r2) { | 514 Format(instr, "trunc.l.d 'fd, 'fs"); |
508 Format(instr, "trunc.l.d 'fd, 'fs"); | |
509 } else { | |
510 Unknown(instr); | |
511 } | |
512 break; | 515 break; |
513 } | |
514 case ROUND_W_D: | 516 case ROUND_W_D: |
515 Format(instr, "round.w.d 'fd, 'fs"); | 517 Format(instr, "round.w.d 'fd, 'fs"); |
516 break; | 518 break; |
517 case FLOOR_W_D: | 519 case FLOOR_W_D: |
518 Format(instr, "floor.w.d 'fd, 'fs"); | 520 Format(instr, "floor.w.d 'fd, 'fs"); |
519 break; | 521 break; |
520 case CEIL_W_D: | 522 case CEIL_W_D: |
521 Format(instr, "ceil.w.d 'fd, 'fs"); | 523 Format(instr, "ceil.w.d 'fd, 'fs"); |
522 break; | 524 break; |
523 case CVT_S_D: | 525 case CVT_S_D: |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 break; | 564 break; |
563 case CVT_D_W: // Convert word to double. | 565 case CVT_D_W: // Convert word to double. |
564 Format(instr, "cvt.d.w 'fd, 'fs"); | 566 Format(instr, "cvt.d.w 'fd, 'fs"); |
565 break; | 567 break; |
566 default: | 568 default: |
567 UNREACHABLE(); | 569 UNREACHABLE(); |
568 } | 570 } |
569 break; | 571 break; |
570 case L: | 572 case L: |
571 switch (instr->FunctionFieldRaw()) { | 573 switch (instr->FunctionFieldRaw()) { |
572 case CVT_D_L: { | 574 case CVT_D_L: |
573 if (kArchVariant == kMips32r2) { | 575 Format(instr, "cvt.d.l 'fd, 'fs"); |
574 Format(instr, "cvt.d.l 'fd, 'fs"); | |
575 } else { | |
576 Unknown(instr); | |
577 } | |
578 break; | 576 break; |
579 } | 577 case CVT_S_L: |
580 case CVT_S_L: { | 578 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; | 579 break; |
587 } | 580 case CMP_UN: |
| 581 Format(instr, "cmp.un.d 'fd, 'fs, 'ft"); |
| 582 break; |
| 583 case CMP_EQ: |
| 584 Format(instr, "cmp.eq.d 'fd, 'fs, 'ft"); |
| 585 break; |
| 586 case CMP_UEQ: |
| 587 Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft"); |
| 588 break; |
| 589 case CMP_LT: |
| 590 Format(instr, "cmp.lt.d 'fd, 'fs, 'ft"); |
| 591 break; |
| 592 case CMP_ULT: |
| 593 Format(instr, "cmp.ult.d 'fd, 'fs, 'ft"); |
| 594 break; |
| 595 case CMP_LE: |
| 596 Format(instr, "cmp.le.d 'fd, 'fs, 'ft"); |
| 597 break; |
| 598 case CMP_ULE: |
| 599 Format(instr, "cmp.ule.d 'fd, 'fs, 'ft"); |
| 600 break; |
| 601 case CMP_OR: |
| 602 Format(instr, "cmp.or.d 'fd, 'fs, 'ft"); |
| 603 break; |
| 604 case CMP_UNE: |
| 605 Format(instr, "cmp.une.d 'fd, 'fs, 'ft"); |
| 606 break; |
| 607 case CMP_NE: |
| 608 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); |
| 609 break; |
588 default: | 610 default: |
589 UNREACHABLE(); | 611 UNREACHABLE(); |
590 } | 612 } |
591 break; | 613 break; |
592 case PS: | 614 case PS: |
593 UNIMPLEMENTED_MIPS(); | 615 UNIMPLEMENTED_MIPS(); |
594 break; | 616 break; |
595 default: | 617 default: |
596 UNREACHABLE(); | 618 UNREACHABLE(); |
597 } | 619 } |
(...skipping 18 matching lines...) Expand all Loading... |
616 case SLL: | 638 case SLL: |
617 if ( 0x0 == static_cast<int>(instr->InstructionBits())) | 639 if ( 0x0 == static_cast<int>(instr->InstructionBits())) |
618 Format(instr, "nop"); | 640 Format(instr, "nop"); |
619 else | 641 else |
620 Format(instr, "sll 'rd, 'rt, 'sa"); | 642 Format(instr, "sll 'rd, 'rt, 'sa"); |
621 break; | 643 break; |
622 case SRL: | 644 case SRL: |
623 if (instr->RsValue() == 0) { | 645 if (instr->RsValue() == 0) { |
624 Format(instr, "srl 'rd, 'rt, 'sa"); | 646 Format(instr, "srl 'rd, 'rt, 'sa"); |
625 } else { | 647 } else { |
626 if (kArchVariant == kMips32r2) { | 648 if (IsMipsArchVariant(kMips32r2)) { |
627 Format(instr, "rotr 'rd, 'rt, 'sa"); | 649 Format(instr, "rotr 'rd, 'rt, 'sa"); |
628 } else { | 650 } else { |
629 Unknown(instr); | 651 Unknown(instr); |
630 } | 652 } |
631 } | 653 } |
632 break; | 654 break; |
633 case SRA: | 655 case SRA: |
634 Format(instr, "sra 'rd, 'rt, 'sa"); | 656 Format(instr, "sra 'rd, 'rt, 'sa"); |
635 break; | 657 break; |
636 case SLLV: | 658 case SLLV: |
637 Format(instr, "sllv 'rd, 'rt, 'rs"); | 659 Format(instr, "sllv 'rd, 'rt, 'rs"); |
638 break; | 660 break; |
639 case SRLV: | 661 case SRLV: |
640 if (instr->SaValue() == 0) { | 662 if (instr->SaValue() == 0) { |
641 Format(instr, "srlv 'rd, 'rt, 'rs"); | 663 Format(instr, "srlv 'rd, 'rt, 'rs"); |
642 } else { | 664 } else { |
643 if (kArchVariant == kMips32r2) { | 665 if (IsMipsArchVariant(kMips32r2)) { |
644 Format(instr, "rotrv 'rd, 'rt, 'rs"); | 666 Format(instr, "rotrv 'rd, 'rt, 'rs"); |
645 } else { | 667 } else { |
646 Unknown(instr); | 668 Unknown(instr); |
647 } | 669 } |
648 } | 670 } |
649 break; | 671 break; |
650 case SRAV: | 672 case SRAV: |
651 Format(instr, "srav 'rd, 'rt, 'rs"); | 673 Format(instr, "srav 'rd, 'rt, 'rs"); |
652 break; | 674 break; |
653 case MFHI: | 675 case MFHI: |
654 Format(instr, "mfhi 'rd"); | 676 if (instr->Bits(25, 16) == 0) { |
| 677 Format(instr, "mfhi 'rd"); |
| 678 } else { |
| 679 if ((instr->FunctionFieldRaw() == CLZ_R6) |
| 680 && (instr->FdValue() == 1)) { |
| 681 Format(instr, "clz 'rd, 'rs"); |
| 682 } else if ((instr->FunctionFieldRaw() == CLO_R6) |
| 683 && (instr->FdValue() == 1)) { |
| 684 Format(instr, "clo 'rd, 'rs"); |
| 685 } |
| 686 } |
655 break; | 687 break; |
656 case MFLO: | 688 case MFLO: |
657 Format(instr, "mflo 'rd"); | 689 Format(instr, "mflo 'rd"); |
658 break; | 690 break; |
659 case MULT: | 691 case MULT: // @Mips32r6 == MUL_MUH. |
660 Format(instr, "mult 'rs, 'rt"); | 692 if (!IsMipsArchVariant(kMips32r6)) { |
| 693 Format(instr, "mult 'rs, 'rt"); |
| 694 } else { |
| 695 if (instr->SaValue() == MUL_OP) { |
| 696 Format(instr, "mul 'rd, 'rs, 'rt"); |
| 697 } else { |
| 698 Format(instr, "muh 'rd, 'rs, 'rt"); |
| 699 } |
| 700 } |
661 break; | 701 break; |
662 case MULTU: | 702 case MULTU: // @Mips32r6 == MUL_MUH_U. |
663 Format(instr, "multu 'rs, 'rt"); | 703 if (!IsMipsArchVariant(kMips32r6)) { |
| 704 Format(instr, "multu 'rs, 'rt"); |
| 705 } else { |
| 706 if (instr->SaValue() == MUL_OP) { |
| 707 Format(instr, "mulu 'rd, 'rs, 'rt"); |
| 708 } else { |
| 709 Format(instr, "muhu 'rd, 'rs, 'rt"); |
| 710 } |
| 711 } |
664 break; | 712 break; |
665 case DIV: | 713 case DIV: // @Mips32r6 == DIV_MOD. |
666 Format(instr, "div 'rs, 'rt"); | 714 if (!IsMipsArchVariant(kMips32r6)) { |
| 715 Format(instr, "div 'rs, 'rt"); |
| 716 } else { |
| 717 if (instr->SaValue() == DIV_OP) { |
| 718 Format(instr, "div 'rd, 'rs, 'rt"); |
| 719 } else { |
| 720 Format(instr, "mod 'rd, 'rs, 'rt"); |
| 721 } |
| 722 } |
667 break; | 723 break; |
668 case DIVU: | 724 case DIVU: // @Mips32r6 == DIV_MOD_U. |
669 Format(instr, "divu 'rs, 'rt"); | 725 if (!IsMipsArchVariant(kMips32r6)) { |
| 726 Format(instr, "divu 'rs, 'rt"); |
| 727 } else { |
| 728 if (instr->SaValue() == DIV_OP) { |
| 729 Format(instr, "divu 'rd, 'rs, 'rt"); |
| 730 } else { |
| 731 Format(instr, "modu 'rd, 'rs, 'rt"); |
| 732 } |
| 733 } |
670 break; | 734 break; |
671 case ADD: | 735 case ADD: |
672 Format(instr, "add 'rd, 'rs, 'rt"); | 736 Format(instr, "add 'rd, 'rs, 'rt"); |
673 break; | 737 break; |
674 case ADDU: | 738 case ADDU: |
675 Format(instr, "addu 'rd, 'rs, 'rt"); | 739 Format(instr, "addu 'rd, 'rs, 'rt"); |
676 break; | 740 break; |
677 case SUB: | 741 case SUB: |
678 Format(instr, "sub 'rd, 'rs, 'rt"); | 742 Format(instr, "sub 'rd, 'rs, 'rt"); |
679 break; | 743 break; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
731 case MOVN: | 795 case MOVN: |
732 Format(instr, "movn 'rd, 'rs, 'rt"); | 796 Format(instr, "movn 'rd, 'rs, 'rt"); |
733 break; | 797 break; |
734 case MOVCI: | 798 case MOVCI: |
735 if (instr->Bit(16)) { | 799 if (instr->Bit(16)) { |
736 Format(instr, "movt 'rd, 'rs, 'bc"); | 800 Format(instr, "movt 'rd, 'rs, 'bc"); |
737 } else { | 801 } else { |
738 Format(instr, "movf 'rd, 'rs, 'bc"); | 802 Format(instr, "movf 'rd, 'rs, 'bc"); |
739 } | 803 } |
740 break; | 804 break; |
| 805 case SELEQZ_S: |
| 806 Format(instr, "seleqz 'rd, 'rs, 'rt"); |
| 807 break; |
| 808 case SELNEZ_S: |
| 809 Format(instr, "selnez 'rd, 'rs, 'rt"); |
| 810 break; |
741 default: | 811 default: |
742 UNREACHABLE(); | 812 UNREACHABLE(); |
743 } | 813 } |
744 break; | 814 break; |
745 case SPECIAL2: | 815 case SPECIAL2: |
746 switch (instr->FunctionFieldRaw()) { | 816 switch (instr->FunctionFieldRaw()) { |
747 case MUL: | 817 case MUL: |
748 Format(instr, "mul 'rd, 'rs, 'rt"); | 818 Format(instr, "mul 'rd, 'rs, 'rt"); |
749 break; | 819 break; |
750 case CLZ: | 820 case CLZ: |
751 Format(instr, "clz 'rd, 'rs"); | 821 if (!IsMipsArchVariant(kMips32r6)) { |
| 822 Format(instr, "clz 'rd, 'rs"); |
| 823 } |
752 break; | 824 break; |
753 default: | 825 default: |
754 UNREACHABLE(); | 826 UNREACHABLE(); |
755 } | 827 } |
756 break; | 828 break; |
757 case SPECIAL3: | 829 case SPECIAL3: |
758 switch (instr->FunctionFieldRaw()) { | 830 switch (instr->FunctionFieldRaw()) { |
759 case INS: { | 831 case INS: { |
760 if (kArchVariant == kMips32r2) { | 832 if (IsMipsArchVariant(kMips32r2)) { |
761 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); | 833 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); |
762 } else { | 834 } else { |
763 Unknown(instr); | 835 Unknown(instr); |
764 } | 836 } |
765 break; | 837 break; |
766 } | 838 } |
767 case EXT: { | 839 case EXT: { |
768 if (kArchVariant == kMips32r2) { | 840 if (IsMipsArchVariant(kMips32r2)) { |
769 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); | 841 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); |
770 } else { | 842 } else { |
771 Unknown(instr); | 843 Unknown(instr); |
772 } | 844 } |
773 break; | 845 break; |
774 } | 846 } |
775 default: | 847 default: |
776 UNREACHABLE(); | 848 UNREACHABLE(); |
777 } | 849 } |
778 break; | 850 break; |
779 default: | 851 default: |
780 UNREACHABLE(); | 852 UNREACHABLE(); |
781 } | 853 } |
782 } | 854 } |
783 | 855 |
784 | 856 |
785 void Decoder::DecodeTypeImmediate(Instruction* instr) { | 857 void Decoder::DecodeTypeImmediate(Instruction* instr) { |
786 switch (instr->OpcodeFieldRaw()) { | 858 switch (instr->OpcodeFieldRaw()) { |
787 // ------------- REGIMM class. | |
788 case COP1: | 859 case COP1: |
789 switch (instr->RsFieldRaw()) { | 860 switch (instr->RsFieldRaw()) { |
790 case BC1: | 861 case BC1: |
791 if (instr->FBtrueValue()) { | 862 if (instr->FBtrueValue()) { |
792 Format(instr, "bc1t 'bc, 'imm16u"); | 863 Format(instr, "bc1t 'bc, 'imm16u"); |
793 } else { | 864 } else { |
794 Format(instr, "bc1f 'bc, 'imm16u"); | 865 Format(instr, "bc1f 'bc, 'imm16u"); |
795 } | 866 } |
796 break; | 867 break; |
| 868 case BC1EQZ: |
| 869 Format(instr, "bc1eqz 'ft, 'imm16u"); |
| 870 break; |
| 871 case BC1NEZ: |
| 872 Format(instr, "bc1nez 'ft, 'imm16u"); |
| 873 break; |
| 874 case W: // CMP.S instruction. |
| 875 switch (instr->FunctionValue()) { |
| 876 case CMP_AF: |
| 877 Format(instr, "cmp.af.S 'ft, 'fs, 'fd"); |
| 878 break; |
| 879 case CMP_UN: |
| 880 Format(instr, "cmp.un.S 'ft, 'fs, 'fd"); |
| 881 break; |
| 882 case CMP_EQ: |
| 883 Format(instr, "cmp.eq.S 'ft, 'fs, 'fd"); |
| 884 break; |
| 885 case CMP_UEQ: |
| 886 Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd"); |
| 887 break; |
| 888 case CMP_LT: |
| 889 Format(instr, "cmp.lt.S 'ft, 'fs, 'fd"); |
| 890 break; |
| 891 case CMP_ULT: |
| 892 Format(instr, "cmp.ult.S 'ft, 'fs, 'fd"); |
| 893 break; |
| 894 case CMP_LE: |
| 895 Format(instr, "cmp.le.S 'ft, 'fs, 'fd"); |
| 896 break; |
| 897 case CMP_ULE: |
| 898 Format(instr, "cmp.ule.S 'ft, 'fs, 'fd"); |
| 899 break; |
| 900 case CMP_OR: |
| 901 Format(instr, "cmp.or.S 'ft, 'fs, 'fd"); |
| 902 break; |
| 903 case CMP_UNE: |
| 904 Format(instr, "cmp.une.S 'ft, 'fs, 'fd"); |
| 905 break; |
| 906 case CMP_NE: |
| 907 Format(instr, "cmp.ne.S 'ft, 'fs, 'fd"); |
| 908 break; |
| 909 default: |
| 910 UNREACHABLE(); |
| 911 } |
| 912 break; |
| 913 case L: // CMP.D instruction. |
| 914 switch (instr->FunctionValue()) { |
| 915 case CMP_AF: |
| 916 Format(instr, "cmp.af.D 'ft, 'fs, 'fd"); |
| 917 break; |
| 918 case CMP_UN: |
| 919 Format(instr, "cmp.un.D 'ft, 'fs, 'fd"); |
| 920 break; |
| 921 case CMP_EQ: |
| 922 Format(instr, "cmp.eq.D 'ft, 'fs, 'fd"); |
| 923 break; |
| 924 case CMP_UEQ: |
| 925 Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd"); |
| 926 break; |
| 927 case CMP_LT: |
| 928 Format(instr, "cmp.lt.D 'ft, 'fs, 'fd"); |
| 929 break; |
| 930 case CMP_ULT: |
| 931 Format(instr, "cmp.ult.D 'ft, 'fs, 'fd"); |
| 932 break; |
| 933 case CMP_LE: |
| 934 Format(instr, "cmp.le.D 'ft, 'fs, 'fd"); |
| 935 break; |
| 936 case CMP_ULE: |
| 937 Format(instr, "cmp.ule.D 'ft, 'fs, 'fd"); |
| 938 break; |
| 939 case CMP_OR: |
| 940 Format(instr, "cmp.or.D 'ft, 'fs, 'fd"); |
| 941 break; |
| 942 case CMP_UNE: |
| 943 Format(instr, "cmp.une.D 'ft, 'fs, 'fd"); |
| 944 break; |
| 945 case CMP_NE: |
| 946 Format(instr, "cmp.ne.D 'ft, 'fs, 'fd"); |
| 947 break; |
| 948 default: |
| 949 UNREACHABLE(); |
| 950 } |
| 951 break; |
| 952 case S: |
| 953 switch (instr->FunctionValue()) { |
| 954 case SEL: |
| 955 Format(instr, "sel.S 'ft, 'fs, 'fd"); |
| 956 break; |
| 957 case SELEQZ_C: |
| 958 Format(instr, "seleqz.S 'ft, 'fs, 'fd"); |
| 959 break; |
| 960 case SELNEZ_C: |
| 961 Format(instr, "selnez.S 'ft, 'fs, 'fd"); |
| 962 break; |
| 963 case MIN: |
| 964 Format(instr, "min.S 'ft, 'fs, 'fd"); |
| 965 break; |
| 966 case MINA: |
| 967 Format(instr, "mina.S 'ft, 'fs, 'fd"); |
| 968 break; |
| 969 case MAX: |
| 970 Format(instr, "max.S 'ft, 'fs, 'fd"); |
| 971 break; |
| 972 case MAXA: |
| 973 Format(instr, "maxa.S 'ft, 'fs, 'fd"); |
| 974 break; |
| 975 default: |
| 976 UNREACHABLE(); |
| 977 } |
| 978 break; |
| 979 case D: |
| 980 switch (instr->FunctionValue()) { |
| 981 case SEL: |
| 982 Format(instr, "sel.D 'ft, 'fs, 'fd"); |
| 983 break; |
| 984 case SELEQZ_C: |
| 985 Format(instr, "seleqz.D 'ft, 'fs, 'fd"); |
| 986 break; |
| 987 case SELNEZ_C: |
| 988 Format(instr, "selnez.D 'ft, 'fs, 'fd"); |
| 989 break; |
| 990 case MIN: |
| 991 Format(instr, "min.D 'ft, 'fs, 'fd"); |
| 992 break; |
| 993 case MINA: |
| 994 Format(instr, "mina.D 'ft, 'fs, 'fd"); |
| 995 break; |
| 996 case MAX: |
| 997 Format(instr, "max.D 'ft, 'fs, 'fd"); |
| 998 break; |
| 999 case MAXA: |
| 1000 Format(instr, "maxa.D 'ft, 'fs, 'fd"); |
| 1001 break; |
| 1002 default: |
| 1003 UNREACHABLE(); |
| 1004 } |
| 1005 break; |
797 default: | 1006 default: |
798 UNREACHABLE(); | 1007 UNREACHABLE(); |
799 } | 1008 } |
| 1009 |
800 break; // Case COP1. | 1010 break; // Case COP1. |
| 1011 // ------------- REGIMM class. |
801 case REGIMM: | 1012 case REGIMM: |
802 switch (instr->RtFieldRaw()) { | 1013 switch (instr->RtFieldRaw()) { |
803 case BLTZ: | 1014 case BLTZ: |
804 Format(instr, "bltz 'rs, 'imm16u"); | 1015 Format(instr, "bltz 'rs, 'imm16u"); |
805 break; | 1016 break; |
806 case BLTZAL: | 1017 case BLTZAL: |
807 Format(instr, "bltzal 'rs, 'imm16u"); | 1018 Format(instr, "bltzal 'rs, 'imm16u"); |
808 break; | 1019 break; |
809 case BGEZ: | 1020 case BGEZ: |
810 Format(instr, "bgez 'rs, 'imm16u"); | 1021 Format(instr, "bgez 'rs, 'imm16u"); |
811 break; | 1022 break; |
812 case BGEZAL: | 1023 case BGEZAL: |
813 Format(instr, "bgezal 'rs, 'imm16u"); | 1024 Format(instr, "bgezal 'rs, 'imm16u"); |
814 break; | 1025 break; |
| 1026 case BGEZALL: |
| 1027 Format(instr, "bgezall 'rs, 'imm16u"); |
| 1028 break; |
815 default: | 1029 default: |
816 UNREACHABLE(); | 1030 UNREACHABLE(); |
817 } | 1031 } |
818 break; // Case REGIMM. | 1032 break; // Case REGIMM. |
819 // ------------- Branch instructions. | 1033 // ------------- Branch instructions. |
820 case BEQ: | 1034 case BEQ: |
821 Format(instr, "beq 'rs, 'rt, 'imm16u"); | 1035 Format(instr, "beq 'rs, 'rt, 'imm16u"); |
822 break; | 1036 break; |
823 case BNE: | 1037 case BNE: |
824 Format(instr, "bne 'rs, 'rt, 'imm16u"); | 1038 Format(instr, "bne 'rs, 'rt, 'imm16u"); |
825 break; | 1039 break; |
826 case BLEZ: | 1040 case BLEZ: |
827 Format(instr, "blez 'rs, 'imm16u"); | 1041 if ((instr->RtFieldRaw() == 0) |
| 1042 && (instr->RsFieldRaw() != 0)) { |
| 1043 Format(instr, "blez 'rs, 'imm16u"); |
| 1044 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) |
| 1045 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { |
| 1046 Format(instr, "bgeuc 'rs, 'rt, 'imm16u"); |
| 1047 } else if ((instr->RtFieldRaw() == instr->RsFieldRaw()) |
| 1048 && (instr->RtFieldRaw() != 0)) { |
| 1049 Format(instr, "bgezalc 'rs, 'imm16u"); |
| 1050 } else if ((instr->RsFieldRaw() == 0) |
| 1051 && (instr->RtFieldRaw() != 0)) { |
| 1052 Format(instr, "blezalc 'rs, 'imm16u"); |
| 1053 } else { |
| 1054 UNREACHABLE(); |
| 1055 } |
828 break; | 1056 break; |
829 case BGTZ: | 1057 case BGTZ: |
830 Format(instr, "bgtz 'rs, 'imm16u"); | 1058 if ((instr->RtFieldRaw() == 0) |
| 1059 && (instr->RsFieldRaw() != 0)) { |
| 1060 Format(instr, "bgtz 'rs, 'imm16u"); |
| 1061 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) |
| 1062 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { |
| 1063 Format(instr, "bltuc 'rs, 'rt, 'imm16u"); |
| 1064 } else if ((instr->RtFieldRaw() == instr->RsFieldRaw()) |
| 1065 && (instr->RtFieldRaw() != 0)) { |
| 1066 Format(instr, "bltzalc 'rt, 'imm16u"); |
| 1067 } else if ((instr->RsFieldRaw() == 0) |
| 1068 && (instr->RtFieldRaw() != 0)) { |
| 1069 Format(instr, "bgtzalc 'rt, 'imm16u"); |
| 1070 } else { |
| 1071 UNREACHABLE(); |
| 1072 } |
| 1073 break; |
| 1074 case BLEZL: |
| 1075 if ((instr->RtFieldRaw() == instr->RsFieldRaw()) |
| 1076 && (instr->RtFieldRaw() != 0)) { |
| 1077 Format(instr, "bgezc 'rt, 'imm16u"); |
| 1078 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) |
| 1079 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { |
| 1080 Format(instr, "bgec 'rs, 'rt, 'imm16u"); |
| 1081 } else if ((instr->RsFieldRaw() == 0) |
| 1082 && (instr->RtFieldRaw() != 0)) { |
| 1083 Format(instr, "blezc 'rt, 'imm16u"); |
| 1084 } else { |
| 1085 UNREACHABLE(); |
| 1086 } |
| 1087 break; |
| 1088 case BGTZL: |
| 1089 if ((instr->RtFieldRaw() == instr->RsFieldRaw()) |
| 1090 && (instr->RtFieldRaw() != 0)) { |
| 1091 Format(instr, "bltzc 'rt, 'imm16u"); |
| 1092 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) |
| 1093 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { |
| 1094 Format(instr, "bltc 'rs, 'rt, 'imm16u"); |
| 1095 } else if ((instr->RsFieldRaw() == 0) |
| 1096 && (instr->RtFieldRaw() != 0)) { |
| 1097 Format(instr, "bgtzc 'rt, 'imm16u"); |
| 1098 } else { |
| 1099 UNREACHABLE(); |
| 1100 } |
| 1101 break; |
| 1102 case BEQZC: |
| 1103 if (instr->RsFieldRaw() != 0) { |
| 1104 Format(instr, "beqzc 'rs, 'imm21x"); |
| 1105 } |
| 1106 break; |
| 1107 case BNEZC: |
| 1108 if (instr->RsFieldRaw() != 0) { |
| 1109 Format(instr, "bnezc 'rs, 'imm21x"); |
| 1110 } |
831 break; | 1111 break; |
832 // ------------- Arithmetic instructions. | 1112 // ------------- Arithmetic instructions. |
833 case ADDI: | 1113 case ADDI: |
834 Format(instr, "addi 'rt, 'rs, 'imm16s"); | 1114 if (!IsMipsArchVariant(kMips32r6)) { |
| 1115 Format(instr, "addi 'rt, 'rs, 'imm16s"); |
| 1116 } else { |
| 1117 // Check if BOVC or BEQC instruction. |
| 1118 if (instr->RsFieldRaw() >= instr->RtFieldRaw()) { |
| 1119 Format(instr, "bovc 'rs, 'rt, 'imm16s"); |
| 1120 } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) { |
| 1121 Format(instr, "beqc 'rs, 'rt, 'imm16s"); |
| 1122 } else { |
| 1123 UNREACHABLE(); |
| 1124 } |
| 1125 } |
| 1126 break; |
| 1127 case DADDI: |
| 1128 if (IsMipsArchVariant(kMips32r6)) { |
| 1129 // Check if BNVC or BNEC instruction. |
| 1130 if (instr->RsFieldRaw() >= instr->RtFieldRaw()) { |
| 1131 Format(instr, "bnvc 'rs, 'rt, 'imm16s"); |
| 1132 } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) { |
| 1133 Format(instr, "bnec 'rs, 'rt, 'imm16s"); |
| 1134 } else { |
| 1135 UNREACHABLE(); |
| 1136 } |
| 1137 } |
835 break; | 1138 break; |
836 case ADDIU: | 1139 case ADDIU: |
837 Format(instr, "addiu 'rt, 'rs, 'imm16s"); | 1140 Format(instr, "addiu 'rt, 'rs, 'imm16s"); |
838 break; | 1141 break; |
839 case SLTI: | 1142 case SLTI: |
840 Format(instr, "slti 'rt, 'rs, 'imm16s"); | 1143 Format(instr, "slti 'rt, 'rs, 'imm16s"); |
841 break; | 1144 break; |
842 case SLTIU: | 1145 case SLTIU: |
843 Format(instr, "sltiu 'rt, 'rs, 'imm16u"); | 1146 Format(instr, "sltiu 'rt, 'rs, 'imm16u"); |
844 break; | 1147 break; |
845 case ANDI: | 1148 case ANDI: |
846 Format(instr, "andi 'rt, 'rs, 'imm16x"); | 1149 Format(instr, "andi 'rt, 'rs, 'imm16x"); |
847 break; | 1150 break; |
848 case ORI: | 1151 case ORI: |
849 Format(instr, "ori 'rt, 'rs, 'imm16x"); | 1152 Format(instr, "ori 'rt, 'rs, 'imm16x"); |
850 break; | 1153 break; |
851 case XORI: | 1154 case XORI: |
852 Format(instr, "xori 'rt, 'rs, 'imm16x"); | 1155 Format(instr, "xori 'rt, 'rs, 'imm16x"); |
853 break; | 1156 break; |
854 case LUI: | 1157 case LUI: |
855 Format(instr, "lui 'rt, 'imm16x"); | 1158 if (!IsMipsArchVariant(kMips32r6)) { |
| 1159 Format(instr, "lui 'rt, 'imm16x"); |
| 1160 } else { |
| 1161 if (instr->RsValue() != 0) { |
| 1162 Format(instr, "aui 'rt, 'imm16x"); |
| 1163 } else { |
| 1164 Format(instr, "lui 'rt, 'imm16x"); |
| 1165 } |
| 1166 } |
856 break; | 1167 break; |
857 // ------------- Memory instructions. | 1168 // ------------- Memory instructions. |
858 case LB: | 1169 case LB: |
859 Format(instr, "lb 'rt, 'imm16s('rs)"); | 1170 Format(instr, "lb 'rt, 'imm16s('rs)"); |
860 break; | 1171 break; |
861 case LH: | 1172 case LH: |
862 Format(instr, "lh 'rt, 'imm16s('rs)"); | 1173 Format(instr, "lh 'rt, 'imm16s('rs)"); |
863 break; | 1174 break; |
864 case LWL: | 1175 case LWL: |
865 Format(instr, "lwl 'rt, 'imm16s('rs)"); | 1176 Format(instr, "lwl 'rt, 'imm16s('rs)"); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
900 case LDC1: | 1211 case LDC1: |
901 Format(instr, "ldc1 'ft, 'imm16s('rs)"); | 1212 Format(instr, "ldc1 'ft, 'imm16s('rs)"); |
902 break; | 1213 break; |
903 case SWC1: | 1214 case SWC1: |
904 Format(instr, "swc1 'ft, 'imm16s('rs)"); | 1215 Format(instr, "swc1 'ft, 'imm16s('rs)"); |
905 break; | 1216 break; |
906 case SDC1: | 1217 case SDC1: |
907 Format(instr, "sdc1 'ft, 'imm16s('rs)"); | 1218 Format(instr, "sdc1 'ft, 'imm16s('rs)"); |
908 break; | 1219 break; |
909 default: | 1220 default: |
| 1221 printf("a 0x%x \n", instr->OpcodeFieldRaw()); |
910 UNREACHABLE(); | 1222 UNREACHABLE(); |
911 break; | 1223 break; |
912 } | 1224 } |
913 } | 1225 } |
914 | 1226 |
915 | 1227 |
916 void Decoder::DecodeTypeJump(Instruction* instr) { | 1228 void Decoder::DecodeTypeJump(Instruction* instr) { |
917 switch (instr->OpcodeFieldRaw()) { | 1229 switch (instr->OpcodeFieldRaw()) { |
918 case J: | 1230 case J: |
919 Format(instr, "j 'imm26x"); | 1231 Format(instr, "j 'imm26x"); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1344 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
1033 } | 1345 } |
1034 } | 1346 } |
1035 | 1347 |
1036 | 1348 |
1037 #undef UNSUPPORTED | 1349 #undef UNSUPPORTED |
1038 | 1350 |
1039 } // namespace disasm | 1351 } // namespace disasm |
1040 | 1352 |
1041 #endif // V8_TARGET_ARCH_MIPS | 1353 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |