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> | |
2372 T FPUCanonalizeNaNArg(T result, T arg, KeepSign keepSign = KeepSign::no); | |
2373 | |
2374 template <> | |
2375 double FPUCanonalizeNaNArg(double result, double arg, KeepSign keepSign) { | |
2376 DCHECK(std::isnan(arg)); | |
2377 double qNaN = std::numeric_limits<double>::quiet_NaN(); | |
2378 if (keepSign == KeepSign::yes) { | |
2379 uint64_t resBits = bit_cast<uint64_t>(result); | |
2380 return resBits & Double::kSignMask ? -qNaN : qNaN; | |
ivica.bogosavljevic
2016/09/19 08:41:18
There is a more portable way of doing this:
use s
balazs.kilvady
2016/09/20 08:28:39
Thanks for pointing it out. Done.
| |
2381 } | |
2382 return qNaN; | |
2383 } | |
2384 | |
2385 template <> | |
2386 float FPUCanonalizeNaNArg(float result, float arg, KeepSign keepSign) { | |
2387 DCHECK(std::isnan(arg)); | |
2388 float qNaN = std::numeric_limits<float>::quiet_NaN(); | |
2389 if (keepSign == KeepSign::yes) { | |
2390 uint32_t resBits = bit_cast<uint32_t>(result); | |
2391 return resBits & kBinary32SignMask ? -qNaN : qNaN; | |
2392 } | |
2393 return qNaN; | |
2394 } | |
2395 | |
2396 template <typename T> | |
2397 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first) { | |
2398 if (std::isnan(first)) { | |
2399 return FPUCanonalizeNaNArg(result, first, keepSign); | |
2400 } | |
2401 return result; | |
2402 } | |
2403 | |
2404 template <typename T, typename... Args> | |
2405 T FPUCanonalizeNaNArgs(T result, KeepSign keepSign, T first, Args... args) { | |
2406 if (std::isnan(first)) { | |
2407 return FPUCanonalizeNaNArg(result, first, keepSign); | |
2408 } | |
2409 return FPUCanonalizeNaNArgs(result, keepSign, args...); | |
2410 } | |
2411 | |
2412 template <typename Func, typename T, typename... Args> | |
2413 T FPUCanonalizeOperation(Func f, T first, Args... args) { | |
2414 return FPUCanonalizeOperation(f, KeepSign::no, first, args...); | |
2415 } | |
2416 | |
2417 template <typename Func, typename T, typename... Args> | |
2418 T FPUCanonalizeOperation(Func f, KeepSign keepSign, T first, Args... args) { | |
2419 T result = f(first, args...); | |
2420 if (std::isnan(result)) { | |
2421 result = FPUCanonalizeNaNArgs(result, keepSign, first, args...); | |
2422 } | |
2423 return result; | |
2424 } | |
2425 | |
2369 // Handle execution based on instruction types. | 2426 // Handle execution based on instruction types. |
2370 | 2427 |
2371 void Simulator::DecodeTypeRegisterDRsType() { | 2428 void Simulator::DecodeTypeRegisterDRsType() { |
2372 double ft, fs, fd; | 2429 double ft, fs, fd; |
2373 uint32_t cc, fcsr_cc; | 2430 uint32_t cc, fcsr_cc; |
2374 int64_t i64; | 2431 int64_t i64; |
2375 fs = get_fpu_register_double(fs_reg()); | 2432 fs = get_fpu_register_double(fs_reg()); |
2376 ft = (get_instr()->FunctionFieldRaw() != MOVF) | 2433 ft = (get_instr()->FunctionFieldRaw() != MOVF) |
2377 ? get_fpu_register_double(ft_reg()) | 2434 ? get_fpu_register_double(ft_reg()) |
2378 : 0.0; | 2435 : 0.0; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2470 break; | 2527 break; |
2471 case MINA: | 2528 case MINA: |
2472 DCHECK(IsMipsArchVariant(kMips32r6)); | 2529 DCHECK(IsMipsArchVariant(kMips32r6)); |
2473 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); | 2530 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); |
2474 break; | 2531 break; |
2475 case MAXA: | 2532 case MAXA: |
2476 DCHECK(IsMipsArchVariant(kMips32r6)); | 2533 DCHECK(IsMipsArchVariant(kMips32r6)); |
2477 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); | 2534 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); |
2478 break; | 2535 break; |
2479 case ADD_D: | 2536 case ADD_D: |
2480 set_fpu_register_double(fd_reg(), fs + ft); | 2537 set_fpu_register_double( |
2538 fd_reg(), | |
2539 FPUCanonalizeOperation( | |
2540 [](double lhs, double rhs) { return lhs + rhs; }, fs, ft)); | |
2481 break; | 2541 break; |
2482 case SUB_D: | 2542 case SUB_D: |
2483 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)); | |
2484 break; | 2547 break; |
2485 case MADDF_D: | 2548 case MADDF_D: |
2486 DCHECK(IsMipsArchVariant(kMips32r6)); | 2549 DCHECK(IsMipsArchVariant(kMips32r6)); |
2487 set_fpu_register_double(fd_reg(), fd + (fs * ft)); | 2550 set_fpu_register_double(fd_reg(), fd + (fs * ft)); |
2488 break; | 2551 break; |
2489 case MSUBF_D: | 2552 case MSUBF_D: |
2490 DCHECK(IsMipsArchVariant(kMips32r6)); | 2553 DCHECK(IsMipsArchVariant(kMips32r6)); |
2491 set_fpu_register_double(fd_reg(), fd - (fs * ft)); | 2554 set_fpu_register_double(fd_reg(), fd - (fs * ft)); |
2492 break; | 2555 break; |
2493 case MUL_D: | 2556 case MUL_D: |
2494 set_fpu_register_double(fd_reg(), fs * ft); | 2557 set_fpu_register_double( |
2558 fd_reg(), | |
2559 FPUCanonalizeOperation( | |
2560 [](double lhs, double rhs) { return lhs * rhs; }, fs, ft)); | |
2495 break; | 2561 break; |
2496 case DIV_D: | 2562 case DIV_D: |
2497 set_fpu_register_double(fd_reg(), fs / ft); | 2563 set_fpu_register_double( |
2564 fd_reg(), | |
2565 FPUCanonalizeOperation( | |
2566 [](double lhs, double rhs) { return lhs / rhs; }, fs, ft)); | |
2498 break; | 2567 break; |
2499 case ABS_D: | 2568 case ABS_D: |
2500 set_fpu_register_double(fd_reg(), fabs(fs)); | 2569 set_fpu_register_double( |
2570 fd_reg(), | |
2571 FPUCanonalizeOperation([](double fs) { return FPAbs(fs); }, fs)); | |
2501 break; | 2572 break; |
2502 case MOV_D: | 2573 case MOV_D: |
2503 set_fpu_register_double(fd_reg(), fs); | 2574 set_fpu_register_double(fd_reg(), fs); |
2504 break; | 2575 break; |
2505 case NEG_D: | 2576 case NEG_D: |
2506 set_fpu_register_double(fd_reg(), -fs); | 2577 set_fpu_register_double( |
2578 fd_reg(), FPUCanonalizeOperation([](double src) { return -src; }, | |
2579 KeepSign::yes, fs)); | |
2507 break; | 2580 break; |
2508 case SQRT_D: | 2581 case SQRT_D: |
2509 lazily_initialize_fast_sqrt(isolate_); | 2582 set_fpu_register_double( |
2510 set_fpu_register_double(fd_reg(), fast_sqrt(fs, isolate_)); | 2583 fd_reg(), |
2584 FPUCanonalizeOperation([](double fs) { return std::sqrt(fs); }, fs)); | |
2511 break; | 2585 break; |
2512 case RSQRT_D: { | 2586 case RSQRT_D: |
2513 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2587 set_fpu_register_double( |
2514 lazily_initialize_fast_sqrt(isolate_); | 2588 fd_reg(), FPUCanonalizeOperation( |
2515 double result = 1.0 / fast_sqrt(fs, isolate_); | 2589 [](double fs) { return 1.0 / std::sqrt(fs); }, fs)); |
2516 set_fpu_register_double(fd_reg(), result); | |
2517 break; | 2590 break; |
2518 } | 2591 case RECIP_D: |
2519 case RECIP_D: { | 2592 set_fpu_register_double( |
2520 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 2593 fd_reg(), |
2521 double result = 1.0 / fs; | 2594 FPUCanonalizeOperation([](double fs) { return 1.0 / fs; }, fs)); |
2522 set_fpu_register_double(fd_reg(), result); | |
2523 break; | 2595 break; |
2524 } | |
2525 case C_UN_D: | 2596 case C_UN_D: |
2526 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 2597 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
2527 break; | 2598 break; |
2528 case C_EQ_D: | 2599 case C_EQ_D: |
2529 set_fcsr_bit(fcsr_cc, (fs == ft)); | 2600 set_fcsr_bit(fcsr_cc, (fs == ft)); |
2530 break; | 2601 break; |
2531 case C_UEQ_D: | 2602 case C_UEQ_D: |
2532 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); | 2603 set_fcsr_bit(fcsr_cc, (fs == ft) || (std::isnan(fs) || std::isnan(ft))); |
2533 break; | 2604 break; |
2534 case C_OLT_D: | 2605 case C_OLT_D: |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2883 result = lower; | 2954 result = lower; |
2884 break; | 2955 break; |
2885 } | 2956 } |
2886 set_fpu_register_float(fd_reg(), result); | 2957 set_fpu_register_float(fd_reg(), result); |
2887 if (result != fs) { | 2958 if (result != fs) { |
2888 set_fcsr_bit(kFCSRInexactFlagBit, true); | 2959 set_fcsr_bit(kFCSRInexactFlagBit, true); |
2889 } | 2960 } |
2890 break; | 2961 break; |
2891 } | 2962 } |
2892 case ADD_S: | 2963 case ADD_S: |
2893 set_fpu_register_float(fd_reg(), fs + ft); | 2964 set_fpu_register_float( |
2965 fd_reg(), | |
2966 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs + rhs; }, | |
2967 fs, ft)); | |
2894 break; | 2968 break; |
2895 case SUB_S: | 2969 case SUB_S: |
2896 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)); | |
2897 break; | 2974 break; |
2898 case MADDF_S: | 2975 case MADDF_S: |
2899 DCHECK(IsMipsArchVariant(kMips32r6)); | 2976 DCHECK(IsMipsArchVariant(kMips32r6)); |
2900 set_fpu_register_float(fd_reg(), fd + (fs * ft)); | 2977 set_fpu_register_float(fd_reg(), fd + (fs * ft)); |
2901 break; | 2978 break; |
2902 case MSUBF_S: | 2979 case MSUBF_S: |
2903 DCHECK(IsMipsArchVariant(kMips32r6)); | 2980 DCHECK(IsMipsArchVariant(kMips32r6)); |
2904 set_fpu_register_float(fd_reg(), fd - (fs * ft)); | 2981 set_fpu_register_float(fd_reg(), fd - (fs * ft)); |
2905 break; | 2982 break; |
2906 case MUL_S: | 2983 case MUL_S: |
2907 set_fpu_register_float(fd_reg(), fs * ft); | 2984 set_fpu_register_float( |
2985 fd_reg(), | |
2986 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs * rhs; }, | |
2987 fs, ft)); | |
2908 break; | 2988 break; |
2909 case DIV_S: | 2989 case DIV_S: |
2910 set_fpu_register_float(fd_reg(), fs / ft); | 2990 set_fpu_register_float( |
2991 fd_reg(), | |
2992 FPUCanonalizeOperation([](float lhs, float rhs) { return lhs / rhs; }, | |
2993 fs, ft)); | |
2911 break; | 2994 break; |
2912 case ABS_S: | 2995 case ABS_S: |
2913 set_fpu_register_float(fd_reg(), fabs(fs)); | 2996 set_fpu_register_float( |
2997 fd_reg(), | |
2998 FPUCanonalizeOperation([](float fs) { return FPAbs(fs); }, fs)); | |
2914 break; | 2999 break; |
2915 case MOV_S: | 3000 case MOV_S: |
2916 set_fpu_register_float(fd_reg(), fs); | 3001 set_fpu_register_float(fd_reg(), fs); |
2917 break; | 3002 break; |
2918 case NEG_S: | 3003 case NEG_S: |
2919 set_fpu_register_float(fd_reg(), -fs); | 3004 set_fpu_register_float( |
3005 fd_reg(), FPUCanonalizeOperation([](float src) { return -src; }, | |
3006 KeepSign::yes, fs)); | |
2920 break; | 3007 break; |
2921 case SQRT_S: | 3008 case SQRT_S: |
2922 lazily_initialize_fast_sqrt(isolate_); | 3009 set_fpu_register_float( |
2923 set_fpu_register_float(fd_reg(), fast_sqrt(fs, isolate_)); | 3010 fd_reg(), |
3011 FPUCanonalizeOperation([](float src) { return std::sqrt(src); }, fs)); | |
2924 break; | 3012 break; |
2925 case RSQRT_S: { | 3013 case RSQRT_S: |
2926 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3014 set_fpu_register_float( |
2927 lazily_initialize_fast_sqrt(isolate_); | 3015 fd_reg(), FPUCanonalizeOperation( |
2928 float result = 1.0 / fast_sqrt(fs, isolate_); | 3016 [](float src) { return 1.0 / std::sqrt(src); }, fs)); |
2929 set_fpu_register_float(fd_reg(), result); | |
2930 break; | 3017 break; |
2931 } | 3018 case RECIP_S: |
2932 case RECIP_S: { | 3019 set_fpu_register_float( |
2933 DCHECK(IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)); | 3020 fd_reg(), |
2934 float result = 1.0 / fs; | 3021 FPUCanonalizeOperation([](float src) { return 1.0 / src; }, fs)); |
2935 set_fpu_register_float(fd_reg(), result); | |
2936 break; | 3022 break; |
2937 } | |
2938 case C_F_D: | 3023 case C_F_D: |
2939 set_fcsr_bit(fcsr_cc, false); | 3024 set_fcsr_bit(fcsr_cc, false); |
2940 break; | 3025 break; |
2941 case C_UN_D: | 3026 case C_UN_D: |
2942 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); | 3027 set_fcsr_bit(fcsr_cc, std::isnan(fs) || std::isnan(ft)); |
2943 break; | 3028 break; |
2944 case C_EQ_D: | 3029 case C_EQ_D: |
2945 set_fcsr_bit(fcsr_cc, (fs == ft)); | 3030 set_fcsr_bit(fcsr_cc, (fs == ft)); |
2946 break; | 3031 break; |
2947 case C_UEQ_D: | 3032 case C_UEQ_D: |
(...skipping 1678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4626 | 4711 |
4627 | 4712 |
4628 #undef UNSUPPORTED | 4713 #undef UNSUPPORTED |
4629 | 4714 |
4630 } // namespace internal | 4715 } // namespace internal |
4631 } // namespace v8 | 4716 } // namespace v8 |
4632 | 4717 |
4633 #endif // USE_SIMULATOR | 4718 #endif // USE_SIMULATOR |
4634 | 4719 |
4635 #endif // V8_TARGET_ARCH_MIPS | 4720 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |