Skip to content

Commit

Permalink
target/alpha: Use float64_to_int64_modulo for CVTTQ
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rth7680 committed Jul 1, 2023
1 parent 7012b69 commit aa3bad5
Showing 1 changed file with 19 additions and 68 deletions.
87 changes: 19 additions & 68 deletions target/alpha/fpu_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit aa3bad5

Please sign in to comment.