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 int DecodeBreakInstr(Instruction* instr); | 102 int DecodeBreakInstr(Instruction* instr); |
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 DecodeTypeRegisterCOP1(Instruction* instr); | 113 void DecodeTypeRegisterCOP1(Instruction* instr); |
113 void DecodeTypeRegisterCOP1X(Instruction* instr); | 114 void DecodeTypeRegisterCOP1X(Instruction* instr); |
114 int DecodeTypeRegister(Instruction* instr); | 115 int DecodeTypeRegister(Instruction* instr); |
115 | 116 |
116 void DecodeTypeImmediateCOP1W(Instruction* instr); | |
117 void DecodeTypeImmediateCOP1L(Instruction* instr); | |
118 void DecodeTypeImmediateCOP1S(Instruction* instr); | |
119 void DecodeTypeImmediateCOP1D(Instruction* instr); | |
120 void DecodeTypeImmediateCOP1(Instruction* instr); | 117 void DecodeTypeImmediateCOP1(Instruction* instr); |
121 void DecodeTypeImmediateREGIMM(Instruction* instr); | 118 void DecodeTypeImmediateREGIMM(Instruction* instr); |
122 void DecodeTypeImmediate(Instruction* instr); | 119 void DecodeTypeImmediate(Instruction* instr); |
123 | 120 |
124 void DecodeTypeJump(Instruction* instr); | 121 void DecodeTypeJump(Instruction* instr); |
125 | 122 |
126 const disasm::NameConverter& converter_; | 123 const disasm::NameConverter& converter_; |
127 v8::internal::Vector<char> out_buffer_; | 124 v8::internal::Vector<char> out_buffer_; |
128 int out_buffer_pos_; | 125 int out_buffer_pos_; |
129 | 126 |
(...skipping 384 matching lines...) Loading... |
514 } else { | 511 } else { |
515 Format(instr, "break, code: 'code"); | 512 Format(instr, "break, code: 'code"); |
516 return Instruction::kInstrSize; | 513 return Instruction::kInstrSize; |
517 } | 514 } |
518 } | 515 } |
519 | 516 |
520 | 517 |
521 bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) { | 518 bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) { |
522 switch (instr->FunctionFieldRaw()) { | 519 switch (instr->FunctionFieldRaw()) { |
523 case SELEQZ_C: | 520 case SELEQZ_C: |
524 Format(instr, "seleqz.'t 'ft, 'fs, 'fd"); | 521 Format(instr, "seleqz.'t 'fd, 'fs, 'ft"); |
525 break; | 522 break; |
526 case SELNEZ_C: | 523 case SELNEZ_C: |
527 Format(instr, "selnez.'t 'ft, 'fs, 'fd"); | 524 Format(instr, "selnez.'t 'fd, 'fs, 'ft"); |
| 525 break; |
| 526 case MIN: |
| 527 Format(instr, "min.'t 'fd, 'fs, 'ft"); |
| 528 break; |
| 529 case MAX: |
| 530 Format(instr, "max.'t 'fd, 'fs, 'ft"); |
| 531 break; |
| 532 case MINA: |
| 533 Format(instr, "mina.'t 'fd, 'fs, 'ft"); |
| 534 break; |
| 535 case MAXA: |
| 536 Format(instr, "maxa.'t 'fd, 'fs, 'ft"); |
528 break; | 537 break; |
529 case ADD_D: | 538 case ADD_D: |
530 Format(instr, "add.'t 'fd, 'fs, 'ft"); | 539 Format(instr, "add.'t 'fd, 'fs, 'ft"); |
531 break; | 540 break; |
532 case SUB_D: | 541 case SUB_D: |
533 Format(instr, "sub.'t 'fd, 'fs, 'ft"); | 542 Format(instr, "sub.'t 'fd, 'fs, 'ft"); |
534 break; | 543 break; |
535 case MUL_D: | 544 case MUL_D: |
536 Format(instr, "mul.'t 'fd, 'fs, 'ft"); | 545 Format(instr, "mul.'t 'fd, 'fs, 'ft"); |
537 break; | 546 break; |
(...skipping 134 matching lines...) Loading... |
672 break; | 681 break; |
673 case CMP_NE: | 682 case CMP_NE: |
674 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); | 683 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); |
675 break; | 684 break; |
676 default: | 685 default: |
677 UNREACHABLE(); | 686 UNREACHABLE(); |
678 } | 687 } |
679 } | 688 } |
680 | 689 |
681 | 690 |
| 691 void Decoder::DecodeTypeRegisterWRsType(Instruction* instr) { |
| 692 switch (instr->FunctionValue()) { |
| 693 case CVT_S_W: // Convert word to float (single). |
| 694 Format(instr, "cvt.s.w 'fd, 'fs"); |
| 695 break; |
| 696 case CVT_D_W: // Convert word to double. |
| 697 Format(instr, "cvt.d.w 'fd, 'fs"); |
| 698 break; |
| 699 case CMP_AF: |
| 700 Format(instr, "cmp.af.s 'fd, 'fs, 'ft"); |
| 701 break; |
| 702 case CMP_UN: |
| 703 Format(instr, "cmp.un.s 'fd, 'fs, 'ft"); |
| 704 break; |
| 705 case CMP_EQ: |
| 706 Format(instr, "cmp.eq.s 'fd, 'fs, 'ft"); |
| 707 break; |
| 708 case CMP_UEQ: |
| 709 Format(instr, "cmp.ueq.s 'fd, 'fs, 'ft"); |
| 710 break; |
| 711 case CMP_LT: |
| 712 Format(instr, "cmp.lt.s 'fd, 'fs, 'ft"); |
| 713 break; |
| 714 case CMP_ULT: |
| 715 Format(instr, "cmp.ult.s 'fd, 'fs, 'ft"); |
| 716 break; |
| 717 case CMP_LE: |
| 718 Format(instr, "cmp.le.s 'fd, 'fs, 'ft"); |
| 719 break; |
| 720 case CMP_ULE: |
| 721 Format(instr, "cmp.ule.s 'fd, 'fs, 'ft"); |
| 722 break; |
| 723 case CMP_OR: |
| 724 Format(instr, "cmp.or.s 'fd, 'fs, 'ft"); |
| 725 break; |
| 726 case CMP_UNE: |
| 727 Format(instr, "cmp.une.s 'fd, 'fs, 'ft"); |
| 728 break; |
| 729 case CMP_NE: |
| 730 Format(instr, "cmp.ne.s 'fd, 'fs, 'ft"); |
| 731 break; |
| 732 default: |
| 733 UNREACHABLE(); |
| 734 } |
| 735 } |
| 736 |
| 737 |
682 void Decoder::DecodeTypeRegisterCOP1(Instruction* instr) { | 738 void Decoder::DecodeTypeRegisterCOP1(Instruction* instr) { |
683 switch (instr->RsFieldRaw()) { | 739 switch (instr->RsFieldRaw()) { |
684 case MFC1: | 740 case MFC1: |
685 Format(instr, "mfc1 'rt, 'fs"); | 741 Format(instr, "mfc1 'rt, 'fs"); |
686 break; | 742 break; |
687 case DMFC1: | 743 case DMFC1: |
688 Format(instr, "dmfc1 'rt, 'fs"); | 744 Format(instr, "dmfc1 'rt, 'fs"); |
689 break; | 745 break; |
690 case MFHC1: | 746 case MFHC1: |
691 Format(instr, "mfhc1 'rt, 'fs"); | 747 Format(instr, "mfhc1 'rt, 'fs"); |
(...skipping 14 matching lines...) Loading... |
706 case MTHC1: | 762 case MTHC1: |
707 Format(instr, "mthc1 'rt, 'fs"); | 763 Format(instr, "mthc1 'rt, 'fs"); |
708 break; | 764 break; |
709 case S: | 765 case S: |
710 DecodeTypeRegisterSRsType(instr); | 766 DecodeTypeRegisterSRsType(instr); |
711 break; | 767 break; |
712 case D: | 768 case D: |
713 DecodeTypeRegisterDRsType(instr); | 769 DecodeTypeRegisterDRsType(instr); |
714 break; | 770 break; |
715 case W: | 771 case W: |
716 switch (instr->FunctionFieldRaw()) { | 772 DecodeTypeRegisterWRsType(instr); |
717 case CVT_D_W: // Convert word to double. | |
718 Format(instr, "cvt.d.w 'fd, 'fs"); | |
719 break; | |
720 default: | |
721 UNREACHABLE(); | |
722 } | |
723 break; | 773 break; |
724 case L: | 774 case L: |
725 DecodeTypeRegisterLRsType(instr); | 775 DecodeTypeRegisterLRsType(instr); |
726 break; | 776 break; |
727 default: | 777 default: |
728 UNREACHABLE(); | 778 UNREACHABLE(); |
729 } | 779 } |
730 } | 780 } |
731 | 781 |
732 | 782 |
(...skipping 273 matching lines...) Loading... |
1006 Format(instr, "movn 'rd, 'rs, 'rt"); | 1056 Format(instr, "movn 'rd, 'rs, 'rt"); |
1007 break; | 1057 break; |
1008 case MOVCI: | 1058 case MOVCI: |
1009 if (instr->Bit(16)) { | 1059 if (instr->Bit(16)) { |
1010 Format(instr, "movt 'rd, 'rs, 'bc"); | 1060 Format(instr, "movt 'rd, 'rs, 'bc"); |
1011 } else { | 1061 } else { |
1012 Format(instr, "movf 'rd, 'rs, 'bc"); | 1062 Format(instr, "movf 'rd, 'rs, 'bc"); |
1013 } | 1063 } |
1014 break; | 1064 break; |
1015 case SELEQZ_S: | 1065 case SELEQZ_S: |
1016 Format(instr, "seleqz 'rs, 'rt, 'rd"); | 1066 Format(instr, "seleqz 'rd, 'rs, 'rt"); |
1017 break; | 1067 break; |
1018 case SELNEZ_S: | 1068 case SELNEZ_S: |
1019 Format(instr, "selnez 'rs, 'rt, 'rd"); | 1069 Format(instr, "selnez 'rd, 'rs, 'rt"); |
1020 break; | 1070 break; |
1021 default: | 1071 default: |
1022 UNREACHABLE(); | 1072 UNREACHABLE(); |
1023 } | 1073 } |
1024 } | 1074 } |
1025 | 1075 |
1026 | 1076 |
1027 void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) { | 1077 void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) { |
1028 switch (instr->FunctionFieldRaw()) { | 1078 switch (instr->FunctionFieldRaw()) { |
1029 case MUL: | 1079 case MUL: |
(...skipping 53 matching lines...) Loading... |
1083 case SPECIAL3: | 1133 case SPECIAL3: |
1084 DecodeTypeRegisterSPECIAL3(instr); | 1134 DecodeTypeRegisterSPECIAL3(instr); |
1085 break; | 1135 break; |
1086 default: | 1136 default: |
1087 UNREACHABLE(); | 1137 UNREACHABLE(); |
1088 } | 1138 } |
1089 return Instruction::kInstrSize; | 1139 return Instruction::kInstrSize; |
1090 } | 1140 } |
1091 | 1141 |
1092 | 1142 |
1093 void Decoder::DecodeTypeImmediateCOP1D(Instruction* instr) { | |
1094 switch (instr->FunctionValue()) { | |
1095 case SEL: | |
1096 Format(instr, "sel.D 'ft, 'fs, 'fd"); | |
1097 break; | |
1098 case SELEQZ_C: | |
1099 Format(instr, "seleqz.D 'ft, 'fs, 'fd"); | |
1100 break; | |
1101 case SELNEZ_C: | |
1102 Format(instr, "selnez.D 'ft, 'fs, 'fd"); | |
1103 break; | |
1104 case MIN: | |
1105 Format(instr, "min.D 'ft, 'fs, 'fd"); | |
1106 break; | |
1107 case MINA: | |
1108 Format(instr, "mina.D 'ft, 'fs, 'fd"); | |
1109 break; | |
1110 case MAX: | |
1111 Format(instr, "max.D 'ft, 'fs, 'fd"); | |
1112 break; | |
1113 case MAXA: | |
1114 Format(instr, "maxa.D 'ft, 'fs, 'fd"); | |
1115 break; | |
1116 default: | |
1117 UNREACHABLE(); | |
1118 } | |
1119 } | |
1120 | |
1121 | |
1122 void Decoder::DecodeTypeImmediateCOP1L(Instruction* instr) { | |
1123 switch (instr->FunctionValue()) { | |
1124 case CMP_AF: | |
1125 Format(instr, "cmp.af.D 'ft, 'fs, 'fd"); | |
1126 break; | |
1127 case CMP_UN: | |
1128 Format(instr, "cmp.un.D 'ft, 'fs, 'fd"); | |
1129 break; | |
1130 case CMP_EQ: | |
1131 Format(instr, "cmp.eq.D 'ft, 'fs, 'fd"); | |
1132 break; | |
1133 case CMP_UEQ: | |
1134 Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd"); | |
1135 break; | |
1136 case CMP_LT: | |
1137 Format(instr, "cmp.lt.D 'ft, 'fs, 'fd"); | |
1138 break; | |
1139 case CMP_ULT: | |
1140 Format(instr, "cmp.ult.D 'ft, 'fs, 'fd"); | |
1141 break; | |
1142 case CMP_LE: | |
1143 Format(instr, "cmp.le.D 'ft, 'fs, 'fd"); | |
1144 break; | |
1145 case CMP_ULE: | |
1146 Format(instr, "cmp.ule.D 'ft, 'fs, 'fd"); | |
1147 break; | |
1148 case CMP_OR: | |
1149 Format(instr, "cmp.or.D 'ft, 'fs, 'fd"); | |
1150 break; | |
1151 case CMP_UNE: | |
1152 Format(instr, "cmp.une.D 'ft, 'fs, 'fd"); | |
1153 break; | |
1154 case CMP_NE: | |
1155 Format(instr, "cmp.ne.D 'ft, 'fs, 'fd"); | |
1156 break; | |
1157 default: | |
1158 UNREACHABLE(); | |
1159 } | |
1160 } | |
1161 | |
1162 | |
1163 void Decoder::DecodeTypeImmediateCOP1S(Instruction* instr) { | |
1164 switch (instr->FunctionValue()) { | |
1165 case SEL: | |
1166 Format(instr, "sel.S 'ft, 'fs, 'fd"); | |
1167 break; | |
1168 case SELEQZ_C: | |
1169 Format(instr, "seleqz.S 'ft, 'fs, 'fd"); | |
1170 break; | |
1171 case SELNEZ_C: | |
1172 Format(instr, "selnez.S 'ft, 'fs, 'fd"); | |
1173 break; | |
1174 case MIN: | |
1175 Format(instr, "min.S 'ft, 'fs, 'fd"); | |
1176 break; | |
1177 case MINA: | |
1178 Format(instr, "mina.S 'ft, 'fs, 'fd"); | |
1179 break; | |
1180 case MAX: | |
1181 Format(instr, "max.S 'ft, 'fs, 'fd"); | |
1182 break; | |
1183 case MAXA: | |
1184 Format(instr, "maxa.S 'ft, 'fs, 'fd"); | |
1185 break; | |
1186 default: | |
1187 UNREACHABLE(); | |
1188 } | |
1189 } | |
1190 | |
1191 | |
1192 void Decoder::DecodeTypeImmediateCOP1W(Instruction* instr) { | |
1193 switch (instr->FunctionValue()) { | |
1194 case CMP_AF: | |
1195 Format(instr, "cmp.af.S 'ft, 'fs, 'fd"); | |
1196 break; | |
1197 case CMP_UN: | |
1198 Format(instr, "cmp.un.S 'ft, 'fs, 'fd"); | |
1199 break; | |
1200 case CMP_EQ: | |
1201 Format(instr, "cmp.eq.S 'ft, 'fs, 'fd"); | |
1202 break; | |
1203 case CMP_UEQ: | |
1204 Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd"); | |
1205 break; | |
1206 case CMP_LT: | |
1207 Format(instr, "cmp.lt.S 'ft, 'fs, 'fd"); | |
1208 break; | |
1209 case CMP_ULT: | |
1210 Format(instr, "cmp.ult.S 'ft, 'fs, 'fd"); | |
1211 break; | |
1212 case CMP_LE: | |
1213 Format(instr, "cmp.le.S 'ft, 'fs, 'fd"); | |
1214 break; | |
1215 case CMP_ULE: | |
1216 Format(instr, "cmp.ule.S 'ft, 'fs, 'fd"); | |
1217 break; | |
1218 case CMP_OR: | |
1219 Format(instr, "cmp.or.S 'ft, 'fs, 'fd"); | |
1220 break; | |
1221 case CMP_UNE: | |
1222 Format(instr, "cmp.une.S 'ft, 'fs, 'fd"); | |
1223 break; | |
1224 case CMP_NE: | |
1225 Format(instr, "cmp.ne.S 'ft, 'fs, 'fd"); | |
1226 break; | |
1227 default: | |
1228 UNREACHABLE(); | |
1229 } | |
1230 } | |
1231 | |
1232 | |
1233 void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) { | 1143 void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) { |
1234 switch (instr->RsFieldRaw()) { | 1144 switch (instr->RsFieldRaw()) { |
1235 case BC1: | 1145 case BC1: |
1236 if (instr->FBtrueValue()) { | 1146 if (instr->FBtrueValue()) { |
1237 Format(instr, "bc1t 'bc, 'imm16u"); | 1147 Format(instr, "bc1t 'bc, 'imm16u"); |
1238 } else { | 1148 } else { |
1239 Format(instr, "bc1f 'bc, 'imm16u"); | 1149 Format(instr, "bc1f 'bc, 'imm16u"); |
1240 } | 1150 } |
1241 break; | 1151 break; |
1242 case BC1EQZ: | 1152 case BC1EQZ: |
1243 Format(instr, "bc1eqz 'ft, 'imm16u"); | 1153 Format(instr, "bc1eqz 'ft, 'imm16u"); |
1244 break; | 1154 break; |
1245 case BC1NEZ: | 1155 case BC1NEZ: |
1246 Format(instr, "bc1nez 'ft, 'imm16u"); | 1156 Format(instr, "bc1nez 'ft, 'imm16u"); |
1247 break; | 1157 break; |
1248 case W: // CMP.S instruction. | |
1249 DecodeTypeImmediateCOP1W(instr); | |
1250 break; | |
1251 case L: // CMP.D instruction. | |
1252 DecodeTypeImmediateCOP1L(instr); | |
1253 break; | |
1254 case S: | |
1255 DecodeTypeImmediateCOP1S(instr); | |
1256 break; | |
1257 case D: | |
1258 DecodeTypeImmediateCOP1D(instr); | |
1259 break; | |
1260 default: | 1158 default: |
1261 UNREACHABLE(); | 1159 UNREACHABLE(); |
1262 } | 1160 } |
1263 } | 1161 } |
1264 | 1162 |
1265 | 1163 |
1266 void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) { | 1164 void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) { |
1267 switch (instr->RtFieldRaw()) { | 1165 switch (instr->RtFieldRaw()) { |
1268 case BLTZ: | 1166 case BLTZ: |
1269 Format(instr, "bltz 'rs, 'imm16u"); | 1167 Format(instr, "bltz 'rs, 'imm16u"); |
(...skipping 370 matching lines...) Loading... |
1640 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1538 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
1641 } | 1539 } |
1642 } | 1540 } |
1643 | 1541 |
1644 | 1542 |
1645 #undef UNSUPPORTED | 1543 #undef UNSUPPORTED |
1646 | 1544 |
1647 } // namespace disasm | 1545 } // namespace disasm |
1648 | 1546 |
1649 #endif // V8_TARGET_ARCH_MIPS64 | 1547 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |