diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2023-05-27 07:19:10 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2023-07-01 08:26:54 +0200 |
commit | 34d03ad9630e377c5d6fffbc74367a55f04c044c (patch) | |
tree | 8fc765d219304d4c40ea74a77f4868b901e4da32 /target | |
parent | aa3bad5b59e773dd107d4c84309be638d17fb867 (diff) | |
download | qemu-34d03ad9630e377c5d6fffbc74367a55f04c044c.zip qemu-34d03ad9630e377c5d6fffbc74367a55f04c044c.tar.gz qemu-34d03ad9630e377c5d6fffbc74367a55f04c044c.tar.bz2 |
target/arm: Use float64_to_int32_modulo for FJCVTZS
The standard floating point results are provided by the generic routine.
We only need handle the extra Z flag result afterward.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20230527141910.1885950-5-richard.henderson@linaro.org>
Diffstat (limited to 'target')
-rw-r--r-- | target/arm/vfp_helper.c | 75 |
1 files changed, 14 insertions, 61 deletions
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c index 36906db..789bba3 100644 --- a/target/arm/vfp_helper.c +++ b/target/arm/vfp_helper.c @@ -1120,68 +1120,21 @@ const FloatRoundMode arm_rmode_to_sf_map[] = { uint64_t HELPER(fjcvtzs)(float64 value, void *vstatus) { float_status *status = vstatus; - uint32_t exp, sign; - uint64_t frac; - uint32_t inexact = 1; /* !Z */ - - sign = extract64(value, 63, 1); - exp = extract64(value, 52, 11); - frac = extract64(value, 0, 52); - - if (exp == 0) { - /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */ - inexact = sign; - if (frac != 0) { - if (status->flush_inputs_to_zero) { - float_raise(float_flag_input_denormal, status); - } else { - float_raise(float_flag_inexact, status); - inexact = 1; - } - } - frac = 0; - } else if (exp == 0x7ff) { - /* This operation raises Invalid for both NaN and overflow (Inf). */ - float_raise(float_flag_invalid, status); - frac = 0; + uint32_t inexact, frac; + uint32_t e_old, e_new; + + e_old = get_float_exception_flags(status); + set_float_exception_flags(0, status); + frac = float64_to_int32_modulo(value, float_round_to_zero, status); + e_new = get_float_exception_flags(status); + set_float_exception_flags(e_old | e_new, status); + + if (value == float64_chs(float64_zero)) { + /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */ + inexact = 1; } else { - int true_exp = exp - 1023; - int shift = true_exp - 52; - - /* Restore implicit bit. */ - frac |= 1ull << 52; - - /* Shift the fraction into place. */ - if (shift >= 0) { - /* The number is so large we must shift the fraction left. */ - if (shift >= 64) { - /* The fraction is shifted out entirely. */ - frac = 0; - } else { - frac <<= shift; - } - } else if (shift > -64) { - /* Normal case -- shift right and notice if bits shift out. */ - inexact = (frac << (64 + shift)) != 0; - frac >>= -shift; - } else { - /* The fraction is shifted out entirely. */ - frac = 0; - } - - /* Notice overflow or inexact exceptions. */ - if (true_exp > 31 || frac > (sign ? 0x80000000ull : 0x7fffffff)) { - /* Overflow, for which this operation raises invalid. */ - float_raise(float_flag_invalid, status); - inexact = 1; - } else if (inexact) { - float_raise(float_flag_inexact, status); - } - - /* Honor the sign. */ - if (sign) { - frac = -frac; - } + /* Normal inexact or overflow or NaN */ + inexact = e_new & (float_flag_inexact | float_flag_invalid); } /* Pack the result and the env->ZF representation of Z together. */ |