| 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 void PrintSd(Instruction* instr); | 79 void PrintSd(Instruction* instr); |
| 80 void PrintSs1(Instruction* instr); | 80 void PrintSs1(Instruction* instr); |
| 81 void PrintSs2(Instruction* instr); | 81 void PrintSs2(Instruction* instr); |
| 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); | |
| 90 void PrintXImm26(Instruction* instr); | 89 void PrintXImm26(Instruction* instr); |
| 91 void PrintCode(Instruction* instr); // For break and trap instructions. | 90 void PrintCode(Instruction* instr); // For break and trap instructions. |
| 92 // Printing of instruction name. | 91 // Printing of instruction name. |
| 93 void PrintInstructionName(Instruction* instr); | 92 void PrintInstructionName(Instruction* instr); |
| 94 | 93 |
| 95 // Handle formatting of instructions and their options. | 94 // Handle formatting of instructions and their options. |
| 96 int FormatRegister(Instruction* instr, const char* option); | 95 int FormatRegister(Instruction* instr, const char* option); |
| 97 int FormatFPURegister(Instruction* instr, const char* option); | 96 int FormatFPURegister(Instruction* instr, const char* option); |
| 98 int FormatOption(Instruction* instr, const char* option); | 97 int FormatOption(Instruction* instr, const char* option); |
| 99 void Format(Instruction* instr, const char* format); | 98 void Format(Instruction* instr, const char* format); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 } | 239 } |
| 241 | 240 |
| 242 | 241 |
| 243 // Print 16-bit hexa immediate value. | 242 // Print 16-bit hexa immediate value. |
| 244 void Decoder::PrintXImm16(Instruction* instr) { | 243 void Decoder::PrintXImm16(Instruction* instr) { |
| 245 int32_t imm = instr->Imm16Value(); | 244 int32_t imm = instr->Imm16Value(); |
| 246 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); | 245 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
| 247 } | 246 } |
| 248 | 247 |
| 249 | 248 |
| 250 // Print 21-bit immediate value. | |
| 251 void Decoder::PrintXImm21(Instruction* instr) { | |
| 252 uint32_t imm = instr->Imm21Value(); | |
| 253 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); | |
| 254 } | |
| 255 | |
| 256 | |
| 257 // Print 26-bit immediate value. | 249 // Print 26-bit immediate value. |
| 258 void Decoder::PrintXImm26(Instruction* instr) { | 250 void Decoder::PrintXImm26(Instruction* instr) { |
| 259 uint32_t imm = instr->Imm26Value() << kImmFieldShift; | 251 uint32_t imm = instr->Imm26Value() << kImmFieldShift; |
| 260 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); | 252 out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
| 261 } | 253 } |
| 262 | 254 |
| 263 | 255 |
| 264 // Print 26-bit immediate value. | 256 // Print 26-bit immediate value. |
| 265 void Decoder::PrintCode(Instruction* instr) { | 257 void Decoder::PrintCode(Instruction* instr) { |
| 266 if (instr->OpcodeFieldRaw() != SPECIAL) | 258 if (instr->OpcodeFieldRaw() != SPECIAL) |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 DCHECK(STRING_STARTS_WITH(format, "imm16s")); | 353 DCHECK(STRING_STARTS_WITH(format, "imm16s")); |
| 362 PrintSImm16(instr); | 354 PrintSImm16(instr); |
| 363 } else if (format[5] == 'u') { | 355 } else if (format[5] == 'u') { |
| 364 DCHECK(STRING_STARTS_WITH(format, "imm16u")); | 356 DCHECK(STRING_STARTS_WITH(format, "imm16u")); |
| 365 PrintSImm16(instr); | 357 PrintSImm16(instr); |
| 366 } else { | 358 } else { |
| 367 DCHECK(STRING_STARTS_WITH(format, "imm16x")); | 359 DCHECK(STRING_STARTS_WITH(format, "imm16x")); |
| 368 PrintXImm16(instr); | 360 PrintXImm16(instr); |
| 369 } | 361 } |
| 370 return 6; | 362 return 6; |
| 371 } else if (format[3] == '2' && format[4] == '1') { | 363 } else { |
| 372 DCHECK(STRING_STARTS_WITH(format, "imm21x")); | |
| 373 PrintXImm21(instr); | |
| 374 return 6; | |
| 375 } else if (format[3] == '2' && format[4] == '6') { | |
| 376 DCHECK(STRING_STARTS_WITH(format, "imm26x")); | 364 DCHECK(STRING_STARTS_WITH(format, "imm26x")); |
| 377 PrintXImm26(instr); | 365 PrintXImm26(instr); |
| 378 return 6; | 366 return 6; |
| 379 } | 367 } |
| 380 } | 368 } |
| 381 case 'r': { // 'r: registers. | 369 case 'r': { // 'r: registers. |
| 382 return FormatRegister(instr, format); | 370 return FormatRegister(instr, format); |
| 383 } | 371 } |
| 384 case 'f': { // 'f: FPUregisters. | 372 case 'f': { // 'f: FPUregisters. |
| 385 return FormatFPURegister(instr, format); | 373 return FormatFPURegister(instr, format); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 break; | 485 break; |
| 498 case NEG_D: | 486 case NEG_D: |
| 499 Format(instr, "neg.d 'fd, 'fs"); | 487 Format(instr, "neg.d 'fd, 'fs"); |
| 500 break; | 488 break; |
| 501 case SQRT_D: | 489 case SQRT_D: |
| 502 Format(instr, "sqrt.d 'fd, 'fs"); | 490 Format(instr, "sqrt.d 'fd, 'fs"); |
| 503 break; | 491 break; |
| 504 case CVT_W_D: | 492 case CVT_W_D: |
| 505 Format(instr, "cvt.w.d 'fd, 'fs"); | 493 Format(instr, "cvt.w.d 'fd, 'fs"); |
| 506 break; | 494 break; |
| 507 case CVT_L_D: | 495 case CVT_L_D: { |
| 508 Format(instr, "cvt.l.d 'fd, 'fs"); | 496 if (kArchVariant == kMips32r2) { |
| 497 Format(instr, "cvt.l.d 'fd, 'fs"); |
| 498 } else { |
| 499 Unknown(instr); |
| 500 } |
| 509 break; | 501 break; |
| 502 } |
| 510 case TRUNC_W_D: | 503 case TRUNC_W_D: |
| 511 Format(instr, "trunc.w.d 'fd, 'fs"); | 504 Format(instr, "trunc.w.d 'fd, 'fs"); |
| 512 break; | 505 break; |
| 513 case TRUNC_L_D: | 506 case TRUNC_L_D: { |
| 514 Format(instr, "trunc.l.d 'fd, 'fs"); | 507 if (kArchVariant == kMips32r2) { |
| 508 Format(instr, "trunc.l.d 'fd, 'fs"); |
| 509 } else { |
| 510 Unknown(instr); |
| 511 } |
| 515 break; | 512 break; |
| 513 } |
| 516 case ROUND_W_D: | 514 case ROUND_W_D: |
| 517 Format(instr, "round.w.d 'fd, 'fs"); | 515 Format(instr, "round.w.d 'fd, 'fs"); |
| 518 break; | 516 break; |
| 519 case FLOOR_W_D: | 517 case FLOOR_W_D: |
| 520 Format(instr, "floor.w.d 'fd, 'fs"); | 518 Format(instr, "floor.w.d 'fd, 'fs"); |
| 521 break; | 519 break; |
| 522 case CEIL_W_D: | 520 case CEIL_W_D: |
| 523 Format(instr, "ceil.w.d 'fd, 'fs"); | 521 Format(instr, "ceil.w.d 'fd, 'fs"); |
| 524 break; | 522 break; |
| 525 case CVT_S_D: | 523 case CVT_S_D: |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 break; | 562 break; |
| 565 case CVT_D_W: // Convert word to double. | 563 case CVT_D_W: // Convert word to double. |
| 566 Format(instr, "cvt.d.w 'fd, 'fs"); | 564 Format(instr, "cvt.d.w 'fd, 'fs"); |
| 567 break; | 565 break; |
| 568 default: | 566 default: |
| 569 UNREACHABLE(); | 567 UNREACHABLE(); |
| 570 } | 568 } |
| 571 break; | 569 break; |
| 572 case L: | 570 case L: |
| 573 switch (instr->FunctionFieldRaw()) { | 571 switch (instr->FunctionFieldRaw()) { |
| 574 case CVT_D_L: | 572 case CVT_D_L: { |
| 575 Format(instr, "cvt.d.l 'fd, 'fs"); | 573 if (kArchVariant == kMips32r2) { |
| 574 Format(instr, "cvt.d.l 'fd, 'fs"); |
| 575 } else { |
| 576 Unknown(instr); |
| 577 } |
| 576 break; | 578 break; |
| 577 case CVT_S_L: | 579 } |
| 578 Format(instr, "cvt.s.l 'fd, 'fs"); | 580 case CVT_S_L: { |
| 581 if (kArchVariant == kMips32r2) { |
| 582 Format(instr, "cvt.s.l 'fd, 'fs"); |
| 583 } else { |
| 584 Unknown(instr); |
| 585 } |
| 579 break; | 586 break; |
| 580 case CMP_UN: | 587 } |
| 581 Format(instr, "cmp.un.d 'fd, 'fs, 'ft"); | |
| 582 break; | |
| 583 case CMP_EQ: | |
| 584 Format(instr, "cmp.eq.d 'fd, 'fs, 'ft"); | |
| 585 break; | |
| 586 case CMP_UEQ: | |
| 587 Format(instr, "cmp.ueq.d 'fd, 'fs, 'ft"); | |
| 588 break; | |
| 589 case CMP_LT: | |
| 590 Format(instr, "cmp.lt.d 'fd, 'fs, 'ft"); | |
| 591 break; | |
| 592 case CMP_ULT: | |
| 593 Format(instr, "cmp.ult.d 'fd, 'fs, 'ft"); | |
| 594 break; | |
| 595 case CMP_LE: | |
| 596 Format(instr, "cmp.le.d 'fd, 'fs, 'ft"); | |
| 597 break; | |
| 598 case CMP_ULE: | |
| 599 Format(instr, "cmp.ule.d 'fd, 'fs, 'ft"); | |
| 600 break; | |
| 601 case CMP_OR: | |
| 602 Format(instr, "cmp.or.d 'fd, 'fs, 'ft"); | |
| 603 break; | |
| 604 case CMP_UNE: | |
| 605 Format(instr, "cmp.une.d 'fd, 'fs, 'ft"); | |
| 606 break; | |
| 607 case CMP_NE: | |
| 608 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); | |
| 609 break; | |
| 610 default: | 588 default: |
| 611 UNREACHABLE(); | 589 UNREACHABLE(); |
| 612 } | 590 } |
| 613 break; | 591 break; |
| 614 case PS: | 592 case PS: |
| 615 UNIMPLEMENTED_MIPS(); | 593 UNIMPLEMENTED_MIPS(); |
| 616 break; | 594 break; |
| 617 default: | 595 default: |
| 618 UNREACHABLE(); | 596 UNREACHABLE(); |
| 619 } | 597 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 638 case SLL: | 616 case SLL: |
| 639 if ( 0x0 == static_cast<int>(instr->InstructionBits())) | 617 if ( 0x0 == static_cast<int>(instr->InstructionBits())) |
| 640 Format(instr, "nop"); | 618 Format(instr, "nop"); |
| 641 else | 619 else |
| 642 Format(instr, "sll 'rd, 'rt, 'sa"); | 620 Format(instr, "sll 'rd, 'rt, 'sa"); |
| 643 break; | 621 break; |
| 644 case SRL: | 622 case SRL: |
| 645 if (instr->RsValue() == 0) { | 623 if (instr->RsValue() == 0) { |
| 646 Format(instr, "srl 'rd, 'rt, 'sa"); | 624 Format(instr, "srl 'rd, 'rt, 'sa"); |
| 647 } else { | 625 } else { |
| 648 if (IsMipsArchVariant(kMips32r2)) { | 626 if (kArchVariant == kMips32r2) { |
| 649 Format(instr, "rotr 'rd, 'rt, 'sa"); | 627 Format(instr, "rotr 'rd, 'rt, 'sa"); |
| 650 } else { | 628 } else { |
| 651 Unknown(instr); | 629 Unknown(instr); |
| 652 } | 630 } |
| 653 } | 631 } |
| 654 break; | 632 break; |
| 655 case SRA: | 633 case SRA: |
| 656 Format(instr, "sra 'rd, 'rt, 'sa"); | 634 Format(instr, "sra 'rd, 'rt, 'sa"); |
| 657 break; | 635 break; |
| 658 case SLLV: | 636 case SLLV: |
| 659 Format(instr, "sllv 'rd, 'rt, 'rs"); | 637 Format(instr, "sllv 'rd, 'rt, 'rs"); |
| 660 break; | 638 break; |
| 661 case SRLV: | 639 case SRLV: |
| 662 if (instr->SaValue() == 0) { | 640 if (instr->SaValue() == 0) { |
| 663 Format(instr, "srlv 'rd, 'rt, 'rs"); | 641 Format(instr, "srlv 'rd, 'rt, 'rs"); |
| 664 } else { | 642 } else { |
| 665 if (IsMipsArchVariant(kMips32r2)) { | 643 if (kArchVariant == kMips32r2) { |
| 666 Format(instr, "rotrv 'rd, 'rt, 'rs"); | 644 Format(instr, "rotrv 'rd, 'rt, 'rs"); |
| 667 } else { | 645 } else { |
| 668 Unknown(instr); | 646 Unknown(instr); |
| 669 } | 647 } |
| 670 } | 648 } |
| 671 break; | 649 break; |
| 672 case SRAV: | 650 case SRAV: |
| 673 Format(instr, "srav 'rd, 'rt, 'rs"); | 651 Format(instr, "srav 'rd, 'rt, 'rs"); |
| 674 break; | 652 break; |
| 675 case MFHI: | 653 case MFHI: |
| 676 if (instr->Bits(25, 16) == 0) { | 654 Format(instr, "mfhi 'rd"); |
| 677 Format(instr, "mfhi 'rd"); | |
| 678 } else { | |
| 679 if ((instr->FunctionFieldRaw() == CLZ_R6) | |
| 680 && (instr->FdValue() == 1)) { | |
| 681 Format(instr, "clz 'rd, 'rs"); | |
| 682 } else if ((instr->FunctionFieldRaw() == CLO_R6) | |
| 683 && (instr->FdValue() == 1)) { | |
| 684 Format(instr, "clo 'rd, 'rs"); | |
| 685 } | |
| 686 } | |
| 687 break; | 655 break; |
| 688 case MFLO: | 656 case MFLO: |
| 689 Format(instr, "mflo 'rd"); | 657 Format(instr, "mflo 'rd"); |
| 690 break; | 658 break; |
| 691 case MULT: // @Mips32r6 == MUL_MUH. | 659 case MULT: |
| 692 if (!IsMipsArchVariant(kMips32r6)) { | 660 Format(instr, "mult 'rs, 'rt"); |
| 693 Format(instr, "mult 'rs, 'rt"); | |
| 694 } else { | |
| 695 if (instr->SaValue() == MUL_OP) { | |
| 696 Format(instr, "mul 'rd, 'rs, 'rt"); | |
| 697 } else { | |
| 698 Format(instr, "muh 'rd, 'rs, 'rt"); | |
| 699 } | |
| 700 } | |
| 701 break; | 661 break; |
| 702 case MULTU: // @Mips32r6 == MUL_MUH_U. | 662 case MULTU: |
| 703 if (!IsMipsArchVariant(kMips32r6)) { | 663 Format(instr, "multu 'rs, 'rt"); |
| 704 Format(instr, "multu 'rs, 'rt"); | |
| 705 } else { | |
| 706 if (instr->SaValue() == MUL_OP) { | |
| 707 Format(instr, "mulu 'rd, 'rs, 'rt"); | |
| 708 } else { | |
| 709 Format(instr, "muhu 'rd, 'rs, 'rt"); | |
| 710 } | |
| 711 } | |
| 712 break; | 664 break; |
| 713 case DIV: // @Mips32r6 == DIV_MOD. | 665 case DIV: |
| 714 if (!IsMipsArchVariant(kMips32r6)) { | 666 Format(instr, "div 'rs, 'rt"); |
| 715 Format(instr, "div 'rs, 'rt"); | |
| 716 } else { | |
| 717 if (instr->SaValue() == DIV_OP) { | |
| 718 Format(instr, "div 'rd, 'rs, 'rt"); | |
| 719 } else { | |
| 720 Format(instr, "mod 'rd, 'rs, 'rt"); | |
| 721 } | |
| 722 } | |
| 723 break; | 667 break; |
| 724 case DIVU: // @Mips32r6 == DIV_MOD_U. | 668 case DIVU: |
| 725 if (!IsMipsArchVariant(kMips32r6)) { | 669 Format(instr, "divu 'rs, 'rt"); |
| 726 Format(instr, "divu 'rs, 'rt"); | |
| 727 } else { | |
| 728 if (instr->SaValue() == DIV_OP) { | |
| 729 Format(instr, "divu 'rd, 'rs, 'rt"); | |
| 730 } else { | |
| 731 Format(instr, "modu 'rd, 'rs, 'rt"); | |
| 732 } | |
| 733 } | |
| 734 break; | 670 break; |
| 735 case ADD: | 671 case ADD: |
| 736 Format(instr, "add 'rd, 'rs, 'rt"); | 672 Format(instr, "add 'rd, 'rs, 'rt"); |
| 737 break; | 673 break; |
| 738 case ADDU: | 674 case ADDU: |
| 739 Format(instr, "addu 'rd, 'rs, 'rt"); | 675 Format(instr, "addu 'rd, 'rs, 'rt"); |
| 740 break; | 676 break; |
| 741 case SUB: | 677 case SUB: |
| 742 Format(instr, "sub 'rd, 'rs, 'rt"); | 678 Format(instr, "sub 'rd, 'rs, 'rt"); |
| 743 break; | 679 break; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 case MOVN: | 731 case MOVN: |
| 796 Format(instr, "movn 'rd, 'rs, 'rt"); | 732 Format(instr, "movn 'rd, 'rs, 'rt"); |
| 797 break; | 733 break; |
| 798 case MOVCI: | 734 case MOVCI: |
| 799 if (instr->Bit(16)) { | 735 if (instr->Bit(16)) { |
| 800 Format(instr, "movt 'rd, 'rs, 'bc"); | 736 Format(instr, "movt 'rd, 'rs, 'bc"); |
| 801 } else { | 737 } else { |
| 802 Format(instr, "movf 'rd, 'rs, 'bc"); | 738 Format(instr, "movf 'rd, 'rs, 'bc"); |
| 803 } | 739 } |
| 804 break; | 740 break; |
| 805 case SELEQZ_S: | |
| 806 Format(instr, "seleqz 'rd, 'rs, 'rt"); | |
| 807 break; | |
| 808 case SELNEZ_S: | |
| 809 Format(instr, "selnez 'rd, 'rs, 'rt"); | |
| 810 break; | |
| 811 default: | 741 default: |
| 812 UNREACHABLE(); | 742 UNREACHABLE(); |
| 813 } | 743 } |
| 814 break; | 744 break; |
| 815 case SPECIAL2: | 745 case SPECIAL2: |
| 816 switch (instr->FunctionFieldRaw()) { | 746 switch (instr->FunctionFieldRaw()) { |
| 817 case MUL: | 747 case MUL: |
| 818 Format(instr, "mul 'rd, 'rs, 'rt"); | 748 Format(instr, "mul 'rd, 'rs, 'rt"); |
| 819 break; | 749 break; |
| 820 case CLZ: | 750 case CLZ: |
| 821 if (!IsMipsArchVariant(kMips32r6)) { | 751 Format(instr, "clz 'rd, 'rs"); |
| 822 Format(instr, "clz 'rd, 'rs"); | |
| 823 } | |
| 824 break; | 752 break; |
| 825 default: | 753 default: |
| 826 UNREACHABLE(); | 754 UNREACHABLE(); |
| 827 } | 755 } |
| 828 break; | 756 break; |
| 829 case SPECIAL3: | 757 case SPECIAL3: |
| 830 switch (instr->FunctionFieldRaw()) { | 758 switch (instr->FunctionFieldRaw()) { |
| 831 case INS: { | 759 case INS: { |
| 832 if (IsMipsArchVariant(kMips32r2)) { | 760 if (kArchVariant == kMips32r2) { |
| 833 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); | 761 Format(instr, "ins 'rt, 'rs, 'sa, 'ss2"); |
| 834 } else { | 762 } else { |
| 835 Unknown(instr); | 763 Unknown(instr); |
| 836 } | 764 } |
| 837 break; | 765 break; |
| 838 } | 766 } |
| 839 case EXT: { | 767 case EXT: { |
| 840 if (IsMipsArchVariant(kMips32r2)) { | 768 if (kArchVariant == kMips32r2) { |
| 841 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); | 769 Format(instr, "ext 'rt, 'rs, 'sa, 'ss1"); |
| 842 } else { | 770 } else { |
| 843 Unknown(instr); | 771 Unknown(instr); |
| 844 } | 772 } |
| 845 break; | 773 break; |
| 846 } | 774 } |
| 847 default: | 775 default: |
| 848 UNREACHABLE(); | 776 UNREACHABLE(); |
| 849 } | 777 } |
| 850 break; | 778 break; |
| 851 default: | 779 default: |
| 852 UNREACHABLE(); | 780 UNREACHABLE(); |
| 853 } | 781 } |
| 854 } | 782 } |
| 855 | 783 |
| 856 | 784 |
| 857 void Decoder::DecodeTypeImmediate(Instruction* instr) { | 785 void Decoder::DecodeTypeImmediate(Instruction* instr) { |
| 858 switch (instr->OpcodeFieldRaw()) { | 786 switch (instr->OpcodeFieldRaw()) { |
| 787 // ------------- REGIMM class. |
| 859 case COP1: | 788 case COP1: |
| 860 switch (instr->RsFieldRaw()) { | 789 switch (instr->RsFieldRaw()) { |
| 861 case BC1: | 790 case BC1: |
| 862 if (instr->FBtrueValue()) { | 791 if (instr->FBtrueValue()) { |
| 863 Format(instr, "bc1t 'bc, 'imm16u"); | 792 Format(instr, "bc1t 'bc, 'imm16u"); |
| 864 } else { | 793 } else { |
| 865 Format(instr, "bc1f 'bc, 'imm16u"); | 794 Format(instr, "bc1f 'bc, 'imm16u"); |
| 866 } | 795 } |
| 867 break; | 796 break; |
| 868 case BC1EQZ: | |
| 869 Format(instr, "bc1eqz 'ft, 'imm16u"); | |
| 870 break; | |
| 871 case BC1NEZ: | |
| 872 Format(instr, "bc1nez 'ft, 'imm16u"); | |
| 873 break; | |
| 874 case W: // CMP.S instruction. | |
| 875 switch (instr->FunctionValue()) { | |
| 876 case CMP_AF: | |
| 877 Format(instr, "cmp.af.S 'ft, 'fs, 'fd"); | |
| 878 break; | |
| 879 case CMP_UN: | |
| 880 Format(instr, "cmp.un.S 'ft, 'fs, 'fd"); | |
| 881 break; | |
| 882 case CMP_EQ: | |
| 883 Format(instr, "cmp.eq.S 'ft, 'fs, 'fd"); | |
| 884 break; | |
| 885 case CMP_UEQ: | |
| 886 Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd"); | |
| 887 break; | |
| 888 case CMP_LT: | |
| 889 Format(instr, "cmp.lt.S 'ft, 'fs, 'fd"); | |
| 890 break; | |
| 891 case CMP_ULT: | |
| 892 Format(instr, "cmp.ult.S 'ft, 'fs, 'fd"); | |
| 893 break; | |
| 894 case CMP_LE: | |
| 895 Format(instr, "cmp.le.S 'ft, 'fs, 'fd"); | |
| 896 break; | |
| 897 case CMP_ULE: | |
| 898 Format(instr, "cmp.ule.S 'ft, 'fs, 'fd"); | |
| 899 break; | |
| 900 case CMP_OR: | |
| 901 Format(instr, "cmp.or.S 'ft, 'fs, 'fd"); | |
| 902 break; | |
| 903 case CMP_UNE: | |
| 904 Format(instr, "cmp.une.S 'ft, 'fs, 'fd"); | |
| 905 break; | |
| 906 case CMP_NE: | |
| 907 Format(instr, "cmp.ne.S 'ft, 'fs, 'fd"); | |
| 908 break; | |
| 909 default: | |
| 910 UNREACHABLE(); | |
| 911 } | |
| 912 break; | |
| 913 case L: // CMP.D instruction. | |
| 914 switch (instr->FunctionValue()) { | |
| 915 case CMP_AF: | |
| 916 Format(instr, "cmp.af.D 'ft, 'fs, 'fd"); | |
| 917 break; | |
| 918 case CMP_UN: | |
| 919 Format(instr, "cmp.un.D 'ft, 'fs, 'fd"); | |
| 920 break; | |
| 921 case CMP_EQ: | |
| 922 Format(instr, "cmp.eq.D 'ft, 'fs, 'fd"); | |
| 923 break; | |
| 924 case CMP_UEQ: | |
| 925 Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd"); | |
| 926 break; | |
| 927 case CMP_LT: | |
| 928 Format(instr, "cmp.lt.D 'ft, 'fs, 'fd"); | |
| 929 break; | |
| 930 case CMP_ULT: | |
| 931 Format(instr, "cmp.ult.D 'ft, 'fs, 'fd"); | |
| 932 break; | |
| 933 case CMP_LE: | |
| 934 Format(instr, "cmp.le.D 'ft, 'fs, 'fd"); | |
| 935 break; | |
| 936 case CMP_ULE: | |
| 937 Format(instr, "cmp.ule.D 'ft, 'fs, 'fd"); | |
| 938 break; | |
| 939 case CMP_OR: | |
| 940 Format(instr, "cmp.or.D 'ft, 'fs, 'fd"); | |
| 941 break; | |
| 942 case CMP_UNE: | |
| 943 Format(instr, "cmp.une.D 'ft, 'fs, 'fd"); | |
| 944 break; | |
| 945 case CMP_NE: | |
| 946 Format(instr, "cmp.ne.D 'ft, 'fs, 'fd"); | |
| 947 break; | |
| 948 default: | |
| 949 UNREACHABLE(); | |
| 950 } | |
| 951 break; | |
| 952 case S: | |
| 953 switch (instr->FunctionValue()) { | |
| 954 case SEL: | |
| 955 Format(instr, "sel.S 'ft, 'fs, 'fd"); | |
| 956 break; | |
| 957 case SELEQZ_C: | |
| 958 Format(instr, "seleqz.S 'ft, 'fs, 'fd"); | |
| 959 break; | |
| 960 case SELNEZ_C: | |
| 961 Format(instr, "selnez.S 'ft, 'fs, 'fd"); | |
| 962 break; | |
| 963 case MIN: | |
| 964 Format(instr, "min.S 'ft, 'fs, 'fd"); | |
| 965 break; | |
| 966 case MINA: | |
| 967 Format(instr, "mina.S 'ft, 'fs, 'fd"); | |
| 968 break; | |
| 969 case MAX: | |
| 970 Format(instr, "max.S 'ft, 'fs, 'fd"); | |
| 971 break; | |
| 972 case MAXA: | |
| 973 Format(instr, "maxa.S 'ft, 'fs, 'fd"); | |
| 974 break; | |
| 975 default: | |
| 976 UNREACHABLE(); | |
| 977 } | |
| 978 break; | |
| 979 case D: | |
| 980 switch (instr->FunctionValue()) { | |
| 981 case SEL: | |
| 982 Format(instr, "sel.D 'ft, 'fs, 'fd"); | |
| 983 break; | |
| 984 case SELEQZ_C: | |
| 985 Format(instr, "seleqz.D 'ft, 'fs, 'fd"); | |
| 986 break; | |
| 987 case SELNEZ_C: | |
| 988 Format(instr, "selnez.D 'ft, 'fs, 'fd"); | |
| 989 break; | |
| 990 case MIN: | |
| 991 Format(instr, "min.D 'ft, 'fs, 'fd"); | |
| 992 break; | |
| 993 case MINA: | |
| 994 Format(instr, "mina.D 'ft, 'fs, 'fd"); | |
| 995 break; | |
| 996 case MAX: | |
| 997 Format(instr, "max.D 'ft, 'fs, 'fd"); | |
| 998 break; | |
| 999 case MAXA: | |
| 1000 Format(instr, "maxa.D 'ft, 'fs, 'fd"); | |
| 1001 break; | |
| 1002 default: | |
| 1003 UNREACHABLE(); | |
| 1004 } | |
| 1005 break; | |
| 1006 default: | 797 default: |
| 1007 UNREACHABLE(); | 798 UNREACHABLE(); |
| 1008 } | 799 } |
| 1009 | |
| 1010 break; // Case COP1. | 800 break; // Case COP1. |
| 1011 // ------------- REGIMM class. | |
| 1012 case REGIMM: | 801 case REGIMM: |
| 1013 switch (instr->RtFieldRaw()) { | 802 switch (instr->RtFieldRaw()) { |
| 1014 case BLTZ: | 803 case BLTZ: |
| 1015 Format(instr, "bltz 'rs, 'imm16u"); | 804 Format(instr, "bltz 'rs, 'imm16u"); |
| 1016 break; | 805 break; |
| 1017 case BLTZAL: | 806 case BLTZAL: |
| 1018 Format(instr, "bltzal 'rs, 'imm16u"); | 807 Format(instr, "bltzal 'rs, 'imm16u"); |
| 1019 break; | 808 break; |
| 1020 case BGEZ: | 809 case BGEZ: |
| 1021 Format(instr, "bgez 'rs, 'imm16u"); | 810 Format(instr, "bgez 'rs, 'imm16u"); |
| 1022 break; | 811 break; |
| 1023 case BGEZAL: | 812 case BGEZAL: |
| 1024 Format(instr, "bgezal 'rs, 'imm16u"); | 813 Format(instr, "bgezal 'rs, 'imm16u"); |
| 1025 break; | 814 break; |
| 1026 case BGEZALL: | |
| 1027 Format(instr, "bgezall 'rs, 'imm16u"); | |
| 1028 break; | |
| 1029 default: | 815 default: |
| 1030 UNREACHABLE(); | 816 UNREACHABLE(); |
| 1031 } | 817 } |
| 1032 break; // Case REGIMM. | 818 break; // Case REGIMM. |
| 1033 // ------------- Branch instructions. | 819 // ------------- Branch instructions. |
| 1034 case BEQ: | 820 case BEQ: |
| 1035 Format(instr, "beq 'rs, 'rt, 'imm16u"); | 821 Format(instr, "beq 'rs, 'rt, 'imm16u"); |
| 1036 break; | 822 break; |
| 1037 case BNE: | 823 case BNE: |
| 1038 Format(instr, "bne 'rs, 'rt, 'imm16u"); | 824 Format(instr, "bne 'rs, 'rt, 'imm16u"); |
| 1039 break; | 825 break; |
| 1040 case BLEZ: | 826 case BLEZ: |
| 1041 if ((instr->RtFieldRaw() == 0) | 827 Format(instr, "blez 'rs, 'imm16u"); |
| 1042 && (instr->RsFieldRaw() != 0)) { | |
| 1043 Format(instr, "blez 'rs, 'imm16u"); | |
| 1044 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) | |
| 1045 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { | |
| 1046 Format(instr, "bgeuc 'rs, 'rt, 'imm16u"); | |
| 1047 } else if ((instr->RtFieldRaw() == instr->RsFieldRaw()) | |
| 1048 && (instr->RtFieldRaw() != 0)) { | |
| 1049 Format(instr, "bgezalc 'rs, 'imm16u"); | |
| 1050 } else if ((instr->RsFieldRaw() == 0) | |
| 1051 && (instr->RtFieldRaw() != 0)) { | |
| 1052 Format(instr, "blezalc 'rs, 'imm16u"); | |
| 1053 } else { | |
| 1054 UNREACHABLE(); | |
| 1055 } | |
| 1056 break; | 828 break; |
| 1057 case BGTZ: | 829 case BGTZ: |
| 1058 if ((instr->RtFieldRaw() == 0) | 830 Format(instr, "bgtz 'rs, 'imm16u"); |
| 1059 && (instr->RsFieldRaw() != 0)) { | |
| 1060 Format(instr, "bgtz 'rs, 'imm16u"); | |
| 1061 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) | |
| 1062 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { | |
| 1063 Format(instr, "bltuc 'rs, 'rt, 'imm16u"); | |
| 1064 } else if ((instr->RtFieldRaw() == instr->RsFieldRaw()) | |
| 1065 && (instr->RtFieldRaw() != 0)) { | |
| 1066 Format(instr, "bltzalc 'rt, 'imm16u"); | |
| 1067 } else if ((instr->RsFieldRaw() == 0) | |
| 1068 && (instr->RtFieldRaw() != 0)) { | |
| 1069 Format(instr, "bgtzalc 'rt, 'imm16u"); | |
| 1070 } else { | |
| 1071 UNREACHABLE(); | |
| 1072 } | |
| 1073 break; | |
| 1074 case BLEZL: | |
| 1075 if ((instr->RtFieldRaw() == instr->RsFieldRaw()) | |
| 1076 && (instr->RtFieldRaw() != 0)) { | |
| 1077 Format(instr, "bgezc 'rt, 'imm16u"); | |
| 1078 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) | |
| 1079 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { | |
| 1080 Format(instr, "bgec 'rs, 'rt, 'imm16u"); | |
| 1081 } else if ((instr->RsFieldRaw() == 0) | |
| 1082 && (instr->RtFieldRaw() != 0)) { | |
| 1083 Format(instr, "blezc 'rt, 'imm16u"); | |
| 1084 } else { | |
| 1085 UNREACHABLE(); | |
| 1086 } | |
| 1087 break; | |
| 1088 case BGTZL: | |
| 1089 if ((instr->RtFieldRaw() == instr->RsFieldRaw()) | |
| 1090 && (instr->RtFieldRaw() != 0)) { | |
| 1091 Format(instr, "bltzc 'rt, 'imm16u"); | |
| 1092 } else if ((instr->RtFieldRaw() != instr->RsFieldRaw()) | |
| 1093 && (instr->RsFieldRaw() != 0) && (instr->RtFieldRaw() != 0)) { | |
| 1094 Format(instr, "bltc 'rs, 'rt, 'imm16u"); | |
| 1095 } else if ((instr->RsFieldRaw() == 0) | |
| 1096 && (instr->RtFieldRaw() != 0)) { | |
| 1097 Format(instr, "bgtzc 'rt, 'imm16u"); | |
| 1098 } else { | |
| 1099 UNREACHABLE(); | |
| 1100 } | |
| 1101 break; | |
| 1102 case BEQZC: | |
| 1103 if (instr->RsFieldRaw() != 0) { | |
| 1104 Format(instr, "beqzc 'rs, 'imm21x"); | |
| 1105 } | |
| 1106 break; | |
| 1107 case BNEZC: | |
| 1108 if (instr->RsFieldRaw() != 0) { | |
| 1109 Format(instr, "bnezc 'rs, 'imm21x"); | |
| 1110 } | |
| 1111 break; | 831 break; |
| 1112 // ------------- Arithmetic instructions. | 832 // ------------- Arithmetic instructions. |
| 1113 case ADDI: | 833 case ADDI: |
| 1114 if (!IsMipsArchVariant(kMips32r6)) { | 834 Format(instr, "addi 'rt, 'rs, 'imm16s"); |
| 1115 Format(instr, "addi 'rt, 'rs, 'imm16s"); | |
| 1116 } else { | |
| 1117 // Check if BOVC or BEQC instruction. | |
| 1118 if (instr->RsFieldRaw() >= instr->RtFieldRaw()) { | |
| 1119 Format(instr, "bovc 'rs, 'rt, 'imm16s"); | |
| 1120 } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) { | |
| 1121 Format(instr, "beqc 'rs, 'rt, 'imm16s"); | |
| 1122 } else { | |
| 1123 UNREACHABLE(); | |
| 1124 } | |
| 1125 } | |
| 1126 break; | |
| 1127 case DADDI: | |
| 1128 if (IsMipsArchVariant(kMips32r6)) { | |
| 1129 // Check if BNVC or BNEC instruction. | |
| 1130 if (instr->RsFieldRaw() >= instr->RtFieldRaw()) { | |
| 1131 Format(instr, "bnvc 'rs, 'rt, 'imm16s"); | |
| 1132 } else if (instr->RsFieldRaw() < instr->RtFieldRaw()) { | |
| 1133 Format(instr, "bnec 'rs, 'rt, 'imm16s"); | |
| 1134 } else { | |
| 1135 UNREACHABLE(); | |
| 1136 } | |
| 1137 } | |
| 1138 break; | 835 break; |
| 1139 case ADDIU: | 836 case ADDIU: |
| 1140 Format(instr, "addiu 'rt, 'rs, 'imm16s"); | 837 Format(instr, "addiu 'rt, 'rs, 'imm16s"); |
| 1141 break; | 838 break; |
| 1142 case SLTI: | 839 case SLTI: |
| 1143 Format(instr, "slti 'rt, 'rs, 'imm16s"); | 840 Format(instr, "slti 'rt, 'rs, 'imm16s"); |
| 1144 break; | 841 break; |
| 1145 case SLTIU: | 842 case SLTIU: |
| 1146 Format(instr, "sltiu 'rt, 'rs, 'imm16u"); | 843 Format(instr, "sltiu 'rt, 'rs, 'imm16u"); |
| 1147 break; | 844 break; |
| 1148 case ANDI: | 845 case ANDI: |
| 1149 Format(instr, "andi 'rt, 'rs, 'imm16x"); | 846 Format(instr, "andi 'rt, 'rs, 'imm16x"); |
| 1150 break; | 847 break; |
| 1151 case ORI: | 848 case ORI: |
| 1152 Format(instr, "ori 'rt, 'rs, 'imm16x"); | 849 Format(instr, "ori 'rt, 'rs, 'imm16x"); |
| 1153 break; | 850 break; |
| 1154 case XORI: | 851 case XORI: |
| 1155 Format(instr, "xori 'rt, 'rs, 'imm16x"); | 852 Format(instr, "xori 'rt, 'rs, 'imm16x"); |
| 1156 break; | 853 break; |
| 1157 case LUI: | 854 case LUI: |
| 1158 if (!IsMipsArchVariant(kMips32r6)) { | 855 Format(instr, "lui 'rt, 'imm16x"); |
| 1159 Format(instr, "lui 'rt, 'imm16x"); | |
| 1160 } else { | |
| 1161 if (instr->RsValue() != 0) { | |
| 1162 Format(instr, "aui 'rt, 'imm16x"); | |
| 1163 } else { | |
| 1164 Format(instr, "lui 'rt, 'imm16x"); | |
| 1165 } | |
| 1166 } | |
| 1167 break; | 856 break; |
| 1168 // ------------- Memory instructions. | 857 // ------------- Memory instructions. |
| 1169 case LB: | 858 case LB: |
| 1170 Format(instr, "lb 'rt, 'imm16s('rs)"); | 859 Format(instr, "lb 'rt, 'imm16s('rs)"); |
| 1171 break; | 860 break; |
| 1172 case LH: | 861 case LH: |
| 1173 Format(instr, "lh 'rt, 'imm16s('rs)"); | 862 Format(instr, "lh 'rt, 'imm16s('rs)"); |
| 1174 break; | 863 break; |
| 1175 case LWL: | 864 case LWL: |
| 1176 Format(instr, "lwl 'rt, 'imm16s('rs)"); | 865 Format(instr, "lwl 'rt, 'imm16s('rs)"); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1211 case LDC1: | 900 case LDC1: |
| 1212 Format(instr, "ldc1 'ft, 'imm16s('rs)"); | 901 Format(instr, "ldc1 'ft, 'imm16s('rs)"); |
| 1213 break; | 902 break; |
| 1214 case SWC1: | 903 case SWC1: |
| 1215 Format(instr, "swc1 'ft, 'imm16s('rs)"); | 904 Format(instr, "swc1 'ft, 'imm16s('rs)"); |
| 1216 break; | 905 break; |
| 1217 case SDC1: | 906 case SDC1: |
| 1218 Format(instr, "sdc1 'ft, 'imm16s('rs)"); | 907 Format(instr, "sdc1 'ft, 'imm16s('rs)"); |
| 1219 break; | 908 break; |
| 1220 default: | 909 default: |
| 1221 printf("a 0x%x \n", instr->OpcodeFieldRaw()); | |
| 1222 UNREACHABLE(); | 910 UNREACHABLE(); |
| 1223 break; | 911 break; |
| 1224 } | 912 } |
| 1225 } | 913 } |
| 1226 | 914 |
| 1227 | 915 |
| 1228 void Decoder::DecodeTypeJump(Instruction* instr) { | 916 void Decoder::DecodeTypeJump(Instruction* instr) { |
| 1229 switch (instr->OpcodeFieldRaw()) { | 917 switch (instr->OpcodeFieldRaw()) { |
| 1230 case J: | 918 case J: |
| 1231 Format(instr, "j 'imm26x"); | 919 Format(instr, "j 'imm26x"); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1344 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1032 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1345 } | 1033 } |
| 1346 } | 1034 } |
| 1347 | 1035 |
| 1348 | 1036 |
| 1349 #undef UNSUPPORTED | 1037 #undef UNSUPPORTED |
| 1350 | 1038 |
| 1351 } // namespace disasm | 1039 } // namespace disasm |
| 1352 | 1040 |
| 1353 #endif // V8_TARGET_ARCH_MIPS | 1041 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |