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