Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/fpu/softfloat-parts.h | 7 +++++++
fpu/softfloat.c | 19 ++++++++++++++++---
2 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/include/fpu/softfloat-parts.h b/include/fpu/softfloat-parts.h
index 9f7ee34d6a..eb76b47934 100644
--- a/include/fpu/softfloat-parts.h
+++ b/include/fpu/softfloat-parts.h
@@ -175,4 +175,11 @@ FloatParts64 parts64_pick_nan(const FloatParts64 *, const FloatParts64 *,
FloatParts128 parts128_pick_nan(const FloatParts128 *, const FloatParts128 *,
float_status *);
+/*
+ * Operations
+ */
+
+void parts64_round_canonical(FloatParts64 *p, float_status *s,
+ const FloatFmt *fmt);
+
#endif
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index e42782c656..0c931842c3 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1396,6 +1396,21 @@ float64 float64_round_pack_canonical(FloatParts64 *p, float_status *s)
return pack_raw64(p, &float64_params);
}
+/*
+ * Round to Fmt while remaining canonicalized.
+ */
+void parts64_round_canonical(FloatParts64 *p, float_status *s,
+ const FloatFmt *fmt)
+{
+ parts64_uncanon(p, s, fmt, false);
+ /*
+ * We normally expect uncanon to be followed by pack_raw,
+ * so we don't actually crop the bits. Do so now.
+ */
+ p->frac &= MAKE_64BIT_MASK(0, fmt->frac_size);
+ parts64_canonicalize(p, s, fmt);
+}
+
static float64 float64r32_pack_raw(FloatParts64 *p)
{
/*
@@ -5175,10 +5190,8 @@ static void parts_s390_divide_to_integer(FloatParts64 *a, FloatParts64 *b,
/* Round remainder to the target format */
*r = *r_precise;
status->float_exception_flags = 0;
- parts64_uncanon(r, status, fmt, false);
+ parts64_round_canonical(r, status, fmt);
r_flags = status->float_exception_flags;
- r->frac &= (1ULL << fmt->frac_size) - 1;
- parts64_canonicalize(r, status, fmt);
/* POp table "Results: DIVIDE TO INTEGER (Part 2 of 2)" */
if (is_q_smallish) {
--
2.43.0