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 #if V8_TARGET_ARCH_MIPS64 | 10 #if V8_TARGET_ARCH_MIPS64 |
(...skipping 880 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 break_instr_ = 0; | 891 break_instr_ = 0; |
892 | 892 |
893 // Set up architecture state. | 893 // Set up architecture state. |
894 // All registers are initialized to zero to start with. | 894 // All registers are initialized to zero to start with. |
895 for (int i = 0; i < kNumSimuRegisters; i++) { | 895 for (int i = 0; i < kNumSimuRegisters; i++) { |
896 registers_[i] = 0; | 896 registers_[i] = 0; |
897 } | 897 } |
898 for (int i = 0; i < kNumFPURegisters; i++) { | 898 for (int i = 0; i < kNumFPURegisters; i++) { |
899 FPUregisters_[i] = 0; | 899 FPUregisters_[i] = 0; |
900 } | 900 } |
901 FCSR_ = 0; | 901 |
| 902 if (kArchVariant == kMips64r6) { |
| 903 FCSR_ = kFCSRNaN2008FlagMask; |
| 904 } else { |
| 905 FCSR_ = 0; |
| 906 } |
902 | 907 |
903 // The sp is initialized to point to the bottom (high address) of the | 908 // The sp is initialized to point to the bottom (high address) of the |
904 // allocated stack area. To be safe in potential stack underflows we leave | 909 // allocated stack area. To be safe in potential stack underflows we leave |
905 // some buffer below. | 910 // some buffer below. |
906 registers_[sp] = reinterpret_cast<int64_t>(stack_) + stack_size_ - 64; | 911 registers_[sp] = reinterpret_cast<int64_t>(stack_) + stack_size_ - 64; |
907 // The ra and pc are initialized to a known bad value that will cause an | 912 // The ra and pc are initialized to a known bad value that will cause an |
908 // access violation if the simulator ever tries to execute it. | 913 // access violation if the simulator ever tries to execute it. |
909 registers_[pc] = bad_ra; | 914 registers_[pc] = bad_ra; |
910 registers_[ra] = bad_ra; | 915 registers_[ra] = bad_ra; |
911 InitializeCoverage(); | 916 InitializeCoverage(); |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1308 if (rounded > max_int32 || rounded < min_int32) { | 1313 if (rounded > max_int32 || rounded < min_int32) { |
1309 set_fcsr_bit(kFCSROverflowFlagBit, true); | 1314 set_fcsr_bit(kFCSROverflowFlagBit, true); |
1310 // The reference is not really clear but it seems this is required: | 1315 // The reference is not really clear but it seems this is required: |
1311 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1316 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
1312 ret = true; | 1317 ret = true; |
1313 } | 1318 } |
1314 | 1319 |
1315 return ret; | 1320 return ret; |
1316 } | 1321 } |
1317 | 1322 |
| 1323 void Simulator::set_fpu_register_word_invalid_result(float original, |
| 1324 float rounded) { |
| 1325 if (FCSR_ & kFCSRNaN2008FlagMask) { |
| 1326 double max_int32 = std::numeric_limits<int32_t>::max(); |
| 1327 double min_int32 = std::numeric_limits<int32_t>::min(); |
| 1328 if (std::isnan(original)) { |
| 1329 set_fpu_register_word(fd_reg(), 0); |
| 1330 } else if (rounded > max_int32) { |
| 1331 set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| 1332 } else if (rounded < min_int32) { |
| 1333 set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative); |
| 1334 } else { |
| 1335 UNREACHABLE(); |
| 1336 } |
| 1337 } else { |
| 1338 set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| 1339 } |
| 1340 } |
| 1341 |
| 1342 |
| 1343 void Simulator::set_fpu_register_invalid_result(float original, float rounded) { |
| 1344 if (FCSR_ & kFCSRNaN2008FlagMask) { |
| 1345 double max_int32 = std::numeric_limits<int32_t>::max(); |
| 1346 double min_int32 = std::numeric_limits<int32_t>::min(); |
| 1347 if (std::isnan(original)) { |
| 1348 set_fpu_register(fd_reg(), 0); |
| 1349 } else if (rounded > max_int32) { |
| 1350 set_fpu_register(fd_reg(), kFPUInvalidResult); |
| 1351 } else if (rounded < min_int32) { |
| 1352 set_fpu_register(fd_reg(), kFPUInvalidResultNegative); |
| 1353 } else { |
| 1354 UNREACHABLE(); |
| 1355 } |
| 1356 } else { |
| 1357 set_fpu_register(fd_reg(), kFPUInvalidResult); |
| 1358 } |
| 1359 } |
| 1360 |
| 1361 |
| 1362 void Simulator::set_fpu_register_invalid_result64(float original, |
| 1363 float rounded) { |
| 1364 if (FCSR_ & kFCSRNaN2008FlagMask) { |
| 1365 double max_int64 = std::numeric_limits<int64_t>::max(); |
| 1366 double min_int64 = std::numeric_limits<int64_t>::min(); |
| 1367 if (std::isnan(original)) { |
| 1368 set_fpu_register(fd_reg(), 0); |
| 1369 } else if (rounded > max_int64) { |
| 1370 set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| 1371 } else if (rounded < min_int64) { |
| 1372 set_fpu_register(fd_reg(), kFPU64InvalidResultNegative); |
| 1373 } else { |
| 1374 UNREACHABLE(); |
| 1375 } |
| 1376 } else { |
| 1377 set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| 1378 } |
| 1379 } |
| 1380 |
| 1381 |
| 1382 void Simulator::set_fpu_register_word_invalid_result(double original, |
| 1383 double rounded) { |
| 1384 if (FCSR_ & kFCSRNaN2008FlagMask) { |
| 1385 double max_int32 = std::numeric_limits<int32_t>::max(); |
| 1386 double min_int32 = std::numeric_limits<int32_t>::min(); |
| 1387 if (std::isnan(original)) { |
| 1388 set_fpu_register_word(fd_reg(), 0); |
| 1389 } else if (rounded > max_int32) { |
| 1390 set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| 1391 } else if (rounded < min_int32) { |
| 1392 set_fpu_register_word(fd_reg(), kFPUInvalidResultNegative); |
| 1393 } else { |
| 1394 UNREACHABLE(); |
| 1395 } |
| 1396 } else { |
| 1397 set_fpu_register_word(fd_reg(), kFPUInvalidResult); |
| 1398 } |
| 1399 } |
| 1400 |
| 1401 |
| 1402 void Simulator::set_fpu_register_invalid_result(double original, |
| 1403 double rounded) { |
| 1404 if (FCSR_ & kFCSRNaN2008FlagMask) { |
| 1405 double max_int32 = std::numeric_limits<int32_t>::max(); |
| 1406 double min_int32 = std::numeric_limits<int32_t>::min(); |
| 1407 if (std::isnan(original)) { |
| 1408 set_fpu_register(fd_reg(), 0); |
| 1409 } else if (rounded > max_int32) { |
| 1410 set_fpu_register(fd_reg(), kFPUInvalidResult); |
| 1411 } else if (rounded < min_int32) { |
| 1412 set_fpu_register(fd_reg(), kFPUInvalidResultNegative); |
| 1413 } else { |
| 1414 UNREACHABLE(); |
| 1415 } |
| 1416 } else { |
| 1417 set_fpu_register(fd_reg(), kFPUInvalidResult); |
| 1418 } |
| 1419 } |
| 1420 |
| 1421 |
| 1422 void Simulator::set_fpu_register_invalid_result64(double original, |
| 1423 double rounded) { |
| 1424 if (FCSR_ & kFCSRNaN2008FlagMask) { |
| 1425 double max_int64 = std::numeric_limits<int64_t>::max(); |
| 1426 double min_int64 = std::numeric_limits<int64_t>::min(); |
| 1427 if (std::isnan(original)) { |
| 1428 set_fpu_register(fd_reg(), 0); |
| 1429 } else if (rounded > max_int64) { |
| 1430 set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| 1431 } else if (rounded < min_int64) { |
| 1432 set_fpu_register(fd_reg(), kFPU64InvalidResultNegative); |
| 1433 } else { |
| 1434 UNREACHABLE(); |
| 1435 } |
| 1436 } else { |
| 1437 set_fpu_register(fd_reg(), kFPU64InvalidResult); |
| 1438 } |
| 1439 } |
| 1440 |
1318 | 1441 |
1319 // Sets the rounding error codes in FCSR based on the result of the rounding. | 1442 // Sets the rounding error codes in FCSR based on the result of the rounding. |
1320 // Returns true if the operation was invalid. | 1443 // Returns true if the operation was invalid. |
1321 bool Simulator::set_fcsr_round64_error(float original, float rounded) { | 1444 bool Simulator::set_fcsr_round64_error(float original, float rounded) { |
1322 bool ret = false; | 1445 bool ret = false; |
1323 double max_int64 = std::numeric_limits<int64_t>::max(); | 1446 double max_int64 = std::numeric_limits<int64_t>::max(); |
1324 double min_int64 = std::numeric_limits<int64_t>::min(); | 1447 double min_int64 = std::numeric_limits<int64_t>::min(); |
1325 | 1448 |
1326 if (!std::isfinite(original) || !std::isfinite(rounded)) { | 1449 if (!std::isfinite(original) || !std::isfinite(rounded)) { |
1327 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1450 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
(...skipping 1036 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2364 set_fpu_register_float(fd_reg(), fResult); | 2487 set_fpu_register_float(fd_reg(), fResult); |
2365 | 2488 |
2366 break; | 2489 break; |
2367 } | 2490 } |
2368 case CVT_L_S: { | 2491 case CVT_L_S: { |
2369 float rounded; | 2492 float rounded; |
2370 int64_t result; | 2493 int64_t result; |
2371 round64_according_to_fcsr(fs, rounded, result, fs); | 2494 round64_according_to_fcsr(fs, rounded, result, fs); |
2372 set_fpu_register(fd_reg(), result); | 2495 set_fpu_register(fd_reg(), result); |
2373 if (set_fcsr_round64_error(fs, rounded)) { | 2496 if (set_fcsr_round64_error(fs, rounded)) { |
2374 set_fpu_register(fd_reg(), kFPU64InvalidResult); | 2497 set_fpu_register_invalid_result64(fs, rounded); |
2375 } | 2498 } |
2376 break; | 2499 break; |
2377 } | 2500 } |
2378 case CVT_W_S: { | 2501 case CVT_W_S: { |
2379 float rounded; | 2502 float rounded; |
2380 int32_t result; | 2503 int32_t result; |
2381 round_according_to_fcsr(fs, rounded, result, fs); | 2504 round_according_to_fcsr(fs, rounded, result, fs); |
2382 set_fpu_register_word(fd_reg(), result); | 2505 set_fpu_register_word(fd_reg(), result); |
2383 if (set_fcsr_round_error(fs, rounded)) { | 2506 if (set_fcsr_round_error(fs, rounded)) { |
2384 set_fpu_register_word(fd_reg(), kFPUInvalidResult); | 2507 set_fpu_register_word_invalid_result(fs, rounded); |
2385 } | 2508 } |
2386 break; | 2509 break; |
2387 } | 2510 } |
2388 case TRUNC_W_S: { // Truncate single to word (round towards 0). | 2511 case TRUNC_W_S: { // Truncate single to word (round towards 0). |
2389 float rounded = trunc(fs); | 2512 float rounded = trunc(fs); |
2390 int32_t result = static_cast<int32_t>(rounded); | 2513 int32_t result = static_cast<int32_t>(rounded); |
2391 set_fpu_register_word(fd_reg(), result); | 2514 set_fpu_register_word(fd_reg(), result); |
2392 if (set_fcsr_round_error(fs, rounded)) { | 2515 if (set_fcsr_round_error(fs, rounded)) { |
2393 set_fpu_register_word(fd_reg(), kFPUInvalidResult); | 2516 set_fpu_register_word_invalid_result(fs, rounded); |
2394 } | 2517 } |
2395 } break; | 2518 } break; |
2396 case TRUNC_L_S: { // Mips64r2 instruction. | 2519 case TRUNC_L_S: { // Mips64r2 instruction. |
2397 float rounded = trunc(fs); | 2520 float rounded = trunc(fs); |
2398 int64_t result = static_cast<int64_t>(rounded); | 2521 int64_t result = static_cast<int64_t>(rounded); |
2399 set_fpu_register(fd_reg(), result); | 2522 set_fpu_register(fd_reg(), result); |
2400 if (set_fcsr_round64_error(fs, rounded)) { | 2523 if (set_fcsr_round64_error(fs, rounded)) { |
2401 set_fpu_register(fd_reg(), kFPU64InvalidResult); | 2524 set_fpu_register_invalid_result64(fs, rounded); |
2402 } | 2525 } |
2403 break; | 2526 break; |
2404 } | 2527 } |
2405 case ROUND_W_S: { | 2528 case ROUND_W_S: { |
2406 float rounded = std::floor(fs + 0.5); | 2529 float rounded = std::floor(fs + 0.5); |
2407 int32_t result = static_cast<int32_t>(rounded); | 2530 int32_t result = static_cast<int32_t>(rounded); |
2408 if ((result & 1) != 0 && result - fs == 0.5) { | 2531 if ((result & 1) != 0 && result - fs == 0.5) { |
2409 // If the number is halfway between two integers, | 2532 // If the number is halfway between two integers, |
2410 // round to the even one. | 2533 // round to the even one. |
2411 result--; | 2534 result--; |
2412 } | 2535 } |
2413 set_fpu_register_word(fd_reg(), result); | 2536 set_fpu_register_word(fd_reg(), result); |
2414 if (set_fcsr_round_error(fs, rounded)) { | 2537 if (set_fcsr_round_error(fs, rounded)) { |
2415 set_fpu_register_word(fd_reg(), kFPUInvalidResult); | 2538 set_fpu_register_word_invalid_result(fs, rounded); |
2416 } | 2539 } |
2417 break; | 2540 break; |
2418 } | 2541 } |
2419 case ROUND_L_S: { // Mips64r2 instruction. | 2542 case ROUND_L_S: { // Mips64r2 instruction. |
2420 float rounded = std::floor(fs + 0.5); | 2543 float rounded = std::floor(fs + 0.5); |
2421 int64_t result = static_cast<int64_t>(rounded); | 2544 int64_t result = static_cast<int64_t>(rounded); |
2422 if ((result & 1) != 0 && result - fs == 0.5) { | 2545 if ((result & 1) != 0 && result - fs == 0.5) { |
2423 // If the number is halfway between two integers, | 2546 // If the number is halfway between two integers, |
2424 // round to the even one. | 2547 // round to the even one. |
2425 result--; | 2548 result--; |
2426 } | 2549 } |
2427 int64_t i64 = static_cast<int64_t>(result); | 2550 int64_t i64 = static_cast<int64_t>(result); |
2428 set_fpu_register(fd_reg(), i64); | 2551 set_fpu_register(fd_reg(), i64); |
2429 if (set_fcsr_round64_error(fs, rounded)) { | 2552 if (set_fcsr_round64_error(fs, rounded)) { |
2430 set_fpu_register(fd_reg(), kFPU64InvalidResult); | 2553 set_fpu_register_invalid_result64(fs, rounded); |
2431 } | 2554 } |
2432 break; | 2555 break; |
2433 } | 2556 } |
2434 case FLOOR_L_S: { // Mips64r2 instruction. | 2557 case FLOOR_L_S: { // Mips64r2 instruction. |
2435 float rounded = floor(fs); | 2558 float rounded = floor(fs); |
2436 int64_t result = static_cast<int64_t>(rounded); | 2559 int64_t result = static_cast<int64_t>(rounded); |
2437 set_fpu_register(fd_reg(), result); | 2560 set_fpu_register(fd_reg(), result); |
2438 if (set_fcsr_round64_error(fs, rounded)) { | 2561 if (set_fcsr_round64_error(fs, rounded)) { |
2439 set_fpu_register(fd_reg(), kFPU64InvalidResult); | 2562 set_fpu_register_invalid_result64(fs, rounded); |
2440 } | 2563 } |
2441 break; | 2564 break; |
2442 } | 2565 } |
2443 case FLOOR_W_S: // Round double to word towards negative infinity. | 2566 case FLOOR_W_S: // Round double to word towards negative infinity. |
2444 { | 2567 { |
2445 float rounded = std::floor(fs); | 2568 float rounded = std::floor(fs); |
2446 int32_t result = static_cast<int32_t>(rounded); | 2569 int32_t result = static_cast<int32_t>(rounded); |
2447 set_fpu_register_word(fd_reg(), result); | 2570 set_fpu_register_word(fd_reg(), result); |
2448 if (set_fcsr_round_error(fs, rounded)) { | 2571 if (set_fcsr_round_error(fs, rounded)) { |
2449 set_fpu_register_word(fd_reg(), kFPUInvalidResult); | 2572 set_fpu_register_word_invalid_result(fs, rounded); |
2450 } | 2573 } |
2451 } break; | 2574 } break; |
2452 case CEIL_W_S: // Round double to word towards positive infinity. | 2575 case CEIL_W_S: // Round double to word towards positive infinity. |
2453 { | 2576 { |
2454 float rounded = std::ceil(fs); | 2577 float rounded = std::ceil(fs); |
2455 int32_t result = static_cast<int32_t>(rounded); | 2578 int32_t result = static_cast<int32_t>(rounded); |
2456 set_fpu_register_word(fd_reg(), result); | 2579 set_fpu_register_word(fd_reg(), result); |
2457 if (set_fcsr_round_error(fs, rounded)) { | 2580 if (set_fcsr_round_error(fs, rounded)) { |
2458 set_fpu_register(fd_reg(), kFPUInvalidResult); | 2581 set_fpu_register_invalid_result(fs, rounded); |
2459 } | 2582 } |
2460 } break; | 2583 } break; |
2461 case CEIL_L_S: { // Mips64r2 instruction. | 2584 case CEIL_L_S: { // Mips64r2 instruction. |
2462 float rounded = ceil(fs); | 2585 float rounded = ceil(fs); |
2463 int64_t result = static_cast<int64_t>(rounded); | 2586 int64_t result = static_cast<int64_t>(rounded); |
2464 set_fpu_register(fd_reg(), result); | 2587 set_fpu_register(fd_reg(), result); |
2465 if (set_fcsr_round64_error(fs, rounded)) { | 2588 if (set_fcsr_round64_error(fs, rounded)) { |
2466 set_fpu_register(fd_reg(), kFPU64InvalidResult); | 2589 set_fpu_register_invalid_result64(fs, rounded); |
2467 } | 2590 } |
2468 break; | 2591 break; |
2469 } | 2592 } |
2470 case MINA: | 2593 case MINA: |
2471 DCHECK(kArchVariant == kMips64r6); | 2594 DCHECK(kArchVariant == kMips64r6); |
2472 fs = get_fpu_register_float(fs_reg()); | 2595 fs = get_fpu_register_float(fs_reg()); |
2473 if (std::isnan(fs) && std::isnan(ft)) { | 2596 if (std::isnan(fs) && std::isnan(ft)) { |
2474 set_fpu_register_float(fd_reg(), fs); | 2597 set_fpu_register_float(fd_reg(), fs); |
2475 } else if (std::isnan(fs) && !std::isnan(ft)) { | 2598 } else if (std::isnan(fs) && !std::isnan(ft)) { |
2476 set_fpu_register_float(fd_reg(), ft); | 2599 set_fpu_register_float(fd_reg(), ft); |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2800 break; | 2923 break; |
2801 case C_ULE_D: | 2924 case C_ULE_D: |
2802 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); | 2925 set_fcsr_bit(fcsr_cc, (fs <= ft) || (std::isnan(fs) || std::isnan(ft))); |
2803 break; | 2926 break; |
2804 case CVT_W_D: { // Convert double to word. | 2927 case CVT_W_D: { // Convert double to word. |
2805 double rounded; | 2928 double rounded; |
2806 int32_t result; | 2929 int32_t result; |
2807 round_according_to_fcsr(fs, rounded, result, fs); | 2930 round_according_to_fcsr(fs, rounded, result, fs); |
2808 set_fpu_register_word(fd_reg(), result); | 2931 set_fpu_register_word(fd_reg(), result); |
2809 if (set_fcsr_round_error(fs, rounded)) { | 2932 if (set_fcsr_round_error(fs, rounded)) { |
2810 set_fpu_register_word(fd_reg(), kFPUInvalidResult); | 2933 set_fpu_register_word_invalid_result(fs, rounded); |
2811 } | 2934 } |
2812 break; | 2935 break; |
2813 } | 2936 } |
2814 case ROUND_W_D: // Round double to word (round half to even). | 2937 case ROUND_W_D: // Round double to word (round half to even). |
2815 { | 2938 { |
2816 double rounded = std::floor(fs + 0.5); | 2939 double rounded = std::floor(fs + 0.5); |
2817 int32_t result = static_cast<int32_t>(rounded); | 2940 int32_t result = static_cast<int32_t>(rounded); |
2818 if ((result & 1) != 0 && result - fs == 0.5) { | 2941 if ((result & 1) != 0 && result - fs == 0.5) { |
2819 // If the number is halfway between two integers, | 2942 // If the number is halfway between two integers, |
2820 // round to the even one. | 2943 // round to the even one. |
2821 result--; | 2944 result--; |
2822 } | 2945 } |
2823 set_fpu_register_word(fd_reg(), result); | 2946 set_fpu_register_word(fd_reg(), result); |
2824 if (set_fcsr_round_error(fs, rounded)) { | 2947 if (set_fcsr_round_error(fs, rounded)) { |
2825 set_fpu_register(fd_reg(), kFPUInvalidResult); | 2948 set_fpu_register_invalid_result(fs, rounded); |
2826 } | 2949 } |
2827 } break; | 2950 } break; |
2828 case TRUNC_W_D: // Truncate double to word (round towards 0). | 2951 case TRUNC_W_D: // Truncate double to word (round towards 0). |
2829 { | 2952 { |
2830 double rounded = trunc(fs); | 2953 double rounded = trunc(fs); |
2831 int32_t result = static_cast<int32_t>(rounded); | 2954 int32_t result = static_cast<int32_t>(rounded); |
2832 set_fpu_register_word(fd_reg(), result); | 2955 set_fpu_register_word(fd_reg(), result); |
2833 if (set_fcsr_round_error(fs, rounded)) { | 2956 if (set_fcsr_round_error(fs, rounded)) { |
2834 set_fpu_register(fd_reg(), kFPUInvalidResult); | 2957 set_fpu_register_invalid_result(fs, rounded); |
2835 } | 2958 } |
2836 } break; | 2959 } break; |
2837 case FLOOR_W_D: // Round double to word towards negative infinity. | 2960 case FLOOR_W_D: // Round double to word towards negative infinity. |
2838 { | 2961 { |
2839 double rounded = std::floor(fs); | 2962 double rounded = std::floor(fs); |
2840 int32_t result = static_cast<int32_t>(rounded); | 2963 int32_t result = static_cast<int32_t>(rounded); |
2841 set_fpu_register_word(fd_reg(), result); | 2964 set_fpu_register_word(fd_reg(), result); |
2842 if (set_fcsr_round_error(fs, rounded)) { | 2965 if (set_fcsr_round_error(fs, rounded)) { |
2843 set_fpu_register(fd_reg(), kFPUInvalidResult); | 2966 set_fpu_register_invalid_result(fs, rounded); |
2844 } | 2967 } |
2845 } break; | 2968 } break; |
2846 case CEIL_W_D: // Round double to word towards positive infinity. | 2969 case CEIL_W_D: // Round double to word towards positive infinity. |
2847 { | 2970 { |
2848 double rounded = std::ceil(fs); | 2971 double rounded = std::ceil(fs); |
2849 int32_t result = static_cast<int32_t>(rounded); | 2972 int32_t result = static_cast<int32_t>(rounded); |
2850 set_fpu_register_word(fd_reg(), result); | 2973 set_fpu_register_word(fd_reg(), result); |
2851 if (set_fcsr_round_error(fs, rounded)) { | 2974 if (set_fcsr_round_error(fs, rounded)) { |
2852 set_fpu_register(fd_reg(), kFPUInvalidResult); | 2975 set_fpu_register_invalid_result(fs, rounded); |
2853 } | 2976 } |
2854 } break; | 2977 } break; |
2855 case CVT_S_D: // Convert double to float (single). | 2978 case CVT_S_D: // Convert double to float (single). |
2856 set_fpu_register_float(fd_reg(), static_cast<float>(fs)); | 2979 set_fpu_register_float(fd_reg(), static_cast<float>(fs)); |
2857 break; | 2980 break; |
2858 case CVT_L_D: { // Mips64r2: Truncate double to 64-bit long-word. | 2981 case CVT_L_D: { // Mips64r2: Truncate double to 64-bit long-word. |
2859 double rounded; | 2982 double rounded; |
2860 int64_t result; | 2983 int64_t result; |
2861 round64_according_to_fcsr(fs, rounded, result, fs); | 2984 round64_according_to_fcsr(fs, rounded, result, fs); |
2862 set_fpu_register(fd_reg(), result); | 2985 set_fpu_register(fd_reg(), result); |
2863 if (set_fcsr_round64_error(fs, rounded)) { | 2986 if (set_fcsr_round64_error(fs, rounded)) { |
2864 set_fpu_register(fd_reg(), kFPU64InvalidResult); | 2987 set_fpu_register_invalid_result64(fs, rounded); |
2865 } | 2988 } |
2866 break; | 2989 break; |
2867 } | 2990 } |
2868 case ROUND_L_D: { // Mips64r2 instruction. | 2991 case ROUND_L_D: { // Mips64r2 instruction. |
2869 double rounded = std::floor(fs + 0.5); | 2992 double rounded = std::floor(fs + 0.5); |
2870 int64_t result = static_cast<int64_t>(rounded); | 2993 int64_t result = static_cast<int64_t>(rounded); |
2871 if ((result & 1) != 0 && result - fs == 0.5) { | 2994 if ((result & 1) != 0 && result - fs == 0.5) { |
2872 // If the number is halfway between two integers, | 2995 // If the number is halfway between two integers, |
2873 // round to the even one. | 2996 // round to the even one. |
2874 result--; | 2997 result--; |
2875 } | 2998 } |
2876 int64_t i64 = static_cast<int64_t>(result); | 2999 int64_t i64 = static_cast<int64_t>(result); |
2877 set_fpu_register(fd_reg(), i64); | 3000 set_fpu_register(fd_reg(), i64); |
2878 if (set_fcsr_round64_error(fs, rounded)) { | 3001 if (set_fcsr_round64_error(fs, rounded)) { |
2879 set_fpu_register(fd_reg(), kFPU64InvalidResult); | 3002 set_fpu_register_invalid_result64(fs, rounded); |
2880 } | 3003 } |
2881 break; | 3004 break; |
2882 } | 3005 } |
2883 case TRUNC_L_D: { // Mips64r2 instruction. | 3006 case TRUNC_L_D: { // Mips64r2 instruction. |
2884 double rounded = trunc(fs); | 3007 double rounded = trunc(fs); |
2885 int64_t result = static_cast<int64_t>(rounded); | 3008 int64_t result = static_cast<int64_t>(rounded); |
2886 set_fpu_register(fd_reg(), result); | 3009 set_fpu_register(fd_reg(), result); |
2887 if (set_fcsr_round64_error(fs, rounded)) { | 3010 if (set_fcsr_round64_error(fs, rounded)) { |
2888 set_fpu_register(fd_reg(), kFPU64InvalidResult); | 3011 set_fpu_register_invalid_result64(fs, rounded); |
2889 } | 3012 } |
2890 break; | 3013 break; |
2891 } | 3014 } |
2892 case FLOOR_L_D: { // Mips64r2 instruction. | 3015 case FLOOR_L_D: { // Mips64r2 instruction. |
2893 double rounded = floor(fs); | 3016 double rounded = floor(fs); |
2894 int64_t result = static_cast<int64_t>(rounded); | 3017 int64_t result = static_cast<int64_t>(rounded); |
2895 set_fpu_register(fd_reg(), result); | 3018 set_fpu_register(fd_reg(), result); |
2896 if (set_fcsr_round64_error(fs, rounded)) { | 3019 if (set_fcsr_round64_error(fs, rounded)) { |
2897 set_fpu_register(fd_reg(), kFPU64InvalidResult); | 3020 set_fpu_register_invalid_result64(fs, rounded); |
2898 } | 3021 } |
2899 break; | 3022 break; |
2900 } | 3023 } |
2901 case CEIL_L_D: { // Mips64r2 instruction. | 3024 case CEIL_L_D: { // Mips64r2 instruction. |
2902 double rounded = ceil(fs); | 3025 double rounded = ceil(fs); |
2903 int64_t result = static_cast<int64_t>(rounded); | 3026 int64_t result = static_cast<int64_t>(rounded); |
2904 set_fpu_register(fd_reg(), result); | 3027 set_fpu_register(fd_reg(), result); |
2905 if (set_fcsr_round64_error(fs, rounded)) { | 3028 if (set_fcsr_round64_error(fs, rounded)) { |
2906 set_fpu_register(fd_reg(), kFPU64InvalidResult); | 3029 set_fpu_register_invalid_result64(fs, rounded); |
2907 } | 3030 } |
2908 break; | 3031 break; |
2909 } | 3032 } |
2910 case CLASS_D: { // Mips64r6 instruction | 3033 case CLASS_D: { // Mips64r6 instruction |
2911 // Convert double input to uint64_t for easier bit manipulation | 3034 // Convert double input to uint64_t for easier bit manipulation |
2912 uint64_t classed = bit_cast<uint64_t>(fs); | 3035 uint64_t classed = bit_cast<uint64_t>(fs); |
2913 | 3036 |
2914 // Extracting sign, exponent and mantissa from the input double | 3037 // Extracting sign, exponent and mantissa from the input double |
2915 uint32_t sign = (classed >> 63) & 1; | 3038 uint32_t sign = (classed >> 63) & 1; |
2916 uint32_t exponent = (classed >> 52) & 0x00000000000007ff; | 3039 uint32_t exponent = (classed >> 52) & 0x00000000000007ff; |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3181 case MFC1: | 3304 case MFC1: |
3182 set_register(rt_reg(), | 3305 set_register(rt_reg(), |
3183 static_cast<int64_t>(get_fpu_register_word(fs_reg()))); | 3306 static_cast<int64_t>(get_fpu_register_word(fs_reg()))); |
3184 break; | 3307 break; |
3185 case DMFC1: | 3308 case DMFC1: |
3186 set_register(rt_reg(), get_fpu_register(fs_reg())); | 3309 set_register(rt_reg(), get_fpu_register(fs_reg())); |
3187 break; | 3310 break; |
3188 case MFHC1: | 3311 case MFHC1: |
3189 set_register(rt_reg(), get_fpu_register_hi_word(fs_reg())); | 3312 set_register(rt_reg(), get_fpu_register_hi_word(fs_reg())); |
3190 break; | 3313 break; |
3191 case CTC1: | 3314 case CTC1: { |
3192 // At the moment only FCSR is supported. | 3315 // At the moment only FCSR is supported. |
3193 DCHECK(fs_reg() == kFCSRRegister); | 3316 DCHECK(fs_reg() == kFCSRRegister); |
3194 FCSR_ = static_cast<uint32_t>(rt()); | 3317 uint32_t reg = static_cast<uint32_t>(rt()); |
| 3318 if (kArchVariant == kMips64r6) { |
| 3319 FCSR_ = reg | kFCSRNaN2008FlagMask; |
| 3320 } else { |
| 3321 DCHECK(kArchVariant == kMips64r2); |
| 3322 FCSR_ = reg & ~kFCSRNaN2008FlagMask; |
| 3323 } |
3195 break; | 3324 break; |
| 3325 } |
3196 case MTC1: | 3326 case MTC1: |
3197 // Hardware writes upper 32-bits to zero on mtc1. | 3327 // Hardware writes upper 32-bits to zero on mtc1. |
3198 set_fpu_register_hi_word(fs_reg(), 0); | 3328 set_fpu_register_hi_word(fs_reg(), 0); |
3199 set_fpu_register_word(fs_reg(), static_cast<int32_t>(rt())); | 3329 set_fpu_register_word(fs_reg(), static_cast<int32_t>(rt())); |
3200 break; | 3330 break; |
3201 case DMTC1: | 3331 case DMTC1: |
3202 set_fpu_register(fs_reg(), rt()); | 3332 set_fpu_register(fs_reg(), rt()); |
3203 break; | 3333 break; |
3204 case MTHC1: | 3334 case MTHC1: |
3205 set_fpu_register_hi_word(fs_reg(), static_cast<int32_t>(rt())); | 3335 set_fpu_register_hi_word(fs_reg(), static_cast<int32_t>(rt())); |
(...skipping 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4590 } | 4720 } |
4591 | 4721 |
4592 | 4722 |
4593 #undef UNSUPPORTED | 4723 #undef UNSUPPORTED |
4594 } // namespace internal | 4724 } // namespace internal |
4595 } // namespace v8 | 4725 } // namespace v8 |
4596 | 4726 |
4597 #endif // USE_SIMULATOR | 4727 #endif // USE_SIMULATOR |
4598 | 4728 |
4599 #endif // V8_TARGET_ARCH_MIPS64 | 4729 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |