OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 void DecodeType3(Instr* instr); | 122 void DecodeType3(Instr* instr); |
123 void DecodeType4(Instr* instr); | 123 void DecodeType4(Instr* instr); |
124 void DecodeType5(Instr* instr); | 124 void DecodeType5(Instr* instr); |
125 void DecodeType6(Instr* instr); | 125 void DecodeType6(Instr* instr); |
126 void DecodeType7(Instr* instr); | 126 void DecodeType7(Instr* instr); |
127 void DecodeUnconditional(Instr* instr); | 127 void DecodeUnconditional(Instr* instr); |
128 // For VFP support. | 128 // For VFP support. |
129 void DecodeTypeVFP(Instr* instr); | 129 void DecodeTypeVFP(Instr* instr); |
130 void DecodeType6CoprocessorIns(Instr* instr); | 130 void DecodeType6CoprocessorIns(Instr* instr); |
131 | 131 |
| 132 void DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr); |
| 133 void DecodeVCMP(Instr* instr); |
| 134 void DecodeVCVTBetweenDoubleAndSingle(Instr* instr); |
| 135 void DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr); |
132 | 136 |
133 const disasm::NameConverter& converter_; | 137 const disasm::NameConverter& converter_; |
134 v8::internal::Vector<char> out_buffer_; | 138 v8::internal::Vector<char> out_buffer_; |
135 int out_buffer_pos_; | 139 int out_buffer_pos_; |
136 | 140 |
137 DISALLOW_COPY_AND_ASSIGN(Decoder); | 141 DISALLOW_COPY_AND_ASSIGN(Decoder); |
138 }; | 142 }; |
139 | 143 |
140 | 144 |
141 // Support for assertions in the Decoder formatting functions. | 145 // Support for assertions in the Decoder formatting functions. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 } | 178 } |
175 | 179 |
176 | 180 |
177 // Print the register name according to the active name converter. | 181 // Print the register name according to the active name converter. |
178 void Decoder::PrintRegister(int reg) { | 182 void Decoder::PrintRegister(int reg) { |
179 Print(converter_.NameOfCPURegister(reg)); | 183 Print(converter_.NameOfCPURegister(reg)); |
180 } | 184 } |
181 | 185 |
182 // Print the VFP S register name according to the active name converter. | 186 // Print the VFP S register name according to the active name converter. |
183 void Decoder::PrintSRegister(int reg) { | 187 void Decoder::PrintSRegister(int reg) { |
184 Print(assembler::arm::VFPRegisters::Name(reg)); | 188 Print(assembler::arm::VFPRegisters::Name(reg, false)); |
185 } | 189 } |
186 | 190 |
187 // Print the VFP D register name according to the active name converter. | 191 // Print the VFP D register name according to the active name converter. |
188 void Decoder::PrintDRegister(int reg) { | 192 void Decoder::PrintDRegister(int reg) { |
189 Print(assembler::arm::VFPRegisters::Name(reg + 32)); | 193 Print(assembler::arm::VFPRegisters::Name(reg, true)); |
190 } | 194 } |
191 | 195 |
192 | 196 |
193 // These shift names are defined in a way to match the native disassembler | 197 // These shift names are defined in a way to match the native disassembler |
194 // formatting. See for example the command "objdump -d <binary file>". | 198 // formatting. See for example the command "objdump -d <binary file>". |
195 static const char* shift_names[max_shift] = { | 199 static const char* shift_names[max_shift] = { |
196 "lsl", "lsr", "asr", "ror" | 200 "lsl", "lsr", "asr", "ror" |
197 }; | 201 }; |
198 | 202 |
199 | 203 |
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 // vcvt: Dd = Sm | 927 // vcvt: Dd = Sm |
924 // vcvt: Sd = Dm | 928 // vcvt: Sd = Dm |
925 // Dd = vadd(Dn, Dm) | 929 // Dd = vadd(Dn, Dm) |
926 // Dd = vsub(Dn, Dm) | 930 // Dd = vsub(Dn, Dm) |
927 // Dd = vmul(Dn, Dm) | 931 // Dd = vmul(Dn, Dm) |
928 // Dd = vdiv(Dn, Dm) | 932 // Dd = vdiv(Dn, Dm) |
929 // vcmp(Dd, Dm) | 933 // vcmp(Dd, Dm) |
930 // VMRS | 934 // VMRS |
931 void Decoder::DecodeTypeVFP(Instr* instr) { | 935 void Decoder::DecodeTypeVFP(Instr* instr) { |
932 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) ); | 936 ASSERT((instr->TypeField() == 7) && (instr->Bit(24) == 0x0) ); |
| 937 ASSERT(instr->Bits(11, 9) == 0x5); |
933 | 938 |
934 if (instr->Bit(23) == 1) { | 939 if (instr->Bit(4) == 0) { |
935 if ((instr->Bits(21, 19) == 0x7) && | 940 if (instr->Opc1Field() == 0x7) { |
936 (instr->Bits(18, 16) == 0x5) && | 941 // Other data processing instructions |
937 (instr->Bits(11, 9) == 0x5) && | 942 if ((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)) { |
938 (instr->Bit(8) == 1) && | 943 DecodeVCVTBetweenDoubleAndSingle(instr); |
939 (instr->Bit(6) == 1) && | 944 } else if ((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) { |
940 (instr->Bit(4) == 0)) { | 945 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
941 Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm"); | 946 } else if (((instr->Opc2Field() >> 1) == 0x6) && |
942 } else if ((instr->Bits(21, 19) == 0x7) && | 947 (instr->Opc3Field() & 0x1)) { |
943 (instr->Bits(18, 16) == 0x0) && | 948 DecodeVCVTBetweenFloatingPointAndInteger(instr); |
944 (instr->Bits(11, 9) == 0x5) && | 949 } else if (((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && |
945 (instr->Bit(8) == 1) && | 950 (instr->Opc3Field() & 0x1)) { |
946 (instr->Bit(7) == 1) && | 951 DecodeVCMP(instr); |
947 (instr->Bit(6) == 1) && | 952 } else { |
948 (instr->Bit(4) == 0)) { | 953 Unknown(instr); // Not used by V8. |
949 Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm"); | 954 } |
950 } else if ((instr->Bit(21) == 0x0) && | 955 } else if (instr->Opc1Field() == 0x3) { |
951 (instr->Bit(20) == 0x0) && | 956 if (instr->SzField() == 0x1) { |
952 (instr->Bits(11, 9) == 0x5) && | 957 if (instr->Opc3Field() & 0x1) { |
953 (instr->Bit(8) == 1) && | 958 Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm"); |
954 (instr->Bit(6) == 0) && | 959 } else { |
955 (instr->Bit(4) == 0)) { | 960 Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm"); |
| 961 } |
| 962 } else { |
| 963 Unknown(instr); // Not used by V8. |
| 964 } |
| 965 } else if ((instr->Opc1Field() == 0x2) && !(instr->Opc3Field() & 0x1)) { |
| 966 if (instr->SzField() == 0x1) { |
| 967 Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm"); |
| 968 } else { |
| 969 Unknown(instr); // Not used by V8. |
| 970 } |
| 971 } else if ((instr->Opc1Field() == 0x4) && !(instr->Opc3Field() & 0x1)) { |
| 972 if (instr->SzField() == 0x1) { |
956 Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm"); | 973 Format(instr, "vdiv.f64'cond 'Dd, 'Dn, 'Dm"); |
957 } else if ((instr->Bits(21, 20) == 0x3) && | 974 } else { |
958 (instr->Bits(19, 16) == 0x4) && | 975 Unknown(instr); // Not used by V8. |
959 (instr->Bits(11, 9) == 0x5) && | 976 } |
960 (instr->Bit(8) == 0x1) && | |
961 (instr->Bit(6) == 0x1) && | |
962 (instr->Bit(4) == 0x0)) { | |
963 Format(instr, "vcmp.f64'cond 'Dd, 'Dm"); | |
964 } else if ((instr->Bits(23, 20) == 0xF) && | |
965 (instr->Bits(19, 16) == 0x1) && | |
966 (instr->Bits(11, 8) == 0xA) && | |
967 (instr->Bits(7, 5) == 0x0) && | |
968 (instr->Bit(4) == 0x1) && | |
969 (instr->Bits(3, 0) == 0x0)) { | |
970 if (instr->Bits(15, 12) == 0xF) | |
971 Format(instr, "vmrs'cond APSR, FPSCR"); | |
972 else | |
973 Unknown(instr); // Not used by V8. | |
974 } else { | |
975 Unknown(instr); // Not used by V8. | |
976 } | |
977 } else if (instr->Bit(21) == 1) { | |
978 if ((instr->Bit(20) == 0x1) && | |
979 (instr->Bits(11, 9) == 0x5) && | |
980 (instr->Bit(8) == 0x1) && | |
981 (instr->Bit(6) == 0) && | |
982 (instr->Bit(4) == 0)) { | |
983 Format(instr, "vadd.f64'cond 'Dd, 'Dn, 'Dm"); | |
984 } else if ((instr->Bit(20) == 0x1) && | |
985 (instr->Bits(11, 9) == 0x5) && | |
986 (instr->Bit(8) == 0x1) && | |
987 (instr->Bit(6) == 1) && | |
988 (instr->Bit(4) == 0)) { | |
989 Format(instr, "vsub.f64'cond 'Dd, 'Dn, 'Dm"); | |
990 } else if ((instr->Bit(20) == 0x0) && | |
991 (instr->Bits(11, 9) == 0x5) && | |
992 (instr->Bit(8) == 0x1) && | |
993 (instr->Bit(6) == 0) && | |
994 (instr->Bit(4) == 0)) { | |
995 Format(instr, "vmul.f64'cond 'Dd, 'Dn, 'Dm"); | |
996 } else { | 977 } else { |
997 Unknown(instr); // Not used by V8. | 978 Unknown(instr); // Not used by V8. |
998 } | 979 } |
999 } else { | 980 } else { |
1000 if ((instr->Bit(20) == 0x0) && | 981 if ((instr->VCField() == 0x0) && |
1001 (instr->Bits(11, 8) == 0xA) && | 982 (instr->VAField() == 0x0)) { |
1002 (instr->Bits(6, 5) == 0x0) && | 983 DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(instr); |
1003 (instr->Bit(4) == 1) && | 984 } else if ((instr->VLField() == 0x1) && |
1004 (instr->Bits(3, 0) == 0x0)) { | 985 (instr->VCField() == 0x0) && |
1005 Format(instr, "vmov'cond 'Sn, 'rt"); | 986 (instr->VAField() == 0x7) && |
1006 } else if ((instr->Bit(20) == 0x1) && | 987 (instr->Bits(19, 16) == 0x1)) { |
1007 (instr->Bits(11, 8) == 0xA) && | 988 if (instr->Bits(15, 12) == 0xF) |
1008 (instr->Bits(6, 5) == 0x0) && | 989 Format(instr, "vmrs'cond APSR, FPSCR"); |
1009 (instr->Bit(4) == 1) && | 990 else |
1010 (instr->Bits(3, 0) == 0x0)) { | 991 Unknown(instr); // Not used by V8. |
1011 Format(instr, "vmov'cond 'rt, 'Sn"); | |
1012 } else { | 992 } else { |
1013 Unknown(instr); // Not used by V8. | 993 Unknown(instr); // Not used by V8. |
1014 } | 994 } |
1015 } | 995 } |
1016 } | 996 } |
1017 | 997 |
| 998 |
| 999 void Decoder::DecodeVMOVBetweenCoreAndSinglePrecisionRegisters(Instr* instr) { |
| 1000 ASSERT((instr->Bit(4) == 1) && (instr->VCField() == 0x0) && |
| 1001 (instr->VAField() == 0x0)); |
| 1002 |
| 1003 bool to_arm_register = (instr->VLField() == 0x1); |
| 1004 |
| 1005 if (to_arm_register) { |
| 1006 Format(instr, "vmov'cond 'rt, 'Sn"); |
| 1007 } else { |
| 1008 Format(instr, "vmov'cond 'Sn, 'rt"); |
| 1009 } |
| 1010 } |
| 1011 |
| 1012 |
| 1013 void Decoder::DecodeVCMP(Instr* instr) { |
| 1014 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); |
| 1015 ASSERT(((instr->Opc2Field() == 0x4) || (instr->Opc2Field() == 0x5)) && |
| 1016 (instr->Opc3Field() & 0x1)); |
| 1017 |
| 1018 // Comparison. |
| 1019 bool dp_operation = (instr->SzField() == 1); |
| 1020 bool raise_exception_for_qnan = (instr->Bit(7) == 0x1); |
| 1021 |
| 1022 if (dp_operation && !raise_exception_for_qnan) { |
| 1023 Format(instr, "vcmp.f64'cond 'Dd, 'Dm"); |
| 1024 } else { |
| 1025 Unknown(instr); // Not used by V8. |
| 1026 } |
| 1027 } |
| 1028 |
| 1029 |
| 1030 void Decoder::DecodeVCVTBetweenDoubleAndSingle(Instr* instr) { |
| 1031 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); |
| 1032 ASSERT((instr->Opc2Field() == 0x7) && (instr->Opc3Field() == 0x3)); |
| 1033 |
| 1034 bool double_to_single = (instr->SzField() == 1); |
| 1035 |
| 1036 if (double_to_single) { |
| 1037 Format(instr, "vcvt.f32.f64'cond 'Sd, 'Dm"); |
| 1038 } else { |
| 1039 Format(instr, "vcvt.f64.f32'cond 'Dd, 'Sm"); |
| 1040 } |
| 1041 } |
| 1042 |
| 1043 |
| 1044 void Decoder::DecodeVCVTBetweenFloatingPointAndInteger(Instr* instr) { |
| 1045 ASSERT((instr->Bit(4) == 0) && (instr->Opc1Field() == 0x7)); |
| 1046 ASSERT(((instr->Opc2Field() == 0x8) && (instr->Opc3Field() & 0x1)) || |
| 1047 (((instr->Opc2Field() >> 1) == 0x6) && (instr->Opc3Field() & 0x1))); |
| 1048 |
| 1049 bool to_integer = (instr->Bit(18) == 1); |
| 1050 bool dp_operation = (instr->SzField() == 1); |
| 1051 if (to_integer) { |
| 1052 bool unsigned_integer = (instr->Bit(16) == 0); |
| 1053 |
| 1054 if (dp_operation) { |
| 1055 if (unsigned_integer) { |
| 1056 Format(instr, "vcvt.u32.f64'cond 'Sd, 'Dm"); |
| 1057 } else { |
| 1058 Format(instr, "vcvt.s32.f64'cond 'Sd, 'Dm"); |
| 1059 } |
| 1060 } else { |
| 1061 if (unsigned_integer) { |
| 1062 Format(instr, "vcvt.u32.f32'cond 'Sd, 'Sm"); |
| 1063 } else { |
| 1064 Format(instr, "vcvt.s32.f32'cond 'Sd, 'Sm"); |
| 1065 } |
| 1066 } |
| 1067 } else { |
| 1068 bool unsigned_integer = (instr->Bit(7) == 0); |
| 1069 |
| 1070 if (dp_operation) { |
| 1071 if (unsigned_integer) { |
| 1072 Format(instr, "vcvt.f64.u32'cond 'Dd, 'Sm"); |
| 1073 } else { |
| 1074 Format(instr, "vcvt.f64.s32'cond 'Dd, 'Sm"); |
| 1075 } |
| 1076 } else { |
| 1077 if (unsigned_integer) { |
| 1078 Format(instr, "vcvt.f32.u32'cond 'Sd, 'Sm"); |
| 1079 } else { |
| 1080 Format(instr, "vcvt.f32.s32'cond 'Sd, 'Sm"); |
| 1081 } |
| 1082 } |
| 1083 } |
| 1084 } |
| 1085 |
1018 | 1086 |
1019 // Decode Type 6 coprocessor instructions. | 1087 // Decode Type 6 coprocessor instructions. |
1020 // Dm = vmov(Rt, Rt2) | 1088 // Dm = vmov(Rt, Rt2) |
1021 // <Rt, Rt2> = vmov(Dm) | 1089 // <Rt, Rt2> = vmov(Dm) |
1022 // Ddst = MEM(Rbase + 4*offset). | 1090 // Ddst = MEM(Rbase + 4*offset). |
1023 // MEM(Rbase + 4*offset) = Dsrc. | 1091 // MEM(Rbase + 4*offset) = Dsrc. |
1024 void Decoder::DecodeType6CoprocessorIns(Instr* instr) { | 1092 void Decoder::DecodeType6CoprocessorIns(Instr* instr) { |
1025 ASSERT((instr->TypeField() == 6)); | 1093 ASSERT((instr->TypeField() == 6)); |
1026 | 1094 |
1027 if (instr->CoprocessorField() != 0xB) { | 1095 if (instr->CoprocessorField() == 0xA) { |
1028 Unknown(instr); // Not used by V8. | 1096 switch (instr->OpcodeField()) { |
1029 } else { | 1097 case 0x8: |
| 1098 if (instr->HasL()) { |
| 1099 Format(instr, "vldr'cond 'Sd, ['rn - 4*'off8]"); |
| 1100 } else { |
| 1101 Format(instr, "vstr'cond 'Sd, ['rn - 4*'off8]"); |
| 1102 } |
| 1103 break; |
| 1104 case 0xC: |
| 1105 if (instr->HasL()) { |
| 1106 Format(instr, "vldr'cond 'Sd, ['rn + 4*'off8]"); |
| 1107 } else { |
| 1108 Format(instr, "vstr'cond 'Sd, ['rn + 4*'off8]"); |
| 1109 } |
| 1110 break; |
| 1111 default: |
| 1112 Unknown(instr); // Not used by V8. |
| 1113 break; |
| 1114 } |
| 1115 } else if (instr->CoprocessorField() == 0xB) { |
1030 switch (instr->OpcodeField()) { | 1116 switch (instr->OpcodeField()) { |
1031 case 0x2: | 1117 case 0x2: |
1032 // Load and store double to two GP registers | 1118 // Load and store double to two GP registers |
1033 if (instr->Bits(7, 4) != 0x1) { | 1119 if (instr->Bits(7, 4) != 0x1) { |
1034 Unknown(instr); // Not used by V8. | 1120 Unknown(instr); // Not used by V8. |
1035 } else if (instr->HasL()) { | 1121 } else if (instr->HasL()) { |
1036 Format(instr, "vmov'cond 'rt, 'rn, 'Dm"); | 1122 Format(instr, "vmov'cond 'rt, 'rn, 'Dm"); |
1037 } else { | 1123 } else { |
1038 Format(instr, "vmov'cond 'Dm, 'rt, 'rn"); | 1124 Format(instr, "vmov'cond 'Dm, 'rt, 'rn"); |
1039 } | 1125 } |
1040 break; | 1126 break; |
1041 case 0x8: | 1127 case 0x8: |
1042 if (instr->HasL()) { | 1128 if (instr->HasL()) { |
1043 Format(instr, "vldr'cond 'Dd, ['rn - 4*'off8]"); | 1129 Format(instr, "vldr'cond 'Dd, ['rn - 4*'off8]"); |
1044 } else { | 1130 } else { |
1045 Format(instr, "vstr'cond 'Dd, ['rn - 4*'off8]"); | 1131 Format(instr, "vstr'cond 'Dd, ['rn - 4*'off8]"); |
1046 } | 1132 } |
1047 break; | 1133 break; |
1048 case 0xC: | 1134 case 0xC: |
1049 if (instr->HasL()) { | 1135 if (instr->HasL()) { |
1050 Format(instr, "vldr'cond 'Dd, ['rn + 4*'off8]"); | 1136 Format(instr, "vldr'cond 'Dd, ['rn + 4*'off8]"); |
1051 } else { | 1137 } else { |
1052 Format(instr, "vstr'cond 'Dd, ['rn + 4*'off8]"); | 1138 Format(instr, "vstr'cond 'Dd, ['rn + 4*'off8]"); |
1053 } | 1139 } |
1054 break; | 1140 break; |
1055 default: | 1141 default: |
1056 Unknown(instr); // Not used by V8. | 1142 Unknown(instr); // Not used by V8. |
1057 break; | 1143 break; |
1058 } | 1144 } |
| 1145 } else { |
| 1146 UNIMPLEMENTED(); // Not used by V8. |
1059 } | 1147 } |
1060 } | 1148 } |
1061 | 1149 |
1062 | 1150 |
1063 // Disassemble the instruction at *instr_ptr into the output buffer. | 1151 // Disassemble the instruction at *instr_ptr into the output buffer. |
1064 int Decoder::InstructionDecode(byte* instr_ptr) { | 1152 int Decoder::InstructionDecode(byte* instr_ptr) { |
1065 Instr* instr = Instr::At(instr_ptr); | 1153 Instr* instr = Instr::At(instr_ptr); |
1066 // Print raw instruction bytes. | 1154 // Print raw instruction bytes. |
1067 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 1155 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
1068 "%08x ", | 1156 "%08x ", |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1192 buffer[0] = '\0'; | 1280 buffer[0] = '\0'; |
1193 byte* prev_pc = pc; | 1281 byte* prev_pc = pc; |
1194 pc += d.InstructionDecode(buffer, pc); | 1282 pc += d.InstructionDecode(buffer, pc); |
1195 fprintf(f, "%p %08x %s\n", | 1283 fprintf(f, "%p %08x %s\n", |
1196 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1284 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
1197 } | 1285 } |
1198 } | 1286 } |
1199 | 1287 |
1200 | 1288 |
1201 } // namespace disasm | 1289 } // namespace disasm |
OLD | NEW |