softfloat: Move scalbn_decomposed to softfloat-parts.c.inc

Rename to parts$N_scalbn.
Reimplement float128_scalbn with FloatParts128.

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2020-11-14 20:28:02 -08:00
parent 6eb169b89a
commit 39626b0ce8
2 changed files with 55 additions and 69 deletions

View File

@ -1075,3 +1075,24 @@ static FloatRelation partsN(compare)(FloatPartsN *a, FloatPartsN *b,
b_sign: b_sign:
return b->sign ? float_relation_greater : float_relation_less; return b->sign ? float_relation_greater : float_relation_less;
} }
/*
* Multiply A by 2 raised to the power N.
*/
static void partsN(scalbn)(FloatPartsN *a, int n, float_status *s)
{
switch (a->cls) {
case float_class_snan:
case float_class_qnan:
parts_return_nan(a, s);
break;
case float_class_zero:
case float_class_inf:
break;
case float_class_normal:
a->exp += MIN(MAX(n, -0x10000), 0x10000);
break;
default:
g_assert_not_reached();
}
}

View File

@ -890,6 +890,12 @@ static int parts128_compare(FloatParts128 *a, FloatParts128 *b,
#define parts_compare(A, B, S, Q) \ #define parts_compare(A, B, S, Q) \
PARTS_GENERIC_64_128(compare, A)(A, B, S, Q) PARTS_GENERIC_64_128(compare, A)(A, B, S, Q)
static void parts64_scalbn(FloatParts64 *a, int n, float_status *s);
static void parts128_scalbn(FloatParts128 *a, int n, float_status *s);
#define parts_scalbn(A, N, S) \
PARTS_GENERIC_64_128(scalbn, A)(A, N, S)
/* /*
* Helper functions for softfloat-parts.c.inc, per-size operations. * Helper functions for softfloat-parts.c.inc, per-size operations.
*/ */
@ -3529,58 +3535,53 @@ FloatRelation float128_compare_quiet(float128 a, float128 b, float_status *s)
return float128_do_compare(a, b, s, true); return float128_do_compare(a, b, s, true);
} }
/* Multiply A by 2 raised to the power N. */ /*
static FloatParts64 scalbn_decomposed(FloatParts64 a, int n, float_status *s) * Scale by 2**N
{
if (unlikely(is_nan(a.cls))) {
parts_return_nan(&a, s);
}
if (a.cls == float_class_normal) {
/* The largest float type (even though not supported by FloatParts64)
* is float128, which has a 15 bit exponent. Bounding N to 16 bits
* still allows rounding to infinity, without allowing overflow
* within the int32_t that backs FloatParts64.exp.
*/ */
n = MIN(MAX(n, -0x10000), 0x10000);
a.exp += n;
}
return a;
}
float16 float16_scalbn(float16 a, int n, float_status *status) float16 float16_scalbn(float16 a, int n, float_status *status)
{ {
FloatParts64 pa, pr; FloatParts64 p;
float16_unpack_canonical(&pa, a, status); float16_unpack_canonical(&p, a, status);
pr = scalbn_decomposed(pa, n, status); parts_scalbn(&p, n, status);
return float16_round_pack_canonical(&pr, status); return float16_round_pack_canonical(&p, status);
} }
float32 float32_scalbn(float32 a, int n, float_status *status) float32 float32_scalbn(float32 a, int n, float_status *status)
{ {
FloatParts64 pa, pr; FloatParts64 p;
float32_unpack_canonical(&pa, a, status); float32_unpack_canonical(&p, a, status);
pr = scalbn_decomposed(pa, n, status); parts_scalbn(&p, n, status);
return float32_round_pack_canonical(&pr, status); return float32_round_pack_canonical(&p, status);
} }
float64 float64_scalbn(float64 a, int n, float_status *status) float64 float64_scalbn(float64 a, int n, float_status *status)
{ {
FloatParts64 pa, pr; FloatParts64 p;
float64_unpack_canonical(&pa, a, status); float64_unpack_canonical(&p, a, status);
pr = scalbn_decomposed(pa, n, status); parts_scalbn(&p, n, status);
return float64_round_pack_canonical(&pr, status); return float64_round_pack_canonical(&p, status);
} }
bfloat16 bfloat16_scalbn(bfloat16 a, int n, float_status *status) bfloat16 bfloat16_scalbn(bfloat16 a, int n, float_status *status)
{ {
FloatParts64 pa, pr; FloatParts64 p;
bfloat16_unpack_canonical(&pa, a, status); bfloat16_unpack_canonical(&p, a, status);
pr = scalbn_decomposed(pa, n, status); parts_scalbn(&p, n, status);
return bfloat16_round_pack_canonical(&pr, status); return bfloat16_round_pack_canonical(&p, status);
}
float128 float128_scalbn(float128 a, int n, float_status *status)
{
FloatParts128 p;
float128_unpack_canonical(&p, a, status);
parts_scalbn(&p, n, status);
return float128_round_pack_canonical(&p, status);
} }
/* /*
@ -6638,42 +6639,6 @@ floatx80 floatx80_scalbn(floatx80 a, int n, float_status *status)
aSign, aExp, aSig, 0, status); aSign, aExp, aSig, 0, status);
} }
float128 float128_scalbn(float128 a, int n, float_status *status)
{
bool aSign;
int32_t aExp;
uint64_t aSig0, aSig1;
aSig1 = extractFloat128Frac1( a );
aSig0 = extractFloat128Frac0( a );
aExp = extractFloat128Exp( a );
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
if ( aSig0 | aSig1 ) {
return propagateFloat128NaN(a, a, status);
}
return a;
}
if (aExp != 0) {
aSig0 |= UINT64_C(0x0001000000000000);
} else if (aSig0 == 0 && aSig1 == 0) {
return a;
} else {
aExp++;
}
if (n > 0x10000) {
n = 0x10000;
} else if (n < -0x10000) {
n = -0x10000;
}
aExp += n - 1;
return normalizeRoundAndPackFloat128( aSign, aExp, aSig0, aSig1
, status);
}
static void __attribute__((constructor)) softfloat_init(void) static void __attribute__((constructor)) softfloat_init(void)
{ {
union_float64 ua, ub, uc, ur; union_float64 ua, ub, uc, ur;