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