| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
| 10 #include "vm/os.h" | 10 #include "vm/os.h" |
| (...skipping 2584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2595 __ ret(); | 2595 __ ret(); |
| 2596 } | 2596 } |
| 2597 | 2597 |
| 2598 | 2598 |
| 2599 ASSEMBLER_TEST_RUN(Vsubx, test) { | 2599 ASSEMBLER_TEST_RUN(Vsubx, test) { |
| 2600 typedef int (*SimpleCode)(); | 2600 typedef int (*SimpleCode)(); |
| 2601 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry())); | 2601 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry())); |
| 2602 } | 2602 } |
| 2603 | 2603 |
| 2604 | 2604 |
| 2605 ASSEMBLER_TEST_GENERATE(Vceqs, assembler) { |
| 2606 __ LoadDImmediate(V0, 42.0, kNoPP); |
| 2607 __ LoadDImmediate(V1, -42.0, kNoPP); |
| 2608 |
| 2609 __ fcvtsd(V0, V0); |
| 2610 __ fcvtsd(V1, V1); |
| 2611 |
| 2612 __ vdups(V2, V0, 0); |
| 2613 __ vinss(V3, 0, V0, 0); |
| 2614 __ vinss(V3, 1, V1, 0); |
| 2615 __ vinss(V3, 2, V0, 0); |
| 2616 __ vinss(V3, 3, V1, 0); |
| 2617 |
| 2618 __ vceqs(V4, V2, V3); |
| 2619 |
| 2620 __ vmovrs(R1, V4, 0); |
| 2621 __ vmovrs(R2, V4, 1); |
| 2622 __ vmovrs(R3, V4, 2); |
| 2623 __ vmovrs(R4, V4, 3); |
| 2624 |
| 2625 __ addw(R0, R1, Operand(R2)); |
| 2626 __ addw(R0, R0, Operand(R3)); |
| 2627 __ addw(R0, R0, Operand(R4)); |
| 2628 __ ret(); |
| 2629 } |
| 2630 |
| 2631 |
| 2632 ASSEMBLER_TEST_RUN(Vceqs, test) { |
| 2633 typedef int (*SimpleCode)(); |
| 2634 EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry())); |
| 2635 } |
| 2636 |
| 2637 |
| 2638 ASSEMBLER_TEST_GENERATE(Vceqd, assembler) { |
| 2639 __ LoadDImmediate(V0, 42.0, kNoPP); |
| 2640 __ LoadDImmediate(V1, -42.0, kNoPP); |
| 2641 |
| 2642 __ vdupd(V2, V0, 0); |
| 2643 __ vinsd(V3, 0, V0, 0); |
| 2644 __ vinsd(V3, 1, V1, 0); |
| 2645 |
| 2646 __ vceqd(V4, V2, V3); |
| 2647 |
| 2648 __ vmovrd(R1, V4, 0); |
| 2649 __ vmovrd(R2, V4, 1); |
| 2650 |
| 2651 __ add(R0, R1, Operand(R2)); |
| 2652 __ ret(); |
| 2653 } |
| 2654 |
| 2655 |
| 2656 ASSEMBLER_TEST_RUN(Vceqd, test) { |
| 2657 typedef int (*SimpleCode)(); |
| 2658 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry())); |
| 2659 } |
| 2660 |
| 2661 |
| 2662 ASSEMBLER_TEST_GENERATE(Vcgts, assembler) { |
| 2663 __ LoadDImmediate(V0, 42.0, kNoPP); |
| 2664 __ LoadDImmediate(V1, -42.0, kNoPP); |
| 2665 |
| 2666 __ fcvtsd(V0, V0); |
| 2667 __ fcvtsd(V1, V1); |
| 2668 |
| 2669 __ vdups(V2, V0, 0); |
| 2670 __ vinss(V3, 0, V0, 0); |
| 2671 __ vinss(V3, 1, V1, 0); |
| 2672 __ vinss(V3, 2, V0, 0); |
| 2673 __ vinss(V3, 3, V1, 0); |
| 2674 |
| 2675 __ vcgts(V4, V2, V3); |
| 2676 |
| 2677 __ vmovrs(R1, V4, 0); |
| 2678 __ vmovrs(R2, V4, 1); |
| 2679 __ vmovrs(R3, V4, 2); |
| 2680 __ vmovrs(R4, V4, 3); |
| 2681 |
| 2682 __ addw(R0, R1, Operand(R2)); |
| 2683 __ addw(R0, R0, Operand(R3)); |
| 2684 __ addw(R0, R0, Operand(R4)); |
| 2685 __ ret(); |
| 2686 } |
| 2687 |
| 2688 |
| 2689 ASSEMBLER_TEST_RUN(Vcgts, test) { |
| 2690 typedef int (*SimpleCode)(); |
| 2691 EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry())); |
| 2692 } |
| 2693 |
| 2694 |
| 2695 ASSEMBLER_TEST_GENERATE(Vcgtd, assembler) { |
| 2696 __ LoadDImmediate(V0, 42.0, kNoPP); |
| 2697 __ LoadDImmediate(V1, -42.0, kNoPP); |
| 2698 |
| 2699 __ vdupd(V2, V0, 0); |
| 2700 __ vinsd(V3, 0, V0, 0); |
| 2701 __ vinsd(V3, 1, V1, 0); |
| 2702 |
| 2703 __ vcgtd(V4, V2, V3); |
| 2704 |
| 2705 __ vmovrd(R1, V4, 0); |
| 2706 __ vmovrd(R2, V4, 1); |
| 2707 |
| 2708 __ add(R0, R1, Operand(R2)); |
| 2709 __ ret(); |
| 2710 } |
| 2711 |
| 2712 |
| 2713 ASSEMBLER_TEST_RUN(Vcgtd, test) { |
| 2714 typedef int (*SimpleCode)(); |
| 2715 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry())); |
| 2716 } |
| 2717 |
| 2718 |
| 2719 ASSEMBLER_TEST_GENERATE(Vcges, assembler) { |
| 2720 __ LoadDImmediate(V0, 42.0, kNoPP); |
| 2721 __ LoadDImmediate(V1, 43.0, kNoPP); |
| 2722 |
| 2723 __ fcvtsd(V0, V0); |
| 2724 __ fcvtsd(V1, V1); |
| 2725 |
| 2726 __ vdups(V2, V0, 0); |
| 2727 __ vinss(V3, 0, V0, 0); |
| 2728 __ vinss(V3, 1, V1, 0); |
| 2729 __ vinss(V3, 2, V0, 0); |
| 2730 __ vinss(V3, 3, V1, 0); |
| 2731 |
| 2732 __ vcges(V4, V2, V3); |
| 2733 |
| 2734 __ vmovrs(R1, V4, 0); |
| 2735 __ vmovrs(R2, V4, 1); |
| 2736 __ vmovrs(R3, V4, 2); |
| 2737 __ vmovrs(R4, V4, 3); |
| 2738 |
| 2739 __ addw(R0, R1, Operand(R2)); |
| 2740 __ addw(R0, R0, Operand(R3)); |
| 2741 __ addw(R0, R0, Operand(R4)); |
| 2742 __ ret(); |
| 2743 } |
| 2744 |
| 2745 |
| 2746 ASSEMBLER_TEST_RUN(Vcges, test) { |
| 2747 typedef int (*SimpleCode)(); |
| 2748 EXPECT_EQ(0xfffffffe, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry())); |
| 2749 } |
| 2750 |
| 2751 |
| 2752 ASSEMBLER_TEST_GENERATE(Vcged, assembler) { |
| 2753 __ LoadDImmediate(V0, 42.0, kNoPP); |
| 2754 __ LoadDImmediate(V1, 43.0, kNoPP); |
| 2755 |
| 2756 __ vdupd(V2, V0, 0); |
| 2757 __ vinsd(V3, 0, V0, 0); |
| 2758 __ vinsd(V3, 1, V1, 0); |
| 2759 |
| 2760 __ vcged(V4, V2, V3); |
| 2761 |
| 2762 __ vmovrd(R1, V4, 0); |
| 2763 __ vmovrd(R2, V4, 1); |
| 2764 |
| 2765 __ add(R0, R1, Operand(R2)); |
| 2766 __ ret(); |
| 2767 } |
| 2768 |
| 2769 |
| 2770 ASSEMBLER_TEST_RUN(Vcged, test) { |
| 2771 typedef int (*SimpleCode)(); |
| 2772 EXPECT_EQ(-1, EXECUTE_TEST_CODE_INT64(SimpleCode, test->entry())); |
| 2773 } |
| 2774 |
| 2775 |
| 2776 ASSEMBLER_TEST_GENERATE(Vmaxs, assembler) { |
| 2777 __ LoadDImmediate(V0, 10.5, kNoPP); |
| 2778 __ LoadDImmediate(V1, 10.0, kNoPP); |
| 2779 |
| 2780 __ fcvtsd(V0, V0); |
| 2781 __ fcvtsd(V1, V1); |
| 2782 |
| 2783 __ vdups(V2, V0, 0); |
| 2784 __ vinss(V3, 0, V0, 0); |
| 2785 __ vinss(V3, 1, V1, 0); |
| 2786 __ vinss(V3, 2, V0, 0); |
| 2787 __ vinss(V3, 3, V1, 0); |
| 2788 |
| 2789 __ vmaxs(V4, V2, V3); |
| 2790 |
| 2791 __ vinss(V0, 0, V4, 0); |
| 2792 __ vinss(V1, 0, V4, 1); |
| 2793 __ vinss(V2, 0, V4, 2); |
| 2794 __ vinss(V3, 0, V4, 3); |
| 2795 |
| 2796 __ fcvtds(V0, V0); |
| 2797 __ fcvtds(V1, V1); |
| 2798 __ fcvtds(V2, V2); |
| 2799 __ fcvtds(V3, V3); |
| 2800 |
| 2801 __ faddd(V0, V0, V1); |
| 2802 __ faddd(V0, V0, V2); |
| 2803 __ faddd(V0, V0, V3); |
| 2804 __ ret(); |
| 2805 } |
| 2806 |
| 2807 |
| 2808 ASSEMBLER_TEST_RUN(Vmaxs, test) { |
| 2809 typedef int (*SimpleCode)(); |
| 2810 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry())); |
| 2811 } |
| 2812 |
| 2813 |
| 2814 ASSEMBLER_TEST_GENERATE(Vmaxd, assembler) { |
| 2815 __ LoadDImmediate(V0, 21.0, kNoPP); |
| 2816 __ LoadDImmediate(V1, 20.5, kNoPP); |
| 2817 |
| 2818 __ vdupd(V2, V0, 0); |
| 2819 __ vinsd(V3, 0, V0, 0); |
| 2820 __ vinsd(V3, 1, V1, 0); |
| 2821 |
| 2822 __ vmaxd(V4, V2, V3); |
| 2823 |
| 2824 __ vinsd(V0, 0, V4, 0); |
| 2825 __ vinsd(V1, 0, V4, 1); |
| 2826 |
| 2827 __ faddd(V0, V0, V1); |
| 2828 __ ret(); |
| 2829 } |
| 2830 |
| 2831 |
| 2832 ASSEMBLER_TEST_RUN(Vmaxd, test) { |
| 2833 typedef int (*SimpleCode)(); |
| 2834 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry())); |
| 2835 } |
| 2836 |
| 2837 |
| 2838 ASSEMBLER_TEST_GENERATE(Vmins, assembler) { |
| 2839 __ LoadDImmediate(V0, 10.5, kNoPP); |
| 2840 __ LoadDImmediate(V1, 11.0, kNoPP); |
| 2841 |
| 2842 __ fcvtsd(V0, V0); |
| 2843 __ fcvtsd(V1, V1); |
| 2844 |
| 2845 __ vdups(V2, V0, 0); |
| 2846 __ vinss(V3, 0, V0, 0); |
| 2847 __ vinss(V3, 1, V1, 0); |
| 2848 __ vinss(V3, 2, V0, 0); |
| 2849 __ vinss(V3, 3, V1, 0); |
| 2850 |
| 2851 __ vmins(V4, V2, V3); |
| 2852 |
| 2853 __ vinss(V0, 0, V4, 0); |
| 2854 __ vinss(V1, 0, V4, 1); |
| 2855 __ vinss(V2, 0, V4, 2); |
| 2856 __ vinss(V3, 0, V4, 3); |
| 2857 |
| 2858 __ fcvtds(V0, V0); |
| 2859 __ fcvtds(V1, V1); |
| 2860 __ fcvtds(V2, V2); |
| 2861 __ fcvtds(V3, V3); |
| 2862 |
| 2863 __ faddd(V0, V0, V1); |
| 2864 __ faddd(V0, V0, V2); |
| 2865 __ faddd(V0, V0, V3); |
| 2866 __ ret(); |
| 2867 } |
| 2868 |
| 2869 |
| 2870 ASSEMBLER_TEST_RUN(Vmins, test) { |
| 2871 typedef int (*SimpleCode)(); |
| 2872 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry())); |
| 2873 } |
| 2874 |
| 2875 |
| 2876 ASSEMBLER_TEST_GENERATE(Vmind, assembler) { |
| 2877 __ LoadDImmediate(V0, 21.0, kNoPP); |
| 2878 __ LoadDImmediate(V1, 21.5, kNoPP); |
| 2879 |
| 2880 __ vdupd(V2, V0, 0); |
| 2881 __ vinsd(V3, 0, V0, 0); |
| 2882 __ vinsd(V3, 1, V1, 0); |
| 2883 |
| 2884 __ vmind(V4, V2, V3); |
| 2885 |
| 2886 __ vinsd(V0, 0, V4, 0); |
| 2887 __ vinsd(V1, 0, V4, 1); |
| 2888 |
| 2889 __ faddd(V0, V0, V1); |
| 2890 __ ret(); |
| 2891 } |
| 2892 |
| 2893 |
| 2894 ASSEMBLER_TEST_RUN(Vmind, test) { |
| 2895 typedef int (*SimpleCode)(); |
| 2896 EXPECT_EQ(42.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry())); |
| 2897 } |
| 2898 |
| 2899 |
| 2900 ASSEMBLER_TEST_GENERATE(Vsqrts, assembler) { |
| 2901 __ LoadDImmediate(V0, 64.0, kNoPP); |
| 2902 __ LoadDImmediate(V1, 49.0, kNoPP); |
| 2903 |
| 2904 __ fcvtsd(V0, V0); |
| 2905 __ fcvtsd(V1, V1); |
| 2906 |
| 2907 __ veor(V3, V3, V3); |
| 2908 __ vinss(V3, 1, V0, 0); |
| 2909 __ vinss(V3, 3, V1, 0); |
| 2910 |
| 2911 __ vsqrts(V4, V3); |
| 2912 |
| 2913 __ vinss(V5, 0, V4, 1); |
| 2914 __ vinss(V6, 0, V4, 3); |
| 2915 |
| 2916 __ fcvtds(V5, V5); |
| 2917 __ fcvtds(V6, V6); |
| 2918 |
| 2919 __ faddd(V0, V5, V6); |
| 2920 __ ret(); |
| 2921 } |
| 2922 |
| 2923 |
| 2924 ASSEMBLER_TEST_RUN(Vsqrts, test) { |
| 2925 typedef int (*SimpleCode)(); |
| 2926 EXPECT_EQ(15.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry())); |
| 2927 } |
| 2928 |
| 2929 |
| 2930 ASSEMBLER_TEST_GENERATE(Vsqrtd, assembler) { |
| 2931 __ LoadDImmediate(V0, 64.0, kNoPP); |
| 2932 __ LoadDImmediate(V1, 49.0, kNoPP); |
| 2933 |
| 2934 __ vinsd(V3, 0, V0, 0); |
| 2935 __ vinsd(V3, 1, V1, 0); |
| 2936 |
| 2937 __ vsqrtd(V4, V3); |
| 2938 |
| 2939 __ vinsd(V5, 0, V4, 0); |
| 2940 __ vinsd(V6, 0, V4, 1); |
| 2941 |
| 2942 __ faddd(V0, V5, V6); |
| 2943 __ ret(); |
| 2944 } |
| 2945 |
| 2946 |
| 2947 ASSEMBLER_TEST_RUN(Vsqrtd, test) { |
| 2948 typedef int (*SimpleCode)(); |
| 2949 EXPECT_EQ(15.0, EXECUTE_TEST_CODE_DOUBLE(SimpleCode, test->entry())); |
| 2950 } |
| 2951 |
| 2952 |
| 2953 // This is the same function as in the Simulator. |
| 2954 static float arm_recip_estimate(float a) { |
| 2955 // From the ARM Architecture Reference Manual A2-85. |
| 2956 if (isinf(a) || (fabs(a) >= exp2f(126))) return 0.0; |
| 2957 else if (a == 0.0) return INFINITY; |
| 2958 else if (isnan(a)) return a; |
| 2959 |
| 2960 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
| 2961 // scaled = '0011 1111 1110' : a<22:0> : Zeros(29) |
| 2962 uint64_t scaled = (static_cast<uint64_t>(0x3fe) << 52) | |
| 2963 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); |
| 2964 // result_exp = 253 - UInt(a<30:23>) |
| 2965 int32_t result_exp = 253 - ((a_bits >> 23) & 0xff); |
| 2966 ASSERT((result_exp >= 1) && (result_exp <= 252)); |
| 2967 |
| 2968 double scaled_d = bit_cast<double, uint64_t>(scaled); |
| 2969 ASSERT((scaled_d >= 0.5) && (scaled_d < 1.0)); |
| 2970 |
| 2971 // a in units of 1/512 rounded down. |
| 2972 int32_t q = static_cast<int32_t>(scaled_d * 512.0); |
| 2973 // reciprocal r. |
| 2974 double r = 1.0 / ((static_cast<double>(q) + 0.5) / 512.0); |
| 2975 // r in units of 1/256 rounded to nearest. |
| 2976 int32_t s = static_cast<int32_t>(256.0 * r + 0.5); |
| 2977 double estimate = static_cast<double>(s) / 256.0; |
| 2978 ASSERT((estimate >= 1.0) && (estimate <= (511.0/256.0))); |
| 2979 |
| 2980 // result = sign : result_exp<7:0> : estimate<51:29> |
| 2981 int32_t result_bits = |
| 2982 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) | |
| 2983 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
| 2984 return bit_cast<float, int32_t>(result_bits); |
| 2985 } |
| 2986 |
| 2987 |
| 2988 ASSEMBLER_TEST_GENERATE(Vrecpes, assembler) { |
| 2989 __ LoadDImmediate(V1, 147.0, kNoPP); |
| 2990 __ fcvtsd(V1, V1); |
| 2991 __ vinss(V2, 0, V1, 0); |
| 2992 __ vinss(V2, 1, V1, 0); |
| 2993 __ vinss(V2, 2, V1, 0); |
| 2994 __ vinss(V2, 3, V1, 0); |
| 2995 __ vrecpes(V0, V2); |
| 2996 __ fcvtds(V0, V0); |
| 2997 __ ret(); |
| 2998 } |
| 2999 |
| 3000 |
| 3001 ASSEMBLER_TEST_RUN(Vrecpes, test) { |
| 3002 EXPECT(test != NULL); |
| 3003 typedef double (*Vrecpes)(); |
| 3004 float res = EXECUTE_TEST_CODE_DOUBLE(Vrecpes, test->entry()); |
| 3005 EXPECT_FLOAT_EQ(arm_recip_estimate(147.0), res, 0.0001); |
| 3006 } |
| 3007 |
| 3008 |
| 3009 ASSEMBLER_TEST_GENERATE(Vrecpss, assembler) { |
| 3010 __ LoadDImmediate(V1, 5.0, kNoPP); |
| 3011 __ LoadDImmediate(V2, 10.0, kNoPP); |
| 3012 |
| 3013 __ fcvtsd(V1, V1); |
| 3014 __ fcvtsd(V2, V2); |
| 3015 |
| 3016 __ vrecpss(V0, V1, V2); |
| 3017 |
| 3018 __ fcvtds(V0, V0); |
| 3019 __ ret(); |
| 3020 } |
| 3021 |
| 3022 |
| 3023 ASSEMBLER_TEST_RUN(Vrecpss, test) { |
| 3024 EXPECT(test != NULL); |
| 3025 typedef double (*Vrecpss)(); |
| 3026 double res = EXECUTE_TEST_CODE_DOUBLE(Vrecpss, test->entry()); |
| 3027 EXPECT_FLOAT_EQ(2.0 - 10.0 * 5.0, res, 0.0001); |
| 3028 } |
| 3029 |
| 3030 |
| 3031 ASSEMBLER_TEST_GENERATE(VRecps, assembler) { |
| 3032 __ LoadDImmediate(V0, 1.0 / 10.5, kNoPP); |
| 3033 __ fcvtsd(V0, V0); |
| 3034 |
| 3035 __ vdups(V1, V0, 0); |
| 3036 |
| 3037 __ VRecps(V2, V1); |
| 3038 |
| 3039 __ vinss(V0, 0, V2, 0); |
| 3040 __ vinss(V1, 0, V2, 1); |
| 3041 __ vinss(V2, 0, V2, 2); |
| 3042 __ vinss(V3, 0, V2, 3); |
| 3043 |
| 3044 __ fcvtds(V0, V0); |
| 3045 __ fcvtds(V1, V1); |
| 3046 __ fcvtds(V2, V2); |
| 3047 __ fcvtds(V3, V3); |
| 3048 |
| 3049 __ faddd(V0, V0, V1); |
| 3050 __ faddd(V0, V0, V2); |
| 3051 __ faddd(V0, V0, V3); |
| 3052 __ ret(); |
| 3053 } |
| 3054 |
| 3055 |
| 3056 ASSEMBLER_TEST_RUN(VRecps, test) { |
| 3057 typedef double (*VRecps)(); |
| 3058 double res = EXECUTE_TEST_CODE_DOUBLE(VRecps, test->entry()); |
| 3059 EXPECT_FLOAT_EQ(42.0, res, 0.0001); |
| 3060 } |
| 3061 |
| 3062 |
| 3063 static float arm_reciprocal_sqrt_estimate(float a) { |
| 3064 // From the ARM Architecture Reference Manual A2-87. |
| 3065 if (isinf(a) || (fabs(a) >= exp2f(126))) return 0.0; |
| 3066 else if (a == 0.0) return INFINITY; |
| 3067 else if (isnan(a)) return a; |
| 3068 |
| 3069 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
| 3070 uint64_t scaled; |
| 3071 if (((a_bits >> 23) & 1) != 0) { |
| 3072 // scaled = '0 01111111101' : operand<22:0> : Zeros(29) |
| 3073 scaled = (static_cast<uint64_t>(0x3fd) << 52) | |
| 3074 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); |
| 3075 } else { |
| 3076 // scaled = '0 01111111110' : operand<22:0> : Zeros(29) |
| 3077 scaled = (static_cast<uint64_t>(0x3fe) << 52) | |
| 3078 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); |
| 3079 } |
| 3080 // result_exp = (380 - UInt(operand<30:23>) DIV 2; |
| 3081 int32_t result_exp = (380 - ((a_bits >> 23) & 0xff)) / 2; |
| 3082 |
| 3083 double scaled_d = bit_cast<double, uint64_t>(scaled); |
| 3084 ASSERT((scaled_d >= 0.25) && (scaled_d < 1.0)); |
| 3085 |
| 3086 double r; |
| 3087 if (scaled_d < 0.5) { |
| 3088 // range 0.25 <= a < 0.5 |
| 3089 |
| 3090 // a in units of 1/512 rounded down. |
| 3091 int32_t q0 = static_cast<int32_t>(scaled_d * 512.0); |
| 3092 // reciprocal root r. |
| 3093 r = 1.0 / sqrt((static_cast<double>(q0) + 0.5) / 512.0); |
| 3094 } else { |
| 3095 // range 0.5 <= a < 1.0 |
| 3096 |
| 3097 // a in units of 1/256 rounded down. |
| 3098 int32_t q1 = static_cast<int32_t>(scaled_d * 256.0); |
| 3099 // reciprocal root r. |
| 3100 r = 1.0 / sqrt((static_cast<double>(q1) + 0.5) / 256.0); |
| 3101 } |
| 3102 // r in units of 1/256 rounded to nearest. |
| 3103 int32_t s = static_cast<int>(256.0 * r + 0.5); |
| 3104 double estimate = static_cast<double>(s) / 256.0; |
| 3105 ASSERT((estimate >= 1.0) && (estimate <= (511.0/256.0))); |
| 3106 |
| 3107 // result = 0 : result_exp<7:0> : estimate<51:29> |
| 3108 int32_t result_bits = ((result_exp & 0xff) << 23) | |
| 3109 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
| 3110 return bit_cast<float, int32_t>(result_bits); |
| 3111 } |
| 3112 |
| 3113 |
| 3114 ASSEMBLER_TEST_GENERATE(Vrsqrtes, assembler) { |
| 3115 __ LoadDImmediate(V1, 147.0, kNoPP); |
| 3116 __ fcvtsd(V1, V1); |
| 3117 |
| 3118 __ vrsqrtes(V0, V1); |
| 3119 |
| 3120 __ fcvtds(V0, V0); |
| 3121 __ ret(); |
| 3122 } |
| 3123 |
| 3124 |
| 3125 ASSEMBLER_TEST_RUN(Vrsqrtes, test) { |
| 3126 EXPECT(test != NULL); |
| 3127 typedef double (*Vrsqrtes)(); |
| 3128 double res = EXECUTE_TEST_CODE_DOUBLE(Vrsqrtes, test->entry()); |
| 3129 EXPECT_FLOAT_EQ(arm_reciprocal_sqrt_estimate(147.0), res, 0.0001); |
| 3130 } |
| 3131 |
| 3132 |
| 3133 ASSEMBLER_TEST_GENERATE(Vrsqrtss, assembler) { |
| 3134 __ LoadDImmediate(V1, 5.0, kNoPP); |
| 3135 __ LoadDImmediate(V2, 10.0, kNoPP); |
| 3136 |
| 3137 __ fcvtsd(V1, V1); |
| 3138 __ fcvtsd(V2, V2); |
| 3139 |
| 3140 __ vrsqrtss(V0, V1, V2); |
| 3141 |
| 3142 __ fcvtds(V0, V0); |
| 3143 __ ret(); |
| 3144 } |
| 3145 |
| 3146 |
| 3147 ASSEMBLER_TEST_RUN(Vrsqrtss, test) { |
| 3148 EXPECT(test != NULL); |
| 3149 typedef double (*Vrsqrtss)(); |
| 3150 double res = EXECUTE_TEST_CODE_DOUBLE(Vrsqrtss, test->entry()); |
| 3151 EXPECT_FLOAT_EQ((3.0 - 10.0 * 5.0)/2.0, res, 0.0001); |
| 3152 } |
| 3153 |
| 3154 |
| 3155 ASSEMBLER_TEST_GENERATE(ReciprocalSqrt, assembler) { |
| 3156 __ LoadDImmediate(V1, 147000.0, kNoPP); |
| 3157 __ fcvtsd(V1, V1); |
| 3158 |
| 3159 __ VRSqrts(V0, V1); |
| 3160 |
| 3161 __ fcvtds(V0, V0); |
| 3162 __ ret(); |
| 3163 } |
| 3164 |
| 3165 |
| 3166 ASSEMBLER_TEST_RUN(ReciprocalSqrt, test) { |
| 3167 EXPECT(test != NULL); |
| 3168 typedef double (*ReciprocalSqrt)(); |
| 3169 double res = EXECUTE_TEST_CODE_DOUBLE(ReciprocalSqrt, test->entry()); |
| 3170 EXPECT_FLOAT_EQ(1.0/sqrt(147000.0), res, 0.0001); |
| 3171 } |
| 3172 |
| 3173 |
| 2605 // Called from assembler_test.cc. | 3174 // Called from assembler_test.cc. |
| 2606 // LR: return address. | 3175 // LR: return address. |
| 2607 // R0: context. | 3176 // R0: context. |
| 2608 // R1: value. | 3177 // R1: value. |
| 2609 // R2: growable array. | 3178 // R2: growable array. |
| 2610 ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) { | 3179 ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) { |
| 2611 __ TagAndPushPP(); | 3180 __ TagAndPushPP(); |
| 2612 __ LoadPoolPointer(PP); | 3181 __ LoadPoolPointer(PP); |
| 2613 __ Push(CTX); | 3182 __ Push(CTX); |
| 2614 __ Push(LR); | 3183 __ Push(LR); |
| 2615 __ mov(CTX, R0); | 3184 __ mov(CTX, R0); |
| 2616 __ StoreIntoObject(R2, | 3185 __ StoreIntoObject(R2, |
| 2617 FieldAddress(R2, GrowableObjectArray::data_offset()), | 3186 FieldAddress(R2, GrowableObjectArray::data_offset()), |
| 2618 R1); | 3187 R1); |
| 2619 __ Pop(LR); | 3188 __ Pop(LR); |
| 2620 __ Pop(CTX); | 3189 __ Pop(CTX); |
| 2621 __ PopAndUntagPP(); | 3190 __ PopAndUntagPP(); |
| 2622 __ ret(); | 3191 __ ret(); |
| 2623 } | 3192 } |
| 2624 | 3193 |
| 2625 } // namespace dart | 3194 } // namespace dart |
| 2626 | 3195 |
| 2627 #endif // defined(TARGET_ARCH_ARM64) | 3196 #endif // defined(TARGET_ARCH_ARM64) |
| OLD | NEW |