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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/simulator_arm.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include <setjmp.h> 5 #include <setjmp.h>
6 #include <stdlib.h> 6 #include <stdlib.h>
7 7
8 #include "vm/globals.h" 8 #include "vm/globals.h"
9 #if defined(TARGET_ARCH_ARM) 9 #if defined(TARGET_ARCH_ARM)
10 10
(...skipping 1203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1214 c_flag_ = val; 1214 c_flag_ = val;
1215 } 1215 }
1216 1216
1217 1217
1218 // Set the oVerflow flag. 1218 // Set the oVerflow flag.
1219 void Simulator::SetVFlag(bool val) { 1219 void Simulator::SetVFlag(bool val) {
1220 v_flag_ = val; 1220 v_flag_ = val;
1221 } 1221 }
1222 1222
1223 1223
1224 // Calculate C flag value for additions. 1224 // Calculate C flag value for additions (and subtractions with adjusted args).
1225 bool Simulator::CarryFrom(int32_t left, int32_t right) { 1225 bool Simulator::CarryFrom(int32_t left, int32_t right, int32_t carry) {
1226 uint32_t uleft = static_cast<uint32_t>(left); 1226 uint64_t uleft = static_cast<uint32_t>(left);
1227 uint32_t uright = static_cast<uint32_t>(right); 1227 uint64_t uright = static_cast<uint32_t>(right);
1228 uint32_t urest = 0xffffffffU - uleft; 1228 uint64_t ucarry = static_cast<uint32_t>(carry);
1229 1229 return ((uleft + uright + ucarry) >> 32) != 0;
1230 return (uright > urest);
1231 } 1230 }
1232 1231
1233 1232
1234 // Calculate C flag value for subtractions. 1233 // Calculate V flag value for additions (and subtractions with adjusted args).
1235 bool Simulator::BorrowFrom(int32_t left, int32_t right) { 1234 bool Simulator::OverflowFrom(int32_t left, int32_t right, int32_t carry) {
1236 uint32_t uleft = static_cast<uint32_t>(left); 1235 int64_t result = static_cast<int64_t>(left) + right + carry;
1237 uint32_t uright = static_cast<uint32_t>(right); 1236 return (result >> 31) != (result >> 32);
1238
1239 return (uright > uleft);
1240 }
1241
1242
1243 // Calculate V flag value for additions and subtractions.
1244 bool Simulator::OverflowFrom(int32_t alu_out,
1245 int32_t left, int32_t right, bool addition) {
1246 bool overflow;
1247 if (addition) {
1248 // operands have the same sign
1249 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0))
1250 // and operands and result have different sign
1251 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1252 } else {
1253 // operands have different signs
1254 overflow = ((left < 0 && right >= 0) || (left >= 0 && right < 0))
1255 // and first operand and result have different signs
1256 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0));
1257 }
1258 return overflow;
1259 } 1237 }
1260 1238
1261 1239
1262 // Addressing Mode 1 - Data-processing operands: 1240 // Addressing Mode 1 - Data-processing operands:
1263 // Get the value based on the shifter_operand with register. 1241 // Get the value based on the shifter_operand with register.
1264 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) { 1242 int32_t Simulator::GetShiftRm(Instr* instr, bool* carry_out) {
1265 Shift shift = instr->ShiftField(); 1243 Shift shift = instr->ShiftField();
1266 int shift_amount = instr->ShiftAmountField(); 1244 int shift_amount = instr->ShiftAmountField();
1267 int32_t result = get_register(instr->RmField()); 1245 int32_t result = get_register(instr->RmField());
1268 if (instr->Bit(4) == 0) { 1246 if (instr->Bit(4) == 0) {
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after
2038 Register rn = instr->RnField(); 2016 Register rn = instr->RnField();
2039 int32_t rn_val = get_register(rn); 2017 int32_t rn_val = get_register(rn);
2040 int32_t shifter_operand = 0; 2018 int32_t shifter_operand = 0;
2041 bool shifter_carry_out = 0; 2019 bool shifter_carry_out = 0;
2042 if (instr->TypeField() == 0) { 2020 if (instr->TypeField() == 0) {
2043 shifter_operand = GetShiftRm(instr, &shifter_carry_out); 2021 shifter_operand = GetShiftRm(instr, &shifter_carry_out);
2044 } else { 2022 } else {
2045 ASSERT(instr->TypeField() == 1); 2023 ASSERT(instr->TypeField() == 1);
2046 shifter_operand = GetImm(instr, &shifter_carry_out); 2024 shifter_operand = GetImm(instr, &shifter_carry_out);
2047 } 2025 }
2026 int32_t carry_in;
2048 int32_t alu_out; 2027 int32_t alu_out;
2049 2028
2050 switch (instr->OpcodeField()) { 2029 switch (instr->OpcodeField()) {
2051 case AND: { 2030 case AND: {
2052 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm"); 2031 // Format(instr, "and'cond's 'rd, 'rn, 'shift_rm");
2053 // Format(instr, "and'cond's 'rd, 'rn, 'imm"); 2032 // Format(instr, "and'cond's 'rd, 'rn, 'imm");
2054 alu_out = rn_val & shifter_operand; 2033 alu_out = rn_val & shifter_operand;
2055 set_register(rd, alu_out); 2034 set_register(rd, alu_out);
2056 if (instr->HasS()) { 2035 if (instr->HasS()) {
2057 SetNZFlags(alu_out); 2036 SetNZFlags(alu_out);
(...skipping 14 matching lines...) Expand all
2072 break; 2051 break;
2073 } 2052 }
2074 2053
2075 case SUB: { 2054 case SUB: {
2076 // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm"); 2055 // Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm");
2077 // Format(instr, "sub'cond's 'rd, 'rn, 'imm"); 2056 // Format(instr, "sub'cond's 'rd, 'rn, 'imm");
2078 alu_out = rn_val - shifter_operand; 2057 alu_out = rn_val - shifter_operand;
2079 set_register(rd, alu_out); 2058 set_register(rd, alu_out);
2080 if (instr->HasS()) { 2059 if (instr->HasS()) {
2081 SetNZFlags(alu_out); 2060 SetNZFlags(alu_out);
2082 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); 2061 SetCFlag(CarryFrom(rn_val, ~shifter_operand, 1));
2083 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); 2062 SetVFlag(OverflowFrom(rn_val, ~shifter_operand, 1));
2084 } 2063 }
2085 break; 2064 break;
2086 } 2065 }
2087 2066
2088 case RSB: { 2067 case RSB: {
2089 // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm"); 2068 // Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm");
2090 // Format(instr, "rsb'cond's 'rd, 'rn, 'imm"); 2069 // Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
2091 alu_out = shifter_operand - rn_val; 2070 alu_out = shifter_operand - rn_val;
2092 set_register(rd, alu_out); 2071 set_register(rd, alu_out);
2093 if (instr->HasS()) { 2072 if (instr->HasS()) {
2094 SetNZFlags(alu_out); 2073 SetNZFlags(alu_out);
2095 SetCFlag(!BorrowFrom(shifter_operand, rn_val)); 2074 SetCFlag(CarryFrom(shifter_operand, ~rn_val, 1));
2096 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false)); 2075 SetVFlag(OverflowFrom(shifter_operand, ~rn_val, 1));
2097 } 2076 }
2098 break; 2077 break;
2099 } 2078 }
2100 2079
2101 case ADD: { 2080 case ADD: {
2102 // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm"); 2081 // Format(instr, "add'cond's 'rd, 'rn, 'shift_rm");
2103 // Format(instr, "add'cond's 'rd, 'rn, 'imm"); 2082 // Format(instr, "add'cond's 'rd, 'rn, 'imm");
2104 alu_out = rn_val + shifter_operand; 2083 alu_out = rn_val + shifter_operand;
2105 set_register(rd, alu_out); 2084 set_register(rd, alu_out);
2106 if (instr->HasS()) { 2085 if (instr->HasS()) {
2107 SetNZFlags(alu_out); 2086 SetNZFlags(alu_out);
2108 SetCFlag(CarryFrom(rn_val, shifter_operand)); 2087 SetCFlag(CarryFrom(rn_val, shifter_operand, 0));
2109 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 2088 SetVFlag(OverflowFrom(rn_val, shifter_operand, 0));
2110 } 2089 }
2111 break; 2090 break;
2112 } 2091 }
2113 2092
2114 case ADC: { 2093 case ADC: {
2115 // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm"); 2094 // Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm");
2116 // Format(instr, "adc'cond's 'rd, 'rn, 'imm"); 2095 // Format(instr, "adc'cond's 'rd, 'rn, 'imm");
2117 alu_out = rn_val + shifter_operand + (c_flag_ ? 1 : 0); 2096 carry_in = c_flag_ ? 1 : 0;
2097 alu_out = rn_val + shifter_operand + carry_in;
2118 set_register(rd, alu_out); 2098 set_register(rd, alu_out);
2119 if (instr->HasS()) { 2099 if (instr->HasS()) {
2120 SetNZFlags(alu_out); 2100 SetNZFlags(alu_out);
2121 SetCFlag(CarryFrom(rn_val, shifter_operand)); 2101 SetCFlag(CarryFrom(rn_val, shifter_operand, carry_in));
2122 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 2102 SetVFlag(OverflowFrom(rn_val, shifter_operand, carry_in));
2123 } 2103 }
2124 break; 2104 break;
2125 } 2105 }
2126 2106
2127 case SBC: { 2107 case SBC: {
2128 // Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm"); 2108 // Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm");
2129 // Format(instr, "sbc'cond's 'rd, 'rn, 'imm"); 2109 // Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
2130 alu_out = rn_val - shifter_operand - (!c_flag_ ? 1 : 0); 2110 carry_in = c_flag_ ? 1 : 0;
2111 alu_out = rn_val + ~shifter_operand + carry_in;
2131 set_register(rd, alu_out); 2112 set_register(rd, alu_out);
2132 if (instr->HasS()) { 2113 if (instr->HasS()) {
2133 SetNZFlags(alu_out); 2114 SetNZFlags(alu_out);
2134 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); 2115 SetCFlag(CarryFrom(rn_val, ~shifter_operand, carry_in));
2135 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); 2116 SetVFlag(OverflowFrom(rn_val, ~shifter_operand, carry_in));
2136 } 2117 }
2137 break; 2118 break;
2138 } 2119 }
2139 2120
2140 case RSC: { 2121 case RSC: {
2141 // Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm"); 2122 // Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm");
2142 // Format(instr, "rsc'cond's 'rd, 'rn, 'imm"); 2123 // Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
2143 alu_out = shifter_operand - rn_val - (!c_flag_ ? 1 : 0); 2124 carry_in = c_flag_ ? 1 : 0;
2125 alu_out = shifter_operand + ~rn_val + carry_in;
2144 set_register(rd, alu_out); 2126 set_register(rd, alu_out);
2145 if (instr->HasS()) { 2127 if (instr->HasS()) {
2146 SetNZFlags(alu_out); 2128 SetNZFlags(alu_out);
2147 SetCFlag(!BorrowFrom(shifter_operand, rn_val)); 2129 SetCFlag(CarryFrom(shifter_operand, ~rn_val, carry_in));
2148 SetVFlag(OverflowFrom(alu_out, shifter_operand, rn_val, false)); 2130 SetVFlag(OverflowFrom(shifter_operand, ~rn_val, carry_in));
2149 } 2131 }
2150 break; 2132 break;
2151 } 2133 }
2152 2134
2153 case TST: { 2135 case TST: {
2154 if (instr->HasS()) { 2136 if (instr->HasS()) {
2155 // Format(instr, "tst'cond 'rn, 'shift_rm"); 2137 // Format(instr, "tst'cond 'rn, 'shift_rm");
2156 // Format(instr, "tst'cond 'rn, 'imm"); 2138 // Format(instr, "tst'cond 'rn, 'imm");
2157 alu_out = rn_val & shifter_operand; 2139 alu_out = rn_val & shifter_operand;
2158 SetNZFlags(alu_out); 2140 SetNZFlags(alu_out);
(...skipping 16 matching lines...) Expand all
2175 } 2157 }
2176 break; 2158 break;
2177 } 2159 }
2178 2160
2179 case CMP: { 2161 case CMP: {
2180 if (instr->HasS()) { 2162 if (instr->HasS()) {
2181 // Format(instr, "cmp'cond 'rn, 'shift_rm"); 2163 // Format(instr, "cmp'cond 'rn, 'shift_rm");
2182 // Format(instr, "cmp'cond 'rn, 'imm"); 2164 // Format(instr, "cmp'cond 'rn, 'imm");
2183 alu_out = rn_val - shifter_operand; 2165 alu_out = rn_val - shifter_operand;
2184 SetNZFlags(alu_out); 2166 SetNZFlags(alu_out);
2185 SetCFlag(!BorrowFrom(rn_val, shifter_operand)); 2167 SetCFlag(CarryFrom(rn_val, ~shifter_operand, 1));
2186 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, false)); 2168 SetVFlag(OverflowFrom(rn_val, ~shifter_operand, 1));
2187 } else { 2169 } else {
2188 UnimplementedInstruction(instr); 2170 UnimplementedInstruction(instr);
2189 } 2171 }
2190 break; 2172 break;
2191 } 2173 }
2192 2174
2193 case CMN: { 2175 case CMN: {
2194 if (instr->HasS()) { 2176 if (instr->HasS()) {
2195 // Format(instr, "cmn'cond 'rn, 'shift_rm"); 2177 // Format(instr, "cmn'cond 'rn, 'shift_rm");
2196 // Format(instr, "cmn'cond 'rn, 'imm"); 2178 // Format(instr, "cmn'cond 'rn, 'imm");
2197 alu_out = rn_val + shifter_operand; 2179 alu_out = rn_val + shifter_operand;
2198 SetNZFlags(alu_out); 2180 SetNZFlags(alu_out);
2199 SetCFlag(CarryFrom(rn_val, shifter_operand)); 2181 SetCFlag(CarryFrom(rn_val, shifter_operand, 0));
2200 SetVFlag(OverflowFrom(alu_out, rn_val, shifter_operand, true)); 2182 SetVFlag(OverflowFrom(rn_val, shifter_operand, 0));
2201 } else { 2183 } else {
2202 UnimplementedInstruction(instr); 2184 UnimplementedInstruction(instr);
2203 } 2185 }
2204 break; 2186 break;
2205 } 2187 }
2206 2188
2207 case ORR: { 2189 case ORR: {
2208 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm"); 2190 // Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm");
2209 // Format(instr, "orr'cond's 'rd, 'rn, 'imm"); 2191 // Format(instr, "orr'cond's 'rd, 'rn, 'imm");
2210 alu_out = rn_val | shifter_operand; 2192 alu_out = rn_val | shifter_operand;
(...skipping 1655 matching lines...) Expand 10 before | Expand all | Expand 10 after
3866 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception)); 3848 set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception));
3867 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace)); 3849 set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace));
3868 buf->Longjmp(); 3850 buf->Longjmp();
3869 } 3851 }
3870 3852
3871 } // namespace dart 3853 } // namespace dart
3872 3854
3873 #endif // !defined(HOST_ARCH_ARM) 3855 #endif // !defined(HOST_ARCH_ARM)
3874 3856
3875 #endif // defined TARGET_ARCH_ARM 3857 #endif // defined TARGET_ARCH_ARM
OLDNEW
« 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