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 |