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 88 matching lines...) Loading... |
99 int FormatOption(Instruction* instr, const char* option); | 99 int FormatOption(Instruction* instr, const char* option); |
100 void Format(Instruction* instr, const char* format); | 100 void Format(Instruction* instr, const char* format); |
101 void Unknown(Instruction* instr); | 101 void Unknown(Instruction* instr); |
102 | 102 |
103 | 103 |
104 // Each of these functions decodes one particular instruction type. | 104 // Each of these functions decodes one particular instruction type. |
105 bool DecodeTypeRegisterRsType(Instruction* instr); | 105 bool DecodeTypeRegisterRsType(Instruction* instr); |
106 void DecodeTypeRegisterSRsType(Instruction* instr); | 106 void DecodeTypeRegisterSRsType(Instruction* instr); |
107 void DecodeTypeRegisterDRsType(Instruction* instr); | 107 void DecodeTypeRegisterDRsType(Instruction* instr); |
108 void DecodeTypeRegisterLRsType(Instruction* instr); | 108 void DecodeTypeRegisterLRsType(Instruction* instr); |
| 109 void DecodeTypeRegisterWRsType(Instruction* instr); |
109 void DecodeTypeRegisterSPECIAL(Instruction* instr); | 110 void DecodeTypeRegisterSPECIAL(Instruction* instr); |
110 void DecodeTypeRegisterSPECIAL2(Instruction* instr); | 111 void DecodeTypeRegisterSPECIAL2(Instruction* instr); |
111 void DecodeTypeRegisterSPECIAL3(Instruction* instr); | 112 void DecodeTypeRegisterSPECIAL3(Instruction* instr); |
112 void DecodeTypeRegister(Instruction* instr); | 113 void DecodeTypeRegister(Instruction* instr); |
113 void DecodeTypeImmediate(Instruction* instr); | 114 void DecodeTypeImmediate(Instruction* instr); |
114 void DecodeTypeJump(Instruction* instr); | 115 void DecodeTypeJump(Instruction* instr); |
115 | 116 |
116 const disasm::NameConverter& converter_; | 117 const disasm::NameConverter& converter_; |
117 v8::internal::Vector<char> out_buffer_; | 118 v8::internal::Vector<char> out_buffer_; |
118 int out_buffer_pos_; | 119 int out_buffer_pos_; |
(...skipping 360 matching lines...) Loading... |
479 | 480 |
480 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 481 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
481 // which will just print "unknown" of the instruction bits. | 482 // which will just print "unknown" of the instruction bits. |
482 void Decoder::Unknown(Instruction* instr) { | 483 void Decoder::Unknown(Instruction* instr) { |
483 Format(instr, "unknown"); | 484 Format(instr, "unknown"); |
484 } | 485 } |
485 | 486 |
486 | 487 |
487 bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) { | 488 bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) { |
488 switch (instr->FunctionFieldRaw()) { | 489 switch (instr->FunctionFieldRaw()) { |
| 490 case MIN: |
| 491 Format(instr, "min.'t 'fd, 'fs, 'ft"); |
| 492 break; |
| 493 case MAX: |
| 494 Format(instr, "max.'t 'fd, 'fs, 'ft"); |
| 495 break; |
| 496 case MINA: |
| 497 Format(instr, "mina.'t 'fd, 'fs, 'ft"); |
| 498 break; |
| 499 case MAXA: |
| 500 Format(instr, "maxa.'t 'fd, 'fs, 'ft"); |
| 501 break; |
| 502 case SEL: |
| 503 Format(instr, "sel.'t 'fd, 'fs, 'ft"); |
| 504 break; |
| 505 case SELEQZ_C: |
| 506 Format(instr, "seleqz.'t 'fd, 'fs, 'ft"); |
| 507 break; |
| 508 case SELNEZ_C: |
| 509 Format(instr, "selnez.'t 'fd, 'fs, 'ft"); |
| 510 break; |
489 case ADD_D: | 511 case ADD_D: |
490 Format(instr, "add.'t 'fd, 'fs, 'ft"); | 512 Format(instr, "add.'t 'fd, 'fs, 'ft"); |
491 break; | 513 break; |
492 case SUB_D: | 514 case SUB_D: |
493 Format(instr, "sub.'t 'fd, 'fs, 'ft"); | 515 Format(instr, "sub.'t 'fd, 'fs, 'ft"); |
494 break; | 516 break; |
495 case MUL_D: | 517 case MUL_D: |
496 Format(instr, "mul.'t 'fd, 'fs, 'ft"); | 518 Format(instr, "mul.'t 'fd, 'fs, 'ft"); |
497 break; | 519 break; |
498 case DIV_D: | 520 case DIV_D: |
(...skipping 124 matching lines...) Loading... |
623 break; | 645 break; |
624 case CMP_NE: | 646 case CMP_NE: |
625 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); | 647 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); |
626 break; | 648 break; |
627 default: | 649 default: |
628 UNREACHABLE(); | 650 UNREACHABLE(); |
629 } | 651 } |
630 } | 652 } |
631 | 653 |
632 | 654 |
| 655 void Decoder::DecodeTypeRegisterWRsType(Instruction* instr) { |
| 656 switch (instr->FunctionValue()) { |
| 657 case CVT_S_W: // Convert word to float (single). |
| 658 Format(instr, "cvt.s.w 'fd, 'fs"); |
| 659 break; |
| 660 case CVT_D_W: // Convert word to double. |
| 661 Format(instr, "cvt.d.w 'fd, 'fs"); |
| 662 break; |
| 663 case CMP_AF: |
| 664 Format(instr, "cmp.af.s 'fd, 'fs, 'ft"); |
| 665 break; |
| 666 case CMP_UN: |
| 667 Format(instr, "cmp.un.s 'fd, 'fs, 'ft"); |
| 668 break; |
| 669 case CMP_EQ: |
| 670 Format(instr, "cmp.eq.s 'fd, 'fs, 'ft"); |
| 671 break; |
| 672 case CMP_UEQ: |
| 673 Format(instr, "cmp.ueq.s 'fd, 'fs, 'ft"); |
| 674 break; |
| 675 case CMP_LT: |
| 676 Format(instr, "cmp.lt.s 'fd, 'fs, 'ft"); |
| 677 break; |
| 678 case CMP_ULT: |
| 679 Format(instr, "cmp.ult.s 'fd, 'fs, 'ft"); |
| 680 break; |
| 681 case CMP_LE: |
| 682 Format(instr, "cmp.le.s 'fd, 'fs, 'ft"); |
| 683 break; |
| 684 case CMP_ULE: |
| 685 Format(instr, "cmp.ule.s 'fd, 'fs, 'ft"); |
| 686 break; |
| 687 case CMP_OR: |
| 688 Format(instr, "cmp.or.s 'fd, 'fs, 'ft"); |
| 689 break; |
| 690 case CMP_UNE: |
| 691 Format(instr, "cmp.une.s 'fd, 'fs, 'ft"); |
| 692 break; |
| 693 case CMP_NE: |
| 694 Format(instr, "cmp.ne.s 'fd, 'fs, 'ft"); |
| 695 break; |
| 696 default: |
| 697 UNREACHABLE(); |
| 698 } |
| 699 } |
| 700 |
| 701 |
633 void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) { | 702 void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) { |
634 switch (instr->FunctionFieldRaw()) { | 703 switch (instr->FunctionFieldRaw()) { |
635 case JR: | 704 case JR: |
636 Format(instr, "jr 'rs"); | 705 Format(instr, "jr 'rs"); |
637 break; | 706 break; |
638 case JALR: | 707 case JALR: |
639 Format(instr, "jalr 'rs"); | 708 Format(instr, "jalr 'rs"); |
640 break; | 709 break; |
641 case SLL: | 710 case SLL: |
642 if (0x0 == static_cast<int>(instr->InstructionBits())) | 711 if (0x0 == static_cast<int>(instr->InstructionBits())) |
(...skipping 155 matching lines...) Loading... |
798 Format(instr, "movn 'rd, 'rs, 'rt"); | 867 Format(instr, "movn 'rd, 'rs, 'rt"); |
799 break; | 868 break; |
800 case MOVCI: | 869 case MOVCI: |
801 if (instr->Bit(16)) { | 870 if (instr->Bit(16)) { |
802 Format(instr, "movt 'rd, 'rs, 'bc"); | 871 Format(instr, "movt 'rd, 'rs, 'bc"); |
803 } else { | 872 } else { |
804 Format(instr, "movf 'rd, 'rs, 'bc"); | 873 Format(instr, "movf 'rd, 'rs, 'bc"); |
805 } | 874 } |
806 break; | 875 break; |
807 case SELEQZ_S: | 876 case SELEQZ_S: |
808 Format(instr, "seleqz 'rs, 'rt, 'rd"); | 877 Format(instr, "seleqz 'rd, 'rs, 'rt"); |
809 break; | 878 break; |
810 case SELNEZ_S: | 879 case SELNEZ_S: |
811 Format(instr, "selnez 'rs, 'rt, 'rd"); | 880 Format(instr, "selnez 'rd, 'rs, 'rt"); |
812 break; | 881 break; |
813 default: | 882 default: |
814 UNREACHABLE(); | 883 UNREACHABLE(); |
815 } | 884 } |
816 } | 885 } |
817 | 886 |
818 | 887 |
819 void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) { | 888 void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) { |
820 switch (instr->FunctionFieldRaw()) { | 889 switch (instr->FunctionFieldRaw()) { |
821 case MUL: | 890 case MUL: |
(...skipping 59 matching lines...) Loading... |
881 break; | 950 break; |
882 case MTHC1: | 951 case MTHC1: |
883 Format(instr, "mthc1 'rt, 'fs"); | 952 Format(instr, "mthc1 'rt, 'fs"); |
884 break; | 953 break; |
885 case S: | 954 case S: |
886 DecodeTypeRegisterSRsType(instr); | 955 DecodeTypeRegisterSRsType(instr); |
887 break; | 956 break; |
888 case D: | 957 case D: |
889 DecodeTypeRegisterDRsType(instr); | 958 DecodeTypeRegisterDRsType(instr); |
890 break; | 959 break; |
891 case W: | |
892 switch (instr->FunctionFieldRaw()) { | |
893 case CVT_S_W: // Convert word to float (single). | |
894 Format(instr, "cvt.s.w 'fd, 'fs"); | |
895 break; | |
896 case CVT_D_W: // Convert word to double. | |
897 Format(instr, "cvt.d.w 'fd, 'fs"); | |
898 break; | |
899 default: | |
900 UNREACHABLE(); | |
901 } | |
902 break; | |
903 case L: | 960 case L: |
904 DecodeTypeRegisterLRsType(instr); | 961 DecodeTypeRegisterLRsType(instr); |
905 break; | 962 break; |
| 963 case W: |
| 964 DecodeTypeRegisterWRsType(instr); |
| 965 break; |
906 case PS: | 966 case PS: |
907 UNIMPLEMENTED_MIPS(); | 967 UNIMPLEMENTED_MIPS(); |
908 break; | 968 break; |
909 default: | 969 default: |
910 UNREACHABLE(); | 970 UNREACHABLE(); |
911 } | 971 } |
912 break; | 972 break; |
913 case COP1X: | 973 case COP1X: |
914 switch (instr->FunctionFieldRaw()) { | 974 switch (instr->FunctionFieldRaw()) { |
915 case MADD_D: | 975 case MADD_D: |
(...skipping 28 matching lines...) Loading... |
944 } else { | 1004 } else { |
945 Format(instr, "bc1f 'bc, 'imm16u"); | 1005 Format(instr, "bc1f 'bc, 'imm16u"); |
946 } | 1006 } |
947 break; | 1007 break; |
948 case BC1EQZ: | 1008 case BC1EQZ: |
949 Format(instr, "bc1eqz 'ft, 'imm16u"); | 1009 Format(instr, "bc1eqz 'ft, 'imm16u"); |
950 break; | 1010 break; |
951 case BC1NEZ: | 1011 case BC1NEZ: |
952 Format(instr, "bc1nez 'ft, 'imm16u"); | 1012 Format(instr, "bc1nez 'ft, 'imm16u"); |
953 break; | 1013 break; |
954 case W: // CMP.S instruction. | |
955 switch (instr->FunctionValue()) { | |
956 case CMP_AF: | |
957 Format(instr, "cmp.af.S 'ft, 'fs, 'fd"); | |
958 break; | |
959 case CMP_UN: | |
960 Format(instr, "cmp.un.S 'ft, 'fs, 'fd"); | |
961 break; | |
962 case CMP_EQ: | |
963 Format(instr, "cmp.eq.S 'ft, 'fs, 'fd"); | |
964 break; | |
965 case CMP_UEQ: | |
966 Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd"); | |
967 break; | |
968 case CMP_LT: | |
969 Format(instr, "cmp.lt.S 'ft, 'fs, 'fd"); | |
970 break; | |
971 case CMP_ULT: | |
972 Format(instr, "cmp.ult.S 'ft, 'fs, 'fd"); | |
973 break; | |
974 case CMP_LE: | |
975 Format(instr, "cmp.le.S 'ft, 'fs, 'fd"); | |
976 break; | |
977 case CMP_ULE: | |
978 Format(instr, "cmp.ule.S 'ft, 'fs, 'fd"); | |
979 break; | |
980 case CMP_OR: | |
981 Format(instr, "cmp.or.S 'ft, 'fs, 'fd"); | |
982 break; | |
983 case CMP_UNE: | |
984 Format(instr, "cmp.une.S 'ft, 'fs, 'fd"); | |
985 break; | |
986 case CMP_NE: | |
987 Format(instr, "cmp.ne.S 'ft, 'fs, 'fd"); | |
988 break; | |
989 default: | |
990 UNREACHABLE(); | |
991 } | |
992 break; | |
993 case L: // CMP.D instruction. | |
994 switch (instr->FunctionValue()) { | |
995 case CMP_AF: | |
996 Format(instr, "cmp.af.D 'ft, 'fs, 'fd"); | |
997 break; | |
998 case CMP_UN: | |
999 Format(instr, "cmp.un.D 'ft, 'fs, 'fd"); | |
1000 break; | |
1001 case CMP_EQ: | |
1002 Format(instr, "cmp.eq.D 'ft, 'fs, 'fd"); | |
1003 break; | |
1004 case CMP_UEQ: | |
1005 Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd"); | |
1006 break; | |
1007 case CMP_LT: | |
1008 Format(instr, "cmp.lt.D 'ft, 'fs, 'fd"); | |
1009 break; | |
1010 case CMP_ULT: | |
1011 Format(instr, "cmp.ult.D 'ft, 'fs, 'fd"); | |
1012 break; | |
1013 case CMP_LE: | |
1014 Format(instr, "cmp.le.D 'ft, 'fs, 'fd"); | |
1015 break; | |
1016 case CMP_ULE: | |
1017 Format(instr, "cmp.ule.D 'ft, 'fs, 'fd"); | |
1018 break; | |
1019 case CMP_OR: | |
1020 Format(instr, "cmp.or.D 'ft, 'fs, 'fd"); | |
1021 break; | |
1022 case CMP_UNE: | |
1023 Format(instr, "cmp.une.D 'ft, 'fs, 'fd"); | |
1024 break; | |
1025 case CMP_NE: | |
1026 Format(instr, "cmp.ne.D 'ft, 'fs, 'fd"); | |
1027 break; | |
1028 default: | |
1029 UNREACHABLE(); | |
1030 } | |
1031 break; | |
1032 case S: | |
1033 switch (instr->FunctionValue()) { | |
1034 case SEL: | |
1035 Format(instr, "sel.S 'ft, 'fs, 'fd"); | |
1036 break; | |
1037 case SELEQZ_C: | |
1038 Format(instr, "seleqz.S 'ft, 'fs, 'fd"); | |
1039 break; | |
1040 case SELNEZ_C: | |
1041 Format(instr, "selnez.S 'ft, 'fs, 'fd"); | |
1042 break; | |
1043 case MIN: | |
1044 Format(instr, "min.S 'ft, 'fs, 'fd"); | |
1045 break; | |
1046 case MINA: | |
1047 Format(instr, "mina.S 'ft, 'fs, 'fd"); | |
1048 break; | |
1049 case MAX: | |
1050 Format(instr, "max.S 'ft, 'fs, 'fd"); | |
1051 break; | |
1052 case MAXA: | |
1053 Format(instr, "maxa.S 'ft, 'fs, 'fd"); | |
1054 break; | |
1055 default: | |
1056 UNREACHABLE(); | |
1057 } | |
1058 break; | |
1059 case D: | |
1060 switch (instr->FunctionValue()) { | |
1061 case SEL: | |
1062 Format(instr, "sel.D 'ft, 'fs, 'fd"); | |
1063 break; | |
1064 case SELEQZ_C: | |
1065 Format(instr, "seleqz.D 'ft, 'fs, 'fd"); | |
1066 break; | |
1067 case SELNEZ_C: | |
1068 Format(instr, "selnez.D 'ft, 'fs, 'fd"); | |
1069 break; | |
1070 case MIN: | |
1071 Format(instr, "min.D 'ft, 'fs, 'fd"); | |
1072 break; | |
1073 case MINA: | |
1074 Format(instr, "mina.D 'ft, 'fs, 'fd"); | |
1075 break; | |
1076 case MAX: | |
1077 Format(instr, "max.D 'ft, 'fs, 'fd"); | |
1078 break; | |
1079 case MAXA: | |
1080 Format(instr, "maxa.D 'ft, 'fs, 'fd"); | |
1081 break; | |
1082 default: | |
1083 UNREACHABLE(); | |
1084 } | |
1085 break; | |
1086 default: | 1014 default: |
1087 UNREACHABLE(); | 1015 UNREACHABLE(); |
1088 } | 1016 } |
1089 | 1017 |
1090 break; // Case COP1. | 1018 break; // Case COP1. |
1091 // ------------- REGIMM class. | 1019 // ------------- REGIMM class. |
1092 case REGIMM: | 1020 case REGIMM: |
1093 switch (instr->RtFieldRaw()) { | 1021 switch (instr->RtFieldRaw()) { |
1094 case BLTZ: | 1022 case BLTZ: |
1095 Format(instr, "bltz 'rs, 'imm16u"); | 1023 Format(instr, "bltz 'rs, 'imm16u"); |
(...skipping 328 matching lines...) Loading... |
1424 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1352 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
1425 } | 1353 } |
1426 } | 1354 } |
1427 | 1355 |
1428 | 1356 |
1429 #undef UNSUPPORTED | 1357 #undef UNSUPPORTED |
1430 | 1358 |
1431 } // namespace disasm | 1359 } // namespace disasm |
1432 | 1360 |
1433 #endif // V8_TARGET_ARCH_MIPS | 1361 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |