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 |