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 |