| 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 99 int FormatOption(Instruction* instr, const char* option); | 99 int FormatOption(Instruction* instr, const char* option); |
| 100 void Format(Instruction* instr, const char* format); | 100 void Format(Instruction* instr, const char* format); |
| 101 void Unknown(Instruction* instr); | 101 void Unknown(Instruction* instr); |
| 102 | 102 |
| 103 | 103 |
| 104 // Each of these functions decodes one particular instruction type. | 104 // Each of these functions decodes one particular instruction type. |
| 105 bool DecodeTypeRegisterRsType(Instruction* instr); | 105 bool DecodeTypeRegisterRsType(Instruction* instr); |
| 106 void DecodeTypeRegisterSRsType(Instruction* instr); | 106 void DecodeTypeRegisterSRsType(Instruction* instr); |
| 107 void DecodeTypeRegisterDRsType(Instruction* instr); | 107 void DecodeTypeRegisterDRsType(Instruction* instr); |
| 108 void DecodeTypeRegisterLRsType(Instruction* instr); | 108 void DecodeTypeRegisterLRsType(Instruction* instr); |
| 109 void DecodeTypeRegisterWRsType(Instruction* instr); |
| 109 void DecodeTypeRegisterSPECIAL(Instruction* instr); | 110 void DecodeTypeRegisterSPECIAL(Instruction* instr); |
| 110 void DecodeTypeRegisterSPECIAL2(Instruction* instr); | 111 void DecodeTypeRegisterSPECIAL2(Instruction* instr); |
| 111 void DecodeTypeRegisterSPECIAL3(Instruction* instr); | 112 void DecodeTypeRegisterSPECIAL3(Instruction* instr); |
| 112 void DecodeTypeRegister(Instruction* instr); | 113 void DecodeTypeRegister(Instruction* instr); |
| 113 void DecodeTypeImmediate(Instruction* instr); | 114 void DecodeTypeImmediate(Instruction* instr); |
| 114 void DecodeTypeJump(Instruction* instr); | 115 void DecodeTypeJump(Instruction* instr); |
| 115 | 116 |
| 116 const disasm::NameConverter& converter_; | 117 const disasm::NameConverter& converter_; |
| 117 v8::internal::Vector<char> out_buffer_; | 118 v8::internal::Vector<char> out_buffer_; |
| 118 int out_buffer_pos_; | 119 int out_buffer_pos_; |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 | 480 |
| 480 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 481 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
| 481 // which will just print "unknown" of the instruction bits. | 482 // which will just print "unknown" of the instruction bits. |
| 482 void Decoder::Unknown(Instruction* instr) { | 483 void Decoder::Unknown(Instruction* instr) { |
| 483 Format(instr, "unknown"); | 484 Format(instr, "unknown"); |
| 484 } | 485 } |
| 485 | 486 |
| 486 | 487 |
| 487 bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) { | 488 bool Decoder::DecodeTypeRegisterRsType(Instruction* instr) { |
| 488 switch (instr->FunctionFieldRaw()) { | 489 switch (instr->FunctionFieldRaw()) { |
| 490 case MIN: |
| 491 Format(instr, "min.'t 'fd, 'fs, 'ft"); |
| 492 break; |
| 493 case MAX: |
| 494 Format(instr, "max.'t 'fd, 'fs, 'ft"); |
| 495 break; |
| 496 case MINA: |
| 497 Format(instr, "mina.'t 'fd, 'fs, 'ft"); |
| 498 break; |
| 499 case MAXA: |
| 500 Format(instr, "maxa.'t 'fd, 'fs, 'ft"); |
| 501 break; |
| 502 case SEL: |
| 503 Format(instr, "sel.'t 'fd, 'fs, 'ft"); |
| 504 break; |
| 505 case SELEQZ_C: |
| 506 Format(instr, "seleqz.'t 'fd, 'fs, 'ft"); |
| 507 break; |
| 508 case SELNEZ_C: |
| 509 Format(instr, "selnez.'t 'fd, 'fs, 'ft"); |
| 510 break; |
| 489 case ADD_D: | 511 case ADD_D: |
| 490 Format(instr, "add.'t 'fd, 'fs, 'ft"); | 512 Format(instr, "add.'t 'fd, 'fs, 'ft"); |
| 491 break; | 513 break; |
| 492 case SUB_D: | 514 case SUB_D: |
| 493 Format(instr, "sub.'t 'fd, 'fs, 'ft"); | 515 Format(instr, "sub.'t 'fd, 'fs, 'ft"); |
| 494 break; | 516 break; |
| 495 case MUL_D: | 517 case MUL_D: |
| 496 Format(instr, "mul.'t 'fd, 'fs, 'ft"); | 518 Format(instr, "mul.'t 'fd, 'fs, 'ft"); |
| 497 break; | 519 break; |
| 498 case DIV_D: | 520 case DIV_D: |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 623 break; | 645 break; |
| 624 case CMP_NE: | 646 case CMP_NE: |
| 625 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); | 647 Format(instr, "cmp.ne.d 'fd, 'fs, 'ft"); |
| 626 break; | 648 break; |
| 627 default: | 649 default: |
| 628 UNREACHABLE(); | 650 UNREACHABLE(); |
| 629 } | 651 } |
| 630 } | 652 } |
| 631 | 653 |
| 632 | 654 |
| 655 void Decoder::DecodeTypeRegisterWRsType(Instruction* instr) { |
| 656 switch (instr->FunctionValue()) { |
| 657 case CVT_S_W: // Convert word to float (single). |
| 658 Format(instr, "cvt.s.w 'fd, 'fs"); |
| 659 break; |
| 660 case CVT_D_W: // Convert word to double. |
| 661 Format(instr, "cvt.d.w 'fd, 'fs"); |
| 662 break; |
| 663 case CMP_AF: |
| 664 Format(instr, "cmp.af.s 'fd, 'fs, 'ft"); |
| 665 break; |
| 666 case CMP_UN: |
| 667 Format(instr, "cmp.un.s 'fd, 'fs, 'ft"); |
| 668 break; |
| 669 case CMP_EQ: |
| 670 Format(instr, "cmp.eq.s 'fd, 'fs, 'ft"); |
| 671 break; |
| 672 case CMP_UEQ: |
| 673 Format(instr, "cmp.ueq.s 'fd, 'fs, 'ft"); |
| 674 break; |
| 675 case CMP_LT: |
| 676 Format(instr, "cmp.lt.s 'fd, 'fs, 'ft"); |
| 677 break; |
| 678 case CMP_ULT: |
| 679 Format(instr, "cmp.ult.s 'fd, 'fs, 'ft"); |
| 680 break; |
| 681 case CMP_LE: |
| 682 Format(instr, "cmp.le.s 'fd, 'fs, 'ft"); |
| 683 break; |
| 684 case CMP_ULE: |
| 685 Format(instr, "cmp.ule.s 'fd, 'fs, 'ft"); |
| 686 break; |
| 687 case CMP_OR: |
| 688 Format(instr, "cmp.or.s 'fd, 'fs, 'ft"); |
| 689 break; |
| 690 case CMP_UNE: |
| 691 Format(instr, "cmp.une.s 'fd, 'fs, 'ft"); |
| 692 break; |
| 693 case CMP_NE: |
| 694 Format(instr, "cmp.ne.s 'fd, 'fs, 'ft"); |
| 695 break; |
| 696 default: |
| 697 UNREACHABLE(); |
| 698 } |
| 699 } |
| 700 |
| 701 |
| 633 void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) { | 702 void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) { |
| 634 switch (instr->FunctionFieldRaw()) { | 703 switch (instr->FunctionFieldRaw()) { |
| 635 case JR: | 704 case JR: |
| 636 Format(instr, "jr 'rs"); | 705 Format(instr, "jr 'rs"); |
| 637 break; | 706 break; |
| 638 case JALR: | 707 case JALR: |
| 639 Format(instr, "jalr 'rs"); | 708 Format(instr, "jalr 'rs"); |
| 640 break; | 709 break; |
| 641 case SLL: | 710 case SLL: |
| 642 if (0x0 == static_cast<int>(instr->InstructionBits())) | 711 if (0x0 == static_cast<int>(instr->InstructionBits())) |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 Format(instr, "movn 'rd, 'rs, 'rt"); | 867 Format(instr, "movn 'rd, 'rs, 'rt"); |
| 799 break; | 868 break; |
| 800 case MOVCI: | 869 case MOVCI: |
| 801 if (instr->Bit(16)) { | 870 if (instr->Bit(16)) { |
| 802 Format(instr, "movt 'rd, 'rs, 'bc"); | 871 Format(instr, "movt 'rd, 'rs, 'bc"); |
| 803 } else { | 872 } else { |
| 804 Format(instr, "movf 'rd, 'rs, 'bc"); | 873 Format(instr, "movf 'rd, 'rs, 'bc"); |
| 805 } | 874 } |
| 806 break; | 875 break; |
| 807 case SELEQZ_S: | 876 case SELEQZ_S: |
| 808 Format(instr, "seleqz 'rs, 'rt, 'rd"); | 877 Format(instr, "seleqz 'rd, 'rs, 'rt"); |
| 809 break; | 878 break; |
| 810 case SELNEZ_S: | 879 case SELNEZ_S: |
| 811 Format(instr, "selnez 'rs, 'rt, 'rd"); | 880 Format(instr, "selnez 'rd, 'rs, 'rt"); |
| 812 break; | 881 break; |
| 813 default: | 882 default: |
| 814 UNREACHABLE(); | 883 UNREACHABLE(); |
| 815 } | 884 } |
| 816 } | 885 } |
| 817 | 886 |
| 818 | 887 |
| 819 void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) { | 888 void Decoder::DecodeTypeRegisterSPECIAL2(Instruction* instr) { |
| 820 switch (instr->FunctionFieldRaw()) { | 889 switch (instr->FunctionFieldRaw()) { |
| 821 case MUL: | 890 case MUL: |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 881 break; | 950 break; |
| 882 case MTHC1: | 951 case MTHC1: |
| 883 Format(instr, "mthc1 'rt, 'fs"); | 952 Format(instr, "mthc1 'rt, 'fs"); |
| 884 break; | 953 break; |
| 885 case S: | 954 case S: |
| 886 DecodeTypeRegisterSRsType(instr); | 955 DecodeTypeRegisterSRsType(instr); |
| 887 break; | 956 break; |
| 888 case D: | 957 case D: |
| 889 DecodeTypeRegisterDRsType(instr); | 958 DecodeTypeRegisterDRsType(instr); |
| 890 break; | 959 break; |
| 891 case W: | |
| 892 switch (instr->FunctionFieldRaw()) { | |
| 893 case CVT_S_W: // Convert word to float (single). | |
| 894 Format(instr, "cvt.s.w 'fd, 'fs"); | |
| 895 break; | |
| 896 case CVT_D_W: // Convert word to double. | |
| 897 Format(instr, "cvt.d.w 'fd, 'fs"); | |
| 898 break; | |
| 899 default: | |
| 900 UNREACHABLE(); | |
| 901 } | |
| 902 break; | |
| 903 case L: | 960 case L: |
| 904 DecodeTypeRegisterLRsType(instr); | 961 DecodeTypeRegisterLRsType(instr); |
| 905 break; | 962 break; |
| 963 case W: |
| 964 DecodeTypeRegisterWRsType(instr); |
| 965 break; |
| 906 case PS: | 966 case PS: |
| 907 UNIMPLEMENTED_MIPS(); | 967 UNIMPLEMENTED_MIPS(); |
| 908 break; | 968 break; |
| 909 default: | 969 default: |
| 910 UNREACHABLE(); | 970 UNREACHABLE(); |
| 911 } | 971 } |
| 912 break; | 972 break; |
| 913 case COP1X: | 973 case COP1X: |
| 914 switch (instr->FunctionFieldRaw()) { | 974 switch (instr->FunctionFieldRaw()) { |
| 915 case MADD_D: | 975 case MADD_D: |
| (...skipping 28 matching lines...) Expand all Loading... |
| 944 } else { | 1004 } else { |
| 945 Format(instr, "bc1f 'bc, 'imm16u"); | 1005 Format(instr, "bc1f 'bc, 'imm16u"); |
| 946 } | 1006 } |
| 947 break; | 1007 break; |
| 948 case BC1EQZ: | 1008 case BC1EQZ: |
| 949 Format(instr, "bc1eqz 'ft, 'imm16u"); | 1009 Format(instr, "bc1eqz 'ft, 'imm16u"); |
| 950 break; | 1010 break; |
| 951 case BC1NEZ: | 1011 case BC1NEZ: |
| 952 Format(instr, "bc1nez 'ft, 'imm16u"); | 1012 Format(instr, "bc1nez 'ft, 'imm16u"); |
| 953 break; | 1013 break; |
| 954 case W: // CMP.S instruction. | |
| 955 switch (instr->FunctionValue()) { | |
| 956 case CMP_AF: | |
| 957 Format(instr, "cmp.af.S 'ft, 'fs, 'fd"); | |
| 958 break; | |
| 959 case CMP_UN: | |
| 960 Format(instr, "cmp.un.S 'ft, 'fs, 'fd"); | |
| 961 break; | |
| 962 case CMP_EQ: | |
| 963 Format(instr, "cmp.eq.S 'ft, 'fs, 'fd"); | |
| 964 break; | |
| 965 case CMP_UEQ: | |
| 966 Format(instr, "cmp.ueq.S 'ft, 'fs, 'fd"); | |
| 967 break; | |
| 968 case CMP_LT: | |
| 969 Format(instr, "cmp.lt.S 'ft, 'fs, 'fd"); | |
| 970 break; | |
| 971 case CMP_ULT: | |
| 972 Format(instr, "cmp.ult.S 'ft, 'fs, 'fd"); | |
| 973 break; | |
| 974 case CMP_LE: | |
| 975 Format(instr, "cmp.le.S 'ft, 'fs, 'fd"); | |
| 976 break; | |
| 977 case CMP_ULE: | |
| 978 Format(instr, "cmp.ule.S 'ft, 'fs, 'fd"); | |
| 979 break; | |
| 980 case CMP_OR: | |
| 981 Format(instr, "cmp.or.S 'ft, 'fs, 'fd"); | |
| 982 break; | |
| 983 case CMP_UNE: | |
| 984 Format(instr, "cmp.une.S 'ft, 'fs, 'fd"); | |
| 985 break; | |
| 986 case CMP_NE: | |
| 987 Format(instr, "cmp.ne.S 'ft, 'fs, 'fd"); | |
| 988 break; | |
| 989 default: | |
| 990 UNREACHABLE(); | |
| 991 } | |
| 992 break; | |
| 993 case L: // CMP.D instruction. | |
| 994 switch (instr->FunctionValue()) { | |
| 995 case CMP_AF: | |
| 996 Format(instr, "cmp.af.D 'ft, 'fs, 'fd"); | |
| 997 break; | |
| 998 case CMP_UN: | |
| 999 Format(instr, "cmp.un.D 'ft, 'fs, 'fd"); | |
| 1000 break; | |
| 1001 case CMP_EQ: | |
| 1002 Format(instr, "cmp.eq.D 'ft, 'fs, 'fd"); | |
| 1003 break; | |
| 1004 case CMP_UEQ: | |
| 1005 Format(instr, "cmp.ueq.D 'ft, 'fs, 'fd"); | |
| 1006 break; | |
| 1007 case CMP_LT: | |
| 1008 Format(instr, "cmp.lt.D 'ft, 'fs, 'fd"); | |
| 1009 break; | |
| 1010 case CMP_ULT: | |
| 1011 Format(instr, "cmp.ult.D 'ft, 'fs, 'fd"); | |
| 1012 break; | |
| 1013 case CMP_LE: | |
| 1014 Format(instr, "cmp.le.D 'ft, 'fs, 'fd"); | |
| 1015 break; | |
| 1016 case CMP_ULE: | |
| 1017 Format(instr, "cmp.ule.D 'ft, 'fs, 'fd"); | |
| 1018 break; | |
| 1019 case CMP_OR: | |
| 1020 Format(instr, "cmp.or.D 'ft, 'fs, 'fd"); | |
| 1021 break; | |
| 1022 case CMP_UNE: | |
| 1023 Format(instr, "cmp.une.D 'ft, 'fs, 'fd"); | |
| 1024 break; | |
| 1025 case CMP_NE: | |
| 1026 Format(instr, "cmp.ne.D 'ft, 'fs, 'fd"); | |
| 1027 break; | |
| 1028 default: | |
| 1029 UNREACHABLE(); | |
| 1030 } | |
| 1031 break; | |
| 1032 case S: | |
| 1033 switch (instr->FunctionValue()) { | |
| 1034 case SEL: | |
| 1035 Format(instr, "sel.S 'ft, 'fs, 'fd"); | |
| 1036 break; | |
| 1037 case SELEQZ_C: | |
| 1038 Format(instr, "seleqz.S 'ft, 'fs, 'fd"); | |
| 1039 break; | |
| 1040 case SELNEZ_C: | |
| 1041 Format(instr, "selnez.S 'ft, 'fs, 'fd"); | |
| 1042 break; | |
| 1043 case MIN: | |
| 1044 Format(instr, "min.S 'ft, 'fs, 'fd"); | |
| 1045 break; | |
| 1046 case MINA: | |
| 1047 Format(instr, "mina.S 'ft, 'fs, 'fd"); | |
| 1048 break; | |
| 1049 case MAX: | |
| 1050 Format(instr, "max.S 'ft, 'fs, 'fd"); | |
| 1051 break; | |
| 1052 case MAXA: | |
| 1053 Format(instr, "maxa.S 'ft, 'fs, 'fd"); | |
| 1054 break; | |
| 1055 default: | |
| 1056 UNREACHABLE(); | |
| 1057 } | |
| 1058 break; | |
| 1059 case D: | |
| 1060 switch (instr->FunctionValue()) { | |
| 1061 case SEL: | |
| 1062 Format(instr, "sel.D 'ft, 'fs, 'fd"); | |
| 1063 break; | |
| 1064 case SELEQZ_C: | |
| 1065 Format(instr, "seleqz.D 'ft, 'fs, 'fd"); | |
| 1066 break; | |
| 1067 case SELNEZ_C: | |
| 1068 Format(instr, "selnez.D 'ft, 'fs, 'fd"); | |
| 1069 break; | |
| 1070 case MIN: | |
| 1071 Format(instr, "min.D 'ft, 'fs, 'fd"); | |
| 1072 break; | |
| 1073 case MINA: | |
| 1074 Format(instr, "mina.D 'ft, 'fs, 'fd"); | |
| 1075 break; | |
| 1076 case MAX: | |
| 1077 Format(instr, "max.D 'ft, 'fs, 'fd"); | |
| 1078 break; | |
| 1079 case MAXA: | |
| 1080 Format(instr, "maxa.D 'ft, 'fs, 'fd"); | |
| 1081 break; | |
| 1082 default: | |
| 1083 UNREACHABLE(); | |
| 1084 } | |
| 1085 break; | |
| 1086 default: | 1014 default: |
| 1087 UNREACHABLE(); | 1015 UNREACHABLE(); |
| 1088 } | 1016 } |
| 1089 | 1017 |
| 1090 break; // Case COP1. | 1018 break; // Case COP1. |
| 1091 // ------------- REGIMM class. | 1019 // ------------- REGIMM class. |
| 1092 case REGIMM: | 1020 case REGIMM: |
| 1093 switch (instr->RtFieldRaw()) { | 1021 switch (instr->RtFieldRaw()) { |
| 1094 case BLTZ: | 1022 case BLTZ: |
| 1095 Format(instr, "bltz 'rs, 'imm16u"); | 1023 Format(instr, "bltz 'rs, 'imm16u"); |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1424 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1352 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 1425 } | 1353 } |
| 1426 } | 1354 } |
| 1427 | 1355 |
| 1428 | 1356 |
| 1429 #undef UNSUPPORTED | 1357 #undef UNSUPPORTED |
| 1430 | 1358 |
| 1431 } // namespace disasm | 1359 } // namespace disasm |
| 1432 | 1360 |
| 1433 #endif // V8_TARGET_ARCH_MIPS | 1361 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |