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

Unified Diff: runtime/vm/simulator_arm.cc

Issue 623823003: Fix carry out calculation in ARM simulator. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 2 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 | « runtime/vm/simulator_arm.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
« no previous file with comments | « runtime/vm/simulator_arm.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698