| 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_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/os.h" | 9 #include "vm/os.h" |
| 10 #include "vm/unit_test.h" | 10 #include "vm/unit_test.h" |
| (...skipping 2906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2917 } | 2917 } |
| 2918 | 2918 |
| 2919 | 2919 |
| 2920 ASSEMBLER_TEST_RUN(Vcgtqs, test) { | 2920 ASSEMBLER_TEST_RUN(Vcgtqs, test) { |
| 2921 EXPECT(test != NULL); | 2921 EXPECT(test != NULL); |
| 2922 typedef int (*Tst)(); | 2922 typedef int (*Tst)(); |
| 2923 EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); | 2923 EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 2924 } | 2924 } |
| 2925 | 2925 |
| 2926 | 2926 |
| 2927 ASSEMBLER_TEST_GENERATE(Vminqs, assembler) { |
| 2928 if (CPUFeatures::neon_supported()) { |
| 2929 __ LoadSImmediate(S0, 1.0); |
| 2930 __ LoadSImmediate(S1, 2.0); |
| 2931 __ LoadSImmediate(S2, 3.0); |
| 2932 __ LoadSImmediate(S3, 4.0); |
| 2933 |
| 2934 __ LoadSImmediate(S4, 2.0); |
| 2935 __ LoadSImmediate(S5, 1.0); |
| 2936 __ LoadSImmediate(S6, 6.0); |
| 2937 __ LoadSImmediate(S7, 3.0); |
| 2938 |
| 2939 __ vminqs(Q2, Q1, Q0); |
| 2940 |
| 2941 __ vadds(S8, S8, S9); |
| 2942 __ vadds(S8, S8, S10); |
| 2943 __ vadds(S8, S8, S11); |
| 2944 |
| 2945 __ vcvtis(S0, S8); |
| 2946 __ vmovrs(R0, S0); |
| 2947 __ bx(LR); |
| 2948 } else { |
| 2949 __ LoadImmediate(R0, 8); |
| 2950 __ bx(LR); |
| 2951 } |
| 2952 } |
| 2953 |
| 2954 |
| 2955 ASSEMBLER_TEST_RUN(Vminqs, test) { |
| 2956 EXPECT(test != NULL); |
| 2957 typedef int (*Tst)(); |
| 2958 EXPECT_EQ(8, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 2959 } |
| 2960 |
| 2961 |
| 2962 ASSEMBLER_TEST_GENERATE(Vmaxqs, assembler) { |
| 2963 if (CPUFeatures::neon_supported()) { |
| 2964 __ LoadSImmediate(S0, 1.0); |
| 2965 __ LoadSImmediate(S1, 2.0); |
| 2966 __ LoadSImmediate(S2, 3.0); |
| 2967 __ LoadSImmediate(S3, 4.0); |
| 2968 |
| 2969 __ LoadSImmediate(S4, 2.0); |
| 2970 __ LoadSImmediate(S5, 1.0); |
| 2971 __ LoadSImmediate(S6, 6.0); |
| 2972 __ LoadSImmediate(S7, 3.0); |
| 2973 |
| 2974 __ vmaxqs(Q2, Q1, Q0); |
| 2975 |
| 2976 __ vadds(S8, S8, S9); |
| 2977 __ vadds(S8, S8, S10); |
| 2978 __ vadds(S8, S8, S11); |
| 2979 |
| 2980 __ vcvtis(S0, S8); |
| 2981 __ vmovrs(R0, S0); |
| 2982 __ bx(LR); |
| 2983 } else { |
| 2984 __ LoadImmediate(R0, 14); |
| 2985 __ bx(LR); |
| 2986 } |
| 2987 } |
| 2988 |
| 2989 |
| 2990 ASSEMBLER_TEST_RUN(Vmaxqs, test) { |
| 2991 EXPECT(test != NULL); |
| 2992 typedef int (*Tst)(); |
| 2993 EXPECT_EQ(14, EXECUTE_TEST_CODE_INT32(Tst, test->entry())); |
| 2994 } |
| 2995 |
| 2996 |
| 2997 // This is the same function as in the Simulator. |
| 2998 static float arm_recip_estimate(float a) { |
| 2999 // From the ARM Architecture Reference Manual A2-85. |
| 3000 if (isinf(a) || (abs(a) >= exp2f(126))) return 0.0; |
| 3001 else if (a == 0.0) return INFINITY; |
| 3002 else if (isnan(a)) return a; |
| 3003 |
| 3004 uint32_t a_bits = bit_cast<uint32_t, float>(a); |
| 3005 // scaled = '0011 1111 1110' : a<22:0> : Zeros(29) |
| 3006 uint64_t scaled = (static_cast<uint64_t>(0x3fe) << 52) | |
| 3007 ((static_cast<uint64_t>(a_bits) & 0x7fffff) << 29); |
| 3008 // result_exp = 253 - UInt(a<30:23>) |
| 3009 int32_t result_exp = 253 - ((a_bits >> 23) & 0xff); |
| 3010 ASSERT((result_exp >= 1) && (result_exp <= 252)); |
| 3011 |
| 3012 double scaled_d = bit_cast<double, uint64_t>(scaled); |
| 3013 ASSERT((scaled_d >= 0.5) && (scaled_d < 1.0)); |
| 3014 |
| 3015 // a in units of 1/512 rounded down. |
| 3016 int32_t q = static_cast<int32_t>(scaled_d * 512.0); |
| 3017 // reciprocal r. |
| 3018 double r = 1.0 / ((static_cast<double>(q) + 0.5) / 512.0); |
| 3019 // r in units of 1/256 rounded to nearest. |
| 3020 int32_t s = static_cast<int32_t>(256.0 * r + 0.5); |
| 3021 double estimate = static_cast<double>(s) / 256.0; |
| 3022 ASSERT((estimate >= 1.0) && (estimate <= (511.0/256.0))); |
| 3023 |
| 3024 // result = sign : result_exp<7:0> : estimate<51:29> |
| 3025 int32_t result_bits = |
| 3026 (a_bits & 0x80000000) | ((result_exp & 0xff) << 23) | |
| 3027 ((bit_cast<uint64_t, double>(estimate) >> 29) & 0x7fffff); |
| 3028 return bit_cast<float, int32_t>(result_bits); |
| 3029 } |
| 3030 |
| 3031 |
| 3032 ASSEMBLER_TEST_GENERATE(Vrecpeqs, assembler) { |
| 3033 if (CPUFeatures::neon_supported()) { |
| 3034 __ LoadSImmediate(S4, 147.0); |
| 3035 __ vmovs(S5, S4); |
| 3036 __ vmovs(S6, S4); |
| 3037 __ vmovs(S7, S4); |
| 3038 |
| 3039 __ vrecpeqs(Q0, Q1); |
| 3040 |
| 3041 __ bx(LR); |
| 3042 } else { |
| 3043 __ LoadSImmediate(S0, arm_recip_estimate(147.0)); |
| 3044 __ bx(LR); |
| 3045 } |
| 3046 } |
| 3047 |
| 3048 |
| 3049 ASSEMBLER_TEST_RUN(Vrecpeqs, test) { |
| 3050 EXPECT(test != NULL); |
| 3051 typedef float (*Vrecpeqs)(); |
| 3052 float res = EXECUTE_TEST_CODE_FLOAT(Vrecpeqs, test->entry()); |
| 3053 EXPECT_FLOAT_EQ(arm_recip_estimate(147.0), res, 0.0001f); |
| 3054 } |
| 3055 |
| 3056 |
| 3057 ASSEMBLER_TEST_GENERATE(Vrecpsqs, assembler) { |
| 3058 if (CPUFeatures::neon_supported()) { |
| 3059 __ LoadSImmediate(S4, 5.0); |
| 3060 __ LoadSImmediate(S5, 2.0); |
| 3061 __ LoadSImmediate(S6, 3.0); |
| 3062 __ LoadSImmediate(S7, 4.0); |
| 3063 |
| 3064 __ LoadSImmediate(S8, 10.0); |
| 3065 __ LoadSImmediate(S9, 1.0); |
| 3066 __ LoadSImmediate(S10, 6.0); |
| 3067 __ LoadSImmediate(S11, 3.0); |
| 3068 |
| 3069 __ vrecpsqs(Q0, Q1, Q2); |
| 3070 |
| 3071 __ bx(LR); |
| 3072 } else { |
| 3073 __ bx(LR); |
| 3074 } |
| 3075 } |
| 3076 |
| 3077 |
| 3078 ASSEMBLER_TEST_RUN(Vrecpsqs, test) { |
| 3079 EXPECT(test != NULL); |
| 3080 typedef float (*Vrecpsqs)(); |
| 3081 float res = EXECUTE_TEST_CODE_FLOAT(Vrecpsqs, test->entry()); |
| 3082 EXPECT_FLOAT_EQ(2 - 10.0 * 5.0, res, 0.0001f); |
| 3083 } |
| 3084 |
| 3085 |
| 3086 ASSEMBLER_TEST_GENERATE(Reciprocal, assembler) { |
| 3087 if (CPUFeatures::neon_supported()) { |
| 3088 __ LoadSImmediate(S4, 147000.0); |
| 3089 __ vmovs(S5, S4); |
| 3090 __ vmovs(S6, S4); |
| 3091 __ vmovs(S7, S4); |
| 3092 |
| 3093 // Reciprocal estimate. |
| 3094 __ vrecpeqs(Q0, Q1); |
| 3095 // 2 Newton-Raphson steps. |
| 3096 __ vrecpsqs(Q2, Q1, Q0); |
| 3097 __ vmulqs(Q0, Q0, Q2); |
| 3098 __ vrecpsqs(Q2, Q1, Q0); |
| 3099 __ vmulqs(Q0, Q0, Q2); |
| 3100 |
| 3101 __ bx(LR); |
| 3102 } else { |
| 3103 __ LoadSImmediate(S0, 1.0/147000.0); |
| 3104 __ bx(LR); |
| 3105 } |
| 3106 } |
| 3107 |
| 3108 |
| 3109 ASSEMBLER_TEST_RUN(Reciprocal, test) { |
| 3110 EXPECT(test != NULL); |
| 3111 typedef float (*Reciprocal)(); |
| 3112 float res = EXECUTE_TEST_CODE_FLOAT(Reciprocal, test->entry()); |
| 3113 EXPECT_FLOAT_EQ(1.0/147000.0, res, 0.0001f); |
| 3114 } |
| 3115 |
| 3116 |
| 2927 // Called from assembler_test.cc. | 3117 // Called from assembler_test.cc. |
| 2928 // LR: return address. | 3118 // LR: return address. |
| 2929 // R0: context. | 3119 // R0: context. |
| 2930 // R1: value. | 3120 // R1: value. |
| 2931 // R2: growable array. | 3121 // R2: growable array. |
| 2932 ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) { | 3122 ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) { |
| 2933 __ PushList((1 << CTX) | (1 << LR)); | 3123 __ PushList((1 << CTX) | (1 << LR)); |
| 2934 __ mov(CTX, ShifterOperand(R0)); | 3124 __ mov(CTX, ShifterOperand(R0)); |
| 2935 __ StoreIntoObject(R2, | 3125 __ StoreIntoObject(R2, |
| 2936 FieldAddress(R2, GrowableObjectArray::data_offset()), | 3126 FieldAddress(R2, GrowableObjectArray::data_offset()), |
| 2937 R1); | 3127 R1); |
| 2938 __ PopList((1 << CTX) | (1 << LR)); | 3128 __ PopList((1 << CTX) | (1 << LR)); |
| 2939 __ Ret(); | 3129 __ Ret(); |
| 2940 } | 3130 } |
| 2941 | 3131 |
| 2942 } // namespace dart | 3132 } // namespace dart |
| 2943 | 3133 |
| 2944 #endif // defined TARGET_ARCH_ARM | 3134 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |