Index: runtime/vm/simulator_arm.cc |
=================================================================== |
--- runtime/vm/simulator_arm.cc (revision 40889) |
+++ runtime/vm/simulator_arm.cc (working copy) |
@@ -1221,44 +1221,22 @@ |
} |
-// Calculate C flag value for additions. |
-bool Simulator::CarryFrom(int32_t left, int32_t right) { |
- uint32_t uleft = static_cast<uint32_t>(left); |
- uint32_t uright = static_cast<uint32_t>(right); |
- uint32_t urest = 0xffffffffU - uleft; |
- |
- return (uright > urest); |
+// Calculate C flag value for additions (and subtractions with adjusted args). |
+bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) { |
+ uint64_t uleft = static_cast<uint32_t>(left); |
+ uint64_t uright = static_cast<uint32_t>(right); |
+ uint64_t ucarry = static_cast<uint32_t>(carry); |
+ return ((uleft + uright + ucarry) >> 32) != 0; |
} |
-// Calculate C flag value for subtractions. |
-bool Simulator::BorrowFrom(int32_t left, int32_t right) { |
- uint32_t uleft = static_cast<uint32_t>(left); |
- uint32_t uright = static_cast<uint32_t>(right); |
- |
- return (uright > uleft); |
+// Calculate V flag value for additions (and subtractions with adjusted args). |
+bool Simulator::OverflowFrom(int32_t left, int32_t right, int32_t carry) { |
+ int64_t result = static_cast<int64_t>(left) + right + carry; |
+ return (result >> 31) != (result >> 32); |
} |
-// Calculate V flag value for additions and subtractions. |
-bool Simulator::OverflowFrom(int32_t alu_out, |
- int32_t left, int32_t right, bool addition) { |
- bool overflow; |
- if (addition) { |
- // operands have the same sign |
- overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) |
- // and operands and result have different sign |
- && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); |
- } else { |
- // operands have different signs |
- overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0)) |
- // and first operand and result have different signs |
- && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); |
- } |
- return overflow; |
-} |
- |
- |
// Addressing Mode 1 - Data-processing operands: |
// Get the value based on the shifter_operand with register. |
int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { |
@@ -2045,6 +2023,7 @@ |
ASSERT(instr->TypeField() == 1); |
shifter_operand = GetImm(instr, &shifter_carry_out); |
} |
+ int32_t carry_in; |
int32_t alu_out; |
switch (instr->OpcodeField()) { |
@@ -2079,8 +2058,8 @@ |
set_register(rd, alu_out); |
if (instr->HasS()) { |
SetNZFlags(alu_out); |
- SetCFlag(!BorrowFrom(rn_val, shifter_operand)); |
- SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); |
+ SetCFlag(CarryFrom(rn_val, ~shifter_operand, 1)); |
+ SetVFlag(OverflowFrom(rn_val, ~shifter_operand, 1)); |
} |
break; |
} |
@@ -2092,8 +2071,8 @@ |
set_register(rd, alu_out); |
if (instr->HasS()) { |
SetNZFlags(alu_out); |
- SetCFlag(!BorrowFrom(shifter_operand, rn_val)); |
- SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false)); |
+ SetCFlag(CarryFrom(shifter_operand, ~rn_val, 1)); |
+ SetVFlag(OverflowFrom(shifter_operand, ~rn_val, 1)); |
} |
break; |
} |
@@ -2105,8 +2084,8 @@ |
set_register(rd, alu_out); |
if (instr->HasS()) { |
SetNZFlags(alu_out); |
- SetCFlag(CarryFrom(rn_val, shifter_operand)); |
- SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); |
+ SetCFlag(CarryFrom(rn_val, shifter_operand, 0)); |
+ SetVFlag(OverflowFrom(rn_val, shifter_operand, 0)); |
} |
break; |
} |
@@ -2114,12 +2093,13 @@ |
case ADC: { |
// Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm"); |
// Format(instr, "adc'cond's 'rd, 'rn, 'imm"); |
- alu_out = rn_val + shifter_operand + (c_flag_ ? 1 : 0); |
+ carry_in = c_flag_ ? 1 : 0; |
+ alu_out = rn_val + shifter_operand + carry_in; |
set_register(rd, alu_out); |
if (instr->HasS()) { |
SetNZFlags(alu_out); |
- SetCFlag(CarryFrom(rn_val, shifter_operand)); |
- SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); |
+ SetCFlag(CarryFrom(rn_val, shifter_operand, carry_in)); |
+ SetVFlag(OverflowFrom(rn_val, shifter_operand, carry_in)); |
} |
break; |
} |
@@ -2127,12 +2107,13 @@ |
case SBC: { |
// Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm"); |
// Format(instr, "sbc'cond's 'rd, 'rn, 'imm"); |
- alu_out = rn_val - shifter_operand - (!c_flag_ ? 1 : 0); |
+ carry_in = c_flag_ ? 1 : 0; |
+ alu_out = rn_val + ~shifter_operand + carry_in; |
set_register(rd, alu_out); |
if (instr->HasS()) { |
SetNZFlags(alu_out); |
- SetCFlag(!BorrowFrom(rn_val, shifter_operand)); |
- SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); |
+ SetCFlag(CarryFrom(rn_val, ~shifter_operand, carry_in)); |
+ SetVFlag(OverflowFrom(rn_val, ~shifter_operand, carry_in)); |
} |
break; |
} |
@@ -2140,12 +2121,13 @@ |
case RSC: { |
// Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm"); |
// Format(instr, "rsc'cond's 'rd, 'rn, 'imm"); |
- alu_out = shifter_operand - rn_val - (!c_flag_ ? 1 : 0); |
+ carry_in = c_flag_ ? 1 : 0; |
+ alu_out = shifter_operand + ~rn_val + carry_in; |
set_register(rd, alu_out); |
if (instr->HasS()) { |
SetNZFlags(alu_out); |
- SetCFlag(!BorrowFrom(shifter_operand, rn_val)); |
- SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false)); |
+ SetCFlag(CarryFrom(shifter_operand, ~rn_val, carry_in)); |
+ SetVFlag(OverflowFrom(shifter_operand, ~rn_val, carry_in)); |
} |
break; |
} |
@@ -2182,8 +2164,8 @@ |
// Format(instr, "cmp'cond 'rn, 'imm"); |
alu_out = rn_val - shifter_operand; |
SetNZFlags(alu_out); |
- SetCFlag(!BorrowFrom(rn_val, shifter_operand)); |
- SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); |
+ SetCFlag(CarryFrom(rn_val, ~shifter_operand, 1)); |
+ SetVFlag(OverflowFrom(rn_val, ~shifter_operand, 1)); |
} else { |
UnimplementedInstruction(instr); |
} |
@@ -2196,8 +2178,8 @@ |
// Format(instr, "cmn'cond 'rn, 'imm"); |
alu_out = rn_val + shifter_operand; |
SetNZFlags(alu_out); |
- SetCFlag(CarryFrom(rn_val, shifter_operand)); |
- SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); |
+ SetCFlag(CarryFrom(rn_val, shifter_operand, 0)); |
+ SetVFlag(OverflowFrom(rn_val, shifter_operand, 0)); |
} else { |
UnimplementedInstruction(instr); |
} |