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:
parent
813437e500
commit
795d6a2c49
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user