Chromium Code Reviews| 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 |