| 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 int DecodeBreakInstr(Instruction* instr); | 101 int DecodeBreakInstr(Instruction* instr); |
| 102 | 102 |
| 103 // 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); |
| 107 void DecodeTypeRegisterSPECIAL2(Instruction* instr); |
| 108 void DecodeTypeRegisterSPECIAL3(Instruction* instr); |
| 109 void DecodeTypeRegisterCOP1(Instruction* instr); |
| 110 void DecodeTypeRegisterCOP1X(Instruction* instr); |
| 104 int DecodeTypeRegister(Instruction* instr); | 111 int DecodeTypeRegister(Instruction* instr); |
| 112 |
| 113 void DecodeTypeImmediateCOP1W(Instruction* instr); |
| 114 void DecodeTypeImmediateCOP1L(Instruction* instr); |
| 115 void DecodeTypeImmediateCOP1S(Instruction* instr); |
| 116 void DecodeTypeImmediateCOP1D(Instruction* instr); |
| 117 void DecodeTypeImmediateCOP1(Instruction* instr); |
| 118 void DecodeTypeImmediateREGIMM(Instruction* instr); |
| 105 void DecodeTypeImmediate(Instruction* instr); | 119 void DecodeTypeImmediate(Instruction* instr); |
| 120 |
| 106 void DecodeTypeJump(Instruction* instr); | 121 void DecodeTypeJump(Instruction* instr); |
| 107 | 122 |
| 108 const disasm::NameConverter& converter_; | 123 const disasm::NameConverter& converter_; |
| 109 v8::internal::Vector<char> out_buffer_; | 124 v8::internal::Vector<char> out_buffer_; |
| 110 int out_buffer_pos_; | 125 int out_buffer_pos_; |
| 111 | 126 |
| 112 DISALLOW_COPY_AND_ASSIGN(Decoder); | 127 DISALLOW_COPY_AND_ASSIGN(Decoder); |
| 113 }; | 128 }; |
| 114 | 129 |
| 115 | 130 |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 + Instruction::kInstrSize)); | 482 + Instruction::kInstrSize)); |
| 468 // Size 3: the break_ instr, plus embedded 64-bit char pointer. | 483 // Size 3: the break_ instr, plus embedded 64-bit char pointer. |
| 469 return 3 * Instruction::kInstrSize; | 484 return 3 * Instruction::kInstrSize; |
| 470 } else { | 485 } else { |
| 471 Format(instr, "break, code: 'code"); | 486 Format(instr, "break, code: 'code"); |
| 472 return Instruction::kInstrSize; | 487 return Instruction::kInstrSize; |
| 473 } | 488 } |
| 474 } | 489 } |
| 475 | 490 |
| 476 | 491 |
| 477 int Decoder::DecodeTypeRegister(Instruction* instr) { | 492 void Decoder::DecodeTypeRegisterDRsType(Instruction* instr) { |
| 478 switch (instr->OpcodeFieldRaw()) { | 493 switch (instr->FunctionFieldRaw()) { |
| 479 case COP1: // Coprocessor instructions. | 494 case SELEQZ_C: |
| 480 switch (instr->RsFieldRaw()) { | 495 Format(instr, "seleqz.D 'ft, 'fs, 'fd"); |
| 481 case MFC1: | 496 break; |
| 482 Format(instr, "mfc1 'rt, 'fs"); | 497 case SELNEZ_C: |
| 483 break; | 498 Format(instr, "selnez.D 'ft, 'fs, 'fd"); |
| 484 case DMFC1: | 499 break; |
| 485 Format(instr, "dmfc1 'rt, 'fs"); | 500 case ADD_D: |
| 486 break; | 501 Format(instr, "add.d 'fd, 'fs, 'ft"); |
| 487 case MFHC1: | 502 break; |
| 488 Format(instr, "mfhc1 'rt, 'fs"); | 503 case SUB_D: |
| 489 break; | 504 Format(instr, "sub.d 'fd, 'fs, 'ft"); |
| 490 case MTC1: | 505 break; |
| 491 Format(instr, "mtc1 'rt, 'fs"); | 506 case MUL_D: |
| 492 break; | 507 Format(instr, "mul.d 'fd, 'fs, 'ft"); |
| 493 case DMTC1: | 508 break; |
| 494 Format(instr, "dmtc1 'rt, 'fs"); | 509 case DIV_D: |
| 495 break; | 510 Format(instr, "div.d 'fd, 'fs, 'ft"); |
| 496 // These are called "fs" too, although they are not FPU registers. | 511 break; |
| 497 case CTC1: | 512 case ABS_D: |
| 498 Format(instr, "ctc1 'rt, 'fs"); | 513 Format(instr, "abs.d 'fd, 'fs"); |
| 499 break; | 514 break; |
| 500 case CFC1: | 515 case MOV_D: |
| 501 Format(instr, "cfc1 'rt, 'fs"); | 516 Format(instr, "mov.d 'fd, 'fs"); |
| 502 break; | 517 break; |
| 503 case MTHC1: | 518 case NEG_D: |
| 504 Format(instr, "mthc1 'rt, 'fs"); | 519 Format(instr, "neg.d 'fd, 'fs"); |
| 505 break; | 520 break; |
| 506 case D: | 521 case SQRT_D: |
| 507 switch (instr->FunctionFieldRaw()) { | 522 Format(instr, "sqrt.d 'fd, 'fs"); |
| 508 case ADD_D: | 523 break; |
| 509 Format(instr, "add.d 'fd, 'fs, 'ft"); | 524 case CVT_W_D: |
| 510 break; | 525 Format(instr, "cvt.w.d 'fd, 'fs"); |
| 511 case SUB_D: | 526 break; |
| 512 Format(instr, "sub.d 'fd, 'fs, 'ft"); | 527 case CVT_L_D: |
| 513 break; | 528 Format(instr, "cvt.l.d 'fd, 'fs"); |
| 514 case MUL_D: | 529 break; |
| 515 Format(instr, "mul.d 'fd, 'fs, 'ft"); | 530 case TRUNC_W_D: |
| 516 break; | 531 Format(instr, "trunc.w.d 'fd, 'fs"); |
| 517 case DIV_D: | 532 break; |
| 518 Format(instr, "div.d 'fd, 'fs, 'ft"); | 533 case TRUNC_L_D: |
| 519 break; | 534 Format(instr, "trunc.l.d 'fd, 'fs"); |
| 520 case ABS_D: | 535 break; |
| 521 Format(instr, "abs.d 'fd, 'fs"); | 536 case ROUND_W_D: |
| 522 break; | 537 Format(instr, "round.w.d 'fd, 'fs"); |
| 523 case MOV_D: | 538 break; |
| 524 Format(instr, "mov.d 'fd, 'fs"); | 539 case ROUND_L_D: |
| 525 break; | 540 Format(instr, "round.l.d 'fd, 'fs"); |
| 526 case NEG_D: | 541 break; |
| 527 Format(instr, "neg.d 'fd, 'fs"); | 542 case FLOOR_W_D: |
| 528 break; | 543 Format(instr, "floor.w.d 'fd, 'fs"); |
| 529 case SQRT_D: | 544 break; |
| 530 Format(instr, "sqrt.d 'fd, 'fs"); | 545 case FLOOR_L_D: |
| 531 break; | 546 Format(instr, "floor.l.d 'fd, 'fs"); |
| 532 case CVT_W_D: | 547 break; |
| 533 Format(instr, "cvt.w.d 'fd, 'fs"); | 548 case CEIL_W_D: |
| 534 break; | 549 Format(instr, "ceil.w.d 'fd, 'fs"); |
| 535 case CVT_L_D: | 550 break; |
| 536 Format(instr, "cvt.l.d 'fd, 'fs"); | 551 case CEIL_L_D: |
| 537 break; | 552 Format(instr, "ceil.l.d 'fd, 'fs"); |
| 538 case TRUNC_W_D: | 553 break; |
| 539 Format(instr, "trunc.w.d 'fd, 'fs"); | 554 case CVT_S_D: |
| 540 break; | 555 Format(instr, "cvt.s.d 'fd, 'fs"); |
| 541 case TRUNC_L_D: | 556 break; |
| 542 Format(instr, "trunc.l.d 'fd, 'fs"); | 557 case C_F_D: |
| 543 break; | 558 Format(instr, "c.f.d 'fs, 'ft, 'Cc"); |
| 544 case ROUND_W_D: | 559 break; |
| 545 Format(instr, "round.w.d 'fd, 'fs"); | 560 case C_UN_D: |
| 546 break; | 561 Format(instr, "c.un.d 'fs, 'ft, 'Cc"); |
| 547 case ROUND_L_D: | 562 break; |
| 548 Format(instr, "round.l.d 'fd, 'fs"); | 563 case C_EQ_D: |
| 549 break; | 564 Format(instr, "c.eq.d 'fs, 'ft, 'Cc"); |
| 550 case FLOOR_W_D: | 565 break; |
| 551 Format(instr, "floor.w.d 'fd, 'fs"); | 566 case C_UEQ_D: |
| 552 break; | 567 Format(instr, "c.ueq.d 'fs, 'ft, 'Cc"); |
| 553 case FLOOR_L_D: | 568 break; |
| 554 Format(instr, "floor.l.d 'fd, 'fs"); | 569 case C_OLT_D: |
| 555 break; | 570 Format(instr, "c.olt.d 'fs, 'ft, 'Cc"); |
| 556 case CEIL_W_D: | 571 break; |
| 557 Format(instr, "ceil.w.d 'fd, 'fs"); | 572 case C_ULT_D: |
| 558 break; | 573 Format(instr, "c.ult.d 'fs, 'ft, 'Cc"); |
| 559 case CEIL_L_D: | 574 break; |
| 560 Format(instr, "ceil.l.d 'fd, 'fs"); | 575 case C_OLE_D: |
| 561 break; | 576 Format(instr, "c.ole.d 'fs, 'ft, 'Cc"); |
| 562 case CVT_S_D: | 577 break; |
| 563 Format(instr, "cvt.s.d 'fd, 'fs"); | 578 case C_ULE_D: |
| 564 break; | 579 Format(instr, "c.ule.d 'fs, 'ft, 'Cc"); |
| 565 case C_F_D: | 580 break; |
| 566 Format(instr, "c.f.d 'fs, 'ft, 'Cc"); | 581 default: |
| 567 break; | 582 Format(instr, "unknown.cop1.d"); |
| 568 case C_UN_D: | 583 break; |
| 569 Format(instr, "c.un.d 'fs, 'ft, 'Cc"); | 584 } |
| 570 break; | 585 } |
| 571 case C_EQ_D: | 586 |
| 572 Format(instr, "c.eq.d 'fs, 'ft, 'Cc"); | 587 |
| 573 break; | 588 void Decoder::DecodeTypeRegisterLRsType(Instruction* instr) { |
| 574 case C_UEQ_D: | 589 switch (instr->FunctionFieldRaw()) { |
| 575 Format(instr, "c.ueq.d 'fs, 'ft, 'Cc"); | 590 case CVT_D_L: |
| 576 break; | 591 Format(instr, "cvt.d.l 'fd, 'fs"); |
| 577 case C_OLT_D: | 592 break; |
| 578 Format(instr, "c.olt.d 'fs, 'ft, 'Cc"); | 593 case CVT_S_L: |
| 579 break; | 594 Format(instr, "cvt.s.l 'fd, 'fs"); |
| 580 case C_ULT_D: | 595 break; |
| 581 Format(instr, "c.ult.d 'fs, 'ft, 'Cc"); | 596 case CMP_UN: |
| 582 break; | 597 Format(instr, "cmp.un.d 'fd, 'fs, 'ft"); |
| 583 case C_OLE_D: | 598 break; |
| 584 Format(instr, "c.ole.d 'fs, 'ft, 'Cc"); | 599 case CMP_EQ: |
| 585 break; | 600 Format(instr, "cmp.eq.d 'fd, 'fs, 'ft"); |
| 586 case C_ULE_D: | 601 break; |
| 587 Format(instr, "c.ule.d 'fs, 'ft, 'Cc"); | 602 case CMP_UEQ: |
| 588 break; | 603 Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft"); |
| 589 default: | 604 break; |
| 590 Format(instr, "unknown.cop1.d"); | 605 case CMP_LT: |
| 591 break; | 606 Format(instr, "cmp.lt.d 'fd, 'fs, 'ft"); |
| 592 } | 607 break; |
| 593 break; | 608 case CMP_ULT: |
| 594 case W: | 609 Format(instr, "cmp.ult.d 'fd, 'fs, 'ft"); |
| 595 switch (instr->FunctionFieldRaw()) { | 610 break; |
| 596 case CVT_D_W: // Convert word to double. | 611 case CMP_LE: |
| 597 Format(instr, "cvt.d.w 'fd, 'fs"); | 612 Format(instr, "cmp.le.d 'fd, 'fs, 'ft"); |
| 598 break; | 613 break; |
| 599 default: | 614 case CMP_ULE: |
| 600 UNREACHABLE(); | 615 Format(instr, "cmp.ule.d 'fd, 'fs, 'ft"); |
| 601 } | 616 break; |
| 602 break; | 617 case CMP_OR: |
| 603 case L: | 618 Format(instr, "cmp.or.d 'fd, 'fs, 'ft"); |
| 604 switch (instr->FunctionFieldRaw()) { | 619 break; |
| 605 case CVT_D_L: | 620 case CMP_UNE: |
| 606 Format(instr, "cvt.d.l 'fd, 'fs"); | 621 Format(instr, "cmp.une.d 'fd, 'fs, 'ft"); |
| 607 break; | 622 break; |
| 608 case CVT_S_L: | 623 case CMP_NE: |
| 609 Format(instr, "cvt.s.l 'fd, 'fs"); | 624 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); |
| 610 break; | 625 break; |
| 611 case CMP_UN: | 626 default: |
| 612 Format(instr, "cmp.un.d 'fd, 'fs, 'ft"); | 627 UNREACHABLE(); |
| 613 break; | 628 } |
| 614 case CMP_EQ: | 629 } |
| 615 Format(instr, "cmp.eq.d 'fd, 'fs, 'ft"); | 630 |
| 616 break; | 631 |
| 617 case CMP_UEQ: | 632 void Decoder::DecodeTypeRegisterCOP1(Instruction* instr) { |
| 618 Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft"); | 633 switch (instr->RsFieldRaw()) { |
| 619 break; | 634 case MFC1: |
| 620 case CMP_LT: | 635 Format(instr, "mfc1 'rt, 'fs"); |
| 621 Format(instr, "cmp.lt.d 'fd, 'fs, 'ft"); | 636 break; |
| 622 break; | 637 case DMFC1: |
| 623 case CMP_ULT: | 638 Format(instr, "dmfc1 'rt, 'fs"); |
| 624 Format(instr, "cmp.ult.d 'fd, 'fs, 'ft"); | 639 break; |
| 625 break; | 640 case MFHC1: |
| 626 case CMP_LE: | 641 Format(instr, "mfhc1 'rt, 'fs"); |
| 627 Format(instr, "cmp.le.d 'fd, 'fs, 'ft"); | 642 break; |
| 628 break; | 643 case MTC1: |
| 629 case CMP_ULE: | 644 Format(instr, "mtc1 'rt, 'fs"); |
| 630 Format(instr, "cmp.ule.d 'fd, 'fs, 'ft"); | 645 break; |
| 631 break; | 646 case DMTC1: |
| 632 case CMP_OR: | 647 Format(instr, "dmtc1 'rt, 'fs"); |
| 633 Format(instr, "cmp.or.d 'fd, 'fs, 'ft"); | 648 break; |
| 634 break; | 649 // These are called "fs" too, although they are not FPU registers. |
| 635 case CMP_UNE: | 650 case CTC1: |
| 636 Format(instr, "cmp.une.d 'fd, 'fs, 'ft"); | 651 Format(instr, "ctc1 'rt, 'fs"); |
| 637 break; | 652 break; |
| 638 case CMP_NE: | 653 case CFC1: |
| 639 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); | 654 Format(instr, "cfc1 'rt, 'fs"); |
| 640 break; | 655 break; |
| 641 default: | 656 case MTHC1: |
| 642 UNREACHABLE(); | 657 Format(instr, "mthc1 'rt, 'fs"); |
| 643 } | 658 break; |
| 659 case D: |
| 660 DecodeTypeRegisterDRsType(instr); |
| 661 break; |
| 662 case W: |
| 663 switch (instr->FunctionFieldRaw()) { |
| 664 case CVT_D_W: // Convert word to double. |
| 665 Format(instr, "cvt.d.w 'fd, 'fs"); |
| 644 break; | 666 break; |
| 645 default: | 667 default: |
| 646 UNREACHABLE(); | 668 UNREACHABLE(); |
| 647 } | 669 } |
| 648 break; | 670 break; |
| 671 case L: |
| 672 DecodeTypeRegisterLRsType(instr); |
| 673 break; |
| 674 default: |
| 675 UNREACHABLE(); |
| 676 } |
| 677 } |
| 678 |
| 679 |
| 680 void Decoder::DecodeTypeRegisterCOP1X(Instruction* instr) { |
| 681 switch (instr->FunctionFieldRaw()) { |
| 682 case MADD_D: |
| 683 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); |
| 684 break; |
| 685 default: |
| 686 UNREACHABLE(); |
| 687 } |
| 688 } |
| 689 |
| 690 |
| 691 void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) { |
| 692 switch (instr->FunctionFieldRaw()) { |
| 693 case JR: |
| 694 Format(instr, "jr 'rs"); |
| 695 break; |
| 696 case JALR: |
| 697 Format(instr, "jalr 'rs"); |
| 698 break; |
| 699 case SLL: |
| 700 if (0x0 == static_cast<int>(instr->InstructionBits())) |
| 701 Format(instr, "nop"); |
| 702 else |
| 703 Format(instr, "sll 'rd, 'rt, 'sa"); |
| 704 break; |
| 705 case DSLL: |
| 706 Format(instr, "dsll 'rd, 'rt, 'sa"); |
| 707 break; |
| 708 case D_MUL_MUH: // Equals to DMUL. |
| 709 if (kArchVariant != kMips64r6) { |
| 710 Format(instr, "dmult 'rs, 'rt"); |
| 711 } else { |
| 712 if (instr->SaValue() == MUL_OP) { |
| 713 Format(instr, "dmul 'rd, 'rs, 'rt"); |
| 714 } else { |
| 715 Format(instr, "dmuh 'rd, 'rs, 'rt"); |
| 716 } |
| 717 } |
| 718 break; |
| 719 case DSLL32: |
| 720 Format(instr, "dsll32 'rd, 'rt, 'sa"); |
| 721 break; |
| 722 case SRL: |
| 723 if (instr->RsValue() == 0) { |
| 724 Format(instr, "srl 'rd, 'rt, 'sa"); |
| 725 } else { |
| 726 if (kArchVariant == kMips64r2) { |
| 727 Format(instr, "rotr 'rd, 'rt, 'sa"); |
| 728 } else { |
| 729 Unknown(instr); |
| 730 } |
| 731 } |
| 732 break; |
| 733 case DSRL: |
| 734 if (instr->RsValue() == 0) { |
| 735 Format(instr, "dsrl 'rd, 'rt, 'sa"); |
| 736 } else { |
| 737 if (kArchVariant == kMips64r2) { |
| 738 Format(instr, "drotr 'rd, 'rt, 'sa"); |
| 739 } else { |
| 740 Unknown(instr); |
| 741 } |
| 742 } |
| 743 break; |
| 744 case DSRL32: |
| 745 Format(instr, "dsrl32 'rd, 'rt, 'sa"); |
| 746 break; |
| 747 case SRA: |
| 748 Format(instr, "sra 'rd, 'rt, 'sa"); |
| 749 break; |
| 750 case DSRA: |
| 751 Format(instr, "dsra 'rd, 'rt, 'sa"); |
| 752 break; |
| 753 case DSRA32: |
| 754 Format(instr, "dsra32 'rd, 'rt, 'sa"); |
| 755 break; |
| 756 case SLLV: |
| 757 Format(instr, "sllv 'rd, 'rt, 'rs"); |
| 758 break; |
| 759 case DSLLV: |
| 760 Format(instr, "dsllv 'rd, 'rt, 'rs"); |
| 761 break; |
| 762 case SRLV: |
| 763 if (instr->SaValue() == 0) { |
| 764 Format(instr, "srlv 'rd, 'rt, 'rs"); |
| 765 } else { |
| 766 if (kArchVariant == kMips64r2) { |
| 767 Format(instr, "rotrv 'rd, 'rt, 'rs"); |
| 768 } else { |
| 769 Unknown(instr); |
| 770 } |
| 771 } |
| 772 break; |
| 773 case DSRLV: |
| 774 if (instr->SaValue() == 0) { |
| 775 Format(instr, "dsrlv 'rd, 'rt, 'rs"); |
| 776 } else { |
| 777 if (kArchVariant == kMips64r2) { |
| 778 Format(instr, "drotrv 'rd, 'rt, 'rs"); |
| 779 } else { |
| 780 Unknown(instr); |
| 781 } |
| 782 } |
| 783 break; |
| 784 case SRAV: |
| 785 Format(instr, "srav 'rd, 'rt, 'rs"); |
| 786 break; |
| 787 case DSRAV: |
| 788 Format(instr, "dsrav 'rd, 'rt, 'rs"); |
| 789 break; |
| 790 case MFHI: |
| 791 if (instr->Bits(25, 16) == 0) { |
| 792 Format(instr, "mfhi 'rd"); |
| 793 } else { |
| 794 if ((instr->FunctionFieldRaw() == CLZ_R6) && (instr->FdValue() == 1)) { |
| 795 Format(instr, "clz 'rd, 'rs"); |
| 796 } else if ((instr->FunctionFieldRaw() == CLO_R6) && |
| 797 (instr->FdValue() == 1)) { |
| 798 Format(instr, "clo 'rd, 'rs"); |
| 799 } |
| 800 } |
| 801 break; |
| 802 case MFLO: |
| 803 Format(instr, "mflo 'rd"); |
| 804 break; |
| 805 case D_MUL_MUH_U: // Equals to DMULTU. |
| 806 if (kArchVariant != kMips64r6) { |
| 807 Format(instr, "dmultu 'rs, 'rt"); |
| 808 } else { |
| 809 if (instr->SaValue() == MUL_OP) { |
| 810 Format(instr, "dmulu 'rd, 'rs, 'rt"); |
| 811 } else { |
| 812 Format(instr, "dmuhu 'rd, 'rs, 'rt"); |
| 813 } |
| 814 } |
| 815 break; |
| 816 case MULT: // @Mips64r6 == MUL_MUH. |
| 817 if (kArchVariant != kMips64r6) { |
| 818 Format(instr, "mult 'rs, 'rt"); |
| 819 } else { |
| 820 if (instr->SaValue() == MUL_OP) { |
| 821 Format(instr, "mul 'rd, 'rs, 'rt"); |
| 822 } else { |
| 823 Format(instr, "muh 'rd, 'rs, 'rt"); |
| 824 } |
| 825 } |
| 826 break; |
| 827 case MULTU: // @Mips64r6 == MUL_MUH_U. |
| 828 if (kArchVariant != kMips64r6) { |
| 829 Format(instr, "multu 'rs, 'rt"); |
| 830 } else { |
| 831 if (instr->SaValue() == MUL_OP) { |
| 832 Format(instr, "mulu 'rd, 'rs, 'rt"); |
| 833 } else { |
| 834 Format(instr, "muhu 'rd, 'rs, 'rt"); |
| 835 } |
| 836 } |
| 837 |
| 838 break; |
| 839 case DIV: // @Mips64r6 == DIV_MOD. |
| 840 if (kArchVariant != kMips64r6) { |
| 841 Format(instr, "div 'rs, 'rt"); |
| 842 } else { |
| 843 if (instr->SaValue() == DIV_OP) { |
| 844 Format(instr, "div 'rd, 'rs, 'rt"); |
| 845 } else { |
| 846 Format(instr, "mod 'rd, 'rs, 'rt"); |
| 847 } |
| 848 } |
| 849 break; |
| 850 case DDIV: // @Mips64r6 == D_DIV_MOD. |
| 851 if (kArchVariant != kMips64r6) { |
| 852 Format(instr, "ddiv 'rs, 'rt"); |
| 853 } else { |
| 854 if (instr->SaValue() == DIV_OP) { |
| 855 Format(instr, "ddiv 'rd, 'rs, 'rt"); |
| 856 } else { |
| 857 Format(instr, "dmod 'rd, 'rs, 'rt"); |
| 858 } |
| 859 } |
| 860 break; |
| 861 case DIVU: // @Mips64r6 == DIV_MOD_U. |
| 862 if (kArchVariant != kMips64r6) { |
| 863 Format(instr, "divu 'rs, 'rt"); |
| 864 } else { |
| 865 if (instr->SaValue() == DIV_OP) { |
| 866 Format(instr, "divu 'rd, 'rs, 'rt"); |
| 867 } else { |
| 868 Format(instr, "modu 'rd, 'rs, 'rt"); |
| 869 } |
| 870 } |
| 871 break; |
| 872 case DDIVU: // @Mips64r6 == D_DIV_MOD_U. |
| 873 if (kArchVariant != kMips64r6) { |
| 874 Format(instr, "ddivu 'rs, 'rt"); |
| 875 } else { |
| 876 if (instr->SaValue() == DIV_OP) { |
| 877 Format(instr, "ddivu 'rd, 'rs, 'rt"); |
| 878 } else { |
| 879 Format(instr, "dmodu 'rd, 'rs, 'rt"); |
| 880 } |
| 881 } |
| 882 break; |
| 883 case ADD: |
| 884 Format(instr, "add 'rd, 'rs, 'rt"); |
| 885 break; |
| 886 case DADD: |
| 887 Format(instr, "dadd 'rd, 'rs, 'rt"); |
| 888 break; |
| 889 case ADDU: |
| 890 Format(instr, "addu 'rd, 'rs, 'rt"); |
| 891 break; |
| 892 case DADDU: |
| 893 Format(instr, "daddu 'rd, 'rs, 'rt"); |
| 894 break; |
| 895 case SUB: |
| 896 Format(instr, "sub 'rd, 'rs, 'rt"); |
| 897 break; |
| 898 case DSUB: |
| 899 Format(instr, "dsub 'rd, 'rs, 'rt"); |
| 900 break; |
| 901 case SUBU: |
| 902 Format(instr, "subu 'rd, 'rs, 'rt"); |
| 903 break; |
| 904 case DSUBU: |
| 905 Format(instr, "dsubu 'rd, 'rs, 'rt"); |
| 906 break; |
| 907 case AND: |
| 908 Format(instr, "and 'rd, 'rs, 'rt"); |
| 909 break; |
| 910 case OR: |
| 911 if (0 == instr->RsValue()) { |
| 912 Format(instr, "mov 'rd, 'rt"); |
| 913 } else if (0 == instr->RtValue()) { |
| 914 Format(instr, "mov 'rd, 'rs"); |
| 915 } else { |
| 916 Format(instr, "or 'rd, 'rs, 'rt"); |
| 917 } |
| 918 break; |
| 919 case XOR: |
| 920 Format(instr, "xor 'rd, 'rs, 'rt"); |
| 921 break; |
| 922 case NOR: |
| 923 Format(instr, "nor 'rd, 'rs, 'rt"); |
| 924 break; |
| 925 case SLT: |
| 926 Format(instr, "slt 'rd, 'rs, 'rt"); |
| 927 break; |
| 928 case SLTU: |
| 929 Format(instr, "sltu 'rd, 'rs, 'rt"); |
| 930 break; |
| 931 case TGE: |
| 932 Format(instr, "tge 'rs, 'rt, code: 'code"); |
| 933 break; |
| 934 case TGEU: |
| 935 Format(instr, "tgeu 'rs, 'rt, code: 'code"); |
| 936 break; |
| 937 case TLT: |
| 938 Format(instr, "tlt 'rs, 'rt, code: 'code"); |
| 939 break; |
| 940 case TLTU: |
| 941 Format(instr, "tltu 'rs, 'rt, code: 'code"); |
| 942 break; |
| 943 case TEQ: |
| 944 Format(instr, "teq 'rs, 'rt, code: 'code"); |
| 945 break; |
| 946 case TNE: |
| 947 Format(instr, "tne 'rs, 'rt, code: 'code"); |
| 948 break; |
| 949 case MOVZ: |
| 950 Format(instr, "movz 'rd, 'rs, 'rt"); |
| 951 break; |
| 952 case MOVN: |
| 953 Format(instr, "movn 'rd, 'rs, 'rt"); |
| 954 break; |
| 955 case MOVCI: |
| 956 if (instr->Bit(16)) { |
| 957 Format(instr, "movt 'rd, 'rs, 'bc"); |
| 958 } else { |
| 959 Format(instr, "movf 'rd, 'rs, 'bc"); |
| 960 } |
| 961 break; |
| 962 case SELEQZ_S: |
| 963 Format(instr, "seleqz 'rs, 'rt, 'rd"); |
| 964 break; |
| 965 case SELNEZ_S: |
| 966 Format(instr, "selnez 'rs, 'rt, 'rd"); |
| 967 break; |
| 968 default: |
| 969 UNREACHABLE(); |
| 970 } |
| 971 } |
| 972 |
| 973 |
| 974 void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) { |
| 975 switch (instr->FunctionFieldRaw()) { |
| 976 case MUL: |
| 977 Format(instr, "mul 'rd, 'rs, 'rt"); |
| 978 break; |
| 979 case CLZ: |
| 980 if (kArchVariant != kMips64r6) { |
| 981 Format(instr, "clz 'rd, 'rs"); |
| 982 } |
| 983 break; |
| 984 default: |
| 985 UNREACHABLE(); |
| 986 } |
| 987 } |
| 988 |
| 989 |
| 990 void Decoder::DecodeTypeRegisterSPECIAL3(Instruction* instr) { |
| 991 switch (instr->FunctionFieldRaw()) { |
| 992 case INS: { |
| 993 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); |
| 994 break; |
| 995 } |
| 996 case EXT: { |
| 997 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); |
| 998 break; |
| 999 } |
| 1000 case DEXT: { |
| 1001 Format(instr, "dext 'rt, 'rs, 'sa, 'ss1"); |
| 1002 break; |
| 1003 } |
| 1004 default: |
| 1005 UNREACHABLE(); |
| 1006 } |
| 1007 } |
| 1008 |
| 1009 |
| 1010 int Decoder::DecodeTypeRegister(Instruction* instr) { |
| 1011 switch (instr->OpcodeFieldRaw()) { |
| 1012 case COP1: // Coprocessor instructions. |
| 1013 DecodeTypeRegisterCOP1(instr); |
| 1014 break; |
| 649 case COP1X: | 1015 case COP1X: |
| 650 switch (instr->FunctionFieldRaw()) { | 1016 DecodeTypeRegisterCOP1X(instr); |
| 651 case MADD_D: | |
| 652 Format(instr, "madd.d 'fd, 'fr, 'fs, 'ft"); | |
| 653 break; | |
| 654 default: | |
| 655 UNREACHABLE(); | |
| 656 } | |
| 657 break; | 1017 break; |
| 658 case SPECIAL: | 1018 case SPECIAL: |
| 659 switch (instr->FunctionFieldRaw()) { | 1019 switch (instr->FunctionFieldRaw()) { |
| 660 case JR: | |
| 661 Format(instr, "jr 'rs"); | |
| 662 break; | |
| 663 case JALR: | |
| 664 Format(instr, "jalr 'rs"); | |
| 665 break; | |
| 666 case SLL: | |
| 667 if (0x0 == static_cast<int>(instr->InstructionBits())) | |
| 668 Format(instr, "nop"); | |
| 669 else | |
| 670 Format(instr, "sll 'rd, 'rt, 'sa"); | |
| 671 break; | |
| 672 case DSLL: | |
| 673 Format(instr, "dsll 'rd, 'rt, 'sa"); | |
| 674 break; | |
| 675 case D_MUL_MUH: // Equals to DMUL. | |
| 676 if (kArchVariant != kMips64r6) { | |
| 677 Format(instr, "dmult 'rs, 'rt"); | |
| 678 } else { | |
| 679 if (instr->SaValue() == MUL_OP) { | |
| 680 Format(instr, "dmul 'rd, 'rs, 'rt"); | |
| 681 } else { | |
| 682 Format(instr, "dmuh 'rd, 'rs, 'rt"); | |
| 683 } | |
| 684 } | |
| 685 break; | |
| 686 case DSLL32: | |
| 687 Format(instr, "dsll32 'rd, 'rt, 'sa"); | |
| 688 break; | |
| 689 case SRL: | |
| 690 if (instr->RsValue() == 0) { | |
| 691 Format(instr, "srl 'rd, 'rt, 'sa"); | |
| 692 } else { | |
| 693 if (kArchVariant == kMips64r2) { | |
| 694 Format(instr, "rotr 'rd, 'rt, 'sa"); | |
| 695 } else { | |
| 696 Unknown(instr); | |
| 697 } | |
| 698 } | |
| 699 break; | |
| 700 case DSRL: | |
| 701 if (instr->RsValue() == 0) { | |
| 702 Format(instr, "dsrl 'rd, 'rt, 'sa"); | |
| 703 } else { | |
| 704 if (kArchVariant == kMips64r2) { | |
| 705 Format(instr, "drotr 'rd, 'rt, 'sa"); | |
| 706 } else { | |
| 707 Unknown(instr); | |
| 708 } | |
| 709 } | |
| 710 break; | |
| 711 case DSRL32: | |
| 712 Format(instr, "dsrl32 'rd, 'rt, 'sa"); | |
| 713 break; | |
| 714 case SRA: | |
| 715 Format(instr, "sra 'rd, 'rt, 'sa"); | |
| 716 break; | |
| 717 case DSRA: | |
| 718 Format(instr, "dsra 'rd, 'rt, 'sa"); | |
| 719 break; | |
| 720 case DSRA32: | |
| 721 Format(instr, "dsra32 'rd, 'rt, 'sa"); | |
| 722 break; | |
| 723 case SLLV: | |
| 724 Format(instr, "sllv 'rd, 'rt, 'rs"); | |
| 725 break; | |
| 726 case DSLLV: | |
| 727 Format(instr, "dsllv 'rd, 'rt, 'rs"); | |
| 728 break; | |
| 729 case SRLV: | |
| 730 if (instr->SaValue() == 0) { | |
| 731 Format(instr, "srlv 'rd, 'rt, 'rs"); | |
| 732 } else { | |
| 733 if (kArchVariant == kMips64r2) { | |
| 734 Format(instr, "rotrv 'rd, 'rt, 'rs"); | |
| 735 } else { | |
| 736 Unknown(instr); | |
| 737 } | |
| 738 } | |
| 739 break; | |
| 740 case DSRLV: | |
| 741 if (instr->SaValue() == 0) { | |
| 742 Format(instr, "dsrlv 'rd, 'rt, 'rs"); | |
| 743 } else { | |
| 744 if (kArchVariant == kMips64r2) { | |
| 745 Format(instr, "drotrv 'rd, 'rt, 'rs"); | |
| 746 } else { | |
| 747 Unknown(instr); | |
| 748 } | |
| 749 } | |
| 750 break; | |
| 751 case SRAV: | |
| 752 Format(instr, "srav 'rd, 'rt, 'rs"); | |
| 753 break; | |
| 754 case DSRAV: | |
| 755 Format(instr, "dsrav 'rd, 'rt, 'rs"); | |
| 756 break; | |
| 757 case MFHI: | |
| 758 if (instr->Bits(25, 16) == 0) { | |
| 759 Format(instr, "mfhi 'rd"); | |
| 760 } else { | |
| 761 if ((instr->FunctionFieldRaw() == CLZ_R6) | |
| 762 && (instr->FdValue() == 1)) { | |
| 763 Format(instr, "clz 'rd, 'rs"); | |
| 764 } else if ((instr->FunctionFieldRaw() == CLO_R6) | |
| 765 && (instr->FdValue() == 1)) { | |
| 766 Format(instr, "clo 'rd, 'rs"); | |
| 767 } | |
| 768 } | |
| 769 break; | |
| 770 case MFLO: | |
| 771 Format(instr, "mflo 'rd"); | |
| 772 break; | |
| 773 case D_MUL_MUH_U: // Equals to DMULTU. | |
| 774 if (kArchVariant != kMips64r6) { | |
| 775 Format(instr, "dmultu 'rs, 'rt"); | |
| 776 } else { | |
| 777 if (instr->SaValue() == MUL_OP) { | |
| 778 Format(instr, "dmulu 'rd, 'rs, 'rt"); | |
| 779 } else { | |
| 780 Format(instr, "dmuhu 'rd, 'rs, 'rt"); | |
| 781 } | |
| 782 } | |
| 783 break; | |
| 784 case MULT: // @Mips64r6 == MUL_MUH. | |
| 785 if (kArchVariant != kMips64r6) { | |
| 786 Format(instr, "mult 'rs, 'rt"); | |
| 787 } else { | |
| 788 if (instr->SaValue() == MUL_OP) { | |
| 789 Format(instr, "mul 'rd, 'rs, 'rt"); | |
| 790 } else { | |
| 791 Format(instr, "muh 'rd, 'rs, 'rt"); | |
| 792 } | |
| 793 } | |
| 794 break; | |
| 795 case MULTU: // @Mips64r6 == MUL_MUH_U. | |
| 796 if (kArchVariant != kMips64r6) { | |
| 797 Format(instr, "multu 'rs, 'rt"); | |
| 798 } else { | |
| 799 if (instr->SaValue() == MUL_OP) { | |
| 800 Format(instr, "mulu 'rd, 'rs, 'rt"); | |
| 801 } else { | |
| 802 Format(instr, "muhu 'rd, 'rs, 'rt"); | |
| 803 } | |
| 804 } | |
| 805 | |
| 806 break; | |
| 807 case DIV: // @Mips64r6 == DIV_MOD. | |
| 808 if (kArchVariant != kMips64r6) { | |
| 809 Format(instr, "div 'rs, 'rt"); | |
| 810 } else { | |
| 811 if (instr->SaValue() == DIV_OP) { | |
| 812 Format(instr, "div 'rd, 'rs, 'rt"); | |
| 813 } else { | |
| 814 Format(instr, "mod 'rd, 'rs, 'rt"); | |
| 815 } | |
| 816 } | |
| 817 break; | |
| 818 case DDIV: // @Mips64r6 == D_DIV_MOD. | |
| 819 if (kArchVariant != kMips64r6) { | |
| 820 Format(instr, "ddiv 'rs, 'rt"); | |
| 821 } else { | |
| 822 if (instr->SaValue() == DIV_OP) { | |
| 823 Format(instr, "ddiv 'rd, 'rs, 'rt"); | |
| 824 } else { | |
| 825 Format(instr, "dmod 'rd, 'rs, 'rt"); | |
| 826 } | |
| 827 } | |
| 828 break; | |
| 829 case DIVU: // @Mips64r6 == DIV_MOD_U. | |
| 830 if (kArchVariant != kMips64r6) { | |
| 831 Format(instr, "divu 'rs, 'rt"); | |
| 832 } else { | |
| 833 if (instr->SaValue() == DIV_OP) { | |
| 834 Format(instr, "divu 'rd, 'rs, 'rt"); | |
| 835 } else { | |
| 836 Format(instr, "modu 'rd, 'rs, 'rt"); | |
| 837 } | |
| 838 } | |
| 839 break; | |
| 840 case DDIVU: // @Mips64r6 == D_DIV_MOD_U. | |
| 841 if (kArchVariant != kMips64r6) { | |
| 842 Format(instr, "ddivu 'rs, 'rt"); | |
| 843 } else { | |
| 844 if (instr->SaValue() == DIV_OP) { | |
| 845 Format(instr, "ddivu 'rd, 'rs, 'rt"); | |
| 846 } else { | |
| 847 Format(instr, "dmodu 'rd, 'rs, 'rt"); | |
| 848 } | |
| 849 } | |
| 850 break; | |
| 851 case ADD: | |
| 852 Format(instr, "add 'rd, 'rs, 'rt"); | |
| 853 break; | |
| 854 case DADD: | |
| 855 Format(instr, "dadd 'rd, 'rs, 'rt"); | |
| 856 break; | |
| 857 case ADDU: | |
| 858 Format(instr, "addu 'rd, 'rs, 'rt"); | |
| 859 break; | |
| 860 case DADDU: | |
| 861 Format(instr, "daddu 'rd, 'rs, 'rt"); | |
| 862 break; | |
| 863 case SUB: | |
| 864 Format(instr, "sub 'rd, 'rs, 'rt"); | |
| 865 break; | |
| 866 case DSUB: | |
| 867 Format(instr, "dsub 'rd, 'rs, 'rt"); | |
| 868 break; | |
| 869 case SUBU: | |
| 870 Format(instr, "subu 'rd, 'rs, 'rt"); | |
| 871 break; | |
| 872 case DSUBU: | |
| 873 Format(instr, "dsubu 'rd, 'rs, 'rt"); | |
| 874 break; | |
| 875 case AND: | |
| 876 Format(instr, "and 'rd, 'rs, 'rt"); | |
| 877 break; | |
| 878 case OR: | |
| 879 if (0 == instr->RsValue()) { | |
| 880 Format(instr, "mov 'rd, 'rt"); | |
| 881 } else if (0 == instr->RtValue()) { | |
| 882 Format(instr, "mov 'rd, 'rs"); | |
| 883 } else { | |
| 884 Format(instr, "or 'rd, 'rs, 'rt"); | |
| 885 } | |
| 886 break; | |
| 887 case XOR: | |
| 888 Format(instr, "xor 'rd, 'rs, 'rt"); | |
| 889 break; | |
| 890 case NOR: | |
| 891 Format(instr, "nor 'rd, 'rs, 'rt"); | |
| 892 break; | |
| 893 case SLT: | |
| 894 Format(instr, "slt 'rd, 'rs, 'rt"); | |
| 895 break; | |
| 896 case SLTU: | |
| 897 Format(instr, "sltu 'rd, 'rs, 'rt"); | |
| 898 break; | |
| 899 case BREAK: | 1020 case BREAK: |
| 900 return DecodeBreakInstr(instr); | 1021 return DecodeBreakInstr(instr); |
| 901 case TGE: | 1022 default: |
| 902 Format(instr, "tge 'rs, 'rt, code: 'code"); | 1023 DecodeTypeRegisterSPECIAL(instr); |
| 903 break; | 1024 break; |
| 904 case TGEU: | |
| 905 Format(instr, "tgeu 'rs, 'rt, code: 'code"); | |
| 906 break; | |
| 907 case TLT: | |
| 908 Format(instr, "tlt 'rs, 'rt, code: 'code"); | |
| 909 break; | |
| 910 case TLTU: | |
| 911 Format(instr, "tltu 'rs, 'rt, code: 'code"); | |
| 912 break; | |
| 913 case TEQ: | |
| 914 Format(instr, "teq 'rs, 'rt, code: 'code"); | |
| 915 break; | |
| 916 case TNE: | |
| 917 Format(instr, "tne 'rs, 'rt, code: 'code"); | |
| 918 break; | |
| 919 case MOVZ: | |
| 920 Format(instr, "movz 'rd, 'rs, 'rt"); | |
| 921 break; | |
| 922 case MOVN: | |
| 923 Format(instr, "movn 'rd, 'rs, 'rt"); | |
| 924 break; | |
| 925 case MOVCI: | |
| 926 if (instr->Bit(16)) { | |
| 927 Format(instr, "movt 'rd, 'rs, 'bc"); | |
| 928 } else { | |
| 929 Format(instr, "movf 'rd, 'rs, 'bc"); | |
| 930 } | |
| 931 break; | |
| 932 case SELEQZ_S: | |
| 933 Format(instr, "seleqz 'rd, 'rs, 'rt"); | |
| 934 break; | |
| 935 case SELNEZ_S: | |
| 936 Format(instr, "selnez 'rd, 'rs, 'rt"); | |
| 937 break; | |
| 938 default: | |
| 939 UNREACHABLE(); | |
| 940 } | 1025 } |
| 941 break; | 1026 break; |
| 942 case SPECIAL2: | 1027 case SPECIAL2: |
| 943 switch (instr->FunctionFieldRaw()) { | 1028 DecodeTypeRegisterSPECIAL2(instr); |
| 944 case MUL: | |
| 945 Format(instr, "mul 'rd, 'rs, 'rt"); | |
| 946 break; | |
| 947 case CLZ: | |
| 948 if (kArchVariant != kMips64r6) { | |
| 949 Format(instr, "clz 'rd, 'rs"); | |
| 950 } | |
| 951 break; | |
| 952 default: | |
| 953 UNREACHABLE(); | |
| 954 } | |
| 955 break; | 1029 break; |
| 956 case SPECIAL3: | 1030 case SPECIAL3: |
| 957 switch (instr->FunctionFieldRaw()) { | 1031 DecodeTypeRegisterSPECIAL3(instr); |
| 958 case INS: { | 1032 break; |
| 959 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); | 1033 default: |
| 960 break; | 1034 UNREACHABLE(); |
| 961 } | 1035 } |
| 962 case EXT: { | |
| 963 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); | |
| 964 break; | |
| 965 } | |
| 966 case DEXT: { | |
| 967 Format(instr, "dext 'rt, 'rs, 'sa, 'ss1"); | |
| 968 break; | |
| 969 } | |
| 970 default: | |
| 971 UNREACHABLE(); | |
| 972 } | |
| 973 break; | |
| 974 default: | |
| 975 UNREACHABLE(); | |
| 976 } | |
| 977 return Instruction::kInstrSize; | 1036 return Instruction::kInstrSize; |
| 978 } | 1037 } |
| 979 | 1038 |
| 980 | 1039 |
| 1040 void Decoder::DecodeTypeImmediateCOP1D(Instruction* instr) { |
| 1041 switch (instr->FunctionValue()) { |
| 1042 case SEL: |
| 1043 Format(instr, "sel.D 'ft, 'fs, 'fd"); |
| 1044 break; |
| 1045 case SELEQZ_C: |
| 1046 Format(instr, "seleqz.D 'ft, 'fs, 'fd"); |
| 1047 break; |
| 1048 case SELNEZ_C: |
| 1049 Format(instr, "selnez.D 'ft, 'fs, 'fd"); |
| 1050 break; |
| 1051 case MIN: |
| 1052 Format(instr, "min.D 'ft, 'fs, 'fd"); |
| 1053 break; |
| 1054 case MINA: |
| 1055 Format(instr, "mina.D 'ft, 'fs, 'fd"); |
| 1056 break; |
| 1057 case MAX: |
| 1058 Format(instr, "max.D 'ft, 'fs, 'fd"); |
| 1059 break; |
| 1060 case MAXA: |
| 1061 Format(instr, "maxa.D 'ft, 'fs, 'fd"); |
| 1062 break; |
| 1063 default: |
| 1064 UNREACHABLE(); |
| 1065 } |
| 1066 } |
| 1067 |
| 1068 |
| 1069 void Decoder::DecodeTypeImmediateCOP1L(Instruction* instr) { |
| 1070 switch (instr->FunctionValue()) { |
| 1071 case CMP_AF: |
| 1072 Format(instr, "cmp.af.D 'ft, 'fs, 'fd"); |
| 1073 break; |
| 1074 case CMP_UN: |
| 1075 Format(instr, "cmp.un.D 'ft, 'fs, 'fd"); |
| 1076 break; |
| 1077 case CMP_EQ: |
| 1078 Format(instr, "cmp.eq.D 'ft, 'fs, 'fd"); |
| 1079 break; |
| 1080 case CMP_UEQ: |
| 1081 Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd"); |
| 1082 break; |
| 1083 case CMP_LT: |
| 1084 Format(instr, "cmp.lt.D 'ft, 'fs, 'fd"); |
| 1085 break; |
| 1086 case CMP_ULT: |
| 1087 Format(instr, "cmp.ult.D 'ft, 'fs, 'fd"); |
| 1088 break; |
| 1089 case CMP_LE: |
| 1090 Format(instr, "cmp.le.D 'ft, 'fs, 'fd"); |
| 1091 break; |
| 1092 case CMP_ULE: |
| 1093 Format(instr, "cmp.ule.D 'ft, 'fs, 'fd"); |
| 1094 break; |
| 1095 case CMP_OR: |
| 1096 Format(instr, "cmp.or.D 'ft, 'fs, 'fd"); |
| 1097 break; |
| 1098 case CMP_UNE: |
| 1099 Format(instr, "cmp.une.D 'ft, 'fs, 'fd"); |
| 1100 break; |
| 1101 case CMP_NE: |
| 1102 Format(instr, "cmp.ne.D 'ft, 'fs, 'fd"); |
| 1103 break; |
| 1104 default: |
| 1105 UNREACHABLE(); |
| 1106 } |
| 1107 } |
| 1108 |
| 1109 |
| 1110 void Decoder::DecodeTypeImmediateCOP1S(Instruction* instr) { |
| 1111 switch (instr->FunctionValue()) { |
| 1112 case SEL: |
| 1113 Format(instr, "sel.S 'ft, 'fs, 'fd"); |
| 1114 break; |
| 1115 case SELEQZ_C: |
| 1116 Format(instr, "seleqz.S 'ft, 'fs, 'fd"); |
| 1117 break; |
| 1118 case SELNEZ_C: |
| 1119 Format(instr, "selnez.S 'ft, 'fs, 'fd"); |
| 1120 break; |
| 1121 case MIN: |
| 1122 Format(instr, "min.S 'ft, 'fs, 'fd"); |
| 1123 break; |
| 1124 case MINA: |
| 1125 Format(instr, "mina.S 'ft, 'fs, 'fd"); |
| 1126 break; |
| 1127 case MAX: |
| 1128 Format(instr, "max.S 'ft, 'fs, 'fd"); |
| 1129 break; |
| 1130 case MAXA: |
| 1131 Format(instr, "maxa.S 'ft, 'fs, 'fd"); |
| 1132 break; |
| 1133 default: |
| 1134 UNREACHABLE(); |
| 1135 } |
| 1136 } |
| 1137 |
| 1138 |
| 1139 void Decoder::DecodeTypeImmediateCOP1W(Instruction* instr) { |
| 1140 switch (instr->FunctionValue()) { |
| 1141 case CMP_AF: |
| 1142 Format(instr, "cmp.af.S 'ft, 'fs, 'fd"); |
| 1143 break; |
| 1144 case CMP_UN: |
| 1145 Format(instr, "cmp.un.S 'ft, 'fs, 'fd"); |
| 1146 break; |
| 1147 case CMP_EQ: |
| 1148 Format(instr, "cmp.eq.S 'ft, 'fs, 'fd"); |
| 1149 break; |
| 1150 case CMP_UEQ: |
| 1151 Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd"); |
| 1152 break; |
| 1153 case CMP_LT: |
| 1154 Format(instr, "cmp.lt.S 'ft, 'fs, 'fd"); |
| 1155 break; |
| 1156 case CMP_ULT: |
| 1157 Format(instr, "cmp.ult.S 'ft, 'fs, 'fd"); |
| 1158 break; |
| 1159 case CMP_LE: |
| 1160 Format(instr, "cmp.le.S 'ft, 'fs, 'fd"); |
| 1161 break; |
| 1162 case CMP_ULE: |
| 1163 Format(instr, "cmp.ule.S 'ft, 'fs, 'fd"); |
| 1164 break; |
| 1165 case CMP_OR: |
| 1166 Format(instr, "cmp.or.S 'ft, 'fs, 'fd"); |
| 1167 break; |
| 1168 case CMP_UNE: |
| 1169 Format(instr, "cmp.une.S 'ft, 'fs, 'fd"); |
| 1170 break; |
| 1171 case CMP_NE: |
| 1172 Format(instr, "cmp.ne.S 'ft, 'fs, 'fd"); |
| 1173 break; |
| 1174 default: |
| 1175 UNREACHABLE(); |
| 1176 } |
| 1177 } |
| 1178 |
| 1179 |
| 1180 void Decoder::DecodeTypeImmediateCOP1(Instruction* instr) { |
| 1181 switch (instr->RsFieldRaw()) { |
| 1182 case BC1: |
| 1183 if (instr->FBtrueValue()) { |
| 1184 Format(instr, "bc1t 'bc, 'imm16u"); |
| 1185 } else { |
| 1186 Format(instr, "bc1f 'bc, 'imm16u"); |
| 1187 } |
| 1188 break; |
| 1189 case BC1EQZ: |
| 1190 Format(instr, "bc1eqz 'ft, 'imm16u"); |
| 1191 break; |
| 1192 case BC1NEZ: |
| 1193 Format(instr, "bc1nez 'ft, 'imm16u"); |
| 1194 break; |
| 1195 case W: // CMP.S instruction. |
| 1196 DecodeTypeImmediateCOP1W(instr); |
| 1197 break; |
| 1198 case L: // CMP.D instruction. |
| 1199 DecodeTypeImmediateCOP1L(instr); |
| 1200 break; |
| 1201 case S: |
| 1202 DecodeTypeImmediateCOP1S(instr); |
| 1203 break; |
| 1204 case D: |
| 1205 DecodeTypeImmediateCOP1D(instr); |
| 1206 break; |
| 1207 default: |
| 1208 UNREACHABLE(); |
| 1209 } |
| 1210 } |
| 1211 |
| 1212 |
| 1213 void Decoder::DecodeTypeImmediateREGIMM(Instruction* instr) { |
| 1214 switch (instr->RtFieldRaw()) { |
| 1215 case BLTZ: |
| 1216 Format(instr, "bltz 'rs, 'imm16u"); |
| 1217 break; |
| 1218 case BLTZAL: |
| 1219 Format(instr, "bltzal 'rs, 'imm16u"); |
| 1220 break; |
| 1221 case BGEZ: |
| 1222 Format(instr, "bgez 'rs, 'imm16u"); |
| 1223 break; |
| 1224 case BGEZAL: |
| 1225 Format(instr, "bgezal 'rs, 'imm16u"); |
| 1226 break; |
| 1227 case BGEZALL: |
| 1228 Format(instr, "bgezall 'rs, 'imm16u"); |
| 1229 break; |
| 1230 case DAHI: |
| 1231 Format(instr, "dahi 'rs, 'imm16u"); |
| 1232 break; |
| 1233 case DATI: |
| 1234 Format(instr, "dati 'rs, 'imm16u"); |
| 1235 break; |
| 1236 default: |
| 1237 UNREACHABLE(); |
| 1238 } |
| 1239 } |
| 1240 |
| 1241 |
| 981 void Decoder::DecodeTypeImmediate(Instruction* instr) { | 1242 void Decoder::DecodeTypeImmediate(Instruction* instr) { |
| 982 switch (instr->OpcodeFieldRaw()) { | 1243 switch (instr->OpcodeFieldRaw()) { |
| 983 case COP1: | 1244 case COP1: |
| 984 switch (instr->RsFieldRaw()) { | 1245 DecodeTypeImmediateCOP1(instr); |
| 985 case BC1: | |
| 986 if (instr->FBtrueValue()) { | |
| 987 Format(instr, "bc1t 'bc, 'imm16u"); | |
| 988 } else { | |
| 989 Format(instr, "bc1f 'bc, 'imm16u"); | |
| 990 } | |
| 991 break; | |
| 992 case BC1EQZ: | |
| 993 Format(instr, "bc1eqz 'ft, 'imm16u"); | |
| 994 break; | |
| 995 case BC1NEZ: | |
| 996 Format(instr, "bc1nez 'ft, 'imm16u"); | |
| 997 break; | |
| 998 case W: // CMP.S instruction. | |
| 999 switch (instr->FunctionValue()) { | |
| 1000 case CMP_AF: | |
| 1001 Format(instr, "cmp.af.S 'ft, 'fs, 'fd"); | |
| 1002 break; | |
| 1003 case CMP_UN: | |
| 1004 Format(instr, "cmp.un.S 'ft, 'fs, 'fd"); | |
| 1005 break; | |
| 1006 case CMP_EQ: | |
| 1007 Format(instr, "cmp.eq.S 'ft, 'fs, 'fd"); | |
| 1008 break; | |
| 1009 case CMP_UEQ: | |
| 1010 Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd"); | |
| 1011 break; | |
| 1012 case CMP_LT: | |
| 1013 Format(instr, "cmp.lt.S 'ft, 'fs, 'fd"); | |
| 1014 break; | |
| 1015 case CMP_ULT: | |
| 1016 Format(instr, "cmp.ult.S 'ft, 'fs, 'fd"); | |
| 1017 break; | |
| 1018 case CMP_LE: | |
| 1019 Format(instr, "cmp.le.S 'ft, 'fs, 'fd"); | |
| 1020 break; | |
| 1021 case CMP_ULE: | |
| 1022 Format(instr, "cmp.ule.S 'ft, 'fs, 'fd"); | |
| 1023 break; | |
| 1024 case CMP_OR: | |
| 1025 Format(instr, "cmp.or.S 'ft, 'fs, 'fd"); | |
| 1026 break; | |
| 1027 case CMP_UNE: | |
| 1028 Format(instr, "cmp.une.S 'ft, 'fs, 'fd"); | |
| 1029 break; | |
| 1030 case CMP_NE: | |
| 1031 Format(instr, "cmp.ne.S 'ft, 'fs, 'fd"); | |
| 1032 break; | |
| 1033 default: | |
| 1034 UNREACHABLE(); | |
| 1035 } | |
| 1036 break; | |
| 1037 case L: // CMP.D instruction. | |
| 1038 switch (instr->FunctionValue()) { | |
| 1039 case CMP_AF: | |
| 1040 Format(instr, "cmp.af.D 'ft, 'fs, 'fd"); | |
| 1041 break; | |
| 1042 case CMP_UN: | |
| 1043 Format(instr, "cmp.un.D 'ft, 'fs, 'fd"); | |
| 1044 break; | |
| 1045 case CMP_EQ: | |
| 1046 Format(instr, "cmp.eq.D 'ft, 'fs, 'fd"); | |
| 1047 break; | |
| 1048 case CMP_UEQ: | |
| 1049 Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd"); | |
| 1050 break; | |
| 1051 case CMP_LT: | |
| 1052 Format(instr, "cmp.lt.D 'ft, 'fs, 'fd"); | |
| 1053 break; | |
| 1054 case CMP_ULT: | |
| 1055 Format(instr, "cmp.ult.D 'ft, 'fs, 'fd"); | |
| 1056 break; | |
| 1057 case CMP_LE: | |
| 1058 Format(instr, "cmp.le.D 'ft, 'fs, 'fd"); | |
| 1059 break; | |
| 1060 case CMP_ULE: | |
| 1061 Format(instr, "cmp.ule.D 'ft, 'fs, 'fd"); | |
| 1062 break; | |
| 1063 case CMP_OR: | |
| 1064 Format(instr, "cmp.or.D 'ft, 'fs, 'fd"); | |
| 1065 break; | |
| 1066 case CMP_UNE: | |
| 1067 Format(instr, "cmp.une.D 'ft, 'fs, 'fd"); | |
| 1068 break; | |
| 1069 case CMP_NE: | |
| 1070 Format(instr, "cmp.ne.D 'ft, 'fs, 'fd"); | |
| 1071 break; | |
| 1072 default: | |
| 1073 UNREACHABLE(); | |
| 1074 } | |
| 1075 break; | |
| 1076 case S: | |
| 1077 switch (instr->FunctionValue()) { | |
| 1078 case SEL: | |
| 1079 Format(instr, "sel.S 'ft, 'fs, 'fd"); | |
| 1080 break; | |
| 1081 case SELEQZ_C: | |
| 1082 Format(instr, "seleqz.S 'ft, 'fs, 'fd"); | |
| 1083 break; | |
| 1084 case SELNEZ_C: | |
| 1085 Format(instr, "selnez.S 'ft, 'fs, 'fd"); | |
| 1086 break; | |
| 1087 case MIN: | |
| 1088 Format(instr, "min.S 'ft, 'fs, 'fd"); | |
| 1089 break; | |
| 1090 case MINA: | |
| 1091 Format(instr, "mina.S 'ft, 'fs, 'fd"); | |
| 1092 break; | |
| 1093 case MAX: | |
| 1094 Format(instr, "max.S 'ft, 'fs, 'fd"); | |
| 1095 break; | |
| 1096 case MAXA: | |
| 1097 Format(instr, "maxa.S 'ft, 'fs, 'fd"); | |
| 1098 break; | |
| 1099 default: | |
| 1100 UNREACHABLE(); | |
| 1101 } | |
| 1102 break; | |
| 1103 case D: | |
| 1104 switch (instr->FunctionValue()) { | |
| 1105 case SEL: | |
| 1106 Format(instr, "sel.D 'ft, 'fs, 'fd"); | |
| 1107 break; | |
| 1108 case SELEQZ_C: | |
| 1109 Format(instr, "seleqz.D 'ft, 'fs, 'fd"); | |
| 1110 break; | |
| 1111 case SELNEZ_C: | |
| 1112 Format(instr, "selnez.D 'ft, 'fs, 'fd"); | |
| 1113 break; | |
| 1114 case MIN: | |
| 1115 Format(instr, "min.D 'ft, 'fs, 'fd"); | |
| 1116 break; | |
| 1117 case MINA: | |
| 1118 Format(instr, "mina.D 'ft, 'fs, 'fd"); | |
| 1119 break; | |
| 1120 case MAX: | |
| 1121 Format(instr, "max.D 'ft, 'fs, 'fd"); | |
| 1122 break; | |
| 1123 case MAXA: | |
| 1124 Format(instr, "maxa.D 'ft, 'fs, 'fd"); | |
| 1125 break; | |
| 1126 default: | |
| 1127 UNREACHABLE(); | |
| 1128 } | |
| 1129 break; | |
| 1130 default: | |
| 1131 UNREACHABLE(); | |
| 1132 } | |
| 1133 | |
| 1134 break; // Case COP1. | 1246 break; // Case COP1. |
| 1135 // ------------- REGIMM class. | 1247 // ------------- REGIMM class. |
| 1136 case REGIMM: | 1248 case REGIMM: |
| 1137 switch (instr->RtFieldRaw()) { | 1249 |
| 1138 case BLTZ: | |
| 1139 Format(instr, "bltz 'rs, 'imm16u"); | |
| 1140 break; | |
| 1141 case BLTZAL: | |
| 1142 Format(instr, "bltzal 'rs, 'imm16u"); | |
| 1143 break; | |
| 1144 case BGEZ: | |
| 1145 Format(instr, "bgez 'rs, 'imm16u"); | |
| 1146 break; | |
| 1147 case BGEZAL: | |
| 1148 Format(instr, "bgezal 'rs, 'imm16u"); | |
| 1149 break; | |
| 1150 case BGEZALL: | |
| 1151 Format(instr, "bgezall 'rs, 'imm16u"); | |
| 1152 break; | |
| 1153 case DAHI: | |
| 1154 Format(instr, "dahi 'rs, 'imm16u"); | |
| 1155 break; | |
| 1156 case DATI: | |
| 1157 Format(instr, "dati 'rs, 'imm16u"); | |
| 1158 break; | |
| 1159 default: | |
| 1160 UNREACHABLE(); | |
| 1161 } | |
| 1162 break; // Case REGIMM. | 1250 break; // Case REGIMM. |
| 1163 // ------------- Branch instructions. | 1251 // ------------- Branch instructions. |
| 1164 case BEQ: | 1252 case BEQ: |
| 1165 Format(instr, "beq 'rs, 'rt, 'imm16u"); | 1253 Format(instr, "beq 'rs, 'rt, 'imm16u"); |
| 1166 break; | 1254 break; |
| 1167 case BNE: | 1255 case BNE: |
| 1168 Format(instr, "bne 'rs, 'rt, 'imm16u"); | 1256 Format(instr, "bne 'rs, 'rt, 'imm16u"); |
| 1169 break; | 1257 break; |
| 1170 case BLEZ: | 1258 case BLEZ: |
| 1171 if ((instr->RtFieldRaw() == 0) | 1259 if ((instr->RtFieldRaw() == 0) |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1499 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1587 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1500 } | 1588 } |
| 1501 } | 1589 } |
| 1502 | 1590 |
| 1503 | 1591 |
| 1504 #undef UNSUPPORTED | 1592 #undef UNSUPPORTED |
| 1505 | 1593 |
| 1506 } // namespace disasm | 1594 } // namespace disasm |
| 1507 | 1595 |
| 1508 #endif // V8_TARGET_ARCH_MIPS64 | 1596 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |