Chromium Code Reviews| 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 1234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1245 set_fcsr_bit(kFCSROverflowFlagBit, true); | 1245 set_fcsr_bit(kFCSROverflowFlagBit, true); |
| 1246 // The reference is not really clear but it seems this is required: | 1246 // The reference is not really clear but it seems this is required: |
| 1247 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1247 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
| 1248 ret = true; | 1248 ret = true; |
| 1249 } | 1249 } |
| 1250 | 1250 |
| 1251 return ret; | 1251 return ret; |
| 1252 } | 1252 } |
| 1253 | 1253 |
| 1254 | 1254 |
| 1255 // for cvt instructions only | |
|
paul.l...
2015/04/27 05:12:50
Style nit: Comments should start with capital lett
Djordje.Pesic
2015/04/27 12:46:58
I've dropped the comment
| |
| 1256 void Simulator::round_according_to_fcsr(double toRound, double& rounded, | |
| 1257 int32_t& rounded_int, double fs) { | |
| 1258 // 0 RN (round to nearest): Round a result to the nearest | |
| 1259 // representable value; if the result is exactly halfway between | |
| 1260 // two representable values, round to zero. Behave like round_w_d | |
| 1261 | |
| 1262 // 1 RZ (round toward zero): Round a result to the closest | |
| 1263 // representable value whose absolute value is less than or | |
| 1264 // equal to the infinitely accurate result. Behave like trunc_w_d | |
| 1265 | |
| 1266 // 2 RP (round up, or toward +infinity): Round a result to the | |
| 1267 // next representable value up. Behave like ceil_w_d | |
| 1268 | |
| 1269 // 3 RN (round down, or toward −infinity): Round a result to | |
| 1270 // the next representable value down. Behave like floor_w_d | |
| 1271 switch (FCSR_ & 3) { | |
| 1272 case kRoundToNearest: | |
| 1273 rounded = std::floor(fs + 0.5); | |
| 1274 rounded_int = static_cast<int32_t>(rounded); | |
| 1275 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { | |
| 1276 // If the number is halfway between two integers, | |
| 1277 // round to the even one. | |
| 1278 rounded_int--; | |
| 1279 } | |
| 1280 break; | |
| 1281 case kRoundToZero: | |
| 1282 rounded = trunc(fs); | |
| 1283 rounded_int = static_cast<int32_t>(rounded); | |
| 1284 break; | |
| 1285 case kRoundToPlusInf: | |
| 1286 rounded = std::ceil(fs); | |
| 1287 rounded_int = static_cast<int32_t>(rounded); | |
| 1288 break; | |
| 1289 case kRoundToMinusInf: | |
| 1290 rounded = std::floor(fs); | |
| 1291 rounded_int = static_cast<int32_t>(rounded); | |
| 1292 break; | |
| 1293 } | |
| 1294 } | |
| 1295 | |
| 1296 | |
| 1297 // for cvt instructions only | |
| 1298 void Simulator::round64_according_to_fcsr(double toRound, double& rounded, | |
| 1299 int64_t& rounded_int, double fs) { | |
| 1300 // 0 RN (round to nearest): Round a result to the nearest | |
| 1301 // representable value; if the result is exactly halfway between | |
| 1302 // two representable values, round to zero. Behave like round_w_d | |
| 1303 | |
| 1304 // 1 RZ (round toward zero): Round a result to the closest | |
| 1305 // representable value whose absolute value is less than or | |
| 1306 // equal to the infinitely accurate result. Behave like trunc_w_d | |
| 1307 | |
| 1308 // 2 RP (round up, or toward +infinity): Round a result to the | |
| 1309 // next representable value up. Behave like ceil_w_d | |
| 1310 | |
| 1311 // 3 RN (round down, or toward −infinity): Round a result to | |
| 1312 // the next representable value down. Behave like floor_w_d | |
| 1313 switch (FCSR_ & 3) { | |
| 1314 case kRoundToNearest: | |
| 1315 rounded = std::floor(fs + 0.5); | |
| 1316 rounded_int = static_cast<int64_t>(rounded); | |
| 1317 if ((rounded_int & 1) != 0 && rounded_int - fs == 0.5) { | |
| 1318 // If the number is halfway between two integers, | |
| 1319 // round to the even one. | |
| 1320 rounded_int--; | |
| 1321 } | |
| 1322 break; | |
| 1323 case kRoundToZero: | |
| 1324 rounded = trunc(fs); | |
| 1325 rounded_int = static_cast<int64_t>(rounded); | |
| 1326 break; | |
| 1327 case kRoundToPlusInf: | |
| 1328 rounded = std::ceil(fs); | |
| 1329 rounded_int = static_cast<int64_t>(rounded); | |
| 1330 break; | |
| 1331 case kRoundToMinusInf: | |
| 1332 rounded = std::floor(fs); | |
| 1333 rounded_int = static_cast<int64_t>(rounded); | |
| 1334 break; | |
| 1335 } | |
| 1336 } | |
| 1337 | |
| 1338 | |
| 1255 // Raw access to the PC register. | 1339 // Raw access to the PC register. |
| 1256 void Simulator::set_pc(int64_t value) { | 1340 void Simulator::set_pc(int64_t value) { |
| 1257 pc_modified_ = true; | 1341 pc_modified_ = true; |
| 1258 registers_[pc] = value; | 1342 registers_[pc] = value; |
| 1259 } | 1343 } |
| 1260 | 1344 |
| 1261 | 1345 |
| 1262 bool Simulator::has_bad_pc() const { | 1346 bool Simulator::has_bad_pc() const { |
| 1263 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); | 1347 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc)); |
| 1264 } | 1348 } |
| (...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2343 double ft, fs, fd; | 2427 double ft, fs, fd; |
| 2344 uint32_t cc, fcsr_cc; | 2428 uint32_t cc, fcsr_cc; |
| 2345 fs = get_fpu_register_double(fs_reg); | 2429 fs = get_fpu_register_double(fs_reg); |
| 2346 ft = get_fpu_register_double(ft_reg); | 2430 ft = get_fpu_register_double(ft_reg); |
| 2347 fd = get_fpu_register_double(fd_reg); | 2431 fd = get_fpu_register_double(fd_reg); |
| 2348 cc = instr->FCccValue(); | 2432 cc = instr->FCccValue(); |
| 2349 fcsr_cc = get_fcsr_condition_bit(cc); | 2433 fcsr_cc = get_fcsr_condition_bit(cc); |
| 2350 int64_t ft_int = bit_cast<int64_t>(ft); | 2434 int64_t ft_int = bit_cast<int64_t>(ft); |
| 2351 int64_t fd_int = bit_cast<int64_t>(fd); | 2435 int64_t fd_int = bit_cast<int64_t>(fd); |
| 2352 switch (instr->FunctionFieldRaw()) { | 2436 switch (instr->FunctionFieldRaw()) { |
| 2437 case RINT: { | |
| 2438 DCHECK(kArchVariant == kMips64r6); | |
| 2439 double result, temp, temp_result; | |
| 2440 double upper = std::ceil(fs); | |
| 2441 double lower = std::floor(fs); | |
| 2442 switch (FCSR_ & 0x3) { | |
| 2443 case kRoundToNearest: | |
| 2444 if (upper - fs < fs - lower) { | |
| 2445 result = upper; | |
| 2446 } else if (upper - fs > fs - lower) { | |
| 2447 result = lower; | |
| 2448 } else { | |
| 2449 temp_result = upper / 2; | |
| 2450 double reminder = modf(temp_result, &temp); | |
| 2451 if (reminder == 0) { | |
| 2452 result = upper; | |
| 2453 } else { | |
| 2454 result = lower; | |
| 2455 } | |
| 2456 } | |
| 2457 break; | |
| 2458 case kRoundToZero: | |
| 2459 result = (fs > 0 ? lower : upper); | |
| 2460 break; | |
| 2461 case kRoundToPlusInf: | |
| 2462 result = upper; | |
| 2463 break; | |
| 2464 case kRoundToMinusInf: | |
| 2465 result = lower; | |
| 2466 break; | |
| 2467 } | |
| 2468 set_fpu_register_double(fd_reg, result); | |
| 2469 if (result != fs) { | |
| 2470 set_fcsr_bit(kFCSRInexactFlagBit, true); | |
| 2471 } | |
| 2472 break; | |
| 2473 } | |
| 2353 case SEL: | 2474 case SEL: |
| 2354 DCHECK(kArchVariant == kMips64r6); | 2475 DCHECK(kArchVariant == kMips64r6); |
| 2355 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); | 2476 set_fpu_register_double(fd_reg, (fd_int & 0x1) == 0 ? fs : ft); |
| 2356 break; | 2477 break; |
| 2357 case SELEQZ_C: | 2478 case SELEQZ_C: |
| 2358 DCHECK(kArchVariant == kMips64r6); | 2479 DCHECK(kArchVariant == kMips64r6); |
| 2359 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); | 2480 set_fpu_register_double(fd_reg, (ft_int & 0x1) == 0 ? fs : 0.0); |
| 2360 break; | 2481 break; |
| 2361 case SELNEZ_C: | 2482 case SELNEZ_C: |
| 2362 DCHECK(kArchVariant == kMips64r6); | 2483 DCHECK(kArchVariant == kMips64r6); |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2426 break; | 2547 break; |
| 2427 case C_ULT_D: | 2548 case C_ULT_D: |
| 2428 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); | 2549 set_fcsr_bit(fcsr_cc, (fs < ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2429 break; | 2550 break; |
| 2430 case C_OLE_D: | 2551 case C_OLE_D: |
| 2431 set_fcsr_bit(fcsr_cc, (fs <= ft)); | 2552 set_fcsr_bit(fcsr_cc, (fs <= ft)); |
| 2432 break; | 2553 break; |
| 2433 case C_ULE_D: | 2554 case C_ULE_D: |
| 2434 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 2555 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
| 2435 break; | 2556 break; |
| 2436 case CVT_W_D: // Convert double to word. | 2557 case CVT_W_D: { // Convert double to word. |
| 2437 // Rounding modes are not yet supported. | 2558 double rounded; |
| 2438 DCHECK((FCSR_ & 3) == 0); | 2559 int32_t result; |
| 2439 // In rounding mode 0 it should behave like ROUND. | 2560 round_according_to_fcsr(fs, rounded, result, fs); |
| 2440 // No break. | 2561 set_fpu_register_word(fd_reg, result); |
| 2562 if (set_fcsr_round_error(fs, rounded)) { | |
| 2563 set_fpu_register_word(fd_reg, kFPUInvalidResult); | |
| 2564 } | |
| 2565 break; | |
| 2566 } | |
| 2441 case ROUND_W_D: // Round double to word (round half to even). | 2567 case ROUND_W_D: // Round double to word (round half to even). |
| 2442 { | 2568 { |
| 2443 double rounded = std::floor(fs + 0.5); | 2569 double rounded = std::floor(fs + 0.5); |
| 2444 int32_t result = static_cast<int32_t>(rounded); | 2570 int32_t result = static_cast<int32_t>(rounded); |
| 2445 if ((result & 1) != 0 && result - fs == 0.5) { | 2571 if ((result & 1) != 0 && result - fs == 0.5) { |
| 2446 // If the number is halfway between two integers, | 2572 // If the number is halfway between two integers, |
| 2447 // round to the even one. | 2573 // round to the even one. |
| 2448 result--; | 2574 result--; |
| 2449 } | 2575 } |
| 2450 set_fpu_register_word(fd_reg, result); | 2576 set_fpu_register_word(fd_reg, result); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 2475 double rounded = std::ceil(fs); | 2601 double rounded = std::ceil(fs); |
| 2476 int32_t result = static_cast<int32_t>(rounded); | 2602 int32_t result = static_cast<int32_t>(rounded); |
| 2477 set_fpu_register_word(fd_reg, result); | 2603 set_fpu_register_word(fd_reg, result); |
| 2478 if (set_fcsr_round_error(fs, rounded)) { | 2604 if (set_fcsr_round_error(fs, rounded)) { |
| 2479 set_fpu_register(fd_reg, kFPUInvalidResult); | 2605 set_fpu_register(fd_reg, kFPUInvalidResult); |
| 2480 } | 2606 } |
| 2481 } break; | 2607 } break; |
| 2482 case CVT_S_D: // Convert double to float (single). | 2608 case CVT_S_D: // Convert double to float (single). |
| 2483 set_fpu_register_float(fd_reg, static_cast<float>(fs)); | 2609 set_fpu_register_float(fd_reg, static_cast<float>(fs)); |
| 2484 break; | 2610 break; |
| 2485 case CVT_L_D: // Mips64r2: Truncate double to 64-bit long-word. | 2611 case CVT_L_D: { // Mips64r2: Truncate double to 64-bit long-word. |
| 2486 // Rounding modes are not yet supported. | 2612 double rounded; |
| 2487 DCHECK((FCSR_ & 3) == 0); | 2613 int64_t result; |
| 2488 // In rounding mode 0 it should behave like ROUND. | 2614 round64_according_to_fcsr(fs, rounded, result, fs); |
| 2489 // No break. | 2615 set_fpu_register(fd_reg, result); |
| 2616 if (set_fcsr_round64_error(fs, rounded)) { | |
| 2617 set_fpu_register(fd_reg, kFPUInvalidResult); | |
| 2618 } | |
| 2619 break; | |
| 2620 } | |
| 2490 case ROUND_L_D: { // Mips64r2 instruction. | 2621 case ROUND_L_D: { // Mips64r2 instruction. |
| 2491 // check error cases | 2622 // check error cases |
| 2492 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); | 2623 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5); |
| 2493 int64_t result = static_cast<int64_t>(rounded); | 2624 int64_t result = static_cast<int64_t>(rounded); |
| 2494 set_fpu_register(fd_reg, result); | 2625 set_fpu_register(fd_reg, result); |
| 2495 if (set_fcsr_round64_error(fs, rounded)) { | 2626 if (set_fcsr_round64_error(fs, rounded)) { |
| 2496 set_fpu_register(fd_reg, kFPU64InvalidResult); | 2627 set_fpu_register(fd_reg, kFPU64InvalidResult); |
| 2497 } | 2628 } |
| 2498 break; | 2629 break; |
| 2499 } | 2630 } |
| (...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3616 uintptr_t Simulator::PopAddress() { | 3747 uintptr_t Simulator::PopAddress() { |
| 3617 int64_t current_sp = get_register(sp); | 3748 int64_t current_sp = get_register(sp); |
| 3618 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); | 3749 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); |
| 3619 uintptr_t address = *stack_slot; | 3750 uintptr_t address = *stack_slot; |
| 3620 set_register(sp, current_sp + sizeof(uintptr_t)); | 3751 set_register(sp, current_sp + sizeof(uintptr_t)); |
| 3621 return address; | 3752 return address; |
| 3622 } | 3753 } |
| 3623 | 3754 |
| 3624 | 3755 |
| 3625 #undef UNSUPPORTED | 3756 #undef UNSUPPORTED |
| 3626 | |
| 3627 } } // namespace v8::internal | 3757 } } // namespace v8::internal |
| 3628 | 3758 |
| 3629 #endif // USE_SIMULATOR | 3759 #endif // USE_SIMULATOR |
| 3630 | 3760 |
| 3631 #endif // V8_TARGET_ARCH_MIPS64 | 3761 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |