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:
parent
6eb169b89a
commit
39626b0ce8
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
103
fpu/softfloat.c
103
fpu/softfloat.c
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user