| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |