OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits.h> | 5 #include <limits.h> |
6 #include <stdarg.h> | 6 #include <stdarg.h> |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "src/v8.h" | 10 #include "src/v8.h" |
(...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1265 FCSR_ &= ~(1 << cc); | 1265 FCSR_ &= ~(1 << cc); |
1266 } | 1266 } |
1267 } | 1267 } |
1268 | 1268 |
1269 | 1269 |
1270 bool Simulator::test_fcsr_bit(uint32_t cc) { | 1270 bool Simulator::test_fcsr_bit(uint32_t cc) { |
1271 return FCSR_ & (1 << cc); | 1271 return FCSR_ & (1 << cc); |
1272 } | 1272 } |
1273 | 1273 |
1274 | 1274 |
1275 void Simulator::set_fcsr_rounding_mode(FPURoundingMode mode) { FCSR_ |= mode; } | |
paul.l...
2015/04/27 05:12:50
Maybe you should ensure this call does not trash o
Djordje.Pesic
2015/04/27 12:46:58
Done.
| |
1276 | |
1277 | |
1278 unsigned int Simulator::get_fcsr_rounding_mode() { return FCSR_ & 0x3; } | |
1279 | |
1280 | |
1275 // Sets the rounding error codes in FCSR based on the result of the rounding. | 1281 // Sets the rounding error codes in FCSR based on the result of the rounding. |
1276 // Returns true if the operation was invalid. | 1282 // Returns true if the operation was invalid. |
1277 bool Simulator::set_fcsr_round_error(double original, double rounded) { | 1283 bool Simulator::set_fcsr_round_error(double original, double rounded) { |
1278 bool ret = false; | 1284 bool ret = false; |
1279 double max_int32 = std::numeric_limits<int32_t>::max(); | 1285 double max_int32 = std::numeric_limits<int32_t>::max(); |
1280 double min_int32 = std::numeric_limits<int32_t>::min(); | 1286 double min_int32 = std::numeric_limits<int32_t>::min(); |
1281 | 1287 |
1282 if (!std::isfinite(original) || !std::isfinite(rounded)) { | 1288 if (!std::isfinite(original) || !std::isfinite(rounded)) { |
1283 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1289 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
1284 ret = true; | 1290 ret = true; |
(...skipping 12 matching lines...) Expand all Loading... | |
1297 set_fcsr_bit(kFCSROverflowFlagBit, true); | 1303 set_fcsr_bit(kFCSROverflowFlagBit, true); |
1298 // The reference is not really clear but it seems this is required: | 1304 // The reference is not really clear but it seems this is required: |
1299 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1305 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
1300 ret = true; | 1306 ret = true; |
1301 } | 1307 } |
1302 | 1308 |
1303 return ret; | 1309 return ret; |
1304 } | 1310 } |
1305 | 1311 |
1306 | 1312 |
1313 void Simulator::round_according_to_fcsr(double toRound, double& rounded, | |
1314 int32_t& rounded_int, double fs) { | |
1315 // 0 RN (round to nearest): Round a result to the nearest | |
1316 // representable value; if the result is exactly halfway between | |
1317 // two representable values, round to zero. Behave like round_w_d | |
paul.l...
2015/04/27 05:12:49
nit: period at end of this sentence, and 3 more be
Djordje.Pesic
2015/04/27 12:46:58
Done.
| |
1318 | |
1319 // 1 RZ (round toward zero): Round a result to the closest | |
1320 // representable value whose absolute value is less than or | |
1321 // equal to the infinitely accurate result. Behave like trunc_w_d | |
1322 | |
1323 // 2 RP (round up, or toward infinity): Round a result to the | |
1324 // next representable value up. Behave like ceil_w_d | |
1325 | |
1326 // 3 RD (round down, or toward −infinity): Round a result to | |
1327 // the next representable value down. Behave like floor_w_d | |
1328 switch (get_fcsr_rounding_mode()) { | |
1329 case kRoundToNearest: | |
1330 rounded = std::floor(fs + 0.5); | |
1331 rounded_int = static_cast<int32_t>(rounded); | |
1332 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { | |
1333 // If the number is halfway between two integers, | |
1334 // round to the even one. | |
1335 rounded_int--; | |
1336 } | |
1337 break; | |
1338 case kRoundToZero: | |
1339 rounded = trunc(fs); | |
1340 rounded_int = static_cast<int32_t>(rounded); | |
1341 break; | |
1342 case kRoundToPlusInf: | |
1343 rounded = std::ceil(fs); | |
1344 rounded_int = static_cast<int32_t>(rounded); | |
1345 break; | |
1346 case kRoundToMinusInf: | |
1347 rounded = std::floor(fs); | |
1348 rounded_int = static_cast<int32_t>(rounded); | |
1349 break; | |
1350 } | |
1351 } | |
1352 | |
1353 | |
1307 // Raw access to the PC register. | 1354 // Raw access to the PC register. |
1308 void Simulator::set_pc(int32_t value) { | 1355 void Simulator::set_pc(int32_t value) { |
1309 pc_modified_ = true; | 1356 pc_modified_ = true; |
1310 registers_[pc] = value; | 1357 registers_[pc] = value; |
1311 } | 1358 } |
1312 | 1359 |
1313 | 1360 |
1314 bool Simulator::has_bad_pc() const { | 1361 bool Simulator::has_bad_pc() const { |
1315 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); | 1362 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); |
1316 } | 1363 } |
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2139 double ft, fs, fd; | 2186 double ft, fs, fd; |
2140 uint32_t cc, fcsr_cc; | 2187 uint32_t cc, fcsr_cc; |
2141 int64_t i64; | 2188 int64_t i64; |
2142 fs = get_fpu_register_double(fs_reg); | 2189 fs = get_fpu_register_double(fs_reg); |
2143 ft = get_fpu_register_double(ft_reg); | 2190 ft = get_fpu_register_double(ft_reg); |
2144 int64_t ft_int = bit_cast<int64_t>(ft); | 2191 int64_t ft_int = bit_cast<int64_t>(ft); |
2145 int64_t fd_int = bit_cast<int64_t>(fd); | 2192 int64_t fd_int = bit_cast<int64_t>(fd); |
2146 cc = instr->FCccValue(); | 2193 cc = instr->FCccValue(); |
2147 fcsr_cc = get_fcsr_condition_bit(cc); | 2194 fcsr_cc = get_fcsr_condition_bit(cc); |
2148 switch (instr->FunctionFieldRaw()) { | 2195 switch (instr->FunctionFieldRaw()) { |
2196 case RINT: { | |
2197 DCHECK(IsMipsArchVariant(kMips32r6)); | |
2198 double result, temp, temp_result; | |
2199 double upper = std::ceil(fs); | |
2200 double lower = std::floor(fs); | |
2201 switch (get_fcsr_rounding_mode()) { | |
2202 case kRoundToNearest: | |
2203 if (upper - fs < fs - lower) { | |
2204 result = upper; | |
2205 } else if (upper - fs > fs - lower) { | |
2206 result = lower; | |
2207 } else { | |
2208 temp_result = upper / 2; | |
2209 double reminder = modf(temp_result, &temp); | |
2210 if (reminder == 0) { | |
2211 result = upper; | |
2212 } else { | |
2213 result = lower; | |
2214 } | |
2215 } | |
2216 break; | |
2217 case kRoundToZero: | |
2218 result = (fs > 0 ? lower : upper); | |
2219 break; | |
2220 case kRoundToPlusInf: | |
2221 result = upper; | |
2222 break; | |
2223 case kRoundToMinusInf: | |
2224 result = lower; | |
2225 break; | |
2226 } | |
2227 set_fpu_register_double(fd_reg, result); | |
2228 if (result != fs) { | |
2229 set_fcsr_bit(kFCSRInexactFlagBit, true); | |
2230 } | |
2231 break; | |
2232 } | |
2149 case SEL: | 2233 case SEL: |
2150 DCHECK(IsMipsArchVariant(kMips32r6)); | 2234 DCHECK(IsMipsArchVariant(kMips32r6)); |
2151 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); | 2235 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); |
2152 break; | 2236 break; |
2153 case SELEQZ_C: | 2237 case SELEQZ_C: |
2154 DCHECK(IsMipsArchVariant(kMips32r6)); | 2238 DCHECK(IsMipsArchVariant(kMips32r6)); |
2155 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); | 2239 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); |
2156 break; | 2240 break; |
2157 case SELNEZ_C: | 2241 case SELNEZ_C: |
2158 DCHECK(IsMipsArchVariant(kMips32r6)); | 2242 DCHECK(IsMipsArchVariant(kMips32r6)); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2223 break; | 2307 break; |
2224 case C_ULT_D: | 2308 case C_ULT_D: |
2225 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 2309 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
2226 break; | 2310 break; |
2227 case C_OLE_D: | 2311 case C_OLE_D: |
2228 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 2312 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
2229 break; | 2313 break; |
2230 case C_ULE_D: | 2314 case C_ULE_D: |
2231 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 2315 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
2232 break; | 2316 break; |
2233 case CVT_W_D: // Convert double to word. | 2317 case CVT_W_D: { // Convert double to word. |
2234 // Rounding modes are not yet supported. | 2318 double rounded; |
2235 DCHECK((FCSR_ & 3) == 0); | 2319 int32_t result; |
2236 // In rounding mode 0 it should behave like ROUND. | 2320 round_according_to_fcsr(fs, rounded, result, fs); |
2321 set_fpu_register_word(fd_reg, result); | |
2322 if (set_fcsr_round_error(fs, rounded)) { | |
2323 set_fpu_register_word(fd_reg, kFPUInvalidResult); | |
2324 } | |
2325 } break; | |
2237 case ROUND_W_D: // Round double to word (round half to even). | 2326 case ROUND_W_D: // Round double to word (round half to even). |
2238 { | 2327 { |
2239 double rounded = std::floor(fs + 0.5); | 2328 double rounded = std::floor(fs + 0.5); |
2240 int32_t result = static_cast<int32_t>(rounded); | 2329 int32_t result = static_cast<int32_t>(rounded); |
2241 if ((result & 1) != 0 && result - fs == 0.5) { | 2330 if ((result & 1) != 0 && result - fs == 0.5) { |
2242 // If the number is halfway between two integers, | 2331 // If the number is halfway between two integers, |
2243 // round to the even one. | 2332 // round to the even one. |
2244 result--; | 2333 result--; |
2245 } | 2334 } |
2246 set_fpu_register_word(fd_reg, result); | 2335 set_fpu_register_word(fd_reg, result); |
(...skipping 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3441 } | 3530 } |
3442 | 3531 |
3443 | 3532 |
3444 #undef UNSUPPORTED | 3533 #undef UNSUPPORTED |
3445 | 3534 |
3446 } } // namespace v8::internal | 3535 } } // namespace v8::internal |
3447 | 3536 |
3448 #endif // USE_SIMULATOR | 3537 #endif // USE_SIMULATOR |
3449 | 3538 |
3450 #endif // V8_TARGET_ARCH_MIPS | 3539 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |