| 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 |