| 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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 PrintXImm21(Instruction* instr); |
| 90 void PrintXImm26(Instruction* instr); | 90 void PrintXImm26(Instruction* instr); |
| 91 void PrintCode(Instruction* instr); // For break and trap instructions. | 91 void PrintCode(Instruction* instr); // For break and trap instructions. |
| 92 void PrintFormat(Instruction* instr); // For floating format postfix. |
| 92 // Printing of instruction name. | 93 // Printing of instruction name. |
| 93 void PrintInstructionName(Instruction* instr); | 94 void PrintInstructionName(Instruction* instr); |
| 94 | 95 |
| 95 // Handle formatting of instructions and their options. | 96 // Handle formatting of instructions and their options. |
| 96 int FormatRegister(Instruction* instr, const char* option); | 97 int FormatRegister(Instruction* instr, const char* option); |
| 97 int FormatFPURegister(Instruction* instr, const char* option); | 98 int FormatFPURegister(Instruction* instr, const char* option); |
| 98 int FormatOption(Instruction* instr, const char* option); | 99 int FormatOption(Instruction* instr, const char* option); |
| 99 void Format(Instruction* instr, const char* format); | 100 void Format(Instruction* instr, const char* format); |
| 100 void Unknown(Instruction* instr); | 101 void Unknown(Instruction* instr); |
| 101 | 102 |
| 102 | 103 |
| 103 // Each of these functions decodes one particular instruction type. | 104 // Each of these functions decodes one particular instruction type. |
| 105 bool DecodeTypeRegisterRsType(Instruction* instr); |
| 106 void DecodeTypeRegisterSRsType(Instruction* instr); |
| 104 void DecodeTypeRegisterDRsType(Instruction* instr); | 107 void DecodeTypeRegisterDRsType(Instruction* instr); |
| 105 void DecodeTypeRegisterLRsType(Instruction* instr); | 108 void DecodeTypeRegisterLRsType(Instruction* instr); |
| 106 void DecodeTypeRegisterSPECIAL(Instruction* instr); | 109 void DecodeTypeRegisterSPECIAL(Instruction* instr); |
| 107 void DecodeTypeRegisterSPECIAL2(Instruction* instr); | 110 void DecodeTypeRegisterSPECIAL2(Instruction* instr); |
| 108 void DecodeTypeRegisterSPECIAL3(Instruction* instr); | 111 void DecodeTypeRegisterSPECIAL3(Instruction* instr); |
| 109 void DecodeTypeRegister(Instruction* instr); | 112 void DecodeTypeRegister(Instruction* instr); |
| 110 void DecodeTypeImmediate(Instruction* instr); | 113 void DecodeTypeImmediate(Instruction* instr); |
| 111 void DecodeTypeJump(Instruction* instr); | 114 void DecodeTypeJump(Instruction* instr); |
| 112 | 115 |
| 113 const disasm::NameConverter& converter_; | 116 const disasm::NameConverter& converter_; |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 out_buffer_pos_ += | 291 out_buffer_pos_ += |
| 289 SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code); | 292 SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code); |
| 290 break; | 293 break; |
| 291 } | 294 } |
| 292 default: // Not a break or trap instruction. | 295 default: // Not a break or trap instruction. |
| 293 break; | 296 break; |
| 294 } | 297 } |
| 295 } | 298 } |
| 296 | 299 |
| 297 | 300 |
| 301 void Decoder::PrintFormat(Instruction* instr) { |
| 302 char formatLetter = ' '; |
| 303 switch (instr->RsFieldRaw()) { |
| 304 case S: |
| 305 formatLetter = 's'; |
| 306 break; |
| 307 case D: |
| 308 formatLetter = 'd'; |
| 309 break; |
| 310 case W: |
| 311 formatLetter = 'w'; |
| 312 break; |
| 313 case L: |
| 314 formatLetter = 'l'; |
| 315 break; |
| 316 default: |
| 317 UNREACHABLE(); |
| 318 break; |
| 319 } |
| 320 PrintChar(formatLetter); |
| 321 } |
| 322 |
| 323 |
| 298 // Printing of instruction name. | 324 // Printing of instruction name. |
| 299 void Decoder::PrintInstructionName(Instruction* instr) { | 325 void Decoder::PrintInstructionName(Instruction* instr) { |
| 300 } | 326 } |
| 301 | 327 |
| 302 | 328 |
| 303 // Handle all register based formatting in this function to reduce the | 329 // Handle all register based formatting in this function to reduce the |
| 304 // complexity of FormatOption. | 330 // complexity of FormatOption. |
| 305 int Decoder::FormatRegister(Instruction* instr, const char* format) { | 331 int Decoder::FormatRegister(Instruction* instr, const char* format) { |
| 306 DCHECK(format[0] == 'r'); | 332 DCHECK(format[0] == 'r'); |
| 307 if (format[1] == 's') { // 'rs: Rs register. | 333 if (format[1] == 's') { // 'rs: Rs register. |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 case 'b': { // 'bc - Special for bc1 cc field. | 444 case 'b': { // 'bc - Special for bc1 cc field. |
| 419 DCHECK(STRING_STARTS_WITH(format, "bc")); | 445 DCHECK(STRING_STARTS_WITH(format, "bc")); |
| 420 PrintBc(instr); | 446 PrintBc(instr); |
| 421 return 2; | 447 return 2; |
| 422 } | 448 } |
| 423 case 'C': { // 'Cc - Special for c.xx.d cc field. | 449 case 'C': { // 'Cc - Special for c.xx.d cc field. |
| 424 DCHECK(STRING_STARTS_WITH(format, "Cc")); | 450 DCHECK(STRING_STARTS_WITH(format, "Cc")); |
| 425 PrintCc(instr); | 451 PrintCc(instr); |
| 426 return 2; | 452 return 2; |
| 427 } | 453 } |
| 454 case 't': |
| 455 PrintFormat(instr); |
| 456 return 1; |
| 428 } | 457 } |
| 429 UNREACHABLE(); | 458 UNREACHABLE(); |
| 430 return -1; | 459 return -1; |
| 431 } | 460 } |
| 432 | 461 |
| 433 | 462 |
| 434 // Format takes a formatting string for a whole instruction and prints it into | 463 // Format takes a formatting string for a whole instruction and prints it into |
| 435 // the output buffer. All escaped options are handed to FormatOption to be | 464 // the output buffer. All escaped options are handed to FormatOption to be |
| 436 // parsed further. | 465 // parsed further. |
| 437 void Decoder::Format(Instruction* instr, const char* format) { | 466 void Decoder::Format(Instruction* instr, const char* format) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 448 } | 477 } |
| 449 | 478 |
| 450 | 479 |
| 451 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 480 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
| 452 // which will just print "unknown" of the instruction bits. | 481 // which will just print "unknown" of the instruction bits. |
| 453 void Decoder::Unknown(Instruction* instr) { | 482 void Decoder::Unknown(Instruction* instr) { |
| 454 Format(instr, "unknown"); | 483 Format(instr, "unknown"); |
| 455 } | 484 } |
| 456 | 485 |
| 457 | 486 |
| 487 bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) { |
| 488 switch (instr->FunctionFieldRaw()) { |
| 489 case ADD_D: |
| 490 Format(instr, "add.'t 'fd, 'fs, 'ft"); |
| 491 break; |
| 492 case SUB_D: |
| 493 Format(instr, "sub.'t 'fd, 'fs, 'ft"); |
| 494 break; |
| 495 case MUL_D: |
| 496 Format(instr, "mul.'t 'fd, 'fs, 'ft"); |
| 497 break; |
| 498 case DIV_D: |
| 499 Format(instr, "div.'t 'fd, 'fs, 'ft"); |
| 500 break; |
| 501 case ABS_D: |
| 502 Format(instr, "abs.'t 'fd, 'fs"); |
| 503 break; |
| 504 case MOV_D: |
| 505 Format(instr, "mov.'t 'fd, 'fs"); |
| 506 break; |
| 507 case NEG_D: |
| 508 Format(instr, "neg.'t 'fd, 'fs"); |
| 509 break; |
| 510 case SQRT_D: |
| 511 Format(instr, "sqrt.'t 'fd, 'fs"); |
| 512 break; |
| 513 case CVT_W_D: |
| 514 Format(instr, "cvt.w.'t 'fd, 'fs"); |
| 515 break; |
| 516 case CVT_L_D: |
| 517 Format(instr, "cvt.l.'t 'fd, 'fs"); |
| 518 break; |
| 519 case TRUNC_W_D: |
| 520 Format(instr, "trunc.w.'t 'fd, 'fs"); |
| 521 break; |
| 522 case TRUNC_L_D: |
| 523 Format(instr, "trunc.l.'t 'fd, 'fs"); |
| 524 break; |
| 525 case ROUND_W_D: |
| 526 Format(instr, "round.w.'t 'fd, 'fs"); |
| 527 break; |
| 528 case FLOOR_W_D: |
| 529 Format(instr, "floor.w.'t 'fd, 'fs"); |
| 530 break; |
| 531 case CEIL_W_D: |
| 532 Format(instr, "ceil.w.'t 'fd, 'fs"); |
| 533 break; |
| 534 case CVT_S_D: |
| 535 Format(instr, "cvt.s.'t 'fd, 'fs"); |
| 536 break; |
| 537 case C_F_D: |
| 538 Format(instr, "c.f.'t 'fs, 'ft, 'Cc"); |
| 539 break; |
| 540 case C_UN_D: |
| 541 Format(instr, "c.un.'t 'fs, 'ft, 'Cc"); |
| 542 break; |
| 543 case C_EQ_D: |
| 544 Format(instr, "c.eq.'t 'fs, 'ft, 'Cc"); |
| 545 break; |
| 546 case C_UEQ_D: |
| 547 Format(instr, "c.ueq.'t 'fs, 'ft, 'Cc"); |
| 548 break; |
| 549 case C_OLT_D: |
| 550 Format(instr, "c.olt.'t 'fs, 'ft, 'Cc"); |
| 551 break; |
| 552 case C_ULT_D: |
| 553 Format(instr, "c.ult.'t 'fs, 'ft, 'Cc"); |
| 554 break; |
| 555 case C_OLE_D: |
| 556 Format(instr, "c.ole.'t 'fs, 'ft, 'Cc"); |
| 557 break; |
| 558 case C_ULE_D: |
| 559 Format(instr, "c.ule.'t 'fs, 'ft, 'Cc"); |
| 560 break; |
| 561 default: |
| 562 return false; |
| 563 } |
| 564 return true; |
| 565 } |
| 566 |
| 567 |
| 568 void Decoder::DecodeTypeRegisterSRsType(Instruction* instr) { |
| 569 if (!DecodeTypeRegisterRsType(instr)) { |
| 570 switch (instr->FunctionFieldRaw()) { |
| 571 case CVT_D_S: |
| 572 Format(instr, "cvt.d.'t 'fd, 'fs"); |
| 573 break; |
| 574 default: |
| 575 Format(instr, "unknown.cop1.'t"); |
| 576 break; |
| 577 } |
| 578 } |
| 579 } |
| 580 |
| 581 |
| 458 void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) { | 582 void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) { |
| 459 switch (instr->FunctionFieldRaw()) { | 583 if (!DecodeTypeRegisterRsType(instr)) { |
| 460 case ADD_D: | 584 Format(instr, "unknown.cop1.'t"); |
| 461 Format(instr, "add.d 'fd, 'fs, 'ft"); | |
| 462 break; | |
| 463 case SUB_D: | |
| 464 Format(instr, "sub.d 'fd, 'fs, 'ft"); | |
| 465 break; | |
| 466 case MUL_D: | |
| 467 Format(instr, "mul.d 'fd, 'fs, 'ft"); | |
| 468 break; | |
| 469 case DIV_D: | |
| 470 Format(instr, "div.d 'fd, 'fs, 'ft"); | |
| 471 break; | |
| 472 case ABS_D: | |
| 473 Format(instr, "abs.d 'fd, 'fs"); | |
| 474 break; | |
| 475 case MOV_D: | |
| 476 Format(instr, "mov.d 'fd, 'fs"); | |
| 477 break; | |
| 478 case NEG_D: | |
| 479 Format(instr, "neg.d 'fd, 'fs"); | |
| 480 break; | |
| 481 case SQRT_D: | |
| 482 Format(instr, "sqrt.d 'fd, 'fs"); | |
| 483 break; | |
| 484 case CVT_W_D: | |
| 485 Format(instr, "cvt.w.d 'fd, 'fs"); | |
| 486 break; | |
| 487 case CVT_L_D: | |
| 488 Format(instr, "cvt.l.d 'fd, 'fs"); | |
| 489 break; | |
| 490 case TRUNC_W_D: | |
| 491 Format(instr, "trunc.w.d 'fd, 'fs"); | |
| 492 break; | |
| 493 case TRUNC_L_D: | |
| 494 Format(instr, "trunc.l.d 'fd, 'fs"); | |
| 495 break; | |
| 496 case ROUND_W_D: | |
| 497 Format(instr, "round.w.d 'fd, 'fs"); | |
| 498 break; | |
| 499 case FLOOR_W_D: | |
| 500 Format(instr, "floor.w.d 'fd, 'fs"); | |
| 501 break; | |
| 502 case CEIL_W_D: | |
| 503 Format(instr, "ceil.w.d 'fd, 'fs"); | |
| 504 break; | |
| 505 case CVT_S_D: | |
| 506 Format(instr, "cvt.s.d 'fd, 'fs"); | |
| 507 break; | |
| 508 case C_F_D: | |
| 509 Format(instr, "c.f.d 'fs, 'ft, 'Cc"); | |
| 510 break; | |
| 511 case C_UN_D: | |
| 512 Format(instr, "c.un.d 'fs, 'ft, 'Cc"); | |
| 513 break; | |
| 514 case C_EQ_D: | |
| 515 Format(instr, "c.eq.d 'fs, 'ft, 'Cc"); | |
| 516 break; | |
| 517 case C_UEQ_D: | |
| 518 Format(instr, "c.ueq.d 'fs, 'ft, 'Cc"); | |
| 519 break; | |
| 520 case C_OLT_D: | |
| 521 Format(instr, "c.olt.d 'fs, 'ft, 'Cc"); | |
| 522 break; | |
| 523 case C_ULT_D: | |
| 524 Format(instr, "c.ult.d 'fs, 'ft, 'Cc"); | |
| 525 break; | |
| 526 case C_OLE_D: | |
| 527 Format(instr, "c.ole.d 'fs, 'ft, 'Cc"); | |
| 528 break; | |
| 529 case C_ULE_D: | |
| 530 Format(instr, "c.ule.d 'fs, 'ft, 'Cc"); | |
| 531 break; | |
| 532 default: | |
| 533 Format(instr, "unknown.cop1.d"); | |
| 534 break; | |
| 535 } | 585 } |
| 536 } | 586 } |
| 537 | 587 |
| 538 | 588 |
| 539 void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) { | 589 void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) { |
| 540 switch (instr->FunctionFieldRaw()) { | 590 switch (instr->FunctionFieldRaw()) { |
| 541 case CVT_D_L: | 591 case CVT_D_L: |
| 542 Format(instr, "cvt.d.l 'fd, 'fs"); | 592 Format(instr, "cvt.d.l 'fd, 'fs"); |
| 543 break; | 593 break; |
| 544 case CVT_S_L: | 594 case CVT_S_L: |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 825 // These are called "fs" too, although they are not FPU registers. | 875 // These are called "fs" too, although they are not FPU registers. |
| 826 case CTC1: | 876 case CTC1: |
| 827 Format(instr, "ctc1 'rt, 'fs"); | 877 Format(instr, "ctc1 'rt, 'fs"); |
| 828 break; | 878 break; |
| 829 case CFC1: | 879 case CFC1: |
| 830 Format(instr, "cfc1 'rt, 'fs"); | 880 Format(instr, "cfc1 'rt, 'fs"); |
| 831 break; | 881 break; |
| 832 case MTHC1: | 882 case MTHC1: |
| 833 Format(instr, "mthc1 'rt, 'fs"); | 883 Format(instr, "mthc1 'rt, 'fs"); |
| 834 break; | 884 break; |
| 885 case S: |
| 886 DecodeTypeRegisterSRsType(instr); |
| 887 break; |
| 835 case D: | 888 case D: |
| 836 DecodeTypeRegisterDRsType(instr); | 889 DecodeTypeRegisterDRsType(instr); |
| 837 break; | 890 break; |
| 838 case S: | |
| 839 switch (instr->FunctionFieldRaw()) { | |
| 840 case CVT_D_S: | |
| 841 Format(instr, "cvt.d.s 'fd, 'fs"); | |
| 842 break; | |
| 843 default: | |
| 844 UNIMPLEMENTED_MIPS(); | |
| 845 } | |
| 846 break; | |
| 847 case W: | 891 case W: |
| 848 switch (instr->FunctionFieldRaw()) { | 892 switch (instr->FunctionFieldRaw()) { |
| 849 case CVT_S_W: // Convert word to float (single). | 893 case CVT_S_W: // Convert word to float (single). |
| 850 Format(instr, "cvt.s.w 'fd, 'fs"); | 894 Format(instr, "cvt.s.w 'fd, 'fs"); |
| 851 break; | 895 break; |
| 852 case CVT_D_W: // Convert word to double. | 896 case CVT_D_W: // Convert word to double. |
| 853 Format(instr, "cvt.d.w 'fd, 'fs"); | 897 Format(instr, "cvt.d.w 'fd, 'fs"); |
| 854 break; | 898 break; |
| 855 default: | 899 default: |
| 856 UNREACHABLE(); | 900 UNREACHABLE(); |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1380 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1424 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1381 } | 1425 } |
| 1382 } | 1426 } |
| 1383 | 1427 |
| 1384 | 1428 |
| 1385 #undef UNSUPPORTED | 1429 #undef UNSUPPORTED |
| 1386 | 1430 |
| 1387 } // namespace disasm | 1431 } // namespace disasm |
| 1388 | 1432 |
| 1389 #endif // V8_TARGET_ARCH_MIPS | 1433 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |