target-arm: fix support for vrecpe.
PATCH 1/1 target-arm: fix support for vrecpe.
Now use the same algorithm as described in the ARM ARM.
Signed-off-by Christophe Lyon <[email protected]>
--- target-arm/helper.c | 72 ++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 60 insertions(+), 12 deletions(-)
target-arm/helper.c +60 -12
@@ -2687,13 +2687,53 @@ float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)/* NEON helpers. */ -/* TODO: The architecture specifies the value that the estimate functions -should return. We return the exact reciprocal/root instead. */ -float32 HELPER (recpe_f32 )(float32 a,CPUState *env) +/* The algorithm that must be used to calculate the estimate +* is specified by the ARM ARM. +*/ +static float64 recip_estimate (float64 a,CPUState *env) {float_status *s = &env->vfp.fp_status; -float32 one =int32_to_float32 (1 , s); -return float32_div (one, a, s); +float64 one =int64_to_float64 (1 , s); +/* q = (int)(a * 512.0) */ +float64 x512 =int64_to_float64 (512 , s); +float64 q =float64_mul (x512, a, s); +int64_t q_int =float64_to_int64_round_to_zero (q, s); + +/* r = 1.0 / (((double)q + 0.5) / 512.0) */ + q =int64_to_float64 (q_int, s); +float64 half =float64_div (one,int64_to_float64 (2 , s), s); + q =float64_add (q, half, s); + q =float64_div (q, x512, s); + q =float64_div (one, q, s); + +/* s = (int)(256.0 * r + 0.5) */ + q =float64_mul (q,int64_to_float64 (256 , s), s); + q =float64_add (q, half, s); + q_int =float64_to_int64_round_to_zero (q, s); + +/* return (double)s / 256.0 */ +return float64_div (int64_to_float64 (q_int, s),int64_to_float64 (256 , s), s); +} + +/* TODO: handle NaNs, zero and infinity as special input values. */ +float32 HELPER (recpe_f32 )(float32 a,CPUState *env) +{ +float64 f64; +uint32_t val32; + +int result_exp; + + f64 =make_float64 (((int64_t )0x3FE <<52 ) + | ((int64_t )(float32_val (a) &0x7FFFFF ) <<29 )); + + result_exp =253 - ((float32_val (a) &0x7F800000 ) >>23 ); + + f64 =recip_estimate (f64, env); + + val32 = (float32_val (a) &0x80000000 ) + | ((result_exp &0xFF ) <<23 ) + | ((float64_val (f64) >>29 ) &0x7FFFFF ); +return make_float32 (val32); }float32 HELPER (rsqrte_f32 )(float32 a,CPUState *env)
@@ -2705,13 +2745,21 @@ float32 HELPER(rsqrte_f32)(float32 a, CPUState *env)uint32_t HELPER (recpe_u32 )(uint32_t a,CPUState *env) { -float_status *s = &env->vfp.fp_status; -float32 tmp; - tmp =int32_to_float32 (a, s); - tmp =float32_scalbn (tmp,-32 , s); - tmp =helper_recpe_f32 (tmp, env); - tmp =float32_scalbn (tmp,31 , s); -return float32_to_int32 (tmp, s); +union { +int64_t i; +float64 f; + } dp_operand; + +if ((a &0x80000000 ) ==0 ) { +return 0xFFFFFFFF ; + } + + dp_operand.i = ((int64_t )0x3FE <<52 ) + | ((int64_t )(a &0x7FFFFFFF ) <<21 ); + + dp_operand.f =recip_estimate (dp_operand.f, env); + +return 0x80000000 | ((dp_operand.i >>21 ) &0x7FFFFFFF ); }uint32_t HELPER (rsqrte_u32 )(uint32_t a,CPUState *env)
Signature · 1 line
1.7.2.3
Quoted 3 lines · Christophe Lyon
Now use the same algorithm as described in the ARM ARM.
oops sorry, I have sent the wrong patch. Please ignore this version.
Christophe.