mirror of https://github.com/xemu-project/xemu.git
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>
This commit is contained in:
parent
7012b69184
commit
aa3bad5b59
|
@ -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)
|
static uint64_t do_cvttq(CPUAlphaState *env, uint64_t a, int roundmode)
|
||||||
{
|
{
|
||||||
uint64_t frac, ret = 0;
|
float64 fa;
|
||||||
uint32_t exp, sign, exc = 0;
|
int64_t ret;
|
||||||
int shift;
|
uint32_t exc;
|
||||||
|
|
||||||
sign = (a >> 63);
|
fa = t_to_float64(a);
|
||||||
exp = (uint32_t)(a >> 52) & 0x7ff;
|
ret = float64_to_int64_modulo(fa, roundmode, &FP_STATUS);
|
||||||
frac = a & 0xfffffffffffffull;
|
|
||||||
|
|
||||||
if (exp == 0) {
|
exc = get_float_exception_flags(&FP_STATUS);
|
||||||
if (unlikely(frac != 0) && !env->fp_status.flush_inputs_to_zero) {
|
if (unlikely(exc)) {
|
||||||
goto do_underflow;
|
set_float_exception_flags(0, &FP_STATUS);
|
||||||
}
|
|
||||||
} else if (exp == 0x7ff) {
|
|
||||||
exc = FPCR_INV;
|
|
||||||
} else {
|
|
||||||
/* Restore implicit bit. */
|
|
||||||
frac |= 0x10000000000000ull;
|
|
||||||
|
|
||||||
shift = exp - 1023 - 52;
|
/* We need to massage the resulting exceptions. */
|
||||||
if (shift >= 0) {
|
if (exc & float_flag_invalid_cvti) {
|
||||||
/* In this case the number is so large that we must shift
|
/* Overflow, either normal or infinity. */
|
||||||
the fraction left. There is no rounding to do. */
|
if (float64_is_infinity(fa)) {
|
||||||
if (shift < 64) {
|
exc = FPCR_INV;
|
||||||
ret = frac << shift;
|
} else {
|
||||||
}
|
|
||||||
/* Check for overflow. Note the special case of -0x1p63. */
|
|
||||||
if (shift >= 11 && a != 0xC3E0000000000000ull) {
|
|
||||||
exc = FPCR_IOV | FPCR_INE;
|
exc = FPCR_IOV | FPCR_INE;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (exc & float_flag_invalid) {
|
||||||
uint64_t round;
|
exc = FPCR_INV;
|
||||||
|
} else if (exc & float_flag_inexact) {
|
||||||
/* In this case the number is smaller than the fraction as
|
exc = FPCR_INE;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sign) {
|
|
||||||
ret = -ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
env->error_code = exc;
|
env->error_code = exc;
|
||||||
|
|
Loading…
Reference in New Issue