target/hexagon: Expand GEN_XF_ROUND

This massive macro is now only used once.
Expand it for use only by float64.

Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-12-08 15:19:19 -06:00
parent 813437e500
commit 795d6a2c49

View File

@ -354,136 +354,135 @@ float32 infinite_float32(uint8_t sign)
} }
/* Return a maximum finite value with the requested sign */ /* Return a maximum finite value with the requested sign */
#define GEN_XF_ROUND(SUFFIX, MANTBITS, INF_EXP, INTERNAL_TYPE) \ static float64 accum_round_float64(Accum a, float_status *fp_status)
static SUFFIX accum_round_##SUFFIX(Accum a, float_status * fp_status) \ {
{ \ if ((int128_gethi(a.mant) == 0) && (int128_getlo(a.mant) == 0)
if ((int128_gethi(a.mant) == 0) && (int128_getlo(a.mant) == 0) \ && ((a.guard | a.round | a.sticky) == 0)) {
&& ((a.guard | a.round | a.sticky) == 0)) { \ /* result zero */
/* result zero */ \ switch (fp_status->float_rounding_mode) {
switch (fp_status->float_rounding_mode) { \ case float_round_down:
case float_round_down: \ return zero_float64(1);
return zero_##SUFFIX(1); \ default:
default: \ return zero_float64(0);
return zero_##SUFFIX(0); \ }
} \ }
} \ /*
/* Normalize right */ \ * Normalize right
/* We want MANTBITS bits of mantissa plus the leading one. */ \ * We want DF_MANTBITS bits of mantissa plus the leading one.
/* That means that we want MANTBITS+1 bits, or 0x000000000000FF_FFFF */ \ * That means that we want DF_MANTBITS+1 bits, or 0x000000000000FF_FFFF
/* So we need to normalize right while the high word is non-zero and \ * So we need to normalize right while the high word is non-zero and
* while the low word is nonzero when masked with 0xffe0_0000_0000_0000 */ \ * while the low word is nonzero when masked with 0xffe0_0000_0000_0000
while ((int128_gethi(a.mant) != 0) || \ */
((int128_getlo(a.mant) >> (MANTBITS + 1)) != 0)) { \ while ((int128_gethi(a.mant) != 0) ||
a = accum_norm_right(a, 1); \ ((int128_getlo(a.mant) >> (DF_MANTBITS + 1)) != 0)) {
} \ a = accum_norm_right(a, 1);
/* \ }
* OK, now normalize left \ /*
* We want to normalize left until we have a leading one in bit 24 \ * OK, now normalize left
* Theoretically, we only need to shift a maximum of one to the left if we \ * We want to normalize left until we have a leading one in bit 24
* shifted out lots of bits from B, or if we had no shift / 1 shift sticky \ * Theoretically, we only need to shift a maximum of one to the left if we
* should be 0 \ * shifted out lots of bits from B, or if we had no shift / 1 shift sticky
*/ \ * should be 0
while ((int128_getlo(a.mant) & (1ULL << MANTBITS)) == 0) { \ */
a = accum_norm_left(a); \ while ((int128_getlo(a.mant) & (1ULL << DF_MANTBITS)) == 0) {
} \ a = accum_norm_left(a);
/* \ }
* OK, now we might need to denormalize because of potential underflow. \ /*
* We need to do this before rounding, and rounding might make us normal \ * OK, now we might need to denormalize because of potential underflow.
* again \ * We need to do this before rounding, and rounding might make us normal
*/ \ * again
while (a.exp <= 0) { \ */
a = accum_norm_right(a, 1 - a.exp); \ while (a.exp <= 0) {
/* \ a = accum_norm_right(a, 1 - a.exp);
* Do we have underflow? \ /*
* That's when we get an inexact answer because we ran out of bits \ * Do we have underflow?
* in a denormal. \ * That's when we get an inexact answer because we ran out of bits
*/ \ * in a denormal.
if (a.guard || a.round || a.sticky) { \ */
float_raise(float_flag_underflow, fp_status); \ if (a.guard || a.round || a.sticky) {
} \ float_raise(float_flag_underflow, fp_status);
} \ }
/* OK, we're relatively canonical... now we need to round */ \ }
if (a.guard || a.round || a.sticky) { \ /* OK, we're relatively canonical... now we need to round */
float_raise(float_flag_inexact, fp_status); \ if (a.guard || a.round || a.sticky) {
switch (fp_status->float_rounding_mode) { \ float_raise(float_flag_inexact, fp_status);
case float_round_to_zero: \ switch (fp_status->float_rounding_mode) {
/* Chop and we're done */ \ case float_round_to_zero:
break; \ /* Chop and we're done */
case float_round_up: \ break;
if (a.sign == 0) { \ case float_round_up:
a.mant = int128_add(a.mant, int128_one()); \ if (a.sign == 0) {
} \ a.mant = int128_add(a.mant, int128_one());
break; \ }
case float_round_down: \ break;
if (a.sign != 0) { \ case float_round_down:
a.mant = int128_add(a.mant, int128_one()); \ if (a.sign != 0) {
} \ a.mant = int128_add(a.mant, int128_one());
break; \ }
default: \ break;
if (a.round || a.sticky) { \ default:
/* round up if guard is 1, down if guard is zero */ \ if (a.round || a.sticky) {
a.mant = int128_add(a.mant, int128_make64(a.guard)); \ /* round up if guard is 1, down if guard is zero */
} else if (a.guard) { \ a.mant = int128_add(a.mant, int128_make64(a.guard));
/* exactly .5, round up if odd */ \ } else if (a.guard) {
a.mant = int128_add(a.mant, int128_and(a.mant, int128_one())); \ /* exactly .5, round up if odd */
} \ a.mant = int128_add(a.mant, int128_and(a.mant, int128_one()));
break; \ }
} \ break;
} \ }
/* \ }
* OK, now we might have carried all the way up. \ /*
* So we might need to shr once \ * OK, now we might have carried all the way up.
* at least we know that the lsb should be zero if we rounded and \ * So we might need to shr once
* got a carry out... \ * at least we know that the lsb should be zero if we rounded and
*/ \ * got a carry out...
if ((int128_getlo(a.mant) >> (MANTBITS + 1)) != 0) { \ */
a = accum_norm_right(a, 1); \ if ((int128_getlo(a.mant) >> (DF_MANTBITS + 1)) != 0) {
} \ a = accum_norm_right(a, 1);
/* Overflow? */ \ }
if (a.exp >= INF_EXP) { \ /* Overflow? */
/* Yep, inf result */ \ if (a.exp >= DF_INF_EXP) {
float_raise(float_flag_overflow, fp_status); \ /* Yep, inf result */
float_raise(float_flag_inexact, fp_status); \ float_raise(float_flag_overflow, fp_status);
switch (fp_status->float_rounding_mode) { \ float_raise(float_flag_inexact, fp_status);
case float_round_to_zero: \ switch (fp_status->float_rounding_mode) {
return maxfinite_##SUFFIX(a.sign); \ case float_round_to_zero:
case float_round_up: \ return maxfinite_float64(a.sign);
if (a.sign == 0) { \ case float_round_up:
return infinite_##SUFFIX(a.sign); \ if (a.sign == 0) {
} else { \ return infinite_float64(a.sign);
return maxfinite_##SUFFIX(a.sign); \ } else {
} \ return maxfinite_float64(a.sign);
case float_round_down: \ }
if (a.sign != 0) { \ case float_round_down:
return infinite_##SUFFIX(a.sign); \ if (a.sign != 0) {
} else { \ return infinite_float64(a.sign);
return maxfinite_##SUFFIX(a.sign); \ } else {
} \ return maxfinite_float64(a.sign);
default: \ }
return infinite_##SUFFIX(a.sign); \ default:
} \ return infinite_float64(a.sign);
} \ }
/* Underflow? */ \ }
if (int128_getlo(a.mant) & (1ULL << MANTBITS)) { \ /* Underflow? */
/* Leading one means: No, we're normal. So, we should be done... */ \ if (int128_getlo(a.mant) & (1ULL << DF_MANTBITS)) {
INTERNAL_TYPE ret; \ /* Leading one means: No, we're normal. So, we should be done... */
ret.i = 0; \ Double ret;
ret.sign = a.sign; \ ret.i = 0;
ret.exp = a.exp; \ ret.sign = a.sign;
ret.mant = int128_getlo(a.mant); \ ret.exp = a.exp;
return ret.i; \ ret.mant = int128_getlo(a.mant);
} \ return ret.i;
assert(a.exp == 1); \ }
INTERNAL_TYPE ret; \ assert(a.exp == 1);
ret.i = 0; \ Double ret;
ret.sign = a.sign; \ ret.i = 0;
ret.exp = 0; \ ret.sign = a.sign;
ret.mant = int128_getlo(a.mant); \ ret.exp = 0;
return ret.i; \ ret.mant = int128_getlo(a.mant);
return ret.i;
} }
GEN_XF_ROUND(float64, DF_MANTBITS, DF_INF_EXP, Double)
float64 internal_mpyhh(float64 a, float64 b, float64 internal_mpyhh(float64 a, float64 b,
unsigned long long int accumulated, unsigned long long int accumulated,
float_status *fp_status) float_status *fp_status)