[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 12/29] softfloat: Adjust parts_uncanon_normal for floatx80
From: |
Richard Henderson |
Subject: |
[PULL 12/29] softfloat: Adjust parts_uncanon_normal for floatx80 |
Date: |
Thu, 3 Jun 2021 14:41:14 -0700 |
With floatx80_precision_x, the rounding happens across
the break between words. Notice this case with
frac_lsb = round_mask + 1 -> 0
and check the bits in frac_hi as needed.
In addition, since frac_shift == 0, we won't implicitly clear
round_mask via the right-shift, so explicitly clear those bits.
This fixes rounding for floatx80_precision_[sd].
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
fpu/softfloat-parts.c.inc | 36 ++++++++++++++++++++++++++++++------
1 file changed, 30 insertions(+), 6 deletions(-)
diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc
index a026581c33..efb81bbebe 100644
--- a/fpu/softfloat-parts.c.inc
+++ b/fpu/softfloat-parts.c.inc
@@ -155,7 +155,13 @@ static void partsN(uncanon_normal)(FloatPartsN *p,
float_status *s,
switch (s->float_rounding_mode) {
case float_round_nearest_even:
- inc = ((p->frac_lo & roundeven_mask) != frac_lsbm1 ? frac_lsbm1 : 0);
+ if (N > 64 && frac_lsb == 0) {
+ inc = ((p->frac_hi & 1) || (p->frac_lo & round_mask) != frac_lsbm1
+ ? frac_lsbm1 : 0);
+ } else {
+ inc = ((p->frac_lo & roundeven_mask) != frac_lsbm1
+ ? frac_lsbm1 : 0);
+ }
break;
case float_round_ties_away:
inc = frac_lsbm1;
@@ -176,7 +182,11 @@ static void partsN(uncanon_normal)(FloatPartsN *p,
float_status *s,
overflow_norm = true;
/* fall through */
case float_round_to_odd_inf:
- inc = p->frac_lo & frac_lsb ? 0 : round_mask;
+ if (N > 64 && frac_lsb == 0) {
+ inc = p->frac_hi & 1 ? 0 : round_mask;
+ } else {
+ inc = p->frac_lo & frac_lsb ? 0 : round_mask;
+ }
break;
default:
g_assert_not_reached();
@@ -191,8 +201,8 @@ static void partsN(uncanon_normal)(FloatPartsN *p,
float_status *s,
p->frac_hi |= DECOMPOSED_IMPLICIT_BIT;
exp++;
}
+ p->frac_lo &= ~round_mask;
}
- frac_shr(p, frac_shift);
if (fmt->arm_althp) {
/* ARM Alt HP eschews Inf and NaN for a wider exponent. */
@@ -201,18 +211,21 @@ static void partsN(uncanon_normal)(FloatPartsN *p,
float_status *s,
flags = float_flag_invalid;
exp = exp_max;
frac_allones(p);
+ p->frac_lo &= ~round_mask;
}
} else if (unlikely(exp >= exp_max)) {
flags |= float_flag_overflow | float_flag_inexact;
if (overflow_norm) {
exp = exp_max - 1;
frac_allones(p);
+ p->frac_lo &= ~round_mask;
} else {
p->cls = float_class_inf;
exp = exp_max;
frac_clear(p);
}
}
+ frac_shr(p, frac_shift);
} else if (s->flush_to_zero) {
flags |= float_flag_output_denormal;
p->cls = float_class_zero;
@@ -232,18 +245,29 @@ static void partsN(uncanon_normal)(FloatPartsN *p,
float_status *s,
/* Need to recompute round-to-even/round-to-odd. */
switch (s->float_rounding_mode) {
case float_round_nearest_even:
- inc = ((p->frac_lo & roundeven_mask) != frac_lsbm1
- ? frac_lsbm1 : 0);
+ if (N > 64 && frac_lsb == 0) {
+ inc = ((p->frac_hi & 1) ||
+ (p->frac_lo & round_mask) != frac_lsbm1
+ ? frac_lsbm1 : 0);
+ } else {
+ inc = ((p->frac_lo & roundeven_mask) != frac_lsbm1
+ ? frac_lsbm1 : 0);
+ }
break;
case float_round_to_odd:
case float_round_to_odd_inf:
- inc = p->frac_lo & frac_lsb ? 0 : round_mask;
+ if (N > 64 && frac_lsb == 0) {
+ inc = p->frac_hi & 1 ? 0 : round_mask;
+ } else {
+ inc = p->frac_lo & frac_lsb ? 0 : round_mask;
+ }
break;
default:
break;
}
flags |= float_flag_inexact;
frac_addi(p, p, inc);
+ p->frac_lo &= ~round_mask;
}
exp = (p->frac_hi & DECOMPOSED_IMPLICIT_BIT) != 0;
--
2.25.1
- [PULL 00/29] softfloat patch queue, Richard Henderson, 2021/06/03
- [PULL 01/29] softfloat: Move round_to_uint_and_pack to softfloat-parts.c.inc, Richard Henderson, 2021/06/03
- [PULL 02/29] softfloat: Move int_to_float to softfloat-parts.c.inc, Richard Henderson, 2021/06/03
- [PULL 04/29] softfloat: Move minmax_flags to softfloat-parts.c.inc, Richard Henderson, 2021/06/03
- [PULL 05/29] softfloat: Implement float128_(min|minnum|minnummag|max|maxnum|maxnummag), Richard Henderson, 2021/06/03
- [PULL 03/29] softfloat: Move uint_to_float to softfloat-parts.c.inc, Richard Henderson, 2021/06/03
- [PULL 06/29] softfloat: Move compare_floats to softfloat-parts.c.inc, Richard Henderson, 2021/06/03
- [PULL 07/29] softfloat: Move scalbn_decomposed to softfloat-parts.c.inc, Richard Henderson, 2021/06/03
- [PULL 09/29] softfloat: Split out parts_uncanon_normal, Richard Henderson, 2021/06/03
- [PULL 08/29] softfloat: Move sqrt_float to softfloat-parts.c.inc, Richard Henderson, 2021/06/03
- [PULL 12/29] softfloat: Adjust parts_uncanon_normal for floatx80,
Richard Henderson <=
- [PULL 11/29] softfloat: Introduce Floatx80RoundPrec, Richard Henderson, 2021/06/03
- [PULL 13/29] tests/fp/fp-test: Reverse order of floatx80 precision tests, Richard Henderson, 2021/06/03
- [PULL 10/29] softfloat: Reduce FloatFmt, Richard Henderson, 2021/06/03
- [PULL 14/29] softfloat: Convert floatx80_add/sub to FloatParts, Richard Henderson, 2021/06/03
- [PULL 18/29] softfloat: Convert floatx80_round to FloatParts, Richard Henderson, 2021/06/03
- [PULL 19/29] softfloat: Convert floatx80_round_to_int to FloatParts, Richard Henderson, 2021/06/03
- [PULL 16/29] softfloat: Convert floatx80_div to FloatParts, Richard Henderson, 2021/06/03
- [PULL 22/29] softfloat: Convert floatx80 to integer to FloatParts, Richard Henderson, 2021/06/03
- [PULL 21/29] softfloat: Convert floatx80 float conversions to FloatParts, Richard Henderson, 2021/06/03
- [PULL 17/29] softfloat: Convert floatx80_sqrt to FloatParts, Richard Henderson, 2021/06/03