diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2023-05-27 07:19:09 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2023-07-01 08:26:54 +0200 |
commit | aa3bad5b59e773dd107d4c84309be638d17fb867 (patch) | |
tree | 5e0713d59b00f37649a464bae3c980bd2a3bc44f /target/alpha | |
parent | 7012b691848d36c7ddaf487f31a01d2f10890e35 (diff) | |
download | qemu-aa3bad5b59e773dd107d4c84309be638d17fb867.zip qemu-aa3bad5b59e773dd107d4c84309be638d17fb867.tar.gz qemu-aa3bad5b59e773dd107d4c84309be638d17fb867.tar.bz2 |
target/alpha: Use float64_to_int64_modulo for CVTTQ
For the most part we can use the new generic routine,
though exceptions need some post-processing to sort
invalid from integer overflow.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-Id: <20230527141910.1885950-4-richard.henderson@linaro.org>
Diffstat (limited to 'target/alpha')
-rw-r--r-- | target/alpha/fpu_helper.c | 87 |
1 files changed, 19 insertions, 68 deletions
diff --git a/target/alpha/fpu_helper.c b/target/alpha/fpu_helper.c index 3ff8bb4..63d9e9c 100644 --- a/target/alpha/fpu_helper.c +++ b/target/alpha/fpu_helper.c @@ -453,78 +453,29 @@ uint64_t helper_cvtqs(CPUAlphaState *env, uint64_t a) static uint64_t do_cvttq(CPUAlphaState *env, uint64_t a, int roundmode) { - uint64_t frac, ret = 0; - uint32_t exp, sign, exc = 0; - int shift; + float64 fa; + int64_t ret; + uint32_t exc; - sign = (a >> 63); - exp = (uint32_t)(a >> 52) & 0x7ff; - frac = a & 0xfffffffffffffull; + fa = t_to_float64(a); + ret = float64_to_int64_modulo(fa, roundmode, &FP_STATUS); - if (exp == 0) { - if (unlikely(frac != 0) && !env->fp_status.flush_inputs_to_zero) { - goto do_underflow; - } - } else if (exp == 0x7ff) { - exc = FPCR_INV; - } else { - /* Restore implicit bit. */ - frac |= 0x10000000000000ull; - - shift = exp - 1023 - 52; - if (shift >= 0) { - /* In this case the number is so large that we must shift - the fraction left. There is no rounding to do. */ - if (shift < 64) { - ret = frac << shift; - } - /* Check for overflow. Note the special case of -0x1p63. */ - if (shift >= 11 && a != 0xC3E0000000000000ull) { - exc = FPCR_IOV | FPCR_INE; - } - } else { - uint64_t round; - - /* In this case the number is smaller than the fraction as - represented by the 52 bit number. Here we must think - about rounding the result. Handle this by shifting the - fractional part of the number into the high bits of ROUND. - This will let us efficiently handle round-to-nearest. */ - shift = -shift; - if (shift < 63) { - ret = frac >> shift; - round = frac << (64 - shift); - } else { - /* The exponent is so small we shift out everything. - Leave a sticky bit for proper rounding below. */ - do_underflow: - round = 1; - } + exc = get_float_exception_flags(&FP_STATUS); + if (unlikely(exc)) { + set_float_exception_flags(0, &FP_STATUS); - if (round) { - exc = FPCR_INE; - switch (roundmode) { - case float_round_nearest_even: - if (round == (1ull << 63)) { - /* Fraction is exactly 0.5; round to even. */ - ret += (ret & 1); - } else if (round > (1ull << 63)) { - ret += 1; - } - break; - case float_round_to_zero: - break; - case float_round_up: - ret += 1 - sign; - break; - case float_round_down: - ret += sign; - break; - } + /* We need to massage the resulting exceptions. */ + if (exc & float_flag_invalid_cvti) { + /* Overflow, either normal or infinity. */ + if (float64_is_infinity(fa)) { + exc = FPCR_INV; + } else { + exc = FPCR_IOV | FPCR_INE; } - } - if (sign) { - ret = -ret; + } else if (exc & float_flag_invalid) { + exc = FPCR_INV; + } else if (exc & float_flag_inexact) { + exc = FPCR_INE; } } env->error_code = exc; |