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_MIPS | 10 #if V8_TARGET_ARCH_MIPS |
(...skipping 2348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2359 result = a; | 2359 result = a; |
2360 } else if (FPAbs(b) > FPAbs(a)) { | 2360 } else if (FPAbs(b) > FPAbs(a)) { |
2361 result = b; | 2361 result = b; |
2362 } else { | 2362 } else { |
2363 result = a > b ? a : b; | 2363 result = a > b ? a : b; |
2364 } | 2364 } |
2365 } | 2365 } |
2366 return result; | 2366 return result; |
2367 } | 2367 } |
2368 | 2368 |
| 2369 enum class KeepSign : bool { no = false, yes }; |
| 2370 |
| 2371 template <typename T, typename std::enable_if<std::is_floating_point<T>::value, |
| 2372 int>::type = 0> |
| 2373 T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no) { |
| 2374 DCHECK(std::isnan(arg)); |
| 2375 T qNaN = std::numeric_limits<T>::quiet_NaN(); |
| 2376 if (keepSign == KeepSign::yes) { |
| 2377 return std::copysign(qNaN, result); |
| 2378 } |
| 2379 return qNaN; |
| 2380 } |
| 2381 |
| 2382 template <typename T> |
| 2383 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) { |
| 2384 if (std::isnan(first)) { |
| 2385 return FPUCanonalizeNaNArg(result, first, keepSign); |
| 2386 } |
| 2387 return result; |
| 2388 } |
| 2389 |
| 2390 template <typename T, typename... Args> |
| 2391 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) { |
| 2392 if (std::isnan(first)) { |
| 2393 return FPUCanonalizeNaNArg(result, first, keepSign); |
| 2394 } |
| 2395 return FPUCanonalizeNaNArgs(result, keepSign, args...); |
| 2396 } |
| 2397 |
| 2398 template <typename Func, typename T, typename... Args> |
| 2399 T FPUCanonalizeOperation(Func f, T first, Args... args) { |
| 2400 return FPUCanonalizeOperation(f, KeepSign::no, first, args...); |
| 2401 } |
| 2402 |
| 2403 template <typename Func, typename T, typename... Args> |
| 2404 T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) { |
| 2405 T result = f(first, args...); |
| 2406 if (std::isnan(result)) { |
| 2407 result = FPUCanonalizeNaNArgs(result, keepSign, first, args...); |
| 2408 } |
| 2409 return result; |
| 2410 } |
| 2411 |
2369 // Handle execution based on instruction types. | 2412 // Handle execution based on instruction types. |
2370 | 2413 |
2371 void Simulator::DecodeTypeRegisterDRsType() { | 2414 void Simulator::DecodeTypeRegisterDRsType() { |
2372 double ft, fs, fd; | 2415 double ft, fs, fd; |
2373 uint32_t cc, fcsr_cc; | 2416 uint32_t cc, fcsr_cc; |
2374 int64_t i64; | 2417 int64_t i64; |
2375 fs = get_fpu_register_double(fs_reg()); | 2418 fs = get_fpu_register_double(fs_reg()); |
2376 ft = (get_instr()->FunctionFieldRaw() != MOVF) | 2419 ft = (get_instr()->FunctionFieldRaw() != MOVF) |
2377 ? get_fpu_register_double(ft_reg()) | 2420 ? get_fpu_register_double(ft_reg()) |
2378 : 0.0; | 2421 : 0.0; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2470 break; | 2513 break; |
2471 case MINA: | 2514 case MINA: |
2472 DCHECK(IsMipsArchVariant(kMips32r6)); | 2515 DCHECK(IsMipsArchVariant(kMips32r6)); |
2473 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); | 2516 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); |
2474 break; | 2517 break; |
2475 case MAXA: | 2518 case MAXA: |
2476 DCHECK(IsMipsArchVariant(kMips32r6)); | 2519 DCHECK(IsMipsArchVariant(kMips32r6)); |
2477 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); | 2520 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); |
2478 break; | 2521 break; |
2479 case ADD_D: | 2522 case ADD_D: |
2480 set_fpu_register_double(fd_reg(), fs + ft); | 2523 set_fpu_register_double( |
| 2524 fd_reg(), |
| 2525 FPUCanonalizeOperation( |
| 2526 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); |
2481 break; | 2527 break; |
2482 case SUB_D: | 2528 case SUB_D: |
2483 set_fpu_register_double(fd_reg(), fs - ft); | 2529 set_fpu_register_double( |
| 2530 fd_reg(), |
| 2531 FPUCanonalizeOperation( |
| 2532 [](double lhs, double rhs) { return lhs - rhs; }, fs, ft)); |
2484 break; | 2533 break; |
2485 case MADDF_D: | 2534 case MADDF_D: |
2486 DCHECK(IsMipsArchVariant(kMips32r6)); | 2535 DCHECK(IsMipsArchVariant(kMips32r6)); |
2487 set_fpu_register_double(fd_reg(), fd + (fs * ft)); | 2536 set_fpu_register_double(fd_reg(), fd + (fs * ft)); |
2488 break; | 2537 break; |
2489 case MSUBF_D: | 2538 case MSUBF_D: |
2490 DCHECK(IsMipsArchVariant(kMips32r6)); | 2539 DCHECK(IsMipsArchVariant(kMips32r6)); |
2491 set_fpu_register_double(fd_reg(), fd - (fs * ft)); | 2540 set_fpu_register_double(fd_reg(), fd - (fs * ft)); |
2492 break; | 2541 break; |
2493 case MUL_D: | 2542 case MUL_D: |
2494 set_fpu_register_double(fd_reg(), fs * ft); | 2543 set_fpu_register_double( |
| 2544 fd_reg(), |
| 2545 FPUCanonalizeOperation( |
| 2546 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); |
2495 break; | 2547 break; |
2496 case DIV_D: | 2548 case DIV_D: |
2497 set_fpu_register_double(fd_reg(), fs / ft); | 2549 set_fpu_register_double( |
| 2550 fd_reg(), |
| 2551 FPUCanonalizeOperation( |
| 2552 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); |
2498 break; | 2553 break; |
2499 case ABS_D: | 2554 case ABS_D: |
2500 set_fpu_register_double(fd_reg(), fabs(fs)); | 2555 set_fpu_register_double( |
| 2556 fd_reg(), |
| 2557 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); |
2501 break; | 2558 break; |
2502 case MOV_D: | 2559 case MOV_D: |
2503 set_fpu_register_double(fd_reg(), fs); | 2560 set_fpu_register_double(fd_reg(), fs); |
2504 break; | 2561 break; |
2505 case NEG_D: | 2562 case NEG_D: |
2506 set_fpu_register_double(fd_reg(), -fs); | 2563 set_fpu_register_double( |
| 2564 fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, |
| 2565 KeepSign::yes, fs)); |
2507 break; | 2566 break; |
2508 case SQRT_D: | 2567 case SQRT_D: |
2509 lazily_initialize_fast_sqrt(isolate_); | 2568 set_fpu_register_double( |
2510 set_fpu_register_double(fd_reg(), fast_sqrt(fs, isolate_)); | 2569 fd_reg(), |
| 2570 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); |
2511 break; | 2571 break; |
2512 case RSQRT_D: { | 2572 case RSQRT_D: |
2513 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2573 set_fpu_register_double( |
2514 lazily_initialize_fast_sqrt(isolate_); | 2574 fd_reg(), FPUCanonalizeOperation( |
2515 double result = 1.0 / fast_sqrt(fs, isolate_); | 2575 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); |
2516 set_fpu_register_double(fd_reg(), result); | |
2517 break; | 2576 break; |
2518 } | 2577 case RECIP_D: |
2519 case RECIP_D: { | 2578 set_fpu_register_double( |
2520 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2579 fd_reg(), |
2521 double result = 1.0 / fs; | 2580 FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); |
2522 set_fpu_register_double(fd_reg(), result); | |
2523 break; | 2581 break; |
2524 } | |
2525 case C_UN_D: | 2582 case C_UN_D: |
2526 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 2583 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
2527 break; | 2584 break; |
2528 case C_EQ_D: | 2585 case C_EQ_D: |
2529 set_fcsr_bit(fcsr_cc, (fs == ft)); | 2586 set_fcsr_bit(fcsr_cc, (fs == ft)); |
2530 break; | 2587 break; |
2531 case C_UEQ_D: | 2588 case C_UEQ_D: |
2532 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 2589 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
2533 break; | 2590 break; |
2534 case C_OLT_D: | 2591 case C_OLT_D: |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2883 result = lower; | 2940 result = lower; |
2884 break; | 2941 break; |
2885 } | 2942 } |
2886 set_fpu_register_float(fd_reg(), result); | 2943 set_fpu_register_float(fd_reg(), result); |
2887 if (result != fs) { | 2944 if (result != fs) { |
2888 set_fcsr_bit(kFCSRInexactFlagBit, true); | 2945 set_fcsr_bit(kFCSRInexactFlagBit, true); |
2889 } | 2946 } |
2890 break; | 2947 break; |
2891 } | 2948 } |
2892 case ADD_S: | 2949 case ADD_S: |
2893 set_fpu_register_float(fd_reg(), fs + ft); | 2950 set_fpu_register_float( |
| 2951 fd_reg(), |
| 2952 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, |
| 2953 fs, ft)); |
2894 break; | 2954 break; |
2895 case SUB_S: | 2955 case SUB_S: |
2896 set_fpu_register_float(fd_reg(), fs - ft); | 2956 set_fpu_register_float( |
| 2957 fd_reg(), |
| 2958 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs - rhs; }, |
| 2959 fs, ft)); |
2897 break; | 2960 break; |
2898 case MADDF_S: | 2961 case MADDF_S: |
2899 DCHECK(IsMipsArchVariant(kMips32r6)); | 2962 DCHECK(IsMipsArchVariant(kMips32r6)); |
2900 set_fpu_register_float(fd_reg(), fd + (fs * ft)); | 2963 set_fpu_register_float(fd_reg(), fd + (fs * ft)); |
2901 break; | 2964 break; |
2902 case MSUBF_S: | 2965 case MSUBF_S: |
2903 DCHECK(IsMipsArchVariant(kMips32r6)); | 2966 DCHECK(IsMipsArchVariant(kMips32r6)); |
2904 set_fpu_register_float(fd_reg(), fd - (fs * ft)); | 2967 set_fpu_register_float(fd_reg(), fd - (fs * ft)); |
2905 break; | 2968 break; |
2906 case MUL_S: | 2969 case MUL_S: |
2907 set_fpu_register_float(fd_reg(), fs * ft); | 2970 set_fpu_register_float( |
| 2971 fd_reg(), |
| 2972 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, |
| 2973 fs, ft)); |
2908 break; | 2974 break; |
2909 case DIV_S: | 2975 case DIV_S: |
2910 set_fpu_register_float(fd_reg(), fs / ft); | 2976 set_fpu_register_float( |
| 2977 fd_reg(), |
| 2978 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, |
| 2979 fs, ft)); |
2911 break; | 2980 break; |
2912 case ABS_S: | 2981 case ABS_S: |
2913 set_fpu_register_float(fd_reg(), fabs(fs)); | 2982 set_fpu_register_float( |
| 2983 fd_reg(), |
| 2984 FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); |
2914 break; | 2985 break; |
2915 case MOV_S: | 2986 case MOV_S: |
2916 set_fpu_register_float(fd_reg(), fs); | 2987 set_fpu_register_float(fd_reg(), fs); |
2917 break; | 2988 break; |
2918 case NEG_S: | 2989 case NEG_S: |
2919 set_fpu_register_float(fd_reg(), -fs); | 2990 set_fpu_register_float( |
| 2991 fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, |
| 2992 KeepSign::yes, fs)); |
2920 break; | 2993 break; |
2921 case SQRT_S: | 2994 case SQRT_S: |
2922 lazily_initialize_fast_sqrt(isolate_); | 2995 set_fpu_register_float( |
2923 set_fpu_register_float(fd_reg(), fast_sqrt(fs, isolate_)); | 2996 fd_reg(), |
| 2997 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); |
2924 break; | 2998 break; |
2925 case RSQRT_S: { | 2999 case RSQRT_S: |
2926 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3000 set_fpu_register_float( |
2927 lazily_initialize_fast_sqrt(isolate_); | 3001 fd_reg(), FPUCanonalizeOperation( |
2928 float result = 1.0 / fast_sqrt(fs, isolate_); | 3002 [](float src) { return 1.0 / std::sqrt(src); }, fs)); |
2929 set_fpu_register_float(fd_reg(), result); | |
2930 break; | 3003 break; |
2931 } | 3004 case RECIP_S: |
2932 case RECIP_S: { | 3005 set_fpu_register_float( |
2933 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3006 fd_reg(), |
2934 float result = 1.0 / fs; | 3007 FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); |
2935 set_fpu_register_float(fd_reg(), result); | |
2936 break; | 3008 break; |
2937 } | |
2938 case C_F_D: | 3009 case C_F_D: |
2939 set_fcsr_bit(fcsr_cc, false); | 3010 set_fcsr_bit(fcsr_cc, false); |
2940 break; | 3011 break; |
2941 case C_UN_D: | 3012 case C_UN_D: |
2942 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 3013 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
2943 break; | 3014 break; |
2944 case C_EQ_D: | 3015 case C_EQ_D: |
2945 set_fcsr_bit(fcsr_cc, (fs == ft)); | 3016 set_fcsr_bit(fcsr_cc, (fs == ft)); |
2946 break; | 3017 break; |
2947 case C_UEQ_D: | 3018 case C_UEQ_D: |
(...skipping 1678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4626 | 4697 |
4627 | 4698 |
4628 #undef UNSUPPORTED | 4699 #undef UNSUPPORTED |
4629 | 4700 |
4630 } // namespace internal | 4701 } // namespace internal |
4631 } // namespace v8 | 4702 } // namespace v8 |
4632 | 4703 |
4633 #endif // USE_SIMULATOR | 4704 #endif // USE_SIMULATOR |
4634 | 4705 |
4635 #endif // V8_TARGET_ARCH_MIPS | 4706 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |