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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm64/simulator-arm64.cc
diff --git a/src/arm64/simulator-arm64.cc b/src/arm64/simulator-arm64.cc
index aa10eb2956377a575882da45335717ad842cac77..f5595a8ed12b139f36017bab2c70b1ecb3f46bef 100644
--- a/src/arm64/simulator-arm64.cc
+++ b/src/arm64/simulator-arm64.cc
@@ -888,36 +888,31 @@ int Simulator::CodeFromName(const char* name) {
// Helpers ---------------------------------------------------------------------
template <typename T>
-T Simulator::AddWithCarry(bool set_flags,
- T src1,
- T src2,
- T carry_in) {
- typedef typename make_unsigned<T>::type unsignedT;
+T Simulator::AddWithCarry(bool set_flags, T left, T right, int carry_in) {
+ // Use unsigned types to avoid implementation-defined overflow behaviour.
+ static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
+ static_assert((sizeof(T) == kWRegSize) || (sizeof(T) == kXRegSize),
+ "Only W- or X-sized operands are tested");
+
DCHECK((carry_in == 0) || (carry_in == 1));
-
- T signed_sum = src1 + src2 + carry_in;
- T result = signed_sum;
-
- bool N, Z, C, V;
-
- // Compute the C flag
- unsignedT u1 = static_cast<unsignedT>(src1);
- unsignedT u2 = static_cast<unsignedT>(src2);
- unsignedT urest = std::numeric_limits<unsignedT>::max() - u1;
- C = (u2 > urest) || (carry_in && (((u2 + 1) > urest) || (u2 > (urest - 1))));
-
- // Overflow iff the sign bit is the same for the two inputs and different
- // for the result.
- V = ((src1 ^ src2) >= 0) && ((src1 ^ result) < 0);
-
- N = CalcNFlag(result);
- Z = CalcZFlag(result);
+ T result = left + right + carry_in;
if (set_flags) {
- nzcv().SetN(N);
- nzcv().SetZ(Z);
- nzcv().SetC(C);
- nzcv().SetV(V);
+ nzcv().SetN(CalcNFlag(result));
+ nzcv().SetZ(CalcZFlag(result));
+
+ // Compute the C flag by comparing the result to the max unsigned integer.
+ T max_uint_2op = std::numeric_limits<T>::max() - carry_in;
+ nzcv().SetC((left > max_uint_2op) || ((max_uint_2op - left) < right));
+
+ // Overflow iff the sign bit is the same for the two inputs and different
+ // for the result.
+ T sign_mask = T(1) << (sizeof(T) * 8 - 1);
+ T left_sign = left & sign_mask;
+ T right_sign = right & sign_mask;
+ T result_sign = result & sign_mask;
+ nzcv().SetV((left_sign == right_sign) && (left_sign != result_sign));
+
LogSystemRegister(NZCV);
}
return result;
@@ -926,6 +921,9 @@ T Simulator::AddWithCarry(bool set_flags,
template<typename T>
void Simulator::AddSubWithCarry(Instruction* instr) {
+ // Use unsigned types to avoid implementation-defined overflow behaviour.
+ static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
+
T op2 = reg<T>(instr->Rm());
T new_val;
@@ -1418,6 +1416,9 @@ void Simulator::VisitCompareBranch(Instruction* instr) {
template<typename T>
void Simulator::AddSubHelper(Instruction* instr, T op2) {
+ // Use unsigned types to avoid implementation-defined overflow behaviour.
+ static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
+
bool set_flags = instr->FlagsUpdate();
T new_val = 0;
Instr operation = instr->Mask(AddSubOpMask);
@@ -1450,11 +1451,10 @@ void Simulator::VisitAddSubShifted(Instruction* instr) {
unsigned shift_amount = instr->ImmDPShift();
if (instr->SixtyFourBits()) {
- int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
+ uint64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
AddSubHelper(instr, op2);
} else {
- int32_t op2 = static_cast<int32_t>(
- ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount));
+ uint32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
AddSubHelper(instr, op2);
}
}
@@ -1463,9 +1463,9 @@ void Simulator::VisitAddSubShifted(Instruction* instr) {
void Simulator::VisitAddSubImmediate(Instruction* instr) {
int64_t op2 = instr->ImmAddSub() << ((instr->ShiftAddSub() == 1) ? 12 : 0);
if (instr->SixtyFourBits()) {
- AddSubHelper<int64_t>(instr, op2);
+ AddSubHelper(instr, static_cast<uint64_t>(op2));
} else {
- AddSubHelper<int32_t>(instr, static_cast<int32_t>(op2));
+ AddSubHelper(instr, static_cast<uint32_t>(op2));
}
}
@@ -1474,10 +1474,10 @@ void Simulator::VisitAddSubExtended(Instruction* instr) {
Extend ext = static_cast<Extend>(instr->ExtendMode());
unsigned left_shift = instr->ImmExtendShift();
if (instr->SixtyFourBits()) {
- int64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift);
+ uint64_t op2 = ExtendValue(xreg(instr->Rm()), ext, left_shift);
AddSubHelper(instr, op2);
} else {
- int32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift);
+ uint32_t op2 = ExtendValue(wreg(instr->Rm()), ext, left_shift);
AddSubHelper(instr, op2);
}
}
@@ -1485,9 +1485,9 @@ void Simulator::VisitAddSubExtended(Instruction* instr) {
void Simulator::VisitAddSubWithCarry(Instruction* instr) {
if (instr->SixtyFourBits()) {
- AddSubWithCarry<int64_t>(instr);
+ AddSubWithCarry<uint64_t>(instr);
} else {
- AddSubWithCarry<int32_t>(instr);
+ AddSubWithCarry<uint32_t>(instr);
}
}
@@ -1497,22 +1497,22 @@ void Simulator::VisitLogicalShifted(Instruction* instr) {
unsigned shift_amount = instr->ImmDPShift();
if (instr->SixtyFourBits()) {
- int64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
+ uint64_t op2 = ShiftOperand(xreg(instr->Rm()), shift_type, shift_amount);
op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
- LogicalHelper<int64_t>(instr, op2);
+ LogicalHelper(instr, op2);
} else {
- int32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
+ uint32_t op2 = ShiftOperand(wreg(instr->Rm()), shift_type, shift_amount);
op2 = (instr->Mask(NOT) == NOT) ? ~op2 : op2;
- LogicalHelper<int32_t>(instr, op2);
+ LogicalHelper(instr, op2);
}
}
void Simulator::VisitLogicalImmediate(Instruction* instr) {
if (instr->SixtyFourBits()) {
- LogicalHelper<int64_t>(instr, instr->ImmLogical());
+ LogicalHelper(instr, static_cast<uint64_t>(instr->ImmLogical()));
} else {
- LogicalHelper<int32_t>(instr, static_cast<int32_t>(instr->ImmLogical()));
+ LogicalHelper(instr, static_cast<uint32_t>(instr->ImmLogical()));
}
}
@@ -1548,24 +1548,27 @@ void Simulator::LogicalHelper(Instruction* instr, T op2) {
void Simulator::VisitConditionalCompareRegister(Instruction* instr) {
if (instr->SixtyFourBits()) {
- ConditionalCompareHelper(instr, xreg(instr->Rm()));
+ ConditionalCompareHelper(instr, static_cast<uint64_t>(xreg(instr->Rm())));
} else {
- ConditionalCompareHelper(instr, wreg(instr->Rm()));
+ ConditionalCompareHelper(instr, static_cast<uint32_t>(wreg(instr->Rm())));
}
}
void Simulator::VisitConditionalCompareImmediate(Instruction* instr) {
if (instr->SixtyFourBits()) {
- ConditionalCompareHelper<int64_t>(instr, instr->ImmCondCmp());
+ ConditionalCompareHelper(instr, static_cast<uint64_t>(instr->ImmCondCmp()));
} else {
- ConditionalCompareHelper<int32_t>(instr, instr->ImmCondCmp());
+ ConditionalCompareHelper(instr, static_cast<uint32_t>(instr->ImmCondCmp()));
}
}
template<typename T>
void Simulator::ConditionalCompareHelper(Instruction* instr, T op2) {
+ // Use unsigned types to avoid implementation-defined overflow behaviour.
+ static_assert(std::is_unsigned<T>::value, "operands must be unsigned");
+
T op1 = reg<T>(instr->Rn());
if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
« 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