Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(992)

Side by Side Diff: src/arm64/simulator-arm64.cc

Issue 2157283003: [arm64] Avoid signed arithmetic in AddWithCarry. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/arm64/simulator-arm64.h ('k') | test/cctest/test-assembler-arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 8
9 #if V8_TARGET_ARCH_ARM64 9 #if V8_TARGET_ARCH_ARM64
10 10
(...skipping 870 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 } 881 }
882 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) { 882 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) {
883 return kSPRegInternalCode; 883 return kSPRegInternalCode;
884 } 884 }
885 return -1; 885 return -1;
886 } 886 }
887 887
888 888
889 // Helpers --------------------------------------------------------------------- 889 // Helpers ---------------------------------------------------------------------
890 template <typename T> 890 template <typename T>
891 T Simulator::AddWithCarry(bool set_flags, 891 T Simulator::AddWithCarry(bool set_flags, T left, T right, int carry_in) {
892 T src1, 892 // Use unsigned types to avoid implementation-defined overflow behaviour.
893 T src2, 893 static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
894 T carry_in) { 894 static_assert((sizeof(T) == kWRegSize) || (sizeof(T) == kXRegSize),
895 typedef typename make_unsigned<T>::type unsignedT; 895 "Only W- or X-sized operands are tested");
896
896 DCHECK((carry_in == 0) || (carry_in == 1)); 897 DCHECK((carry_in == 0) || (carry_in == 1));
897 898 T result = left + right + carry_in;
898 T signed_sum = src1 + src2 + carry_in;
899 T result = signed_sum;
900
901 bool N, Z, C, V;
902
903 // Compute the C flag
904 unsignedT u1 = static_cast<unsignedT>(src1);
905 unsignedT u2 = static_cast<unsignedT>(src2);
906 unsignedT urest = std::numeric_limits<unsignedT>::max() - u1;
907 C = (u2 > urest) || (carry_in && (((u2 + 1) > urest) || (u2 > (urest - 1))));
908
909 // Overflow iff the sign bit is the same for the two inputs and different
910 // for the result.
911 V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0);
912
913 N = CalcNFlag(result);
914 Z = CalcZFlag(result);
915 899
916 if (set_flags) { 900 if (set_flags) {
917 nzcv().SetN(N); 901 nzcv().SetN(CalcNFlag(result));
918 nzcv().SetZ(Z); 902 nzcv().SetZ(CalcZFlag(result));
919 nzcv().SetC(C); 903
920 nzcv().SetV(V); 904 // Compute the C flag by comparing the result to the max unsigned integer.
905 T max_uint_2op = std::numeric_limits<T>::max() - carry_in;
906 nzcv().SetC((left > max_uint_2op) || ((max_uint_2op - left) < right));
907
908 // Overflow iff the sign bit is the same for the two inputs and different
909 // for the result.
910 T sign_mask = T(1) << (sizeof(T) * 8 - 1);
911 T left_sign = left & sign_mask;
912 T right_sign = right & sign_mask;
913 T result_sign = result & sign_mask;
914 nzcv().SetV((left_sign == right_sign) && (left_sign != result_sign));
915
921 LogSystemRegister(NZCV); 916 LogSystemRegister(NZCV);
922 } 917 }
923 return result; 918 return result;
924 } 919 }
925 920
926 921
927 template<typename T> 922 template<typename T>
928 void Simulator::AddSubWithCarry(Instruction* instr) { 923 void Simulator::AddSubWithCarry(Instruction* instr) {
924 // Use unsigned types to avoid implementation-defined overflow behaviour.
925 static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
926
929 T op2 = reg<T>(instr->Rm()); 927 T op2 = reg<T>(instr->Rm());
930 T new_val; 928 T new_val;
931 929
932 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) { 930 if ((instr->Mask(AddSubOpMask) == SUB) || instr->Mask(AddSubOpMask) == SUBS) {
933 op2 = ~op2; 931 op2 = ~op2;
934 } 932 }
935 933
936 new_val = AddWithCarry<T>(instr->FlagsUpdate(), 934 new_val = AddWithCarry<T>(instr->FlagsUpdate(),
937 reg<T>(instr->Rn()), 935 reg<T>(instr->Rn()),
938 op2, 936 op2,
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 default: UNIMPLEMENTED(); 1409 default: UNIMPLEMENTED();
1412 } 1410 }
1413 if (take_branch) { 1411 if (take_branch) {
1414 set_pc(instr->ImmPCOffsetTarget()); 1412 set_pc(instr->ImmPCOffsetTarget());
1415 } 1413 }
1416 } 1414 }
1417 1415
1418 1416
1419 template<typename T> 1417 template<typename T>
1420 void Simulator::AddSubHelper(Instruction* instr, T op2) { 1418 void Simulator::AddSubHelper(Instruction* instr, T op2) {
1419 // Use unsigned types to avoid implementation-defined overflow behaviour.
1420 static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
1421
1421 bool set_flags = instr->FlagsUpdate(); 1422 bool set_flags = instr->FlagsUpdate();
1422 T new_val = 0; 1423 T new_val = 0;
1423 Instr operation = instr->Mask(AddSubOpMask); 1424 Instr operation = instr->Mask(AddSubOpMask);
1424 1425
1425 switch (operation) { 1426 switch (operation) {
1426 case ADD: 1427 case ADD:
1427 case ADDS: { 1428 case ADDS: {
1428 new_val = AddWithCarry<T>(set_flags, 1429 new_val = AddWithCarry<T>(set_flags,
1429 reg<T>(instr->Rn(), instr->RnMode()), 1430 reg<T>(instr->Rn(), instr->RnMode()),
1430 op2); 1431 op2);
(...skipping 12 matching lines...) Expand all
1443 1444
1444 set_reg<T>(instr->Rd(), new_val, instr->RdMode()); 1445 set_reg<T>(instr->Rd(), new_val, instr->RdMode());
1445 } 1446 }
1446 1447
1447 1448
1448 void Simulator::VisitAddSubShifted(Instruction* instr) { 1449 void Simulator::VisitAddSubShifted(Instruction* instr) {
1449 Shift shift_type = static_cast<Shift>(instr->ShiftDP()); 1450 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1450 unsigned shift_amount = instr->ImmDPShift(); 1451 unsigned shift_amount = instr->ImmDPShift();
1451 1452
1452 if (instr->SixtyFourBits()) { 1453 if (instr->SixtyFourBits()) {
1453 int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount); 1454 uint64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1454 AddSubHelper(instr, op2); 1455 AddSubHelper(instr, op2);
1455 } else { 1456 } else {
1456 int32_t op2 = static_cast<int32_t>( 1457 uint32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
1457 ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount));
1458 AddSubHelper(instr, op2); 1458 AddSubHelper(instr, op2);
1459 } 1459 }
1460 } 1460 }
1461 1461
1462 1462
1463 void Simulator::VisitAddSubImmediate(Instruction* instr) { 1463 void Simulator::VisitAddSubImmediate(Instruction* instr) {
1464 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0); 1464 int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
1465 if (instr->SixtyFourBits()) { 1465 if (instr->SixtyFourBits()) {
1466 AddSubHelper<int64_t>(instr, op2); 1466 AddSubHelper(instr, static_cast<uint64_t>(op2));
1467 } else { 1467 } else {
1468 AddSubHelper<int32_t>(instr, static_cast<int32_t>(op2)); 1468 AddSubHelper(instr, static_cast<uint32_t>(op2));
1469 } 1469 }
1470 } 1470 }
1471 1471
1472 1472
1473 void Simulator::VisitAddSubExtended(Instruction* instr) { 1473 void Simulator::VisitAddSubExtended(Instruction* instr) {
1474 Extend ext = static_cast<Extend>(instr->ExtendMode()); 1474 Extend ext = static_cast<Extend>(instr->ExtendMode());
1475 unsigned left_shift = instr->ImmExtendShift(); 1475 unsigned left_shift = instr->ImmExtendShift();
1476 if (instr->SixtyFourBits()) { 1476 if (instr->SixtyFourBits()) {
1477 int64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift); 1477 uint64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift);
1478 AddSubHelper(instr, op2); 1478 AddSubHelper(instr, op2);
1479 } else { 1479 } else {
1480 int32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift); 1480 uint32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift);
1481 AddSubHelper(instr, op2); 1481 AddSubHelper(instr, op2);
1482 } 1482 }
1483 } 1483 }
1484 1484
1485 1485
1486 void Simulator::VisitAddSubWithCarry(Instruction* instr) { 1486 void Simulator::VisitAddSubWithCarry(Instruction* instr) {
1487 if (instr->SixtyFourBits()) { 1487 if (instr->SixtyFourBits()) {
1488 AddSubWithCarry<int64_t>(instr); 1488 AddSubWithCarry<uint64_t>(instr);
1489 } else { 1489 } else {
1490 AddSubWithCarry<int32_t>(instr); 1490 AddSubWithCarry<uint32_t>(instr);
1491 } 1491 }
1492 } 1492 }
1493 1493
1494 1494
1495 void Simulator::VisitLogicalShifted(Instruction* instr) { 1495 void Simulator::VisitLogicalShifted(Instruction* instr) {
1496 Shift shift_type = static_cast<Shift>(instr->ShiftDP()); 1496 Shift shift_type = static_cast<Shift>(instr->ShiftDP());
1497 unsigned shift_amount = instr->ImmDPShift(); 1497 unsigned shift_amount = instr->ImmDPShift();
1498 1498
1499 if (instr->SixtyFourBits()) { 1499 if (instr->SixtyFourBits()) {
1500 int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount); 1500 uint64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
1501 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2; 1501 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1502 LogicalHelper<int64_t>(instr, op2); 1502 LogicalHelper(instr, op2);
1503 } else { 1503 } else {
1504 int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount); 1504 uint32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
1505 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2; 1505 op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
1506 LogicalHelper<int32_t>(instr, op2); 1506 LogicalHelper(instr, op2);
1507 } 1507 }
1508 } 1508 }
1509 1509
1510 1510
1511 void Simulator::VisitLogicalImmediate(Instruction* instr) { 1511 void Simulator::VisitLogicalImmediate(Instruction* instr) {
1512 if (instr->SixtyFourBits()) { 1512 if (instr->SixtyFourBits()) {
1513 LogicalHelper<int64_t>(instr, instr->ImmLogical()); 1513 LogicalHelper(instr, static_cast<uint64_t>(instr->ImmLogical()));
1514 } else { 1514 } else {
1515 LogicalHelper<int32_t>(instr, static_cast<int32_t>(instr->ImmLogical())); 1515 LogicalHelper(instr, static_cast<uint32_t>(instr->ImmLogical()));
1516 } 1516 }
1517 } 1517 }
1518 1518
1519 1519
1520 template<typename T> 1520 template<typename T>
1521 void Simulator::LogicalHelper(Instruction* instr, T op2) { 1521 void Simulator::LogicalHelper(Instruction* instr, T op2) {
1522 T op1 = reg<T>(instr->Rn()); 1522 T op1 = reg<T>(instr->Rn());
1523 T result = 0; 1523 T result = 0;
1524 bool update_flags = false; 1524 bool update_flags = false;
1525 1525
(...skipping 15 matching lines...) Expand all
1541 nzcv().SetV(0); 1541 nzcv().SetV(0);
1542 LogSystemRegister(NZCV); 1542 LogSystemRegister(NZCV);
1543 } 1543 }
1544 1544
1545 set_reg<T>(instr->Rd(), result, instr->RdMode()); 1545 set_reg<T>(instr->Rd(), result, instr->RdMode());
1546 } 1546 }
1547 1547
1548 1548
1549 void Simulator::VisitConditionalCompareRegister(Instruction* instr) { 1549 void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
1550 if (instr->SixtyFourBits()) { 1550 if (instr->SixtyFourBits()) {
1551 ConditionalCompareHelper(instr, xreg(instr->Rm())); 1551 ConditionalCompareHelper(instr, static_cast<uint64_t>(xreg(instr->Rm())));
1552 } else { 1552 } else {
1553 ConditionalCompareHelper(instr, wreg(instr->Rm())); 1553 ConditionalCompareHelper(instr, static_cast<uint32_t>(wreg(instr->Rm())));
1554 } 1554 }
1555 } 1555 }
1556 1556
1557 1557
1558 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) { 1558 void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
1559 if (instr->SixtyFourBits()) { 1559 if (instr->SixtyFourBits()) {
1560 ConditionalCompareHelper<int64_t>(instr, instr->ImmCondCmp()); 1560 ConditionalCompareHelper(instr, static_cast<uint64_t>(instr->ImmCondCmp()));
1561 } else { 1561 } else {
1562 ConditionalCompareHelper<int32_t>(instr, instr->ImmCondCmp()); 1562 ConditionalCompareHelper(instr, static_cast<uint32_t>(instr->ImmCondCmp()));
1563 } 1563 }
1564 } 1564 }
1565 1565
1566 1566
1567 template<typename T> 1567 template<typename T>
1568 void Simulator::ConditionalCompareHelper(Instruction* instr, T op2) { 1568 void Simulator::ConditionalCompareHelper(Instruction* instr, T op2) {
1569 // Use unsigned types to avoid implementation-defined overflow behaviour.
1570 static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
1571
1569 T op1 = reg<T>(instr->Rn()); 1572 T op1 = reg<T>(instr->Rn());
1570 1573
1571 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { 1574 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
1572 // If the condition passes, set the status flags to the result of comparing 1575 // If the condition passes, set the status flags to the result of comparing
1573 // the operands. 1576 // the operands.
1574 if (instr->Mask(ConditionalCompareMask) == CCMP) { 1577 if (instr->Mask(ConditionalCompareMask) == CCMP) {
1575 AddWithCarry<T>(true, op1, ~op2, 1); 1578 AddWithCarry<T>(true, op1, ~op2, 1);
1576 } else { 1579 } else {
1577 DCHECK(instr->Mask(ConditionalCompareMask) == CCMN); 1580 DCHECK(instr->Mask(ConditionalCompareMask) == CCMN);
1578 AddWithCarry<T>(true, op1, op2, 0); 1581 AddWithCarry<T>(true, op1, op2, 0);
(...skipping 2294 matching lines...) Expand 10 before | Expand all | Expand 10 after
3873 delete[] format; 3876 delete[] format;
3874 } 3877 }
3875 3878
3876 3879
3877 #endif // USE_SIMULATOR 3880 #endif // USE_SIMULATOR
3878 3881
3879 } // namespace internal 3882 } // namespace internal
3880 } // namespace v8 3883 } // namespace v8
3881 3884
3882 #endif // V8_TARGET_ARCH_ARM64 3885 #endif // V8_TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « src/arm64/simulator-arm64.h ('k') | test/cctest/test-assembler-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698