OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #include <stdlib.h> | 5 #include <stdlib.h> |
6 #include <cmath> | 6 #include <cmath> |
7 #include <cstdarg> | 7 #include <cstdarg> |
8 #include "v8.h" | 8 #include "v8.h" |
9 | 9 |
10 #if V8_TARGET_ARCH_ARM64 | 10 #if V8_TARGET_ARCH_ARM64 |
(...skipping 805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 } | 816 } |
817 } | 817 } |
818 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) { | 818 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) { |
819 return kSPRegInternalCode; | 819 return kSPRegInternalCode; |
820 } | 820 } |
821 return -1; | 821 return -1; |
822 } | 822 } |
823 | 823 |
824 | 824 |
825 // Helpers --------------------------------------------------------------------- | 825 // Helpers --------------------------------------------------------------------- |
826 int64_t Simulator::AddWithCarry(unsigned reg_size, | 826 template<> struct make_unsigned<int32_t> { |
827 bool set_flags, | 827 typedef uint32_t type; |
828 int64_t src1, | 828 }; |
829 int64_t src2, | 829 |
830 int64_t carry_in) { | 830 |
| 831 template<> struct make_unsigned<int64_t> { |
| 832 typedef uint64_t type; |
| 833 }; |
| 834 |
| 835 |
| 836 template <typename T> |
| 837 T Simulator::AddWithCarry(bool set_flags, |
| 838 T src1, |
| 839 T src2, |
| 840 T carry_in) { |
| 841 typedef typename make_unsigned<T>::type unsignedT; |
831 ASSERT((carry_in == 0) || (carry_in == 1)); | 842 ASSERT((carry_in == 0) || (carry_in == 1)); |
832 ASSERT((reg_size == kXRegSizeInBits) || (reg_size == kWRegSizeInBits)); | |
833 | 843 |
834 uint64_t u1, u2; | 844 T signed_sum = src1 + src2 + carry_in; |
835 int64_t result; | 845 T result = signed_sum; |
836 int64_t signed_sum = src1 + src2 + carry_in; | |
837 | 846 |
838 bool N, Z, C, V; | 847 bool N, Z, C, V; |
| 848 unsignedT u1 = static_cast<unsignedT>(src1); |
| 849 unsignedT u2 = static_cast<unsignedT>(src2); |
839 | 850 |
840 if (reg_size == kWRegSizeInBits) { | 851 // Compute the C flag by comparing the sum to the max unsigned integer. |
841 u1 = static_cast<uint64_t>(src1) & kWRegMask; | 852 C = ((std::numeric_limits<unsignedT>::max() - u1) < (u2 + carry_in)) || |
842 u2 = static_cast<uint64_t>(src2) & kWRegMask; | 853 ((std::numeric_limits<unsignedT>::max() - u1 - carry_in) < u2); |
| 854 // Overflow iff the sign bit is the same for the two inputs and different |
| 855 // for the result. |
| 856 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0); |
843 | 857 |
844 result = signed_sum & kWRegMask; | 858 N = CalcNFlag(result); |
845 // Compute the C flag by comparing the sum to the max unsigned integer. | |
846 C = ((kWMaxUInt - u1) < (u2 + carry_in)) || | |
847 ((kWMaxUInt - u1 - carry_in) < u2); | |
848 // Overflow iff the sign bit is the same for the two inputs and different | |
849 // for the result. | |
850 int64_t s_src1 = src1 << (kXRegSizeInBits - kWRegSizeInBits); | |
851 int64_t s_src2 = src2 << (kXRegSizeInBits - kWRegSizeInBits); | |
852 int64_t s_result = result << (kXRegSizeInBits - kWRegSizeInBits); | |
853 V = ((s_src1 ^ s_src2) >= 0) && ((s_src1 ^ s_result) < 0); | |
854 | |
855 } else { | |
856 u1 = static_cast<uint64_t>(src1); | |
857 u2 = static_cast<uint64_t>(src2); | |
858 | |
859 result = signed_sum; | |
860 // Compute the C flag by comparing the sum to the max unsigned integer. | |
861 C = ((kXMaxUInt - u1) < (u2 + carry_in)) || | |
862 ((kXMaxUInt - u1 - carry_in) < u2); | |
863 // Overflow iff the sign bit is the same for the two inputs and different | |
864 // for the result. | |
865 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0); | |
866 } | |
867 | |
868 N = CalcNFlag(result, reg_size); | |
869 Z = CalcZFlag(result); | 859 Z = CalcZFlag(result); |
870 | 860 |
871 if (set_flags) { | 861 if (set_flags) { |
872 nzcv().SetN(N); | 862 nzcv().SetN(N); |
873 nzcv().SetZ(Z); | 863 nzcv().SetZ(Z); |
874 nzcv().SetC(C); | 864 nzcv().SetC(C); |
875 nzcv().SetV(V); | 865 nzcv().SetV(V); |
876 } | 866 } |
877 return result; | 867 return result; |
878 } | 868 } |
879 | 869 |
880 | 870 |
881 int64_t Simulator::ShiftOperand(unsigned reg_size, | 871 template<typename T> |
882 int64_t value, | 872 void Simulator::AddSubWithCarry(Instruction* instr) { |
883 Shift shift_type, | 873 T op2 = reg<T>(instr->Rm()); |
884 unsigned amount) { | 874 T new_val; |
| 875 |
| 876 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) { |
| 877 op2 = ~op2; |
| 878 } |
| 879 |
| 880 new_val = AddWithCarry<T>(instr->FlagsUpdate(), |
| 881 reg<T>(instr->Rn()), |
| 882 op2, |
| 883 nzcv().C()); |
| 884 |
| 885 set_reg<T>(instr->Rd(), new_val); |
| 886 } |
| 887 |
| 888 template <typename T> |
| 889 T Simulator::ShiftOperand(T value, Shift shift_type, unsigned amount) { |
| 890 typedef typename make_unsigned<T>::type unsignedT; |
| 891 |
885 if (amount == 0) { | 892 if (amount == 0) { |
886 return value; | 893 return value; |
887 } | 894 } |
888 int64_t mask = reg_size == kXRegSizeInBits ? kXRegMask : kWRegMask; | 895 |
889 switch (shift_type) { | 896 switch (shift_type) { |
890 case LSL: | 897 case LSL: |
891 return (value << amount) & mask; | 898 return value << amount; |
892 case LSR: | 899 case LSR: |
893 return static_cast<uint64_t>(value) >> amount; | 900 return static_cast<unsignedT>(value) >> amount; |
894 case ASR: { | 901 case ASR: |
895 // Shift used to restore the sign. | 902 return value >> amount; |
896 unsigned s_shift = kXRegSizeInBits - reg_size; | 903 case ROR: |
897 // Value with its sign restored. | 904 return (static_cast<unsignedT>(value) >> amount) | |
898 int64_t s_value = (value << s_shift) >> s_shift; | 905 ((value & ((1L << amount) - 1L)) << |
899 return (s_value >> amount) & mask; | 906 (sizeof(unsignedT) * 8 - amount)); |
900 } | |
901 case ROR: { | |
902 if (reg_size == kWRegSizeInBits) { | |
903 value &= kWRegMask; | |
904 } | |
905 return (static_cast<uint64_t>(value) >> amount) | | |
906 ((value & ((1L << amount) - 1L)) << (reg_size - amount)); | |
907 } | |
908 default: | 907 default: |
909 UNIMPLEMENTED(); | 908 UNIMPLEMENTED(); |
910 return 0; | 909 return 0; |
911 } | 910 } |
912 } | 911 } |
913 | 912 |
914 | 913 |
915 int64_t Simulator::ExtendValue(unsigned reg_size, | 914 template <typename T> |
916 int64_t value, | 915 T Simulator::ExtendValue(T value, Extend extend_type, unsigned left_shift) { |
917 Extend extend_type, | 916 const unsigned kSignExtendBShift = (sizeof(T) - 1) * 8; |
918 unsigned left_shift) { | 917 const unsigned kSignExtendHShift = (sizeof(T) - 2) * 8; |
| 918 const unsigned kSignExtendWShift = (sizeof(T) - 4) * 8; |
| 919 |
919 switch (extend_type) { | 920 switch (extend_type) { |
920 case UXTB: | 921 case UXTB: |
921 value &= kByteMask; | 922 value &= kByteMask; |
922 break; | 923 break; |
923 case UXTH: | 924 case UXTH: |
924 value &= kHalfWordMask; | 925 value &= kHalfWordMask; |
925 break; | 926 break; |
926 case UXTW: | 927 case UXTW: |
927 value &= kWordMask; | 928 value &= kWordMask; |
928 break; | 929 break; |
929 case SXTB: | 930 case SXTB: |
930 value = (value << 56) >> 56; | 931 value = (value << kSignExtendBShift) >> kSignExtendBShift; |
931 break; | 932 break; |
932 case SXTH: | 933 case SXTH: |
933 value = (value << 48) >> 48; | 934 value = (value << kSignExtendHShift) >> kSignExtendHShift; |
934 break; | 935 break; |
935 case SXTW: | 936 case SXTW: |
936 value = (value << 32) >> 32; | 937 value = (value << kSignExtendWShift) >> kSignExtendWShift; |
937 break; | 938 break; |
938 case UXTX: | 939 case UXTX: |
939 case SXTX: | 940 case SXTX: |
940 break; | 941 break; |
941 default: | 942 default: |
942 UNREACHABLE(); | 943 UNREACHABLE(); |
943 } | 944 } |
944 int64_t mask = (reg_size == kXRegSizeInBits) ? kXRegMask : kWRegMask; | 945 return value << left_shift; |
945 return (value << left_shift) & mask; | |
946 } | 946 } |
947 | 947 |
948 | 948 |
| 949 template <typename T> |
| 950 void Simulator::Extract(Instruction* instr) { |
| 951 unsigned lsb = instr->ImmS(); |
| 952 T op2 = reg<T>(instr->Rm()); |
| 953 T result = op2; |
| 954 |
| 955 if (lsb) { |
| 956 T op1 = reg<T>(instr->Rn()); |
| 957 result = op2 >> lsb | (op1 << ((sizeof(T) * 8) - lsb)); |
| 958 } |
| 959 set_reg<T>(instr->Rd(), result); |
| 960 } |
| 961 |
| 962 |
949 template<> double Simulator::FPDefaultNaN<double>() const { | 963 template<> double Simulator::FPDefaultNaN<double>() const { |
950 return kFP64DefaultNaN; | 964 return kFP64DefaultNaN; |
951 } | 965 } |
952 | 966 |
953 | 967 |
954 template<> float Simulator::FPDefaultNaN<float>() const { | 968 template<> float Simulator::FPDefaultNaN<float>() const { |
955 return kFP32DefaultNaN; | 969 return kFP32DefaultNaN; |
956 } | 970 } |
957 | 971 |
958 | 972 |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1249 case CBNZ_w: take_branch = (wreg(rt) != 0); break; | 1263 case CBNZ_w: take_branch = (wreg(rt) != 0); break; |
1250 case CBNZ_x: take_branch = (xreg(rt) != 0); break; | 1264 case CBNZ_x: take_branch = (xreg(rt) != 0); break; |
1251 default: UNIMPLEMENTED(); | 1265 default: UNIMPLEMENTED(); |
1252 } | 1266 } |
1253 if (take_branch) { | 1267 if (take_branch) { |
1254 set_pc(instr->ImmPCOffsetTarget()); | 1268 set_pc(instr->ImmPCOffsetTarget()); |
1255 } | 1269 } |
1256 } | 1270 } |
1257 | 1271 |
1258 | 1272 |
1259 void Simulator::AddSubHelper(Instruction* instr, int64_t op2) { | 1273 template<typename T> |
1260 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | 1274 void Simulator::AddSubHelper(Instruction* instr, T op2) { |
1261 : kWRegSizeInBits; | |
1262 bool set_flags = instr->FlagsUpdate(); | 1275 bool set_flags = instr->FlagsUpdate(); |
1263 int64_t new_val = 0; | 1276 T new_val = 0; |
1264 Instr operation = instr->Mask(AddSubOpMask); | 1277 Instr operation = instr->Mask(AddSubOpMask); |
1265 | 1278 |
1266 switch (operation) { | 1279 switch (operation) { |
1267 case ADD: | 1280 case ADD: |
1268 case ADDS: { | 1281 case ADDS: { |
1269 new_val = AddWithCarry(reg_size, | 1282 new_val = AddWithCarry<T>(set_flags, |
1270 set_flags, | 1283 reg<T>(instr->Rn(), instr->RnMode()), |
1271 reg(reg_size, instr->Rn(), instr->RnMode()), | 1284 op2); |
1272 op2); | |
1273 break; | 1285 break; |
1274 } | 1286 } |
1275 case SUB: | 1287 case SUB: |
1276 case SUBS: { | 1288 case SUBS: { |
1277 new_val = AddWithCarry(reg_size, | 1289 new_val = AddWithCarry<T>(set_flags, |
1278 set_flags, | 1290 reg<T>(instr->Rn(), instr->RnMode()), |
1279 reg(reg_size, instr->Rn(), instr->RnMode()), | 1291 ~op2, |
1280 ~op2, | 1292 1); |
1281 1); | |
1282 break; | 1293 break; |
1283 } | 1294 } |
1284 default: UNREACHABLE(); | 1295 default: UNREACHABLE(); |
1285 } | 1296 } |
1286 | 1297 |
1287 set_reg(reg_size, instr->Rd(), new_val, instr->RdMode()); | 1298 set_reg<T>(instr->Rd(), new_val, instr->RdMode()); |
1288 } | 1299 } |
1289 | 1300 |
1290 | 1301 |
1291 void Simulator::VisitAddSubShifted(Instruction* instr) { | 1302 void Simulator::VisitAddSubShifted(Instruction* instr) { |
1292 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | 1303 Shift shift_type = static_cast<Shift>(instr->ShiftDP()); |
1293 : kWRegSizeInBits; | 1304 unsigned shift_amount = instr->ImmDPShift(); |
1294 int64_t op2 = ShiftOperand(reg_size, | 1305 |
1295 reg(reg_size, instr->Rm()), | 1306 if (instr->SixtyFourBits()) { |
1296 static_cast<Shift>(instr->ShiftDP()), | 1307 int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount); |
1297 instr->ImmDPShift()); | 1308 AddSubHelper(instr, op2); |
1298 AddSubHelper(instr, op2); | 1309 } else { |
| 1310 int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount); |
| 1311 AddSubHelper(instr, op2); |
| 1312 } |
1299 } | 1313 } |
1300 | 1314 |
1301 | 1315 |
1302 void Simulator::VisitAddSubImmediate(Instruction* instr) { | 1316 void Simulator::VisitAddSubImmediate(Instruction* instr) { |
1303 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0); | 1317 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0); |
1304 AddSubHelper(instr, op2); | 1318 if (instr->SixtyFourBits()) { |
| 1319 AddSubHelper<int64_t>(instr, op2); |
| 1320 } else { |
| 1321 AddSubHelper<int32_t>(instr, op2); |
| 1322 } |
1305 } | 1323 } |
1306 | 1324 |
1307 | 1325 |
1308 void Simulator::VisitAddSubExtended(Instruction* instr) { | 1326 void Simulator::VisitAddSubExtended(Instruction* instr) { |
1309 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | 1327 Extend ext = static_cast<Extend>(instr->ExtendMode()); |
1310 : kWRegSizeInBits; | 1328 unsigned left_shift = instr->ImmExtendShift(); |
1311 int64_t op2 = ExtendValue(reg_size, | 1329 if (instr->SixtyFourBits()) { |
1312 reg(reg_size, instr->Rm()), | 1330 int64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift); |
1313 static_cast<Extend>(instr->ExtendMode()), | 1331 AddSubHelper(instr, op2); |
1314 instr->ImmExtendShift()); | 1332 } else { |
1315 AddSubHelper(instr, op2); | 1333 int32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift); |
| 1334 AddSubHelper(instr, op2); |
| 1335 } |
1316 } | 1336 } |
1317 | 1337 |
1318 | 1338 |
1319 void Simulator::VisitAddSubWithCarry(Instruction* instr) { | 1339 void Simulator::VisitAddSubWithCarry(Instruction* instr) { |
1320 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | 1340 if (instr->SixtyFourBits()) { |
1321 : kWRegSizeInBits; | 1341 AddSubWithCarry<int64_t>(instr); |
1322 int64_t op2 = reg(reg_size, instr->Rm()); | 1342 } else { |
1323 int64_t new_val; | 1343 AddSubWithCarry<int32_t>(instr); |
1324 | |
1325 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) { | |
1326 op2 = ~op2; | |
1327 } | 1344 } |
1328 | |
1329 new_val = AddWithCarry(reg_size, | |
1330 instr->FlagsUpdate(), | |
1331 reg(reg_size, instr->Rn()), | |
1332 op2, | |
1333 nzcv().C()); | |
1334 | |
1335 set_reg(reg_size, instr->Rd(), new_val); | |
1336 } | 1345 } |
1337 | 1346 |
1338 | 1347 |
1339 void Simulator::VisitLogicalShifted(Instruction* instr) { | 1348 void Simulator::VisitLogicalShifted(Instruction* instr) { |
1340 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | |
1341 : kWRegSizeInBits; | |
1342 Shift shift_type = static_cast<Shift>(instr->ShiftDP()); | 1349 Shift shift_type = static_cast<Shift>(instr->ShiftDP()); |
1343 unsigned shift_amount = instr->ImmDPShift(); | 1350 unsigned shift_amount = instr->ImmDPShift(); |
1344 int64_t op2 = ShiftOperand(reg_size, reg(reg_size, instr->Rm()), shift_type, | 1351 |
1345 shift_amount); | 1352 if (instr->SixtyFourBits()) { |
1346 if (instr->Mask(NOT) == NOT) { | 1353 int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount); |
1347 op2 = ~op2; | 1354 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2; |
| 1355 LogicalHelper<int64_t>(instr, op2); |
| 1356 } else { |
| 1357 int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount); |
| 1358 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2; |
| 1359 LogicalHelper<int32_t>(instr, op2); |
1348 } | 1360 } |
1349 LogicalHelper(instr, op2); | |
1350 } | 1361 } |
1351 | 1362 |
1352 | 1363 |
1353 void Simulator::VisitLogicalImmediate(Instruction* instr) { | 1364 void Simulator::VisitLogicalImmediate(Instruction* instr) { |
1354 LogicalHelper(instr, instr->ImmLogical()); | 1365 if (instr->SixtyFourBits()) { |
| 1366 LogicalHelper<int64_t>(instr, instr->ImmLogical()); |
| 1367 } else { |
| 1368 LogicalHelper<int32_t>(instr, instr->ImmLogical()); |
| 1369 } |
1355 } | 1370 } |
1356 | 1371 |
1357 | 1372 |
1358 void Simulator::LogicalHelper(Instruction* instr, int64_t op2) { | 1373 template<typename T> |
1359 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | 1374 void Simulator::LogicalHelper(Instruction* instr, T op2) { |
1360 : kWRegSizeInBits; | 1375 T op1 = reg<T>(instr->Rn()); |
1361 int64_t op1 = reg(reg_size, instr->Rn()); | 1376 T result = 0; |
1362 int64_t result = 0; | |
1363 bool update_flags = false; | 1377 bool update_flags = false; |
1364 | 1378 |
1365 // Switch on the logical operation, stripping out the NOT bit, as it has a | 1379 // Switch on the logical operation, stripping out the NOT bit, as it has a |
1366 // different meaning for logical immediate instructions. | 1380 // different meaning for logical immediate instructions. |
1367 switch (instr->Mask(LogicalOpMask & ~NOT)) { | 1381 switch (instr->Mask(LogicalOpMask & ~NOT)) { |
1368 case ANDS: update_flags = true; // Fall through. | 1382 case ANDS: update_flags = true; // Fall through. |
1369 case AND: result = op1 & op2; break; | 1383 case AND: result = op1 & op2; break; |
1370 case ORR: result = op1 | op2; break; | 1384 case ORR: result = op1 | op2; break; |
1371 case EOR: result = op1 ^ op2; break; | 1385 case EOR: result = op1 ^ op2; break; |
1372 default: | 1386 default: |
1373 UNIMPLEMENTED(); | 1387 UNIMPLEMENTED(); |
1374 } | 1388 } |
1375 | 1389 |
1376 if (update_flags) { | 1390 if (update_flags) { |
1377 nzcv().SetN(CalcNFlag(result, reg_size)); | 1391 nzcv().SetN(CalcNFlag(result)); |
1378 nzcv().SetZ(CalcZFlag(result)); | 1392 nzcv().SetZ(CalcZFlag(result)); |
1379 nzcv().SetC(0); | 1393 nzcv().SetC(0); |
1380 nzcv().SetV(0); | 1394 nzcv().SetV(0); |
1381 } | 1395 } |
1382 | 1396 |
1383 set_reg(reg_size, instr->Rd(), result, instr->RdMode()); | 1397 set_reg<T>(instr->Rd(), result, instr->RdMode()); |
1384 } | 1398 } |
1385 | 1399 |
1386 | 1400 |
1387 void Simulator::VisitConditionalCompareRegister(Instruction* instr) { | 1401 void Simulator::VisitConditionalCompareRegister(Instruction* instr) { |
1388 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | 1402 if (instr->SixtyFourBits()) { |
1389 : kWRegSizeInBits; | 1403 ConditionalCompareHelper(instr, xreg(instr->Rm())); |
1390 ConditionalCompareHelper(instr, reg(reg_size, instr->Rm())); | 1404 } else { |
| 1405 ConditionalCompareHelper(instr, wreg(instr->Rm())); |
| 1406 } |
1391 } | 1407 } |
1392 | 1408 |
1393 | 1409 |
1394 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) { | 1410 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) { |
1395 ConditionalCompareHelper(instr, instr->ImmCondCmp()); | 1411 if (instr->SixtyFourBits()) { |
| 1412 ConditionalCompareHelper<int64_t>(instr, instr->ImmCondCmp()); |
| 1413 } else { |
| 1414 ConditionalCompareHelper<int32_t>(instr, instr->ImmCondCmp()); |
| 1415 } |
1396 } | 1416 } |
1397 | 1417 |
1398 | 1418 |
1399 void Simulator::ConditionalCompareHelper(Instruction* instr, int64_t op2) { | 1419 template<typename T> |
1400 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | 1420 void Simulator::ConditionalCompareHelper(Instruction* instr, T op2) { |
1401 : kWRegSizeInBits; | 1421 T op1 = reg<T>(instr->Rn()); |
1402 int64_t op1 = reg(reg_size, instr->Rn()); | |
1403 | 1422 |
1404 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { | 1423 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { |
1405 // If the condition passes, set the status flags to the result of comparing | 1424 // If the condition passes, set the status flags to the result of comparing |
1406 // the operands. | 1425 // the operands. |
1407 if (instr->Mask(ConditionalCompareMask) == CCMP) { | 1426 if (instr->Mask(ConditionalCompareMask) == CCMP) { |
1408 AddWithCarry(reg_size, true, op1, ~op2, 1); | 1427 AddWithCarry<T>(true, op1, ~op2, 1); |
1409 } else { | 1428 } else { |
1410 ASSERT(instr->Mask(ConditionalCompareMask) == CCMN); | 1429 ASSERT(instr->Mask(ConditionalCompareMask) == CCMN); |
1411 AddWithCarry(reg_size, true, op1, op2, 0); | 1430 AddWithCarry<T>(true, op1, op2, 0); |
1412 } | 1431 } |
1413 } else { | 1432 } else { |
1414 // If the condition fails, set the status flags to the nzcv immediate. | 1433 // If the condition fails, set the status flags to the nzcv immediate. |
1415 nzcv().SetFlags(instr->Nzcv()); | 1434 nzcv().SetFlags(instr->Nzcv()); |
1416 } | 1435 } |
1417 } | 1436 } |
1418 | 1437 |
1419 | 1438 |
1420 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) { | 1439 void Simulator::VisitLoadStoreUnsignedOffset(Instruction* instr) { |
1421 int offset = instr->ImmLSUnsigned() << instr->SizeLS(); | 1440 int offset = instr->ImmLSUnsigned() << instr->SizeLS(); |
(...skipping 14 matching lines...) Expand all Loading... |
1436 void Simulator::VisitLoadStorePostIndex(Instruction* instr) { | 1455 void Simulator::VisitLoadStorePostIndex(Instruction* instr) { |
1437 LoadStoreHelper(instr, instr->ImmLS(), PostIndex); | 1456 LoadStoreHelper(instr, instr->ImmLS(), PostIndex); |
1438 } | 1457 } |
1439 | 1458 |
1440 | 1459 |
1441 void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) { | 1460 void Simulator::VisitLoadStoreRegisterOffset(Instruction* instr) { |
1442 Extend ext = static_cast<Extend>(instr->ExtendMode()); | 1461 Extend ext = static_cast<Extend>(instr->ExtendMode()); |
1443 ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX)); | 1462 ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX)); |
1444 unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS(); | 1463 unsigned shift_amount = instr->ImmShiftLS() * instr->SizeLS(); |
1445 | 1464 |
1446 int64_t offset = ExtendValue(kXRegSizeInBits, xreg(instr->Rm()), ext, | 1465 int64_t offset = ExtendValue(xreg(instr->Rm()), ext, shift_amount); |
1447 shift_amount); | |
1448 LoadStoreHelper(instr, offset, Offset); | 1466 LoadStoreHelper(instr, offset, Offset); |
1449 } | 1467 } |
1450 | 1468 |
1451 | 1469 |
1452 void Simulator::LoadStoreHelper(Instruction* instr, | 1470 void Simulator::LoadStoreHelper(Instruction* instr, |
1453 int64_t offset, | 1471 int64_t offset, |
1454 AddrMode addrmode) { | 1472 AddrMode addrmode) { |
1455 unsigned srcdst = instr->Rt(); | 1473 unsigned srcdst = instr->Rt(); |
1456 unsigned addr_reg = instr->Rn(); | 1474 unsigned addr_reg = instr->Rn(); |
1457 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode); | 1475 uint8_t* address = LoadStoreAddress(addr_reg, offset, addrmode); |
(...skipping 19 matching lines...) Expand all Loading... |
1477 switch (op) { | 1495 switch (op) { |
1478 case LDRB_w: | 1496 case LDRB_w: |
1479 case LDRH_w: | 1497 case LDRH_w: |
1480 case LDR_w: | 1498 case LDR_w: |
1481 case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break; | 1499 case LDR_x: set_xreg(srcdst, MemoryRead(address, num_bytes)); break; |
1482 case STRB_w: | 1500 case STRB_w: |
1483 case STRH_w: | 1501 case STRH_w: |
1484 case STR_w: | 1502 case STR_w: |
1485 case STR_x: MemoryWrite(address, xreg(srcdst), num_bytes); break; | 1503 case STR_x: MemoryWrite(address, xreg(srcdst), num_bytes); break; |
1486 case LDRSB_w: { | 1504 case LDRSB_w: { |
1487 set_wreg(srcdst, | 1505 set_wreg(srcdst, ExtendValue<int32_t>(MemoryRead8(address), SXTB)); |
1488 ExtendValue(kWRegSizeInBits, MemoryRead8(address), SXTB)); | |
1489 break; | 1506 break; |
1490 } | 1507 } |
1491 case LDRSB_x: { | 1508 case LDRSB_x: { |
1492 set_xreg(srcdst, | 1509 set_xreg(srcdst, ExtendValue<int64_t>(MemoryRead8(address), SXTB)); |
1493 ExtendValue(kXRegSizeInBits, MemoryRead8(address), SXTB)); | |
1494 break; | 1510 break; |
1495 } | 1511 } |
1496 case LDRSH_w: { | 1512 case LDRSH_w: { |
1497 set_wreg(srcdst, | 1513 set_wreg(srcdst, ExtendValue<int32_t>(MemoryRead16(address), SXTH)); |
1498 ExtendValue(kWRegSizeInBits, MemoryRead16(address), SXTH)); | |
1499 break; | 1514 break; |
1500 } | 1515 } |
1501 case LDRSH_x: { | 1516 case LDRSH_x: { |
1502 set_xreg(srcdst, | 1517 set_xreg(srcdst, ExtendValue<int64_t>(MemoryRead16(address), SXTH)); |
1503 ExtendValue(kXRegSizeInBits, MemoryRead16(address), SXTH)); | |
1504 break; | 1518 break; |
1505 } | 1519 } |
1506 case LDRSW_x: { | 1520 case LDRSW_x: { |
1507 set_xreg(srcdst, | 1521 set_xreg(srcdst, ExtendValue<int64_t>(MemoryRead32(address), SXTW)); |
1508 ExtendValue(kXRegSizeInBits, MemoryRead32(address), SXTW)); | |
1509 break; | 1522 break; |
1510 } | 1523 } |
1511 case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break; | 1524 case LDR_s: set_sreg(srcdst, MemoryReadFP32(address)); break; |
1512 case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break; | 1525 case LDR_d: set_dreg(srcdst, MemoryReadFP64(address)); break; |
1513 case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break; | 1526 case STR_s: MemoryWriteFP32(address, sreg(srcdst)); break; |
1514 case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break; | 1527 case STR_d: MemoryWriteFP64(address, dreg(srcdst)); break; |
1515 default: UNIMPLEMENTED(); | 1528 default: UNIMPLEMENTED(); |
1516 } | 1529 } |
1517 | 1530 |
1518 // Handle the writeback for loads after the load to ensure safe pop | 1531 // Handle the writeback for loads after the load to ensure safe pop |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1598 set_xreg(rt, MemoryRead64(address)); | 1611 set_xreg(rt, MemoryRead64(address)); |
1599 set_xreg(rt2, MemoryRead64(address + kXRegSize)); | 1612 set_xreg(rt2, MemoryRead64(address + kXRegSize)); |
1600 break; | 1613 break; |
1601 } | 1614 } |
1602 case LDP_d: { | 1615 case LDP_d: { |
1603 set_dreg(rt, MemoryReadFP64(address)); | 1616 set_dreg(rt, MemoryReadFP64(address)); |
1604 set_dreg(rt2, MemoryReadFP64(address + kDRegSize)); | 1617 set_dreg(rt2, MemoryReadFP64(address + kDRegSize)); |
1605 break; | 1618 break; |
1606 } | 1619 } |
1607 case LDPSW_x: { | 1620 case LDPSW_x: { |
1608 set_xreg(rt, ExtendValue(kXRegSizeInBits, MemoryRead32(address), SXTW)); | 1621 set_xreg(rt, ExtendValue<int64_t>(MemoryRead32(address), SXTW)); |
1609 set_xreg(rt2, ExtendValue(kXRegSizeInBits, | 1622 set_xreg(rt2, ExtendValue<int64_t>( |
1610 MemoryRead32(address + kWRegSize), SXTW)); | 1623 MemoryRead32(address + kWRegSize), SXTW)); |
1611 break; | 1624 break; |
1612 } | 1625 } |
1613 case STP_w: { | 1626 case STP_w: { |
1614 MemoryWrite32(address, wreg(rt)); | 1627 MemoryWrite32(address, wreg(rt)); |
1615 MemoryWrite32(address + kWRegSize, wreg(rt2)); | 1628 MemoryWrite32(address + kWRegSize, wreg(rt2)); |
1616 break; | 1629 break; |
1617 } | 1630 } |
1618 case STP_s: { | 1631 case STP_s: { |
1619 MemoryWriteFP32(address, sreg(rt)); | 1632 MemoryWriteFP32(address, sreg(rt)); |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1815 default: | 1828 default: |
1816 UNREACHABLE(); | 1829 UNREACHABLE(); |
1817 } | 1830 } |
1818 | 1831 |
1819 // Update the destination register. | 1832 // Update the destination register. |
1820 set_xreg(instr->Rd(), new_xn_val); | 1833 set_xreg(instr->Rd(), new_xn_val); |
1821 } | 1834 } |
1822 | 1835 |
1823 | 1836 |
1824 void Simulator::VisitConditionalSelect(Instruction* instr) { | 1837 void Simulator::VisitConditionalSelect(Instruction* instr) { |
1825 uint64_t new_val = xreg(instr->Rn()); | |
1826 | |
1827 if (ConditionFailed(static_cast<Condition>(instr->Condition()))) { | 1838 if (ConditionFailed(static_cast<Condition>(instr->Condition()))) { |
1828 new_val = xreg(instr->Rm()); | 1839 uint64_t new_val = xreg(instr->Rm()); |
1829 switch (instr->Mask(ConditionalSelectMask)) { | 1840 switch (instr->Mask(ConditionalSelectMask)) { |
1830 case CSEL_w: | 1841 case CSEL_w: set_wreg(instr->Rd(), new_val); break; |
1831 case CSEL_x: break; | 1842 case CSEL_x: set_xreg(instr->Rd(), new_val); break; |
1832 case CSINC_w: | 1843 case CSINC_w: set_wreg(instr->Rd(), new_val + 1); break; |
1833 case CSINC_x: new_val++; break; | 1844 case CSINC_x: set_xreg(instr->Rd(), new_val + 1); break; |
1834 case CSINV_w: | 1845 case CSINV_w: set_wreg(instr->Rd(), ~new_val); break; |
1835 case CSINV_x: new_val = ~new_val; break; | 1846 case CSINV_x: set_xreg(instr->Rd(), ~new_val); break; |
1836 case CSNEG_w: | 1847 case CSNEG_w: set_wreg(instr->Rd(), -new_val); break; |
1837 case CSNEG_x: new_val = -new_val; break; | 1848 case CSNEG_x: set_xreg(instr->Rd(), -new_val); break; |
1838 default: UNIMPLEMENTED(); | 1849 default: UNIMPLEMENTED(); |
1839 } | 1850 } |
| 1851 } else { |
| 1852 if (instr->SixtyFourBits()) { |
| 1853 set_xreg(instr->Rd(), xreg(instr->Rn())); |
| 1854 } else { |
| 1855 set_wreg(instr->Rd(), wreg(instr->Rn())); |
| 1856 } |
1840 } | 1857 } |
1841 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | |
1842 : kWRegSizeInBits; | |
1843 set_reg(reg_size, instr->Rd(), new_val); | |
1844 } | 1858 } |
1845 | 1859 |
1846 | 1860 |
1847 void Simulator::VisitDataProcessing1Source(Instruction* instr) { | 1861 void Simulator::VisitDataProcessing1Source(Instruction* instr) { |
1848 unsigned dst = instr->Rd(); | 1862 unsigned dst = instr->Rd(); |
1849 unsigned src = instr->Rn(); | 1863 unsigned src = instr->Rn(); |
1850 | 1864 |
1851 switch (instr->Mask(DataProcessing1SourceMask)) { | 1865 switch (instr->Mask(DataProcessing1SourceMask)) { |
1852 case RBIT_w: set_wreg(dst, ReverseBits(wreg(src), kWRegSizeInBits)); break; | 1866 case RBIT_w: set_wreg(dst, ReverseBits(wreg(src), kWRegSizeInBits)); break; |
1853 case RBIT_x: set_xreg(dst, ReverseBits(xreg(src), kXRegSizeInBits)); break; | 1867 case RBIT_x: set_xreg(dst, ReverseBits(xreg(src), kXRegSizeInBits)); break; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1904 {0, 1, 2, 3, 4, 5, 6, 7} }; | 1918 {0, 1, 2, 3, 4, 5, 6, 7} }; |
1905 uint64_t result = 0; | 1919 uint64_t result = 0; |
1906 for (int i = 0; i < 8; i++) { | 1920 for (int i = 0; i < 8; i++) { |
1907 result <<= 8; | 1921 result <<= 8; |
1908 result |= bytes[permute_table[mode][i]]; | 1922 result |= bytes[permute_table[mode][i]]; |
1909 } | 1923 } |
1910 return result; | 1924 return result; |
1911 } | 1925 } |
1912 | 1926 |
1913 | 1927 |
1914 void Simulator::VisitDataProcessing2Source(Instruction* instr) { | 1928 template <typename T> |
| 1929 void Simulator::DataProcessing2Source(Instruction* instr) { |
1915 Shift shift_op = NO_SHIFT; | 1930 Shift shift_op = NO_SHIFT; |
1916 int64_t result = 0; | 1931 T result = 0; |
1917 switch (instr->Mask(DataProcessing2SourceMask)) { | 1932 switch (instr->Mask(DataProcessing2SourceMask)) { |
1918 case SDIV_w: { | 1933 case SDIV_w: |
1919 int32_t rn = wreg(instr->Rn()); | 1934 case SDIV_x: { |
1920 int32_t rm = wreg(instr->Rm()); | 1935 T rn = reg<T>(instr->Rn()); |
1921 if ((rn == kWMinInt) && (rm == -1)) { | 1936 T rm = reg<T>(instr->Rm()); |
1922 result = kWMinInt; | 1937 if ((rn == std::numeric_limits<T>::min()) && (rm == -1)) { |
| 1938 result = std::numeric_limits<T>::min(); |
1923 } else if (rm == 0) { | 1939 } else if (rm == 0) { |
1924 // Division by zero can be trapped, but not on A-class processors. | 1940 // Division by zero can be trapped, but not on A-class processors. |
1925 result = 0; | 1941 result = 0; |
1926 } else { | |
1927 result = rn / rm; | |
1928 } | |
1929 break; | |
1930 } | |
1931 case SDIV_x: { | |
1932 int64_t rn = xreg(instr->Rn()); | |
1933 int64_t rm = xreg(instr->Rm()); | |
1934 if ((rn == kXMinInt) && (rm == -1)) { | |
1935 result = kXMinInt; | |
1936 } else if (rm == 0) { | |
1937 // Division by zero can be trapped, but not on A-class processors. | |
1938 result = 0; | |
1939 } else { | 1942 } else { |
1940 result = rn / rm; | 1943 result = rn / rm; |
1941 } | 1944 } |
1942 break; | 1945 break; |
1943 } | 1946 } |
1944 case UDIV_w: { | 1947 case UDIV_w: |
1945 uint32_t rn = static_cast<uint32_t>(wreg(instr->Rn())); | 1948 case UDIV_x: { |
1946 uint32_t rm = static_cast<uint32_t>(wreg(instr->Rm())); | 1949 typedef typename make_unsigned<T>::type unsignedT; |
| 1950 unsignedT rn = static_cast<unsignedT>(reg<T>(instr->Rn())); |
| 1951 unsignedT rm = static_cast<unsignedT>(reg<T>(instr->Rm())); |
1947 if (rm == 0) { | 1952 if (rm == 0) { |
1948 // Division by zero can be trapped, but not on A-class processors. | 1953 // Division by zero can be trapped, but not on A-class processors. |
1949 result = 0; | 1954 result = 0; |
1950 } else { | |
1951 result = rn / rm; | |
1952 } | |
1953 break; | |
1954 } | |
1955 case UDIV_x: { | |
1956 uint64_t rn = static_cast<uint64_t>(xreg(instr->Rn())); | |
1957 uint64_t rm = static_cast<uint64_t>(xreg(instr->Rm())); | |
1958 if (rm == 0) { | |
1959 // Division by zero can be trapped, but not on A-class processors. | |
1960 result = 0; | |
1961 } else { | 1955 } else { |
1962 result = rn / rm; | 1956 result = rn / rm; |
1963 } | 1957 } |
1964 break; | 1958 break; |
1965 } | 1959 } |
1966 case LSLV_w: | 1960 case LSLV_w: |
1967 case LSLV_x: shift_op = LSL; break; | 1961 case LSLV_x: shift_op = LSL; break; |
1968 case LSRV_w: | 1962 case LSRV_w: |
1969 case LSRV_x: shift_op = LSR; break; | 1963 case LSRV_x: shift_op = LSR; break; |
1970 case ASRV_w: | 1964 case ASRV_w: |
1971 case ASRV_x: shift_op = ASR; break; | 1965 case ASRV_x: shift_op = ASR; break; |
1972 case RORV_w: | 1966 case RORV_w: |
1973 case RORV_x: shift_op = ROR; break; | 1967 case RORV_x: shift_op = ROR; break; |
1974 default: UNIMPLEMENTED(); | 1968 default: UNIMPLEMENTED(); |
1975 } | 1969 } |
1976 | 1970 |
1977 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | |
1978 : kWRegSizeInBits; | |
1979 if (shift_op != NO_SHIFT) { | 1971 if (shift_op != NO_SHIFT) { |
1980 // Shift distance encoded in the least-significant five/six bits of the | 1972 // Shift distance encoded in the least-significant five/six bits of the |
1981 // register. | 1973 // register. |
1982 int mask = (instr->SixtyFourBits() == 1) ? kShiftAmountXRegMask | 1974 unsigned shift = wreg(instr->Rm()); |
1983 : kShiftAmountWRegMask; | 1975 if (sizeof(T) == kWRegSize) { |
1984 unsigned shift = wreg(instr->Rm()) & mask; | 1976 shift &= kShiftAmountWRegMask; |
1985 result = ShiftOperand(reg_size, reg(reg_size, instr->Rn()), shift_op, | 1977 } else { |
1986 shift); | 1978 shift &= kShiftAmountXRegMask; |
| 1979 } |
| 1980 result = ShiftOperand(reg<T>(instr->Rn()), shift_op, shift); |
1987 } | 1981 } |
1988 set_reg(reg_size, instr->Rd(), result); | 1982 set_reg<T>(instr->Rd(), result); |
1989 } | 1983 } |
1990 | 1984 |
1991 | 1985 |
| 1986 void Simulator::VisitDataProcessing2Source(Instruction* instr) { |
| 1987 if (instr->SixtyFourBits()) { |
| 1988 DataProcessing2Source<int64_t>(instr); |
| 1989 } else { |
| 1990 DataProcessing2Source<int32_t>(instr); |
| 1991 } |
| 1992 } |
| 1993 |
| 1994 |
1992 // The algorithm used is described in section 8.2 of | 1995 // The algorithm used is described in section 8.2 of |
1993 // Hacker's Delight, by Henry S. Warren, Jr. | 1996 // Hacker's Delight, by Henry S. Warren, Jr. |
1994 // It assumes that a right shift on a signed integer is an arithmetic shift. | 1997 // It assumes that a right shift on a signed integer is an arithmetic shift. |
1995 static int64_t MultiplyHighSigned(int64_t u, int64_t v) { | 1998 static int64_t MultiplyHighSigned(int64_t u, int64_t v) { |
1996 uint64_t u0, v0, w0; | 1999 uint64_t u0, v0, w0; |
1997 int64_t u1, v1, w1, w2, t; | 2000 int64_t u1, v1, w1, w2, t; |
1998 | 2001 |
1999 u0 = u & 0xffffffffL; | 2002 u0 = u & 0xffffffffL; |
2000 u1 = u >> 32; | 2003 u1 = u >> 32; |
2001 v0 = v & 0xffffffffL; | 2004 v0 = v & 0xffffffffL; |
2002 v1 = v >> 32; | 2005 v1 = v >> 32; |
2003 | 2006 |
2004 w0 = u0 * v0; | 2007 w0 = u0 * v0; |
2005 t = u1 * v0 + (w0 >> 32); | 2008 t = u1 * v0 + (w0 >> 32); |
2006 w1 = t & 0xffffffffL; | 2009 w1 = t & 0xffffffffL; |
2007 w2 = t >> 32; | 2010 w2 = t >> 32; |
2008 w1 = u0 * v1 + w1; | 2011 w1 = u0 * v1 + w1; |
2009 | 2012 |
2010 return u1 * v1 + w2 + (w1 >> 32); | 2013 return u1 * v1 + w2 + (w1 >> 32); |
2011 } | 2014 } |
2012 | 2015 |
2013 | 2016 |
2014 void Simulator::VisitDataProcessing3Source(Instruction* instr) { | 2017 void Simulator::VisitDataProcessing3Source(Instruction* instr) { |
2015 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | |
2016 : kWRegSizeInBits; | |
2017 | |
2018 int64_t result = 0; | 2018 int64_t result = 0; |
2019 // Extract and sign- or zero-extend 32-bit arguments for widening operations. | 2019 // Extract and sign- or zero-extend 32-bit arguments for widening operations. |
2020 uint64_t rn_u32 = reg<uint32_t>(instr->Rn()); | 2020 uint64_t rn_u32 = reg<uint32_t>(instr->Rn()); |
2021 uint64_t rm_u32 = reg<uint32_t>(instr->Rm()); | 2021 uint64_t rm_u32 = reg<uint32_t>(instr->Rm()); |
2022 int64_t rn_s32 = reg<int32_t>(instr->Rn()); | 2022 int64_t rn_s32 = reg<int32_t>(instr->Rn()); |
2023 int64_t rm_s32 = reg<int32_t>(instr->Rm()); | 2023 int64_t rm_s32 = reg<int32_t>(instr->Rm()); |
2024 switch (instr->Mask(DataProcessing3SourceMask)) { | 2024 switch (instr->Mask(DataProcessing3SourceMask)) { |
2025 case MADD_w: | 2025 case MADD_w: |
2026 case MADD_x: | 2026 case MADD_x: |
2027 result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm())); | 2027 result = xreg(instr->Ra()) + (xreg(instr->Rn()) * xreg(instr->Rm())); |
2028 break; | 2028 break; |
2029 case MSUB_w: | 2029 case MSUB_w: |
2030 case MSUB_x: | 2030 case MSUB_x: |
2031 result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm())); | 2031 result = xreg(instr->Ra()) - (xreg(instr->Rn()) * xreg(instr->Rm())); |
2032 break; | 2032 break; |
2033 case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break; | 2033 case SMADDL_x: result = xreg(instr->Ra()) + (rn_s32 * rm_s32); break; |
2034 case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break; | 2034 case SMSUBL_x: result = xreg(instr->Ra()) - (rn_s32 * rm_s32); break; |
2035 case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break; | 2035 case UMADDL_x: result = xreg(instr->Ra()) + (rn_u32 * rm_u32); break; |
2036 case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break; | 2036 case UMSUBL_x: result = xreg(instr->Ra()) - (rn_u32 * rm_u32); break; |
2037 case SMULH_x: | 2037 case SMULH_x: |
2038 ASSERT(instr->Ra() == kZeroRegCode); | 2038 ASSERT(instr->Ra() == kZeroRegCode); |
2039 result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm())); | 2039 result = MultiplyHighSigned(xreg(instr->Rn()), xreg(instr->Rm())); |
2040 break; | 2040 break; |
2041 default: UNIMPLEMENTED(); | 2041 default: UNIMPLEMENTED(); |
2042 } | 2042 } |
2043 set_reg(reg_size, instr->Rd(), result); | 2043 |
| 2044 if (instr->SixtyFourBits()) { |
| 2045 set_xreg(instr->Rd(), result); |
| 2046 } else { |
| 2047 set_wreg(instr->Rd(), result); |
| 2048 } |
2044 } | 2049 } |
2045 | 2050 |
2046 | 2051 |
2047 void Simulator::VisitBitfield(Instruction* instr) { | 2052 template <typename T> |
2048 unsigned reg_size = instr->SixtyFourBits() ? kXRegSizeInBits | 2053 void Simulator::BitfieldHelper(Instruction* instr) { |
2049 : kWRegSizeInBits; | 2054 typedef typename make_unsigned<T>::type unsignedT; |
2050 int64_t reg_mask = instr->SixtyFourBits() ? kXRegMask : kWRegMask; | 2055 T reg_size = sizeof(T) * 8; |
2051 int64_t R = instr->ImmR(); | 2056 T R = instr->ImmR(); |
2052 int64_t S = instr->ImmS(); | 2057 T S = instr->ImmS(); |
2053 int64_t diff = S - R; | 2058 T diff = S - R; |
2054 int64_t mask; | 2059 T mask; |
2055 if (diff >= 0) { | 2060 if (diff >= 0) { |
2056 mask = diff < reg_size - 1 ? (1L << (diff + 1)) - 1 | 2061 mask = diff < reg_size - 1 ? (static_cast<T>(1) << (diff + 1)) - 1 |
2057 : reg_mask; | 2062 : static_cast<T>(-1); |
2058 } else { | 2063 } else { |
2059 mask = ((1L << (S + 1)) - 1); | 2064 mask = ((1L << (S + 1)) - 1); |
2060 mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R)); | 2065 mask = (static_cast<uint64_t>(mask) >> R) | (mask << (reg_size - R)); |
2061 diff += reg_size; | 2066 diff += reg_size; |
2062 } | 2067 } |
2063 | 2068 |
2064 // inzero indicates if the extracted bitfield is inserted into the | 2069 // inzero indicates if the extracted bitfield is inserted into the |
2065 // destination register value or in zero. | 2070 // destination register value or in zero. |
2066 // If extend is true, extend the sign of the extracted bitfield. | 2071 // If extend is true, extend the sign of the extracted bitfield. |
2067 bool inzero = false; | 2072 bool inzero = false; |
2068 bool extend = false; | 2073 bool extend = false; |
2069 switch (instr->Mask(BitfieldMask)) { | 2074 switch (instr->Mask(BitfieldMask)) { |
2070 case BFM_x: | 2075 case BFM_x: |
2071 case BFM_w: | 2076 case BFM_w: |
2072 break; | 2077 break; |
2073 case SBFM_x: | 2078 case SBFM_x: |
2074 case SBFM_w: | 2079 case SBFM_w: |
2075 inzero = true; | 2080 inzero = true; |
2076 extend = true; | 2081 extend = true; |
2077 break; | 2082 break; |
2078 case UBFM_x: | 2083 case UBFM_x: |
2079 case UBFM_w: | 2084 case UBFM_w: |
2080 inzero = true; | 2085 inzero = true; |
2081 break; | 2086 break; |
2082 default: | 2087 default: |
2083 UNIMPLEMENTED(); | 2088 UNIMPLEMENTED(); |
2084 } | 2089 } |
2085 | 2090 |
2086 int64_t dst = inzero ? 0 : reg(reg_size, instr->Rd()); | 2091 T dst = inzero ? 0 : reg<T>(instr->Rd()); |
2087 int64_t src = reg(reg_size, instr->Rn()); | 2092 T src = reg<T>(instr->Rn()); |
2088 // Rotate source bitfield into place. | 2093 // Rotate source bitfield into place. |
2089 int64_t result = (static_cast<uint64_t>(src) >> R) | (src << (reg_size - R)); | 2094 T result = (static_cast<unsignedT>(src) >> R) | (src << (reg_size - R)); |
2090 // Determine the sign extension. | 2095 // Determine the sign extension. |
2091 int64_t topbits_preshift = (1L << (reg_size - diff - 1)) - 1; | 2096 T topbits_preshift = (static_cast<T>(1) << (reg_size - diff - 1)) - 1; |
2092 int64_t signbits = (extend && ((src >> S) & 1) ? topbits_preshift : 0) | 2097 T signbits = (extend && ((src >> S) & 1) ? topbits_preshift : 0) |
2093 << (diff + 1); | 2098 << (diff + 1); |
2094 | 2099 |
2095 // Merge sign extension, dest/zero and bitfield. | 2100 // Merge sign extension, dest/zero and bitfield. |
2096 result = signbits | (result & mask) | (dst & ~mask); | 2101 result = signbits | (result & mask) | (dst & ~mask); |
2097 | 2102 |
2098 set_reg(reg_size, instr->Rd(), result); | 2103 set_reg<T>(instr->Rd(), result); |
| 2104 } |
| 2105 |
| 2106 |
| 2107 void Simulator::VisitBitfield(Instruction* instr) { |
| 2108 if (instr->SixtyFourBits()) { |
| 2109 BitfieldHelper<int64_t>(instr); |
| 2110 } else { |
| 2111 BitfieldHelper<int32_t>(instr); |
| 2112 } |
2099 } | 2113 } |
2100 | 2114 |
2101 | 2115 |
2102 void Simulator::VisitExtract(Instruction* instr) { | 2116 void Simulator::VisitExtract(Instruction* instr) { |
2103 unsigned lsb = instr->ImmS(); | 2117 if (instr->SixtyFourBits()) { |
2104 unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSizeInBits | 2118 Extract<uint64_t>(instr); |
2105 : kWRegSizeInBits; | 2119 } else { |
2106 set_reg(reg_size, | 2120 Extract<uint32_t>(instr); |
2107 instr->Rd(), | 2121 } |
2108 (static_cast<uint64_t>(reg(reg_size, instr->Rm())) >> lsb) | | |
2109 (reg(reg_size, instr->Rn()) << (reg_size - lsb))); | |
2110 } | 2122 } |
2111 | 2123 |
2112 | 2124 |
2113 void Simulator::VisitFPImmediate(Instruction* instr) { | 2125 void Simulator::VisitFPImmediate(Instruction* instr) { |
2114 AssertSupportedFPCR(); | 2126 AssertSupportedFPCR(); |
2115 | 2127 |
2116 unsigned dest = instr->Rd(); | 2128 unsigned dest = instr->Rd(); |
2117 switch (instr->Mask(FPImmediateMask)) { | 2129 switch (instr->Mask(FPImmediateMask)) { |
2118 case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break; | 2130 case FMOV_s_imm: set_sreg(dest, instr->ImmFP32()); break; |
2119 case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break; | 2131 case FMOV_d_imm: set_dreg(dest, instr->ImmFP64()); break; |
(...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3724 | 3736 |
3725 delete[] format; | 3737 delete[] format; |
3726 } | 3738 } |
3727 | 3739 |
3728 | 3740 |
3729 #endif // USE_SIMULATOR | 3741 #endif // USE_SIMULATOR |
3730 | 3742 |
3731 } } // namespace v8::internal | 3743 } } // namespace v8::internal |
3732 | 3744 |
3733 #endif // V8_TARGET_ARCH_ARM64 | 3745 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |