Chromium Code Reviews| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 // Printing of instruction name. | 92 // Printing of instruction name. |
| 93 void PrintInstructionName(Instruction* instr); | 93 void PrintInstructionName(Instruction* instr); |
| 94 | 94 |
| 95 // Handle formatting of instructions and their options. | 95 // Handle formatting of instructions and their options. |
| 96 int FormatRegister(Instruction* instr, const char* option); | 96 int FormatRegister(Instruction* instr, const char* option); |
| 97 int FormatFPURegister(Instruction* instr, const char* option); | 97 int FormatFPURegister(Instruction* instr, const char* option); |
| 98 int FormatOption(Instruction* instr, const char* option); | 98 int FormatOption(Instruction* instr, const char* option); |
| 99 void Format(Instruction* instr, const char* format); | 99 void Format(Instruction* instr, const char* format); |
| 100 void Unknown(Instruction* instr); | 100 void Unknown(Instruction* instr); |
| 101 | 101 |
| 102 | |
| 102 // Each of these functions decodes one particular instruction type. | 103 // Each of these functions decodes one particular instruction type. |
| 104 void DecodeTypeRegisterDRsType(Instruction* instr); | |
| 105 void DecodeTypeRegisterLRsType(Instruction* instr); | |
| 106 void DecodeTypeRegisterSPECIAL(Instruction* instr); | |
|
paul.l...
2015/03/31 04:02:01
nit: consider naming here, maybe: DecodeTypeRegist
| |
| 107 void DecodeTypeRegisterSPECIAL2(Instruction* instr); | |
| 108 void DecodeTypeRegisterSPECIAL3(Instruction* instr); | |
| 103 void DecodeTypeRegister(Instruction* instr); | 109 void DecodeTypeRegister(Instruction* instr); |
| 104 void DecodeTypeImmediate(Instruction* instr); | 110 void DecodeTypeImmediate(Instruction* instr); |
| 105 void DecodeTypeJump(Instruction* instr); | 111 void DecodeTypeJump(Instruction* instr); |
| 106 | 112 |
| 107 const disasm::NameConverter& converter_; | 113 const disasm::NameConverter& converter_; |
| 108 v8::internal::Vector<char> out_buffer_; | 114 v8::internal::Vector<char> out_buffer_; |
| 109 int out_buffer_pos_; | 115 int out_buffer_pos_; |
| 110 | 116 |
| 111 DISALLOW_COPY_AND_ASSIGN(Decoder); | 117 DISALLOW_COPY_AND_ASSIGN(Decoder); |
| 112 }; | 118 }; |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 442 } | 448 } |
| 443 | 449 |
| 444 | 450 |
| 445 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 451 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
| 446 // which will just print "unknown" of the instruction bits. | 452 // which will just print "unknown" of the instruction bits. |
| 447 void Decoder::Unknown(Instruction* instr) { | 453 void Decoder::Unknown(Instruction* instr) { |
| 448 Format(instr, "unknown"); | 454 Format(instr, "unknown"); |
| 449 } | 455 } |
| 450 | 456 |
| 451 | 457 |
| 458 void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) { | |
| 459 switch (instr->FunctionFieldRaw()) { | |
| 460 case ADD_D: | |
| 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 } | |
| 536 } | |
| 537 | |
| 538 | |
| 539 void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) { | |
| 540 switch (instr->FunctionFieldRaw()) { | |
| 541 case CVT_D_L: | |
| 542 Format(instr, "cvt.d.l 'fd, 'fs"); | |
| 543 break; | |
| 544 case CVT_S_L: | |
| 545 Format(instr, "cvt.s.l 'fd, 'fs"); | |
| 546 break; | |
| 547 case CMP_UN: | |
| 548 Format(instr, "cmp.un.d 'fd, 'fs, 'ft"); | |
| 549 break; | |
| 550 case CMP_EQ: | |
| 551 Format(instr, "cmp.eq.d 'fd, 'fs, 'ft"); | |
| 552 break; | |
| 553 case CMP_UEQ: | |
| 554 Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft"); | |
| 555 break; | |
| 556 case CMP_LT: | |
| 557 Format(instr, "cmp.lt.d 'fd, 'fs, 'ft"); | |
| 558 break; | |
| 559 case CMP_ULT: | |
| 560 Format(instr, "cmp.ult.d 'fd, 'fs, 'ft"); | |
| 561 break; | |
| 562 case CMP_LE: | |
| 563 Format(instr, "cmp.le.d 'fd, 'fs, 'ft"); | |
| 564 break; | |
| 565 case CMP_ULE: | |
| 566 Format(instr, "cmp.ule.d 'fd, 'fs, 'ft"); | |
| 567 break; | |
| 568 case CMP_OR: | |
| 569 Format(instr, "cmp.or.d 'fd, 'fs, 'ft"); | |
| 570 break; | |
| 571 case CMP_UNE: | |
| 572 Format(instr, "cmp.une.d 'fd, 'fs, 'ft"); | |
| 573 break; | |
| 574 case CMP_NE: | |
| 575 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); | |
| 576 break; | |
| 577 default: | |
| 578 UNREACHABLE(); | |
| 579 } | |
| 580 } | |
| 581 | |
| 582 | |
| 583 void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) { | |
| 584 switch (instr->FunctionFieldRaw()) { | |
| 585 case JR: | |
| 586 Format(instr, "jr 'rs"); | |
| 587 break; | |
| 588 case JALR: | |
| 589 Format(instr, "jalr 'rs"); | |
| 590 break; | |
| 591 case SLL: | |
| 592 if (0x0 == static_cast<int>(instr->InstructionBits())) | |
| 593 Format(instr, "nop"); | |
| 594 else | |
| 595 Format(instr, "sll 'rd, 'rt, 'sa"); | |
| 596 break; | |
| 597 case SRL: | |
| 598 if (instr->RsValue() == 0) { | |
| 599 Format(instr, "srl 'rd, 'rt, 'sa"); | |
| 600 } else { | |
| 601 if (IsMipsArchVariant(kMips32r2)) { | |
| 602 Format(instr, "rotr 'rd, 'rt, 'sa"); | |
| 603 } else { | |
| 604 Unknown(instr); | |
| 605 } | |
| 606 } | |
| 607 break; | |
| 608 case SRA: | |
| 609 Format(instr, "sra 'rd, 'rt, 'sa"); | |
| 610 break; | |
| 611 case SLLV: | |
| 612 Format(instr, "sllv 'rd, 'rt, 'rs"); | |
| 613 break; | |
| 614 case SRLV: | |
| 615 if (instr->SaValue() == 0) { | |
| 616 Format(instr, "srlv 'rd, 'rt, 'rs"); | |
| 617 } else { | |
| 618 if (IsMipsArchVariant(kMips32r2)) { | |
| 619 Format(instr, "rotrv 'rd, 'rt, 'rs"); | |
| 620 } else { | |
| 621 Unknown(instr); | |
| 622 } | |
| 623 } | |
| 624 break; | |
| 625 case SRAV: | |
| 626 Format(instr, "srav 'rd, 'rt, 'rs"); | |
| 627 break; | |
| 628 case MFHI: | |
| 629 if (instr->Bits(25, 16) == 0) { | |
| 630 Format(instr, "mfhi 'rd"); | |
| 631 } else { | |
| 632 if ((instr->FunctionFieldRaw() == CLZ_R6) && (instr->FdValue() == 1)) { | |
| 633 Format(instr, "clz 'rd, 'rs"); | |
| 634 } else if ((instr->FunctionFieldRaw() == CLO_R6) && | |
| 635 (instr->FdValue() == 1)) { | |
| 636 Format(instr, "clo 'rd, 'rs"); | |
| 637 } | |
| 638 } | |
| 639 break; | |
| 640 case MFLO: | |
| 641 Format(instr, "mflo 'rd"); | |
| 642 break; | |
| 643 case MULT: // @Mips32r6 == MUL_MUH. | |
| 644 if (!IsMipsArchVariant(kMips32r6)) { | |
| 645 Format(instr, "mult 'rs, 'rt"); | |
| 646 } else { | |
| 647 if (instr->SaValue() == MUL_OP) { | |
| 648 Format(instr, "mul 'rd, 'rs, 'rt"); | |
| 649 } else { | |
| 650 Format(instr, "muh 'rd, 'rs, 'rt"); | |
| 651 } | |
| 652 } | |
| 653 break; | |
| 654 case MULTU: // @Mips32r6 == MUL_MUH_U. | |
| 655 if (!IsMipsArchVariant(kMips32r6)) { | |
| 656 Format(instr, "multu 'rs, 'rt"); | |
| 657 } else { | |
| 658 if (instr->SaValue() == MUL_OP) { | |
| 659 Format(instr, "mulu 'rd, 'rs, 'rt"); | |
| 660 } else { | |
| 661 Format(instr, "muhu 'rd, 'rs, 'rt"); | |
| 662 } | |
| 663 } | |
| 664 break; | |
| 665 case DIV: // @Mips32r6 == DIV_MOD. | |
| 666 if (!IsMipsArchVariant(kMips32r6)) { | |
| 667 Format(instr, "div 'rs, 'rt"); | |
| 668 } else { | |
| 669 if (instr->SaValue() == DIV_OP) { | |
| 670 Format(instr, "div 'rd, 'rs, 'rt"); | |
| 671 } else { | |
| 672 Format(instr, "mod 'rd, 'rs, 'rt"); | |
| 673 } | |
| 674 } | |
| 675 break; | |
| 676 case DIVU: // @Mips32r6 == DIV_MOD_U. | |
| 677 if (!IsMipsArchVariant(kMips32r6)) { | |
| 678 Format(instr, "divu 'rs, 'rt"); | |
| 679 } else { | |
| 680 if (instr->SaValue() == DIV_OP) { | |
| 681 Format(instr, "divu 'rd, 'rs, 'rt"); | |
| 682 } else { | |
| 683 Format(instr, "modu 'rd, 'rs, 'rt"); | |
| 684 } | |
| 685 } | |
| 686 break; | |
| 687 case ADD: | |
| 688 Format(instr, "add 'rd, 'rs, 'rt"); | |
| 689 break; | |
| 690 case ADDU: | |
| 691 Format(instr, "addu 'rd, 'rs, 'rt"); | |
| 692 break; | |
| 693 case SUB: | |
| 694 Format(instr, "sub 'rd, 'rs, 'rt"); | |
| 695 break; | |
| 696 case SUBU: | |
| 697 Format(instr, "subu 'rd, 'rs, 'rt"); | |
| 698 break; | |
| 699 case AND: | |
| 700 Format(instr, "and 'rd, 'rs, 'rt"); | |
| 701 break; | |
| 702 case OR: | |
| 703 if (0 == instr->RsValue()) { | |
| 704 Format(instr, "mov 'rd, 'rt"); | |
| 705 } else if (0 == instr->RtValue()) { | |
| 706 Format(instr, "mov 'rd, 'rs"); | |
| 707 } else { | |
| 708 Format(instr, "or 'rd, 'rs, 'rt"); | |
| 709 } | |
| 710 break; | |
| 711 case XOR: | |
| 712 Format(instr, "xor 'rd, 'rs, 'rt"); | |
| 713 break; | |
| 714 case NOR: | |
| 715 Format(instr, "nor 'rd, 'rs, 'rt"); | |
| 716 break; | |
| 717 case SLT: | |
| 718 Format(instr, "slt 'rd, 'rs, 'rt"); | |
| 719 break; | |
| 720 case SLTU: | |
| 721 Format(instr, "sltu 'rd, 'rs, 'rt"); | |
| 722 break; | |
| 723 case BREAK: | |
| 724 Format(instr, "break, code: 'code"); | |
| 725 break; | |
| 726 case TGE: | |
| 727 Format(instr, "tge 'rs, 'rt, code: 'code"); | |
| 728 break; | |
| 729 case TGEU: | |
| 730 Format(instr, "tgeu 'rs, 'rt, code: 'code"); | |
| 731 break; | |
| 732 case TLT: | |
| 733 Format(instr, "tlt 'rs, 'rt, code: 'code"); | |
| 734 break; | |
| 735 case TLTU: | |
| 736 Format(instr, "tltu 'rs, 'rt, code: 'code"); | |
| 737 break; | |
| 738 case TEQ: | |
| 739 Format(instr, "teq 'rs, 'rt, code: 'code"); | |
| 740 break; | |
| 741 case TNE: | |
| 742 Format(instr, "tne 'rs, 'rt, code: 'code"); | |
| 743 break; | |
| 744 case MOVZ: | |
| 745 Format(instr, "movz 'rd, 'rs, 'rt"); | |
| 746 break; | |
| 747 case MOVN: | |
| 748 Format(instr, "movn 'rd, 'rs, 'rt"); | |
| 749 break; | |
| 750 case MOVCI: | |
| 751 if (instr->Bit(16)) { | |
| 752 Format(instr, "movt 'rd, 'rs, 'bc"); | |
| 753 } else { | |
| 754 Format(instr, "movf 'rd, 'rs, 'bc"); | |
| 755 } | |
| 756 break; | |
| 757 case SELEQZ_S: | |
| 758 Format(instr, "seleqz 'rs, 'rt, 'rd"); | |
| 759 break; | |
| 760 case SELNEZ_S: | |
| 761 Format(instr, "selnez 'rs, 'rt, 'rd"); | |
| 762 break; | |
| 763 default: | |
| 764 UNREACHABLE(); | |
| 765 } | |
| 766 } | |
| 767 | |
| 768 | |
| 769 void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) { | |
| 770 switch (instr->FunctionFieldRaw()) { | |
| 771 case MUL: | |
| 772 Format(instr, "mul 'rd, 'rs, 'rt"); | |
| 773 break; | |
| 774 case CLZ: | |
| 775 if (!IsMipsArchVariant(kMips32r6)) { | |
| 776 Format(instr, "clz 'rd, 'rs"); | |
| 777 } | |
| 778 break; | |
| 779 default: | |
| 780 UNREACHABLE(); | |
| 781 } | |
| 782 } | |
| 783 | |
| 784 | |
| 785 void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) { | |
| 786 switch (instr->FunctionFieldRaw()) { | |
| 787 case INS: { | |
| 788 if (IsMipsArchVariant(kMips32r2)) { | |
| 789 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); | |
| 790 } else { | |
| 791 Unknown(instr); | |
| 792 } | |
| 793 break; | |
| 794 } | |
| 795 case EXT: { | |
| 796 if (IsMipsArchVariant(kMips32r2)) { | |
| 797 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); | |
| 798 } else { | |
| 799 Unknown(instr); | |
| 800 } | |
| 801 break; | |
| 802 } | |
| 803 default: | |
| 804 UNREACHABLE(); | |
| 805 } | |
| 806 } | |
| 807 | |
| 808 | |
| 452 void Decoder::DecodeTypeRegister(Instruction* instr) { | 809 void Decoder::DecodeTypeRegister(Instruction* instr) { |
| 453 switch (instr->OpcodeFieldRaw()) { | 810 switch (instr->OpcodeFieldRaw()) { |
| 454 case COP1: // Coprocessor instructions. | 811 case COP1: // Coprocessor instructions. |
| 455 switch (instr->RsFieldRaw()) { | 812 switch (instr->RsFieldRaw()) { |
| 456 case BC1: // bc1 handled in DecodeTypeImmediate. | 813 case BC1: // bc1 handled in DecodeTypeImmediate. |
| 457 UNREACHABLE(); | 814 UNREACHABLE(); |
| 458 break; | 815 break; |
| 459 case MFC1: | 816 case MFC1: |
| 460 Format(instr, "mfc1 'rt, 'fs"); | 817 Format(instr, "mfc1 'rt, 'fs"); |
| 461 break; | 818 break; |
| 462 case MFHC1: | 819 case MFHC1: |
| 463 Format(instr, "mfhc1 'rt, 'fs"); | 820 Format(instr, "mfhc1 'rt, 'fs"); |
| 464 break; | 821 break; |
| 465 case MTC1: | 822 case MTC1: |
| 466 Format(instr, "mtc1 'rt, 'fs"); | 823 Format(instr, "mtc1 'rt, 'fs"); |
| 467 break; | 824 break; |
| 468 // These are called "fs" too, although they are not FPU registers. | 825 // These are called "fs" too, although they are not FPU registers. |
| 469 case CTC1: | 826 case CTC1: |
| 470 Format(instr, "ctc1 'rt, 'fs"); | 827 Format(instr, "ctc1 'rt, 'fs"); |
| 471 break; | 828 break; |
| 472 case CFC1: | 829 case CFC1: |
| 473 Format(instr, "cfc1 'rt, 'fs"); | 830 Format(instr, "cfc1 'rt, 'fs"); |
| 474 break; | 831 break; |
| 475 case MTHC1: | 832 case MTHC1: |
| 476 Format(instr, "mthc1 'rt, 'fs"); | 833 Format(instr, "mthc1 'rt, 'fs"); |
| 477 break; | 834 break; |
| 478 case D: | 835 case D: |
| 479 switch (instr->FunctionFieldRaw()) { | 836 DecodeTypeRegisterDRsType(instr); |
| 480 case ADD_D: | |
| 481 Format(instr, "add.d 'fd, 'fs, 'ft"); | |
| 482 break; | |
| 483 case SUB_D: | |
| 484 Format(instr, "sub.d 'fd, 'fs, 'ft"); | |
| 485 break; | |
| 486 case MUL_D: | |
| 487 Format(instr, "mul.d 'fd, 'fs, 'ft"); | |
| 488 break; | |
| 489 case DIV_D: | |
| 490 Format(instr, "div.d 'fd, 'fs, 'ft"); | |
| 491 break; | |
| 492 case ABS_D: | |
| 493 Format(instr, "abs.d 'fd, 'fs"); | |
| 494 break; | |
| 495 case MOV_D: | |
| 496 Format(instr, "mov.d 'fd, 'fs"); | |
| 497 break; | |
| 498 case NEG_D: | |
| 499 Format(instr, "neg.d 'fd, 'fs"); | |
| 500 break; | |
| 501 case SQRT_D: | |
| 502 Format(instr, "sqrt.d 'fd, 'fs"); | |
| 503 break; | |
| 504 case CVT_W_D: | |
| 505 Format(instr, "cvt.w.d 'fd, 'fs"); | |
| 506 break; | |
| 507 case CVT_L_D: | |
| 508 Format(instr, "cvt.l.d 'fd, 'fs"); | |
| 509 break; | |
| 510 case TRUNC_W_D: | |
| 511 Format(instr, "trunc.w.d 'fd, 'fs"); | |
| 512 break; | |
| 513 case TRUNC_L_D: | |
| 514 Format(instr, "trunc.l.d 'fd, 'fs"); | |
| 515 break; | |
| 516 case ROUND_W_D: | |
| 517 Format(instr, "round.w.d 'fd, 'fs"); | |
| 518 break; | |
| 519 case FLOOR_W_D: | |
| 520 Format(instr, "floor.w.d 'fd, 'fs"); | |
| 521 break; | |
| 522 case CEIL_W_D: | |
| 523 Format(instr, "ceil.w.d 'fd, 'fs"); | |
| 524 break; | |
| 525 case CVT_S_D: | |
| 526 Format(instr, "cvt.s.d 'fd, 'fs"); | |
| 527 break; | |
| 528 case C_F_D: | |
| 529 Format(instr, "c.f.d 'fs, 'ft, 'Cc"); | |
| 530 break; | |
| 531 case C_UN_D: | |
| 532 Format(instr, "c.un.d 'fs, 'ft, 'Cc"); | |
| 533 break; | |
| 534 case C_EQ_D: | |
| 535 Format(instr, "c.eq.d 'fs, 'ft, 'Cc"); | |
| 536 break; | |
| 537 case C_UEQ_D: | |
| 538 Format(instr, "c.ueq.d 'fs, 'ft, 'Cc"); | |
| 539 break; | |
| 540 case C_OLT_D: | |
| 541 Format(instr, "c.olt.d 'fs, 'ft, 'Cc"); | |
| 542 break; | |
| 543 case C_ULT_D: | |
| 544 Format(instr, "c.ult.d 'fs, 'ft, 'Cc"); | |
| 545 break; | |
| 546 case C_OLE_D: | |
| 547 Format(instr, "c.ole.d 'fs, 'ft, 'Cc"); | |
| 548 break; | |
| 549 case C_ULE_D: | |
| 550 Format(instr, "c.ule.d 'fs, 'ft, 'Cc"); | |
| 551 break; | |
| 552 default: | |
| 553 Format(instr, "unknown.cop1.d"); | |
| 554 break; | |
| 555 } | |
| 556 break; | 837 break; |
| 557 case S: | 838 case S: |
| 558 switch (instr->FunctionFieldRaw()) { | 839 switch (instr->FunctionFieldRaw()) { |
| 559 case CVT_D_S: | 840 case CVT_D_S: |
| 560 Format(instr, "cvt.d.s 'fd, 'fs"); | 841 Format(instr, "cvt.d.s 'fd, 'fs"); |
| 561 break; | 842 break; |
| 562 default: | 843 default: |
| 563 UNIMPLEMENTED_MIPS(); | 844 UNIMPLEMENTED_MIPS(); |
| 564 } | 845 } |
| 565 break; | 846 break; |
| 566 case W: | 847 case W: |
| 567 switch (instr->FunctionFieldRaw()) { | 848 switch (instr->FunctionFieldRaw()) { |
| 568 case CVT_S_W: // Convert word to float (single). | 849 case CVT_S_W: // Convert word to float (single). |
| 569 Format(instr, "cvt.s.w 'fd, 'fs"); | 850 Format(instr, "cvt.s.w 'fd, 'fs"); |
| 570 break; | 851 break; |
| 571 case CVT_D_W: // Convert word to double. | 852 case CVT_D_W: // Convert word to double. |
| 572 Format(instr, "cvt.d.w 'fd, 'fs"); | 853 Format(instr, "cvt.d.w 'fd, 'fs"); |
| 573 break; | 854 break; |
| 574 default: | 855 default: |
| 575 UNREACHABLE(); | 856 UNREACHABLE(); |
| 576 } | 857 } |
| 577 break; | 858 break; |
| 578 case L: | 859 case L: |
| 579 switch (instr->FunctionFieldRaw()) { | 860 DecodeTypeRegisterLRsType(instr); |
| 580 case CVT_D_L: | |
| 581 Format(instr, "cvt.d.l 'fd, 'fs"); | |
| 582 break; | |
| 583 case CVT_S_L: | |
| 584 Format(instr, "cvt.s.l 'fd, 'fs"); | |
| 585 break; | |
| 586 case CMP_UN: | |
| 587 Format(instr, "cmp.un.d 'fd, 'fs, 'ft"); | |
| 588 break; | |
| 589 case CMP_EQ: | |
| 590 Format(instr, "cmp.eq.d 'fd, 'fs, 'ft"); | |
| 591 break; | |
| 592 case CMP_UEQ: | |
| 593 Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft"); | |
| 594 break; | |
| 595 case CMP_LT: | |
| 596 Format(instr, "cmp.lt.d 'fd, 'fs, 'ft"); | |
| 597 break; | |
| 598 case CMP_ULT: | |
| 599 Format(instr, "cmp.ult.d 'fd, 'fs, 'ft"); | |
| 600 break; | |
| 601 case CMP_LE: | |
| 602 Format(instr, "cmp.le.d 'fd, 'fs, 'ft"); | |
| 603 break; | |
| 604 case CMP_ULE: | |
| 605 Format(instr, "cmp.ule.d 'fd, 'fs, 'ft"); | |
| 606 break; | |
| 607 case CMP_OR: | |
| 608 Format(instr, "cmp.or.d 'fd, 'fs, 'ft"); | |
| 609 break; | |
| 610 case CMP_UNE: | |
| 611 Format(instr, "cmp.une.d 'fd, 'fs, 'ft"); | |
| 612 break; | |
| 613 case CMP_NE: | |
| 614 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); | |
| 615 break; | |
| 616 default: | |
| 617 UNREACHABLE(); | |
| 618 } | |
| 619 break; | 861 break; |
| 620 case PS: | 862 case PS: |
| 621 UNIMPLEMENTED_MIPS(); | 863 UNIMPLEMENTED_MIPS(); |
| 622 break; | 864 break; |
| 623 default: | 865 default: |
| 624 UNREACHABLE(); | 866 UNREACHABLE(); |
| 625 } | 867 } |
| 626 break; | 868 break; |
| 627 case COP1X: | 869 case COP1X: |
| 628 switch (instr->FunctionFieldRaw()) { | 870 switch (instr->FunctionFieldRaw()) { |
| 629 case MADD_D: | 871 case MADD_D: |
| 630 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); | 872 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); |
| 631 break; | 873 break; |
| 632 default: | 874 default: |
| 633 UNREACHABLE(); | 875 UNREACHABLE(); |
| 634 } | 876 } |
| 635 break; | 877 break; |
| 636 case SPECIAL: | 878 case SPECIAL: |
| 637 switch (instr->FunctionFieldRaw()) { | 879 DecodeTypeRegisterSPECIAL(instr); |
| 638 case JR: | |
| 639 Format(instr, "jr 'rs"); | |
| 640 break; | |
| 641 case JALR: | |
| 642 Format(instr, "jalr 'rs"); | |
| 643 break; | |
| 644 case SLL: | |
| 645 if ( 0x0 == static_cast<int>(instr->InstructionBits())) | |
| 646 Format(instr, "nop"); | |
| 647 else | |
| 648 Format(instr, "sll 'rd, 'rt, 'sa"); | |
| 649 break; | |
| 650 case SRL: | |
| 651 if (instr->RsValue() == 0) { | |
| 652 Format(instr, "srl 'rd, 'rt, 'sa"); | |
| 653 } else { | |
| 654 if (IsMipsArchVariant(kMips32r2)) { | |
| 655 Format(instr, "rotr 'rd, 'rt, 'sa"); | |
| 656 } else { | |
| 657 Unknown(instr); | |
| 658 } | |
| 659 } | |
| 660 break; | |
| 661 case SRA: | |
| 662 Format(instr, "sra 'rd, 'rt, 'sa"); | |
| 663 break; | |
| 664 case SLLV: | |
| 665 Format(instr, "sllv 'rd, 'rt, 'rs"); | |
| 666 break; | |
| 667 case SRLV: | |
| 668 if (instr->SaValue() == 0) { | |
| 669 Format(instr, "srlv 'rd, 'rt, 'rs"); | |
| 670 } else { | |
| 671 if (IsMipsArchVariant(kMips32r2)) { | |
| 672 Format(instr, "rotrv 'rd, 'rt, 'rs"); | |
| 673 } else { | |
| 674 Unknown(instr); | |
| 675 } | |
| 676 } | |
| 677 break; | |
| 678 case SRAV: | |
| 679 Format(instr, "srav 'rd, 'rt, 'rs"); | |
| 680 break; | |
| 681 case MFHI: | |
| 682 if (instr->Bits(25, 16) == 0) { | |
| 683 Format(instr, "mfhi 'rd"); | |
| 684 } else { | |
| 685 if ((instr->FunctionFieldRaw() == CLZ_R6) | |
| 686 && (instr->FdValue() == 1)) { | |
| 687 Format(instr, "clz 'rd, 'rs"); | |
| 688 } else if ((instr->FunctionFieldRaw() == CLO_R6) | |
| 689 && (instr->FdValue() == 1)) { | |
| 690 Format(instr, "clo 'rd, 'rs"); | |
| 691 } | |
| 692 } | |
| 693 break; | |
| 694 case MFLO: | |
| 695 Format(instr, "mflo 'rd"); | |
| 696 break; | |
| 697 case MULT: // @Mips32r6 == MUL_MUH. | |
| 698 if (!IsMipsArchVariant(kMips32r6)) { | |
| 699 Format(instr, "mult 'rs, 'rt"); | |
| 700 } else { | |
| 701 if (instr->SaValue() == MUL_OP) { | |
| 702 Format(instr, "mul 'rd, 'rs, 'rt"); | |
| 703 } else { | |
| 704 Format(instr, "muh 'rd, 'rs, 'rt"); | |
| 705 } | |
| 706 } | |
| 707 break; | |
| 708 case MULTU: // @Mips32r6 == MUL_MUH_U. | |
| 709 if (!IsMipsArchVariant(kMips32r6)) { | |
| 710 Format(instr, "multu 'rs, 'rt"); | |
| 711 } else { | |
| 712 if (instr->SaValue() == MUL_OP) { | |
| 713 Format(instr, "mulu 'rd, 'rs, 'rt"); | |
| 714 } else { | |
| 715 Format(instr, "muhu 'rd, 'rs, 'rt"); | |
| 716 } | |
| 717 } | |
| 718 break; | |
| 719 case DIV: // @Mips32r6 == DIV_MOD. | |
| 720 if (!IsMipsArchVariant(kMips32r6)) { | |
| 721 Format(instr, "div 'rs, 'rt"); | |
| 722 } else { | |
| 723 if (instr->SaValue() == DIV_OP) { | |
| 724 Format(instr, "div 'rd, 'rs, 'rt"); | |
| 725 } else { | |
| 726 Format(instr, "mod 'rd, 'rs, 'rt"); | |
| 727 } | |
| 728 } | |
| 729 break; | |
| 730 case DIVU: // @Mips32r6 == DIV_MOD_U. | |
| 731 if (!IsMipsArchVariant(kMips32r6)) { | |
| 732 Format(instr, "divu 'rs, 'rt"); | |
| 733 } else { | |
| 734 if (instr->SaValue() == DIV_OP) { | |
| 735 Format(instr, "divu 'rd, 'rs, 'rt"); | |
| 736 } else { | |
| 737 Format(instr, "modu 'rd, 'rs, 'rt"); | |
| 738 } | |
| 739 } | |
| 740 break; | |
| 741 case ADD: | |
| 742 Format(instr, "add 'rd, 'rs, 'rt"); | |
| 743 break; | |
| 744 case ADDU: | |
| 745 Format(instr, "addu 'rd, 'rs, 'rt"); | |
| 746 break; | |
| 747 case SUB: | |
| 748 Format(instr, "sub 'rd, 'rs, 'rt"); | |
| 749 break; | |
| 750 case SUBU: | |
| 751 Format(instr, "subu 'rd, 'rs, 'rt"); | |
| 752 break; | |
| 753 case AND: | |
| 754 Format(instr, "and 'rd, 'rs, 'rt"); | |
| 755 break; | |
| 756 case OR: | |
| 757 if (0 == instr->RsValue()) { | |
| 758 Format(instr, "mov 'rd, 'rt"); | |
| 759 } else if (0 == instr->RtValue()) { | |
| 760 Format(instr, "mov 'rd, 'rs"); | |
| 761 } else { | |
| 762 Format(instr, "or 'rd, 'rs, 'rt"); | |
| 763 } | |
| 764 break; | |
| 765 case XOR: | |
| 766 Format(instr, "xor 'rd, 'rs, 'rt"); | |
| 767 break; | |
| 768 case NOR: | |
| 769 Format(instr, "nor 'rd, 'rs, 'rt"); | |
| 770 break; | |
| 771 case SLT: | |
| 772 Format(instr, "slt 'rd, 'rs, 'rt"); | |
| 773 break; | |
| 774 case SLTU: | |
| 775 Format(instr, "sltu 'rd, 'rs, 'rt"); | |
| 776 break; | |
| 777 case BREAK: | |
| 778 Format(instr, "break, code: 'code"); | |
| 779 break; | |
| 780 case TGE: | |
| 781 Format(instr, "tge 'rs, 'rt, code: 'code"); | |
| 782 break; | |
| 783 case TGEU: | |
| 784 Format(instr, "tgeu 'rs, 'rt, code: 'code"); | |
| 785 break; | |
| 786 case TLT: | |
| 787 Format(instr, "tlt 'rs, 'rt, code: 'code"); | |
| 788 break; | |
| 789 case TLTU: | |
| 790 Format(instr, "tltu 'rs, 'rt, code: 'code"); | |
| 791 break; | |
| 792 case TEQ: | |
| 793 Format(instr, "teq 'rs, 'rt, code: 'code"); | |
| 794 break; | |
| 795 case TNE: | |
| 796 Format(instr, "tne 'rs, 'rt, code: 'code"); | |
| 797 break; | |
| 798 case MOVZ: | |
| 799 Format(instr, "movz 'rd, 'rs, 'rt"); | |
| 800 break; | |
| 801 case MOVN: | |
| 802 Format(instr, "movn 'rd, 'rs, 'rt"); | |
| 803 break; | |
| 804 case MOVCI: | |
| 805 if (instr->Bit(16)) { | |
| 806 Format(instr, "movt 'rd, 'rs, 'bc"); | |
| 807 } else { | |
| 808 Format(instr, "movf 'rd, 'rs, 'bc"); | |
| 809 } | |
| 810 break; | |
| 811 case SELEQZ_S: | |
| 812 Format(instr, "seleqz 'rd, 'rs, 'rt"); | |
| 813 break; | |
| 814 case SELNEZ_S: | |
| 815 Format(instr, "selnez 'rd, 'rs, 'rt"); | |
| 816 break; | |
| 817 default: | |
| 818 UNREACHABLE(); | |
| 819 } | |
| 820 break; | 880 break; |
| 821 case SPECIAL2: | 881 case SPECIAL2: |
| 822 switch (instr->FunctionFieldRaw()) { | 882 DecodeTypeRegisterSPECIAL2(instr); |
| 823 case MUL: | |
| 824 Format(instr, "mul 'rd, 'rs, 'rt"); | |
| 825 break; | |
| 826 case CLZ: | |
| 827 if (!IsMipsArchVariant(kMips32r6)) { | |
| 828 Format(instr, "clz 'rd, 'rs"); | |
| 829 } | |
| 830 break; | |
| 831 default: | |
| 832 UNREACHABLE(); | |
| 833 } | |
| 834 break; | 883 break; |
| 835 case SPECIAL3: | 884 case SPECIAL3: |
| 836 switch (instr->FunctionFieldRaw()) { | 885 DecodeTypeRegisterSPECIAL3(instr); |
| 837 case INS: { | |
| 838 if (IsMipsArchVariant(kMips32r2)) { | |
| 839 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); | |
| 840 } else { | |
| 841 Unknown(instr); | |
| 842 } | |
| 843 break; | |
| 844 } | |
| 845 case EXT: { | |
| 846 if (IsMipsArchVariant(kMips32r2)) { | |
| 847 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); | |
| 848 } else { | |
| 849 Unknown(instr); | |
| 850 } | |
| 851 break; | |
| 852 } | |
| 853 default: | |
| 854 UNREACHABLE(); | |
| 855 } | |
| 856 break; | 886 break; |
| 857 default: | 887 default: |
| 858 UNREACHABLE(); | 888 UNREACHABLE(); |
| 859 } | 889 } |
| 860 } | 890 } |
| 861 | 891 |
| 862 | 892 |
| 863 void Decoder::DecodeTypeImmediate(Instruction* instr) { | 893 void Decoder::DecodeTypeImmediate(Instruction* instr) { |
| 864 switch (instr->OpcodeFieldRaw()) { | 894 switch (instr->OpcodeFieldRaw()) { |
| 865 case COP1: | 895 case COP1: |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1350 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1380 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1351 } | 1381 } |
| 1352 } | 1382 } |
| 1353 | 1383 |
| 1354 | 1384 |
| 1355 #undef UNSUPPORTED | 1385 #undef UNSUPPORTED |
| 1356 | 1386 |
| 1357 } // namespace disasm | 1387 } // namespace disasm |
| 1358 | 1388 |
| 1359 #endif // V8_TARGET_ARCH_MIPS | 1389 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |