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 2314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2325 } | 2325 } |
2326 } | 2326 } |
2327 } | 2327 } |
2328 | 2328 |
2329 | 2329 |
2330 void Simulator::SignalException(Exception e) { | 2330 void Simulator::SignalException(Exception e) { |
2331 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", | 2331 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", |
2332 static_cast<int>(e)); | 2332 static_cast<int>(e)); |
2333 } | 2333 } |
2334 | 2334 |
| 2335 template <typename T> |
| 2336 T FPAbs(T a); |
| 2337 |
| 2338 template <> |
| 2339 double FPAbs<double>(double a) { |
| 2340 return fabs(a); |
| 2341 } |
| 2342 |
| 2343 template <> |
| 2344 float FPAbs<float>(float a) { |
| 2345 return fabsf(a); |
| 2346 } |
| 2347 |
| 2348 template <typename T> |
| 2349 bool Simulator::FPUProcessNaNsAndZeros(T a, T b, IsMin min, T& result) { |
| 2350 if (std::isnan(a) && std::isnan(b)) { |
| 2351 result = a; |
| 2352 } else if (std::isnan(a)) { |
| 2353 result = b; |
| 2354 } else if (std::isnan(b)) { |
| 2355 result = a; |
| 2356 } else if (b == a) { |
| 2357 // Handle -0.0 == 0.0 case. |
| 2358 // std::signbit() returns int 0 or 1 so substracting IsMin::kMax negates the |
| 2359 // result. |
| 2360 result = std::signbit(b) - static_cast<int>(min) ? b : a; |
| 2361 } else { |
| 2362 return false; |
| 2363 } |
| 2364 return true; |
| 2365 } |
| 2366 |
| 2367 template <typename T> |
| 2368 T Simulator::FPUMin(T a, T b) { |
| 2369 T result; |
| 2370 if (FPUProcessNaNsAndZeros(a, b, IsMin::kMin, result)) { |
| 2371 return result; |
| 2372 } else { |
| 2373 return b < a ? b : a; |
| 2374 } |
| 2375 } |
| 2376 |
| 2377 template <typename T> |
| 2378 T Simulator::FPUMax(T a, T b) { |
| 2379 T result; |
| 2380 if (FPUProcessNaNsAndZeros(a, b, IsMin::kMax, result)) { |
| 2381 return result; |
| 2382 } else { |
| 2383 return b > a ? b : a; |
| 2384 } |
| 2385 } |
| 2386 |
| 2387 template <typename T> |
| 2388 T Simulator::FPUMinA(T a, T b) { |
| 2389 T result; |
| 2390 if (!FPUProcessNaNsAndZeros(a, b, IsMin::kMin, result)) { |
| 2391 if (FPAbs(a) < FPAbs(b)) { |
| 2392 result = a; |
| 2393 } else if (FPAbs(b) < FPAbs(a)) { |
| 2394 result = b; |
| 2395 } else { |
| 2396 result = a < b ? a : b; |
| 2397 } |
| 2398 } |
| 2399 return result; |
| 2400 } |
| 2401 |
| 2402 template <typename T> |
| 2403 T Simulator::FPUMaxA(T a, T b) { |
| 2404 T result; |
| 2405 if (!FPUProcessNaNsAndZeros(a, b, IsMin::kMin, result)) { |
| 2406 if (FPAbs(a) > FPAbs(b)) { |
| 2407 result = a; |
| 2408 } else if (FPAbs(b) > FPAbs(a)) { |
| 2409 result = b; |
| 2410 } else { |
| 2411 result = a > b ? a : b; |
| 2412 } |
| 2413 } |
| 2414 return result; |
| 2415 } |
2335 | 2416 |
2336 // Handle execution based on instruction types. | 2417 // Handle execution based on instruction types. |
2337 | 2418 |
2338 void Simulator::DecodeTypeRegisterSRsType() { | 2419 void Simulator::DecodeTypeRegisterSRsType() { |
2339 float fs, ft, fd; | 2420 float fs, ft, fd; |
2340 fs = get_fpu_register_float(fs_reg()); | 2421 fs = get_fpu_register_float(fs_reg()); |
2341 ft = get_fpu_register_float(ft_reg()); | 2422 ft = get_fpu_register_float(ft_reg()); |
2342 fd = get_fpu_register_float(fd_reg()); | 2423 fd = get_fpu_register_float(fd_reg()); |
2343 int32_t ft_int = bit_cast<int32_t>(ft); | 2424 int32_t ft_int = bit_cast<int32_t>(ft); |
2344 int32_t fd_int = bit_cast<int32_t>(fd); | 2425 int32_t fd_int = bit_cast<int32_t>(fd); |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2609 float rounded = ceil(fs); | 2690 float rounded = ceil(fs); |
2610 int64_t result = static_cast<int64_t>(rounded); | 2691 int64_t result = static_cast<int64_t>(rounded); |
2611 set_fpu_register(fd_reg(), result); | 2692 set_fpu_register(fd_reg(), result); |
2612 if (set_fcsr_round64_error(fs, rounded)) { | 2693 if (set_fcsr_round64_error(fs, rounded)) { |
2613 set_fpu_register_invalid_result64(fs, rounded); | 2694 set_fpu_register_invalid_result64(fs, rounded); |
2614 } | 2695 } |
2615 break; | 2696 break; |
2616 } | 2697 } |
2617 case MINA: | 2698 case MINA: |
2618 DCHECK(kArchVariant == kMips64r6); | 2699 DCHECK(kArchVariant == kMips64r6); |
2619 fs = get_fpu_register_float(fs_reg()); | 2700 set_fpu_register_float(fd_reg(), FPUMinA(ft, fs)); |
2620 if (std::isnan(fs) && std::isnan(ft)) { | |
2621 set_fpu_register_float(fd_reg(), fs); | |
2622 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
2623 set_fpu_register_float(fd_reg(), ft); | |
2624 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
2625 set_fpu_register_float(fd_reg(), fs); | |
2626 } else { | |
2627 float result; | |
2628 if (fabs(fs) > fabs(ft)) { | |
2629 result = ft; | |
2630 } else if (fabs(fs) < fabs(ft)) { | |
2631 result = fs; | |
2632 } else { | |
2633 result = (fs < ft ? fs : ft); | |
2634 } | |
2635 set_fpu_register_float(fd_reg(), result); | |
2636 } | |
2637 break; | 2701 break; |
2638 case MAXA: | 2702 case MAXA: |
2639 DCHECK(kArchVariant == kMips64r6); | 2703 DCHECK(kArchVariant == kMips64r6); |
2640 fs = get_fpu_register_float(fs_reg()); | 2704 set_fpu_register_float(fd_reg(), FPUMaxA(ft, fs)); |
2641 if (std::isnan(fs) && std::isnan(ft)) { | |
2642 set_fpu_register_float(fd_reg(), fs); | |
2643 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
2644 set_fpu_register_float(fd_reg(), ft); | |
2645 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
2646 set_fpu_register_float(fd_reg(), fs); | |
2647 } else { | |
2648 float result; | |
2649 if (fabs(fs) < fabs(ft)) { | |
2650 result = ft; | |
2651 } else if (fabs(fs) > fabs(ft)) { | |
2652 result = fs; | |
2653 } else { | |
2654 result = (fs > ft ? fs : ft); | |
2655 } | |
2656 set_fpu_register_float(fd_reg(), result); | |
2657 } | |
2658 break; | 2705 break; |
2659 case MIN: | 2706 case MIN: |
2660 DCHECK(kArchVariant == kMips64r6); | 2707 DCHECK(kArchVariant == kMips64r6); |
2661 fs = get_fpu_register_float(fs_reg()); | 2708 set_fpu_register_float(fd_reg(), FPUMin(ft, fs)); |
2662 if (std::isnan(fs) && std::isnan(ft)) { | |
2663 set_fpu_register_float(fd_reg(), fs); | |
2664 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
2665 set_fpu_register_float(fd_reg(), ft); | |
2666 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
2667 set_fpu_register_float(fd_reg(), fs); | |
2668 } else { | |
2669 set_fpu_register_float(fd_reg(), (fs >= ft) ? ft : fs); | |
2670 } | |
2671 break; | 2709 break; |
2672 case MAX: | 2710 case MAX: |
2673 DCHECK(kArchVariant == kMips64r6); | 2711 DCHECK(kArchVariant == kMips64r6); |
2674 fs = get_fpu_register_float(fs_reg()); | 2712 set_fpu_register_float(fd_reg(), FPUMax(ft, fs)); |
2675 if (std::isnan(fs) && std::isnan(ft)) { | |
2676 set_fpu_register_float(fd_reg(), fs); | |
2677 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
2678 set_fpu_register_float(fd_reg(), ft); | |
2679 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
2680 set_fpu_register_float(fd_reg(), fs); | |
2681 } else { | |
2682 set_fpu_register_float(fd_reg(), (fs <= ft) ? ft : fs); | |
2683 } | |
2684 break; | 2713 break; |
2685 case SEL: | 2714 case SEL: |
2686 DCHECK(kArchVariant == kMips64r6); | 2715 DCHECK(kArchVariant == kMips64r6); |
2687 set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); | 2716 set_fpu_register_float(fd_reg(), (fd_int & 0x1) == 0 ? fs : ft); |
2688 break; | 2717 break; |
2689 case SELEQZ_C: | 2718 case SELEQZ_C: |
2690 DCHECK(kArchVariant == kMips64r6); | 2719 DCHECK(kArchVariant == kMips64r6); |
2691 set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0 | 2720 set_fpu_register_float(fd_reg(), (ft_int & 0x1) == 0 |
2692 ? get_fpu_register_float(fs_reg()) | 2721 ? get_fpu_register_float(fs_reg()) |
2693 : 0.0); | 2722 : 0.0); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2818 // MOVT.D | 2847 // MOVT.D |
2819 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2848 if (test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
2820 } else { | 2849 } else { |
2821 // MOVF.D | 2850 // MOVF.D |
2822 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); | 2851 if (!test_fcsr_bit(ft_cc)) set_fpu_register_double(fd_reg(), fs); |
2823 } | 2852 } |
2824 break; | 2853 break; |
2825 } | 2854 } |
2826 case MINA: | 2855 case MINA: |
2827 DCHECK(kArchVariant == kMips64r6); | 2856 DCHECK(kArchVariant == kMips64r6); |
2828 fs = get_fpu_register_double(fs_reg()); | 2857 set_fpu_register_double(fd_reg(), FPUMinA(ft, fs)); |
2829 if (std::isnan(fs) && std::isnan(ft)) { | |
2830 set_fpu_register_double(fd_reg(), fs); | |
2831 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
2832 set_fpu_register_double(fd_reg(), ft); | |
2833 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
2834 set_fpu_register_double(fd_reg(), fs); | |
2835 } else { | |
2836 double result; | |
2837 if (fabs(fs) > fabs(ft)) { | |
2838 result = ft; | |
2839 } else if (fabs(fs) < fabs(ft)) { | |
2840 result = fs; | |
2841 } else { | |
2842 result = (fs < ft ? fs : ft); | |
2843 } | |
2844 set_fpu_register_double(fd_reg(), result); | |
2845 } | |
2846 break; | 2858 break; |
2847 case MAXA: | 2859 case MAXA: |
2848 DCHECK(kArchVariant == kMips64r6); | 2860 DCHECK(kArchVariant == kMips64r6); |
2849 fs = get_fpu_register_double(fs_reg()); | 2861 set_fpu_register_double(fd_reg(), FPUMaxA(ft, fs)); |
2850 if (std::isnan(fs) && std::isnan(ft)) { | |
2851 set_fpu_register_double(fd_reg(), fs); | |
2852 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
2853 set_fpu_register_double(fd_reg(), ft); | |
2854 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
2855 set_fpu_register_double(fd_reg(), fs); | |
2856 } else { | |
2857 double result; | |
2858 if (fabs(fs) < fabs(ft)) { | |
2859 result = ft; | |
2860 } else if (fabs(fs) > fabs(ft)) { | |
2861 result = fs; | |
2862 } else { | |
2863 result = (fs > ft ? fs : ft); | |
2864 } | |
2865 set_fpu_register_double(fd_reg(), result); | |
2866 } | |
2867 break; | 2862 break; |
2868 case MIN: | 2863 case MIN: |
2869 DCHECK(kArchVariant == kMips64r6); | 2864 DCHECK(kArchVariant == kMips64r6); |
2870 fs = get_fpu_register_double(fs_reg()); | 2865 set_fpu_register_double(fd_reg(), FPUMin(ft, fs)); |
2871 if (std::isnan(fs) && std::isnan(ft)) { | |
2872 set_fpu_register_double(fd_reg(), fs); | |
2873 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
2874 set_fpu_register_double(fd_reg(), ft); | |
2875 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
2876 set_fpu_register_double(fd_reg(), fs); | |
2877 } else { | |
2878 set_fpu_register_double(fd_reg(), (fs >= ft) ? ft : fs); | |
2879 } | |
2880 break; | 2866 break; |
2881 case MAX: | 2867 case MAX: |
2882 DCHECK(kArchVariant == kMips64r6); | 2868 DCHECK(kArchVariant == kMips64r6); |
2883 fs = get_fpu_register_double(fs_reg()); | 2869 set_fpu_register_double(fd_reg(), FPUMax(ft, fs)); |
2884 if (std::isnan(fs) && std::isnan(ft)) { | |
2885 set_fpu_register_double(fd_reg(), fs); | |
2886 } else if (std::isnan(fs) && !std::isnan(ft)) { | |
2887 set_fpu_register_double(fd_reg(), ft); | |
2888 } else if (!std::isnan(fs) && std::isnan(ft)) { | |
2889 set_fpu_register_double(fd_reg(), fs); | |
2890 } else { | |
2891 set_fpu_register_double(fd_reg(), (fs <= ft) ? ft : fs); | |
2892 } | |
2893 break; | 2870 break; |
2894 case ADD_D: | 2871 case ADD_D: |
2895 set_fpu_register_double(fd_reg(), fs + ft); | 2872 set_fpu_register_double(fd_reg(), fs + ft); |
2896 break; | 2873 break; |
2897 case SUB_D: | 2874 case SUB_D: |
2898 set_fpu_register_double(fd_reg(), fs - ft); | 2875 set_fpu_register_double(fd_reg(), fs - ft); |
2899 break; | 2876 break; |
2900 case MUL_D: | 2877 case MUL_D: |
2901 set_fpu_register_double(fd_reg(), fs * ft); | 2878 set_fpu_register_double(fd_reg(), fs * ft); |
2902 break; | 2879 break; |
(...skipping 1980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4883 } | 4860 } |
4884 | 4861 |
4885 | 4862 |
4886 #undef UNSUPPORTED | 4863 #undef UNSUPPORTED |
4887 } // namespace internal | 4864 } // namespace internal |
4888 } // namespace v8 | 4865 } // namespace v8 |
4889 | 4866 |
4890 #endif // USE_SIMULATOR | 4867 #endif // USE_SIMULATOR |
4891 | 4868 |
4892 #endif // V8_TARGET_ARCH_MIPS64 | 4869 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |