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 2346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2357 result = a; | 2357 result = a; |
2358 } else if (FPAbs(b) > FPAbs(a)) { | 2358 } else if (FPAbs(b) > FPAbs(a)) { |
2359 result = b; | 2359 result = b; |
2360 } else { | 2360 } else { |
2361 result = a > b ? a : b; | 2361 result = a > b ? a : b; |
2362 } | 2362 } |
2363 } | 2363 } |
2364 return result; | 2364 return result; |
2365 } | 2365 } |
2366 | 2366 |
| 2367 enum class KeepSign : bool { no = false, yes }; |
| 2368 |
| 2369 template <typename T> |
| 2370 T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no); |
| 2371 |
| 2372 template <> |
| 2373 double FPUCanonalizeNaNArg(double result, double arg, KeepSign keepSign) { |
| 2374 DCHECK(std::isnan(arg)); |
| 2375 double qNaN = std::numeric_limits<double>::quiet_NaN(); |
| 2376 if (keepSign == KeepSign::yes) { |
| 2377 uint64_t resBits = bit_cast<uint64_t>(result); |
| 2378 return resBits & Double::kSignMask ? -qNaN : qNaN; |
| 2379 } |
| 2380 return qNaN; |
| 2381 } |
| 2382 |
| 2383 template <> |
| 2384 float FPUCanonalizeNaNArg(float result, float arg, KeepSign keepSign) { |
| 2385 DCHECK(std::isnan(arg)); |
| 2386 float qNaN = std::numeric_limits<float>::quiet_NaN(); |
| 2387 if (keepSign == KeepSign::yes) { |
| 2388 uint32_t resBits = bit_cast<uint32_t>(result); |
| 2389 return resBits & kBinary32SignMask ? -qNaN : qNaN; |
| 2390 } |
| 2391 return qNaN; |
| 2392 } |
| 2393 |
| 2394 template <typename T> |
| 2395 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) { |
| 2396 if (std::isnan(first)) { |
| 2397 return FPUCanonalizeNaNArg(result, first, keepSign); |
| 2398 } |
| 2399 return result; |
| 2400 } |
| 2401 |
| 2402 template <typename T, typename... Args> |
| 2403 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) { |
| 2404 if (std::isnan(first)) { |
| 2405 return FPUCanonalizeNaNArg(result, first, keepSign); |
| 2406 } |
| 2407 return FPUCanonalizeNaNArgs(result, keepSign, args...); |
| 2408 } |
| 2409 |
| 2410 template <typename Func, typename T, typename... Args> |
| 2411 T FPUCanonalizeOperation(Func f, T first, Args... args) { |
| 2412 return FPUCanonalizeOperation(f, KeepSign::no, first, args...); |
| 2413 } |
| 2414 |
| 2415 template <typename Func, typename T, typename... Args> |
| 2416 T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) { |
| 2417 T result = f(first, args...); |
| 2418 if (std::isnan(result)) { |
| 2419 result = FPUCanonalizeNaNArgs(result, keepSign, first, args...); |
| 2420 } |
| 2421 return result; |
| 2422 } |
| 2423 |
2367 // Handle execution based on instruction types. | 2424 // Handle execution based on instruction types. |
2368 | 2425 |
2369 void Simulator::DecodeTypeRegisterSRsType() { | 2426 void Simulator::DecodeTypeRegisterSRsType() { |
2370 float fs, ft, fd; | 2427 float fs, ft, fd; |
2371 fs = get_fpu_register_float(fs_reg()); | 2428 fs = get_fpu_register_float(fs_reg()); |
2372 ft = get_fpu_register_float(ft_reg()); | 2429 ft = get_fpu_register_float(ft_reg()); |
2373 fd = get_fpu_register_float(fd_reg()); | 2430 fd = get_fpu_register_float(fd_reg()); |
2374 int32_t ft_int = bit_cast<int32_t>(ft); | 2431 int32_t ft_int = bit_cast<int32_t>(ft); |
2375 int32_t fd_int = bit_cast<int32_t>(fd); | 2432 int32_t fd_int = bit_cast<int32_t>(fd); |
2376 uint32_t cc, fcsr_cc; | 2433 uint32_t cc, fcsr_cc; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2409 result = lower; | 2466 result = lower; |
2410 break; | 2467 break; |
2411 } | 2468 } |
2412 set_fpu_register_float(fd_reg(), result); | 2469 set_fpu_register_float(fd_reg(), result); |
2413 if (result != fs) { | 2470 if (result != fs) { |
2414 set_fcsr_bit(kFCSRInexactFlagBit, true); | 2471 set_fcsr_bit(kFCSRInexactFlagBit, true); |
2415 } | 2472 } |
2416 break; | 2473 break; |
2417 } | 2474 } |
2418 case ADD_S: | 2475 case ADD_S: |
2419 set_fpu_register_float(fd_reg(), fs + ft); | 2476 set_fpu_register_float( |
| 2477 fd_reg(), |
| 2478 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, |
| 2479 fs, ft)); |
2420 break; | 2480 break; |
2421 case SUB_S: | 2481 case SUB_S: |
2422 set_fpu_register_float(fd_reg(), fs - ft); | 2482 set_fpu_register_float( |
| 2483 fd_reg(), |
| 2484 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, |
| 2485 fs, ft)); |
2423 break; | 2486 break; |
2424 case MADDF_S: | 2487 case MADDF_S: |
2425 DCHECK(kArchVariant == kMips64r6); | 2488 DCHECK(kArchVariant == kMips64r6); |
2426 set_fpu_register_float(fd_reg(), fd + (fs * ft)); | 2489 set_fpu_register_float(fd_reg(), fd + (fs * ft)); |
2427 break; | 2490 break; |
2428 case MSUBF_S: | 2491 case MSUBF_S: |
2429 DCHECK(kArchVariant == kMips64r6); | 2492 DCHECK(kArchVariant == kMips64r6); |
2430 set_fpu_register_float(fd_reg(), fd - (fs * ft)); | 2493 set_fpu_register_float(fd_reg(), fd - (fs * ft)); |
2431 break; | 2494 break; |
2432 case MUL_S: | 2495 case MUL_S: |
2433 set_fpu_register_float(fd_reg(), fs * ft); | 2496 set_fpu_register_float( |
| 2497 fd_reg(), |
| 2498 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, |
| 2499 fs, ft)); |
2434 break; | 2500 break; |
2435 case DIV_S: | 2501 case DIV_S: |
2436 set_fpu_register_float(fd_reg(), fs / ft); | 2502 set_fpu_register_float( |
| 2503 fd_reg(), |
| 2504 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, |
| 2505 fs, ft)); |
2437 break; | 2506 break; |
2438 case ABS_S: | 2507 case ABS_S: |
2439 set_fpu_register_float(fd_reg(), fabs(fs)); | 2508 set_fpu_register_float( |
| 2509 fd_reg(), |
| 2510 FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); |
2440 break; | 2511 break; |
2441 case MOV_S: | 2512 case MOV_S: |
2442 set_fpu_register_float(fd_reg(), fs); | 2513 set_fpu_register_float(fd_reg(), fs); |
2443 break; | 2514 break; |
2444 case NEG_S: | 2515 case NEG_S: |
2445 set_fpu_register_float(fd_reg(), -fs); | 2516 set_fpu_register_float( |
| 2517 fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, |
| 2518 KeepSign::yes, fs)); |
2446 break; | 2519 break; |
2447 case SQRT_S: | 2520 case SQRT_S: |
2448 lazily_initialize_fast_sqrt(isolate_); | 2521 set_fpu_register_float( |
2449 set_fpu_register_float(fd_reg(), fast_sqrt(fs, isolate_)); | 2522 fd_reg(), |
| 2523 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); |
2450 break; | 2524 break; |
2451 case RSQRT_S: { | 2525 case RSQRT_S: |
2452 lazily_initialize_fast_sqrt(isolate_); | 2526 set_fpu_register_float( |
2453 float result = 1.0 / fast_sqrt(fs, isolate_); | 2527 fd_reg(), FPUCanonalizeOperation( |
2454 set_fpu_register_float(fd_reg(), result); | 2528 [](float src) { return 1.0 / std::sqrt(src); }, fs)); |
2455 break; | 2529 break; |
2456 } | 2530 case RECIP_S: |
2457 case RECIP_S: { | 2531 set_fpu_register_float( |
2458 float result = 1.0 / fs; | 2532 fd_reg(), |
2459 set_fpu_register_float(fd_reg(), result); | 2533 FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); |
2460 break; | 2534 break; |
2461 } | |
2462 case C_F_D: | 2535 case C_F_D: |
2463 set_fcsr_bit(fcsr_cc, false); | 2536 set_fcsr_bit(fcsr_cc, false); |
2464 break; | 2537 break; |
2465 case C_UN_D: | 2538 case C_UN_D: |
2466 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 2539 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
2467 break; | 2540 break; |
2468 case C_EQ_D: | 2541 case C_EQ_D: |
2469 set_fcsr_bit(fcsr_cc, (fs == ft)); | 2542 set_fcsr_bit(fcsr_cc, (fs == ft)); |
2470 break; | 2543 break; |
2471 case C_UEQ_D: | 2544 case C_UEQ_D: |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2820 break; | 2893 break; |
2821 case MIN: | 2894 case MIN: |
2822 DCHECK(kArchVariant == kMips64r6); | 2895 DCHECK(kArchVariant == kMips64r6); |
2823 set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); | 2896 set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); |
2824 break; | 2897 break; |
2825 case MAX: | 2898 case MAX: |
2826 DCHECK(kArchVariant == kMips64r6); | 2899 DCHECK(kArchVariant == kMips64r6); |
2827 set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); | 2900 set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); |
2828 break; | 2901 break; |
2829 case ADD_D: | 2902 case ADD_D: |
2830 set_fpu_register_double(fd_reg(), fs + ft); | 2903 set_fpu_register_double( |
| 2904 fd_reg(), |
| 2905 FPUCanonalizeOperation( |
| 2906 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); |
2831 break; | 2907 break; |
2832 case SUB_D: | 2908 case SUB_D: |
2833 set_fpu_register_double(fd_reg(), fs - ft); | 2909 set_fpu_register_double( |
| 2910 fd_reg(), |
| 2911 FPUCanonalizeOperation( |
| 2912 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); |
2834 break; | 2913 break; |
2835 case MADDF_D: | 2914 case MADDF_D: |
2836 DCHECK(kArchVariant == kMips64r6); | 2915 DCHECK(kArchVariant == kMips64r6); |
2837 set_fpu_register_double(fd_reg(), fd + (fs * ft)); | 2916 set_fpu_register_double(fd_reg(), fd + (fs * ft)); |
2838 break; | 2917 break; |
2839 case MSUBF_D: | 2918 case MSUBF_D: |
2840 DCHECK(kArchVariant == kMips64r6); | 2919 DCHECK(kArchVariant == kMips64r6); |
2841 set_fpu_register_double(fd_reg(), fd - (fs * ft)); | 2920 set_fpu_register_double(fd_reg(), fd - (fs * ft)); |
2842 break; | 2921 break; |
2843 case MUL_D: | 2922 case MUL_D: |
2844 set_fpu_register_double(fd_reg(), fs * ft); | 2923 set_fpu_register_double( |
| 2924 fd_reg(), |
| 2925 FPUCanonalizeOperation( |
| 2926 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); |
2845 break; | 2927 break; |
2846 case DIV_D: | 2928 case DIV_D: |
2847 set_fpu_register_double(fd_reg(), fs / ft); | 2929 set_fpu_register_double( |
| 2930 fd_reg(), |
| 2931 FPUCanonalizeOperation( |
| 2932 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); |
2848 break; | 2933 break; |
2849 case ABS_D: | 2934 case ABS_D: |
2850 set_fpu_register_double(fd_reg(), fabs(fs)); | 2935 set_fpu_register_double( |
| 2936 fd_reg(), |
| 2937 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); |
2851 break; | 2938 break; |
2852 case MOV_D: | 2939 case MOV_D: |
2853 set_fpu_register_double(fd_reg(), fs); | 2940 set_fpu_register_double(fd_reg(), fs); |
2854 break; | 2941 break; |
2855 case NEG_D: | 2942 case NEG_D: |
2856 set_fpu_register_double(fd_reg(), -fs); | 2943 set_fpu_register_double( |
| 2944 fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, |
| 2945 KeepSign::yes, fs)); |
2857 break; | 2946 break; |
2858 case SQRT_D: | 2947 case SQRT_D: |
2859 lazily_initialize_fast_sqrt(isolate_); | 2948 set_fpu_register_double( |
2860 set_fpu_register_double(fd_reg(), fast_sqrt(fs, isolate_)); | 2949 fd_reg(), |
| 2950 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); |
2861 break; | 2951 break; |
2862 case RSQRT_D: { | 2952 case RSQRT_D: |
2863 lazily_initialize_fast_sqrt(isolate_); | 2953 set_fpu_register_double( |
2864 double result = 1.0 / fast_sqrt(fs, isolate_); | 2954 fd_reg(), FPUCanonalizeOperation( |
2865 set_fpu_register_double(fd_reg(), result); | 2955 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); |
2866 break; | 2956 break; |
2867 } | 2957 case RECIP_D: |
2868 case RECIP_D: { | 2958 set_fpu_register_double( |
2869 double result = 1.0 / fs; | 2959 fd_reg(), |
2870 set_fpu_register_double(fd_reg(), result); | 2960 FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); |
2871 break; | 2961 break; |
2872 } | |
2873 case C_UN_D: | 2962 case C_UN_D: |
2874 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 2963 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
2875 break; | 2964 break; |
2876 case C_EQ_D: | 2965 case C_EQ_D: |
2877 set_fcsr_bit(fcsr_cc, (fs == ft)); | 2966 set_fcsr_bit(fcsr_cc, (fs == ft)); |
2878 break; | 2967 break; |
2879 case C_UEQ_D: | 2968 case C_UEQ_D: |
2880 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 2969 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
2881 break; | 2970 break; |
2882 case C_OLT_D: | 2971 case C_OLT_D: |
(...skipping 2095 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4978 } | 5067 } |
4979 | 5068 |
4980 | 5069 |
4981 #undef UNSUPPORTED | 5070 #undef UNSUPPORTED |
4982 } // namespace internal | 5071 } // namespace internal |
4983 } // namespace v8 | 5072 } // namespace v8 |
4984 | 5073 |
4985 #endif // USE_SIMULATOR | 5074 #endif // USE_SIMULATOR |
4986 | 5075 |
4987 #endif // V8_TARGET_ARCH_MIPS64 | 5076 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |