| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 82 out_buffer_(out_buffer), | 82 out_buffer_(out_buffer), |
| 83 out_buffer_pos_(0) { | 83 out_buffer_pos_(0) { |
| 84 out_buffer_[out_buffer_pos_] = '\0'; | 84 out_buffer_[out_buffer_pos_] = '\0'; |
| 85 } | 85 } |
| 86 | 86 |
| 87 ~Decoder() {} | 87 ~Decoder() {} |
| 88 | 88 |
| 89 // Writes one disassembled instruction into 'buffer' (0-terminated). | 89 // Writes one disassembled instruction into 'buffer' (0-terminated). |
| 90 // Returns the length of the disassembled machine instruction in bytes. | 90 // Returns the length of the disassembled machine instruction in bytes. |
| 91 int InstructionDecode(byte* instruction); | 91 int InstructionDecode(byte* instruction); |
| 92 int InstructionDecodeArm(byte* instruction); |
| 93 int InstructionDecodeThumb2(const InstrThumb2& instr); |
| 92 | 94 |
| 93 private: | 95 private: |
| 94 // Bottleneck functions to print into the out_buffer. | 96 // Bottleneck functions to print into the out_buffer. |
| 95 void PrintChar(const char ch); | 97 void PrintChar(const char ch); |
| 96 void Print(const char* str); | 98 void Print(const char* str); |
| 97 | 99 |
| 98 // Printing of common values. | 100 // Printing of common values. |
| 99 void PrintRegister(int reg); | 101 void PrintRegister(int reg); |
| 100 void PrintSRegister(int reg); | 102 void PrintSRegister(int reg); |
| 101 void PrintDRegister(int reg); | 103 void PrintDRegister(int reg); |
| 102 int FormatVFPRegister(Instr* instr, const char* format); | 104 int FormatVFPRegister(Instr* instr, const char* format); |
| 103 int FormatVFPinstruction(Instr* instr, const char* format); | 105 int FormatVFPinstruction(Instr* instr, const char* format); |
| 104 void PrintCondition(Instr* instr); | 106 void PrintCondition(Instr* instr); |
| 105 void PrintShiftRm(Instr* instr); | 107 void PrintShiftRm(Instr* instr); |
| 108 void PrintShiftRm(const InstrThumb2& instr); |
| 106 void PrintShiftImm(Instr* instr); | 109 void PrintShiftImm(Instr* instr); |
| 110 void PrintShiftImm(const InstrThumb2& instr); |
| 107 void PrintPU(Instr* instr); | 111 void PrintPU(Instr* instr); |
| 108 void PrintSoftwareInterrupt(SoftwareInterruptCodes swi); | 112 void PrintSoftwareInterrupt(SoftwareInterruptCodes swi); |
| 109 | 113 |
| 110 // Handle formatting of instructions and their options. | 114 // Handle formatting of instructions and their options. |
| 111 int FormatRegister(Instr* instr, const char* option); | 115 int FormatRegister(Instr* instr, const char* option); |
| 116 int FormatRegister(const InstrThumb2& instr, const char* option); |
| 112 int FormatOption(Instr* instr, const char* option); | 117 int FormatOption(Instr* instr, const char* option); |
| 118 int FormatOption(const InstrThumb2& instr, const char* option); |
| 113 void Format(Instr* instr, const char* format); | 119 void Format(Instr* instr, const char* format); |
| 120 void Format(const InstrThumb2& instr, const char* format); |
| 114 void Unknown(Instr* instr); | 121 void Unknown(Instr* instr); |
| 122 void Unknown(const InstrThumb2& instr); |
| 115 | 123 |
| 116 // Each of these functions decodes one particular instruction type, a 3-bit | 124 // Each of these functions decodes one particular instruction type, a 3-bit |
| 117 // field in the instruction encoding. | 125 // field in the instruction encoding. |
| 118 // Types 0 and 1 are combined as they are largely the same except for the way | 126 // Types 0 and 1 are combined as they are largely the same except for the way |
| 119 // they interpret the shifter operand. | 127 // they interpret the shifter operand. |
| 120 void DecodeType01(Instr* instr); | 128 void DecodeType01(Instr* instr); |
| 121 void DecodeType2(Instr* instr); | 129 void DecodeType2(Instr* instr); |
| 122 void DecodeType3(Instr* instr); | 130 void DecodeType3(Instr* instr); |
| 123 void DecodeType4(Instr* instr); | 131 void DecodeType4(Instr* instr); |
| 124 void DecodeType5(Instr* instr); | 132 void DecodeType5(Instr* instr); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 shift_names[shift], shift_amount); | 231 shift_names[shift], shift_amount); |
| 224 } else { | 232 } else { |
| 225 // by register | 233 // by register |
| 226 int rs = instr->RsField(); | 234 int rs = instr->RsField(); |
| 227 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 235 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| 228 ", %s ", shift_names[shift]); | 236 ", %s ", shift_names[shift]); |
| 229 PrintRegister(rs); | 237 PrintRegister(rs); |
| 230 } | 238 } |
| 231 } | 239 } |
| 232 | 240 |
| 241 void Decoder::PrintShiftRm(const InstrThumb2& instr) { |
| 242 int shift = instr.Type(); |
| 243 int shift_amount = instr.Imm(); |
| 244 int rm = instr.Rm(); |
| 245 |
| 246 PrintRegister(rm); |
| 247 |
| 248 if (instr.Variant() != VARIANT_REGISTER_SHIFTED_REGISTER) { |
| 249 if (shift == no_shift) { |
| 250 // Special case for using rm only. |
| 251 return; |
| 252 } |
| 253 if (shift == RRX) { |
| 254 Print(", RRX"); |
| 255 return; |
| 256 } |
| 257 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| 258 ", %s #%d", |
| 259 shift_names[shift], shift_amount); |
| 260 } else { |
| 261 // TODO(haustein) |
| 262 UNIMPLEMENTED(); |
| 263 } |
| 264 } |
| 265 |
| 266 |
| 233 | 267 |
| 234 // Print the immediate operand for the instruction. Generally used for data | 268 // Print the immediate operand for the instruction. Generally used for data |
| 235 // processing instructions. | 269 // processing instructions. |
| 236 void Decoder::PrintShiftImm(Instr* instr) { | 270 void Decoder::PrintShiftImm(Instr* instr) { |
| 237 int rotate = instr->RotateField() * 2; | 271 int rotate = instr->RotateField() * 2; |
| 238 int immed8 = instr->Immed8Field(); | 272 int immed8 = instr->Immed8Field(); |
| 239 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); | 273 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); |
| 240 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 274 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| 241 "#%d", imm); | 275 "#%d", imm); |
| 242 } | 276 } |
| 243 | 277 |
| 278 void Decoder::PrintShiftImm(const InstrThumb2& instr) { |
| 279 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| 280 "#%d", instr.Imm()); |
| 281 } |
| 282 |
| 244 | 283 |
| 245 // Print PU formatting to reduce complexity of FormatOption. | 284 // Print PU formatting to reduce complexity of FormatOption. |
| 246 void Decoder::PrintPU(Instr* instr) { | 285 void Decoder::PrintPU(Instr* instr) { |
| 247 switch (instr->PUField()) { | 286 switch (instr->PUField()) { |
| 248 case 0: { | 287 case 0: { |
| 249 Print("da"); | 288 Print("da"); |
| 250 break; | 289 break; |
| 251 } | 290 } |
| 252 case 1: { | 291 case 1: { |
| 253 Print("ia"); | 292 Print("ia"); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 329 reg++; | 368 reg++; |
| 330 rlist >>= 1; | 369 rlist >>= 1; |
| 331 } | 370 } |
| 332 Print("}"); | 371 Print("}"); |
| 333 return 5; | 372 return 5; |
| 334 } | 373 } |
| 335 UNREACHABLE(); | 374 UNREACHABLE(); |
| 336 return -1; | 375 return -1; |
| 337 } | 376 } |
| 338 | 377 |
| 378 int Decoder::FormatRegister(const InstrThumb2& instr, const char* format) { |
| 379 ASSERT(format[0] == 'r'); |
| 380 if (format[1] == 'n') { // 'rn: Rn register |
| 381 int reg = instr.Rn(); |
| 382 PrintRegister(reg); |
| 383 return 2; |
| 384 } else if (format[1] == 'd') { // 'rd: Rd register |
| 385 int reg = instr.Rd(); |
| 386 PrintRegister(reg); |
| 387 return 2; |
| 388 } else if (format[1] == 's') { // 'rs: Rs register |
| 389 int reg = instr.Rs(); |
| 390 PrintRegister(reg); |
| 391 return 2; |
| 392 } else if (format[1] == 'm') { // 'rm: Rm register |
| 393 int reg = instr.Rm(); |
| 394 PrintRegister(reg); |
| 395 return 2; |
| 396 } else if (format[1] == 't') { // 'rt: Rt register |
| 397 int reg = instr.Rt(); |
| 398 PrintRegister(reg); |
| 399 return 2; |
| 400 } else if (format[1] == 'l') { |
| 401 // 'rlist: register list for load and store multiple instructions |
| 402 ASSERT(STRING_STARTS_WITH(format, "rlist")); |
| 403 // TODO(haustein) |
| 404 UNIMPLEMENTED(); |
| 405 return 5; |
| 406 } |
| 407 UNREACHABLE(); |
| 408 return -1; |
| 409 } |
| 410 |
| 339 | 411 |
| 340 // Handle all VFP register based formatting in this function to reduce the | 412 // Handle all VFP register based formatting in this function to reduce the |
| 341 // complexity of FormatOption. | 413 // complexity of FormatOption. |
| 342 int Decoder::FormatVFPRegister(Instr* instr, const char* format) { | 414 int Decoder::FormatVFPRegister(Instr* instr, const char* format) { |
| 343 ASSERT((format[0] == 'S') || (format[0] == 'D')); | 415 ASSERT((format[0] == 'S') || (format[0] == 'D')); |
| 344 | 416 |
| 345 if (format[1] == 'n') { | 417 if (format[1] == 'n') { |
| 346 int reg = instr->VnField(); | 418 int reg = instr->VnField(); |
| 347 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->NField())); | 419 if (format[0] == 'S') PrintSRegister(((reg << 1) | instr->NField())); |
| 348 if (format[0] == 'D') PrintDRegister(reg); | 420 if (format[0] == 'D') PrintDRegister(reg); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 } | 611 } |
| 540 default: { | 612 default: { |
| 541 UNREACHABLE(); | 613 UNREACHABLE(); |
| 542 break; | 614 break; |
| 543 } | 615 } |
| 544 } | 616 } |
| 545 UNREACHABLE(); | 617 UNREACHABLE(); |
| 546 return -1; | 618 return -1; |
| 547 } | 619 } |
| 548 | 620 |
| 621 int Decoder::FormatOption(const InstrThumb2& instr, const char* format) { |
| 622 switch (format[0]) { |
| 623 // TODO(haustein) Add code for a, b, c, h, l, m, o, p, see ARM |
| 624 case 'r': { |
| 625 return FormatRegister(instr, format); |
| 626 } |
| 627 case 's': { |
| 628 if (format[1] == 'h') { // 'shift_op or 'shift_rm |
| 629 if (format[6] == 'o') { // 'shift_op |
| 630 ASSERT(STRING_STARTS_WITH(format, "shift_op")); |
| 631 if (instr.Type() == 0) { |
| 632 PrintShiftRm(instr); |
| 633 } else { |
| 634 ASSERT(instr.Type() == 1); |
| 635 PrintShiftImm(instr); |
| 636 } |
| 637 return 8; |
| 638 } else { // 'shift_rm |
| 639 ASSERT(STRING_STARTS_WITH(format, "shift_rm")); |
| 640 PrintShiftRm(instr); |
| 641 return 8; |
| 642 } |
| 643 // TODO(haustein) Add code for 'w', 'i', 's' here (see arm code) |
| 644 } |
| 645 // 's: S field of data processing instructions |
| 646 if (instr.HasS()) { |
| 647 Print("s"); |
| 648 } |
| 649 return 1; |
| 650 } |
| 651 // TODO(haustein) Add code for 't', 'u', 'v', 'S', 'D', 'w' below, |
| 652 // see arm code |
| 653 default: { |
| 654 UNIMPLEMENTED(); |
| 655 break; |
| 656 } |
| 657 } |
| 658 UNREACHABLE(); |
| 659 return -1; |
| 660 } |
| 661 |
| 549 | 662 |
| 550 // Format takes a formatting string for a whole instruction and prints it into | 663 // Format takes a formatting string for a whole instruction and prints it into |
| 551 // the output buffer. All escaped options are handed to FormatOption to be | 664 // the output buffer. All escaped options are handed to FormatOption to be |
| 552 // parsed further. | 665 // parsed further. |
| 553 void Decoder::Format(Instr* instr, const char* format) { | 666 void Decoder::Format(Instr* instr, const char* format) { |
| 554 char cur = *format++; | 667 char cur = *format++; |
| 555 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { | 668 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { |
| 556 if (cur == '\'') { // Single quote is used as the formatting escape. | 669 if (cur == '\'') { // Single quote is used as the formatting escape. |
| 557 format += FormatOption(instr, format); | 670 format += FormatOption(instr, format); |
| 558 } else { | 671 } else { |
| 559 out_buffer_[out_buffer_pos_++] = cur; | 672 out_buffer_[out_buffer_pos_++] = cur; |
| 560 } | 673 } |
| 561 cur = *format++; | 674 cur = *format++; |
| 562 } | 675 } |
| 563 out_buffer_[out_buffer_pos_] = '\0'; | 676 out_buffer_[out_buffer_pos_] = '\0'; |
| 564 } | 677 } |
| 565 | 678 |
| 566 | 679 |
| 680 void Decoder::Format(const InstrThumb2& instr, const char* format) { |
| 681 char cur = *format++; |
| 682 while ((cur != 0) && (out_buffer_pos_ < (out_buffer_.length() - 1))) { |
| 683 if (cur == '\'') { // Single quote is used as the formatting escape. |
| 684 format += FormatOption(instr, format); |
| 685 } else { |
| 686 out_buffer_[out_buffer_pos_++] = cur; |
| 687 } |
| 688 cur = *format++; |
| 689 } |
| 690 out_buffer_[out_buffer_pos_] = '\0'; |
| 691 } |
| 692 |
| 693 |
| 694 |
| 567 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 695 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
| 568 // which will just print "unknown" of the instruction bits. | 696 // which will just print "unknown" of the instruction bits. |
| 569 void Decoder::Unknown(Instr* instr) { | 697 void Decoder::Unknown(Instr* instr) { |
| 570 Format(instr, "unknown"); | 698 Format(instr, "unknown"); |
| 571 } | 699 } |
| 572 | 700 |
| 573 | 701 |
| 574 void Decoder::DecodeType01(Instr* instr) { | 702 void Decoder::DecodeType01(Instr* instr) { |
| 575 int type = instr->TypeField(); | 703 int type = instr->TypeField(); |
| 576 if ((type == 0) && instr->IsSpecialType0()) { | 704 if ((type == 0) && instr->IsSpecialType0()) { |
| (...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1055 default: | 1183 default: |
| 1056 Unknown(instr); // Not used by V8. | 1184 Unknown(instr); // Not used by V8. |
| 1057 break; | 1185 break; |
| 1058 } | 1186 } |
| 1059 } | 1187 } |
| 1060 } | 1188 } |
| 1061 | 1189 |
| 1062 | 1190 |
| 1063 // Disassemble the instruction at *instr_ptr into the output buffer. | 1191 // Disassemble the instruction at *instr_ptr into the output buffer. |
| 1064 int Decoder::InstructionDecode(byte* instr_ptr) { | 1192 int Decoder::InstructionDecode(byte* instr_ptr) { |
| 1193 if (reinterpret_cast<int32_t>(instr_ptr) & 1) { |
| 1194 InstrThumb2 instr(instr_ptr); |
| 1195 return InstructionDecodeThumb2(instr); |
| 1196 } else { |
| 1197 return InstructionDecodeArm(instr_ptr); |
| 1198 } |
| 1199 } |
| 1200 |
| 1201 int Decoder::InstructionDecodeArm(byte* instr_ptr) { |
| 1065 Instr* instr = Instr::At(instr_ptr); | 1202 Instr* instr = Instr::At(instr_ptr); |
| 1066 // Print raw instruction bytes. | 1203 // Print raw instruction bytes. |
| 1067 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1204 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| 1068 "%08x ", | 1205 "%08x ", |
| 1069 instr->InstructionBits()); | 1206 instr->InstructionBits()); |
| 1070 if (instr->ConditionField() == special_condition) { | 1207 if (instr->ConditionField() == special_condition) { |
| 1071 DecodeUnconditional(instr); | 1208 DecodeUnconditional(instr); |
| 1072 return Instr::kInstrSize; | 1209 return Instr::kInstrSize; |
| 1073 } | 1210 } |
| 1074 switch (instr->TypeField()) { | 1211 switch (instr->TypeField()) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1104 default: { | 1241 default: { |
| 1105 // The type field is 3-bits in the ARM encoding. | 1242 // The type field is 3-bits in the ARM encoding. |
| 1106 UNREACHABLE(); | 1243 UNREACHABLE(); |
| 1107 break; | 1244 break; |
| 1108 } | 1245 } |
| 1109 } | 1246 } |
| 1110 return Instr::kInstrSize; | 1247 return Instr::kInstrSize; |
| 1111 } | 1248 } |
| 1112 | 1249 |
| 1113 | 1250 |
| 1251 int Decoder::InstructionDecodeThumb2(const InstrThumb2& instr) { |
| 1252 switch (instr.Op()) { |
| 1253 case OP_ADD: |
| 1254 Format(instr, "and's 'rd, 'rn, 'shift_op"); |
| 1255 break; |
| 1256 case OP_AND: |
| 1257 Format(instr, "and's 'rd, 'rn, 'shift_op"); |
| 1258 break; |
| 1259 case OP_SUB: |
| 1260 Format(instr, "sub's 'rd, 'rn, 'shift_op"); |
| 1261 break; |
| 1262 default: |
| 1263 UNIMPLEMENTED(); |
| 1264 break; |
| 1265 } |
| 1266 return instr.Size(); |
| 1267 } |
| 1268 |
| 1269 |
| 1114 } } // namespace assembler::arm | 1270 } } // namespace assembler::arm |
| 1115 | 1271 |
| 1116 | 1272 |
| 1117 | 1273 |
| 1118 //------------------------------------------------------------------------------ | 1274 //------------------------------------------------------------------------------ |
| 1119 | 1275 |
| 1120 namespace disasm { | 1276 namespace disasm { |
| 1121 | 1277 |
| 1122 namespace v8i = v8::internal; | 1278 namespace v8i = v8::internal; |
| 1123 | 1279 |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1192 buffer[0] = '\0'; | 1348 buffer[0] = '\0'; |
| 1193 byte* prev_pc = pc; | 1349 byte* prev_pc = pc; |
| 1194 pc += d.InstructionDecode(buffer, pc); | 1350 pc += d.InstructionDecode(buffer, pc); |
| 1195 fprintf(f, "%p %08x %s\n", | 1351 fprintf(f, "%p %08x %s\n", |
| 1196 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1352 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1197 } | 1353 } |
| 1198 } | 1354 } |
| 1199 | 1355 |
| 1200 | 1356 |
| 1201 } // namespace disasm | 1357 } // namespace disasm |
| OLD | NEW |