| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 // UnknownFormat(instr) which will just print opcode name of the | 364 // UnknownFormat(instr) which will just print opcode name of the |
| 365 // instruction bits. | 365 // instruction bits. |
| 366 void Decoder::UnknownFormat(Instruction* instr, const char* name) { | 366 void Decoder::UnknownFormat(Instruction* instr, const char* name) { |
| 367 char buffer[100]; | 367 char buffer[100]; |
| 368 snprintf(buffer, sizeof(buffer), "%s (unknown-format)", name); | 368 snprintf(buffer, sizeof(buffer), "%s (unknown-format)", name); |
| 369 Format(instr, buffer); | 369 Format(instr, buffer); |
| 370 } | 370 } |
| 371 | 371 |
| 372 | 372 |
| 373 void Decoder::DecodeExt1(Instruction* instr) { | 373 void Decoder::DecodeExt1(Instruction* instr) { |
| 374 switch (instr->Bits(10, 1) << 1) { | 374 switch (EXT1 | (instr->BitField(10, 1))) { |
| 375 case MCRF: { | 375 case MCRF: { |
| 376 UnknownFormat(instr, "mcrf"); // not used by V8 | 376 UnknownFormat(instr, "mcrf"); // not used by V8 |
| 377 break; | 377 break; |
| 378 } | 378 } |
| 379 case BCLRX: { | 379 case BCLRX: { |
| 380 int bo = instr->Bits(25, 21) << 21; | 380 int bo = instr->BitField(25, 21); |
| 381 int bi = instr->Bits(20, 16); | 381 int bi = instr->Bits(20, 16); |
| 382 CRBit cond = static_cast<CRBit>(bi & (CRWIDTH - 1)); | 382 CRBit cond = static_cast<CRBit>(bi & (CRWIDTH - 1)); |
| 383 switch (bo) { | 383 switch (bo) { |
| 384 case DCBNZF: { | 384 case DCBNZF: { |
| 385 UnknownFormat(instr, "bclrx-dcbnzf"); | 385 UnknownFormat(instr, "bclrx-dcbnzf"); |
| 386 break; | 386 break; |
| 387 } | 387 } |
| 388 case DCBEZF: { | 388 case DCBEZF: { |
| 389 UnknownFormat(instr, "bclrx-dcbezf"); | 389 UnknownFormat(instr, "bclrx-dcbezf"); |
| 390 break; | 390 break; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 break; | 440 break; |
| 441 } | 441 } |
| 442 case BA: { | 442 case BA: { |
| 443 Format(instr, "blr'l"); | 443 Format(instr, "blr'l"); |
| 444 break; | 444 break; |
| 445 } | 445 } |
| 446 } | 446 } |
| 447 break; | 447 break; |
| 448 } | 448 } |
| 449 case BCCTRX: { | 449 case BCCTRX: { |
| 450 switch (instr->Bits(25, 21) << 21) { | 450 switch (instr->BitField(25, 21)) { |
| 451 case DCBNZF: { | 451 case DCBNZF: { |
| 452 UnknownFormat(instr, "bcctrx-dcbnzf"); | 452 UnknownFormat(instr, "bcctrx-dcbnzf"); |
| 453 break; | 453 break; |
| 454 } | 454 } |
| 455 case DCBEZF: { | 455 case DCBEZF: { |
| 456 UnknownFormat(instr, "bcctrx-dcbezf"); | 456 UnknownFormat(instr, "bcctrx-dcbezf"); |
| 457 break; | 457 break; |
| 458 } | 458 } |
| 459 case BF: { | 459 case BF: { |
| 460 UnknownFormat(instr, "bcctrx-bf"); | 460 UnknownFormat(instr, "bcctrx-bf"); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 } | 534 } |
| 535 default: { | 535 default: { |
| 536 Unknown(instr); // not used by V8 | 536 Unknown(instr); // not used by V8 |
| 537 } | 537 } |
| 538 } | 538 } |
| 539 } | 539 } |
| 540 | 540 |
| 541 | 541 |
| 542 void Decoder::DecodeExt2(Instruction* instr) { | 542 void Decoder::DecodeExt2(Instruction* instr) { |
| 543 // Some encodings are 10-1 bits, handle those first | 543 // Some encodings are 10-1 bits, handle those first |
| 544 switch (instr->Bits(10, 1) << 1) { | 544 switch (EXT2 | (instr->BitField(10, 1))) { |
| 545 case SRWX: { | 545 case SRWX: { |
| 546 Format(instr, "srw'. 'ra, 'rs, 'rb"); | 546 Format(instr, "srw'. 'ra, 'rs, 'rb"); |
| 547 return; | 547 return; |
| 548 } | 548 } |
| 549 #if V8_TARGET_ARCH_PPC64 | 549 #if V8_TARGET_ARCH_PPC64 |
| 550 case SRDX: { | 550 case SRDX: { |
| 551 Format(instr, "srd'. 'ra, 'rs, 'rb"); | 551 Format(instr, "srd'. 'ra, 'rs, 'rb"); |
| 552 return; | 552 return; |
| 553 } | 553 } |
| 554 #endif | 554 #endif |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 return; | 635 return; |
| 636 } | 636 } |
| 637 #if V8_TARGET_ARCH_PPC64 | 637 #if V8_TARGET_ARCH_PPC64 |
| 638 case POPCNTD: { | 638 case POPCNTD: { |
| 639 Format(instr, "popcntd 'ra, 'rs"); | 639 Format(instr, "popcntd 'ra, 'rs"); |
| 640 return; | 640 return; |
| 641 } | 641 } |
| 642 #endif | 642 #endif |
| 643 } | 643 } |
| 644 | 644 |
| 645 switch (instr->Bits(10, 2) << 2) { | 645 switch (EXT2 | (instr->BitField(10, 2))) { |
| 646 case SRADIX: { | 646 case SRADIX: { |
| 647 Format(instr, "sradi'. 'ra,'rs,'sh"); | 647 Format(instr, "sradi'. 'ra,'rs,'sh"); |
| 648 return; | 648 return; |
| 649 } | 649 } |
| 650 } | 650 } |
| 651 | 651 |
| 652 // ?? are all of these xo_form? | 652 // ?? are all of these xo_form? |
| 653 switch (instr->Bits(9, 1) << 1) { | 653 switch (EXT2 | (instr->BitField(9, 1))) { |
| 654 case CMP: { | 654 case CMP: { |
| 655 #if V8_TARGET_ARCH_PPC64 | 655 #if V8_TARGET_ARCH_PPC64 |
| 656 if (instr->Bit(21)) { | 656 if (instr->Bit(21)) { |
| 657 #endif | 657 #endif |
| 658 Format(instr, "cmp 'ra, 'rb"); | 658 Format(instr, "cmp 'ra, 'rb"); |
| 659 #if V8_TARGET_ARCH_PPC64 | 659 #if V8_TARGET_ARCH_PPC64 |
| 660 } else { | 660 } else { |
| 661 Format(instr, "cmpw 'ra, 'rb"); | 661 Format(instr, "cmpw 'ra, 'rb"); |
| 662 } | 662 } |
| 663 #endif | 663 #endif |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 892 Format(instr, "mtfprwa 'Dt, 'ra"); | 892 Format(instr, "mtfprwa 'Dt, 'ra"); |
| 893 return; | 893 return; |
| 894 } | 894 } |
| 895 case MTVSRWZ: { | 895 case MTVSRWZ: { |
| 896 Format(instr, "mtfprwz 'Dt, 'ra"); | 896 Format(instr, "mtfprwz 'Dt, 'ra"); |
| 897 return; | 897 return; |
| 898 } | 898 } |
| 899 #endif | 899 #endif |
| 900 } | 900 } |
| 901 | 901 |
| 902 switch (instr->Bits(5, 1) << 1) { | 902 switch (EXT2 | (instr->BitField(5, 1))) { |
| 903 case ISEL: { | 903 case ISEL: { |
| 904 Format(instr, "isel 'rt, 'ra, 'rb"); | 904 Format(instr, "isel 'rt, 'ra, 'rb"); |
| 905 return; | 905 return; |
| 906 } | 906 } |
| 907 default: { | 907 default: { |
| 908 Unknown(instr); // not used by V8 | 908 Unknown(instr); // not used by V8 |
| 909 } | 909 } |
| 910 } | 910 } |
| 911 } | 911 } |
| 912 | 912 |
| 913 | 913 |
| 914 void Decoder::DecodeExt3(Instruction* instr) { | 914 void Decoder::DecodeExt3(Instruction* instr) { |
| 915 switch (instr->Bits(10, 1) << 1) { | 915 switch (EXT3 | (instr->BitField(10, 1))) { |
| 916 case FCFID: { | 916 case FCFID: { |
| 917 Format(instr, "fcfids'. 'Dt, 'Db"); | 917 Format(instr, "fcfids'. 'Dt, 'Db"); |
| 918 break; | 918 break; |
| 919 } | 919 } |
| 920 case FCFIDU: { | 920 case FCFIDU: { |
| 921 Format(instr, "fcfidus'.'Dt, 'Db"); | 921 Format(instr, "fcfidus'.'Dt, 'Db"); |
| 922 break; | 922 break; |
| 923 } | 923 } |
| 924 default: { | 924 default: { |
| 925 Unknown(instr); // not used by V8 | 925 Unknown(instr); // not used by V8 |
| 926 } | 926 } |
| 927 } | 927 } |
| 928 } | 928 } |
| 929 | 929 |
| 930 | 930 |
| 931 void Decoder::DecodeExt4(Instruction* instr) { | 931 void Decoder::DecodeExt4(Instruction* instr) { |
| 932 switch (instr->Bits(5, 1) << 1) { | 932 switch (EXT4 | (instr->BitField(5, 1))) { |
| 933 case FDIV: { | 933 case FDIV: { |
| 934 Format(instr, "fdiv'. 'Dt, 'Da, 'Db"); | 934 Format(instr, "fdiv'. 'Dt, 'Da, 'Db"); |
| 935 return; | 935 return; |
| 936 } | 936 } |
| 937 case FSUB: { | 937 case FSUB: { |
| 938 Format(instr, "fsub'. 'Dt, 'Da, 'Db"); | 938 Format(instr, "fsub'. 'Dt, 'Da, 'Db"); |
| 939 return; | 939 return; |
| 940 } | 940 } |
| 941 case FADD: { | 941 case FADD: { |
| 942 Format(instr, "fadd'. 'Dt, 'Da, 'Db"); | 942 Format(instr, "fadd'. 'Dt, 'Da, 'Db"); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 957 case FMSUB: { | 957 case FMSUB: { |
| 958 Format(instr, "fmsub'. 'Dt, 'Da, 'Dc, 'Db"); | 958 Format(instr, "fmsub'. 'Dt, 'Da, 'Dc, 'Db"); |
| 959 return; | 959 return; |
| 960 } | 960 } |
| 961 case FMADD: { | 961 case FMADD: { |
| 962 Format(instr, "fmadd'. 'Dt, 'Da, 'Dc, 'Db"); | 962 Format(instr, "fmadd'. 'Dt, 'Da, 'Dc, 'Db"); |
| 963 return; | 963 return; |
| 964 } | 964 } |
| 965 } | 965 } |
| 966 | 966 |
| 967 switch (instr->Bits(10, 1) << 1) { | 967 switch (EXT4 | (instr->BitField(10, 1))) { |
| 968 case FCMPU: { | 968 case FCMPU: { |
| 969 Format(instr, "fcmpu 'Da, 'Db"); | 969 Format(instr, "fcmpu 'Da, 'Db"); |
| 970 break; | 970 break; |
| 971 } | 971 } |
| 972 case FRSP: { | 972 case FRSP: { |
| 973 Format(instr, "frsp'. 'Dt, 'Db"); | 973 Format(instr, "frsp'. 'Dt, 'Db"); |
| 974 break; | 974 break; |
| 975 } | 975 } |
| 976 case FCFID: { | 976 case FCFID: { |
| 977 Format(instr, "fcfid'. 'Dt, 'Db"); | 977 Format(instr, "fcfid'. 'Dt, 'Db"); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 break; | 1058 break; |
| 1059 } | 1059 } |
| 1060 default: { | 1060 default: { |
| 1061 Unknown(instr); // not used by V8 | 1061 Unknown(instr); // not used by V8 |
| 1062 } | 1062 } |
| 1063 } | 1063 } |
| 1064 } | 1064 } |
| 1065 | 1065 |
| 1066 | 1066 |
| 1067 void Decoder::DecodeExt5(Instruction* instr) { | 1067 void Decoder::DecodeExt5(Instruction* instr) { |
| 1068 switch (instr->Bits(4, 2) << 2) { | 1068 switch (EXT5 | (instr->BitField(4, 2))) { |
| 1069 case RLDICL: { | 1069 case RLDICL: { |
| 1070 Format(instr, "rldicl'. 'ra, 'rs, 'sh, 'mb"); | 1070 Format(instr, "rldicl'. 'ra, 'rs, 'sh, 'mb"); |
| 1071 return; | 1071 return; |
| 1072 } | 1072 } |
| 1073 case RLDICR: { | 1073 case RLDICR: { |
| 1074 Format(instr, "rldicr'. 'ra, 'rs, 'sh, 'me"); | 1074 Format(instr, "rldicr'. 'ra, 'rs, 'sh, 'me"); |
| 1075 return; | 1075 return; |
| 1076 } | 1076 } |
| 1077 case RLDIC: { | 1077 case RLDIC: { |
| 1078 Format(instr, "rldic'. 'ra, 'rs, 'sh, 'mb"); | 1078 Format(instr, "rldic'. 'ra, 'rs, 'sh, 'mb"); |
| 1079 return; | 1079 return; |
| 1080 } | 1080 } |
| 1081 case RLDIMI: { | 1081 case RLDIMI: { |
| 1082 Format(instr, "rldimi'. 'ra, 'rs, 'sh, 'mb"); | 1082 Format(instr, "rldimi'. 'ra, 'rs, 'sh, 'mb"); |
| 1083 return; | 1083 return; |
| 1084 } | 1084 } |
| 1085 } | 1085 } |
| 1086 switch (instr->Bits(4, 1) << 1) { | 1086 switch (EXT5 | (instr->BitField(4, 1))) { |
| 1087 case RLDCL: { | 1087 case RLDCL: { |
| 1088 Format(instr, "rldcl'. 'ra, 'rs, 'sb, 'mb"); | 1088 Format(instr, "rldcl'. 'ra, 'rs, 'sb, 'mb"); |
| 1089 return; | 1089 return; |
| 1090 } | 1090 } |
| 1091 } | 1091 } |
| 1092 Unknown(instr); // not used by V8 | 1092 Unknown(instr); // not used by V8 |
| 1093 } | 1093 } |
| 1094 | 1094 |
| 1095 void Decoder::DecodeExt6(Instruction* instr) { | 1095 void Decoder::DecodeExt6(Instruction* instr) { |
| 1096 switch (instr->Bits(10, 3) << 3) { | 1096 switch (EXT6 | (instr->BitField(10, 3))) { |
| 1097 #define DECODE_XX3_INSTRUCTIONS(name, opcode_name, opcode_value) \ | 1097 #define DECODE_XX3_INSTRUCTIONS(name, opcode_name, opcode_value) \ |
| 1098 case opcode_name: { \ | 1098 case opcode_name: { \ |
| 1099 Format(instr, #name" 'Dt, 'Da, 'Db"); \ | 1099 Format(instr, #name" 'Dt, 'Da, 'Db"); \ |
| 1100 return; \ | 1100 return; \ |
| 1101 } | 1101 } |
| 1102 XX3_OPCODE_LIST(DECODE_XX3_INSTRUCTIONS) | 1102 PPC_XX3_OPCODE_LIST(DECODE_XX3_INSTRUCTIONS) |
| 1103 #undef DECODE_XX3_INSTRUCTIONS | 1103 #undef DECODE_XX3_INSTRUCTIONS |
| 1104 } | 1104 } |
| 1105 switch (instr->Bits(10, 2) << 2) { | 1105 switch (EXT6 | (instr->BitField(10, 2))) { |
| 1106 #define DECODE_XX2_INSTRUCTIONS(name, opcode_name, opcode_value) \ | 1106 #define DECODE_XX2_INSTRUCTIONS(name, opcode_name, opcode_value) \ |
| 1107 case opcode_name: { \ | 1107 case opcode_name: { \ |
| 1108 Format(instr, #name" 'Dt, 'Db"); \ | 1108 Format(instr, #name" 'Dt, 'Db"); \ |
| 1109 return; \ | 1109 return; \ |
| 1110 } | 1110 } |
| 1111 XX2_OPCODE_LIST(DECODE_XX2_INSTRUCTIONS) | 1111 PPC_XX2_OPCODE_LIST(DECODE_XX2_INSTRUCTIONS) |
| 1112 } | 1112 } |
| 1113 #undef DECODE_XX3_INSTRUCTIONS | 1113 #undef DECODE_XX3_INSTRUCTIONS |
| 1114 Unknown(instr); // not used by V8 | 1114 Unknown(instr); // not used by V8 |
| 1115 } | 1115 } |
| 1116 | 1116 |
| 1117 #undef VERIFIY | 1117 #undef VERIFIY |
| 1118 | 1118 |
| 1119 // Disassemble the instruction at *instr_ptr into the output buffer. | 1119 // Disassemble the instruction at *instr_ptr into the output buffer. |
| 1120 int Decoder::InstructionDecode(byte* instr_ptr) { | 1120 int Decoder::InstructionDecode(byte* instr_ptr) { |
| 1121 Instruction* instr = Instruction::At(instr_ptr); | 1121 Instruction* instr = Instruction::At(instr_ptr); |
| 1122 // Print raw instruction bytes. | 1122 // Print raw instruction bytes. |
| 1123 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%08x ", | 1123 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "%08x ", |
| 1124 instr->InstructionBits()); | 1124 instr->InstructionBits()); |
| 1125 | 1125 |
| 1126 if (ABI_USES_FUNCTION_DESCRIPTORS && instr->InstructionBits() == 0) { | 1126 if (ABI_USES_FUNCTION_DESCRIPTORS && instr->InstructionBits() == 0) { |
| 1127 // The first field will be identified as a jump table entry. We | 1127 // The first field will be identified as a jump table entry. We |
| 1128 // emit the rest of the structure as zero, so just skip past them. | 1128 // emit the rest of the structure as zero, so just skip past them. |
| 1129 Format(instr, "constant"); | 1129 Format(instr, "constant"); |
| 1130 return Instruction::kInstrSize; | 1130 return Instruction::kInstrSize; |
| 1131 } | 1131 } |
| 1132 | 1132 |
| 1133 switch (instr->OpcodeValue() << 26) { | 1133 uint32_t opcode = instr->OpcodeValue() << 26; |
| 1134 switch (opcode) { |
| 1134 case TWI: { | 1135 case TWI: { |
| 1135 PrintSoftwareInterrupt(instr->SvcValue()); | 1136 PrintSoftwareInterrupt(instr->SvcValue()); |
| 1136 break; | 1137 break; |
| 1137 } | 1138 } |
| 1138 case MULLI: { | 1139 case MULLI: { |
| 1139 UnknownFormat(instr, "mulli"); | 1140 UnknownFormat(instr, "mulli"); |
| 1140 break; | 1141 break; |
| 1141 } | 1142 } |
| 1142 case SUBFIC: { | 1143 case SUBFIC: { |
| 1143 Format(instr, "subfic 'rt, 'ra, 'int16"); | 1144 Format(instr, "subfic 'rt, 'ra, 'int16"); |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1509 pc += d.InstructionDecode(buffer, pc); | 1510 pc += d.InstructionDecode(buffer, pc); |
| 1510 v8::internal::PrintF(f, "%p %08x %s\n", static_cast<void*>(prev_pc), | 1511 v8::internal::PrintF(f, "%p %08x %s\n", static_cast<void*>(prev_pc), |
| 1511 *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1512 *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1512 } | 1513 } |
| 1513 } | 1514 } |
| 1514 | 1515 |
| 1515 | 1516 |
| 1516 } // namespace disasm | 1517 } // namespace disasm |
| 1517 | 1518 |
| 1518 #endif // V8_TARGET_ARCH_PPC | 1519 #endif // V8_TARGET_ARCH_PPC |
| OLD | NEW |