Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
---
include/fpu/softfloat-parts.h | 3 +++
fpu/softfloat.c | 22 +++++++++++++++++++---
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/include/fpu/softfloat-parts.h b/include/fpu/softfloat-parts.h
index 8c3a94bbbc..1876264d43 100644
--- a/include/fpu/softfloat-parts.h
+++ b/include/fpu/softfloat-parts.h
@@ -196,4 +196,7 @@ FloatParts128 parts128_round_to_int(const FloatParts128 *a,
int scale, float_status *s,
const FloatFmt *fmt);
+FloatParts64 parts64_round_to_fmt(const FloatParts64 *p, float_status *s,
+ const FloatFmt *fmt);
+
#endif
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index b71bd49483..b6cf0c8188 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1396,6 +1396,24 @@ float64 float64_round_pack_canonical(FloatParts64 *p,
float_status *s)
return pack_raw64(p, &float64_params);
}
+/*
+ * Round to Fmt while remaining canonicalized.
+ */
+FloatParts64 parts64_round_to_fmt(const FloatParts64 *p, float_status *s,
+ const FloatFmt *fmt)
+{
+ FloatParts64 r = *p;
+
+ parts64_uncanon(&r, s, fmt, false);
+ /*
+ * We normally expect uncanon to be followed by pack_raw,
+ * so we don't actually crop the bits. Do so now.
+ */
+ r.frac &= MAKE_64BIT_MASK(0, fmt->frac_size);
+ parts64_canonicalize(&r, s, fmt);
+ return r;
+}
+
static float64 float64r32_pack_raw(FloatParts64 *p)
{
/*
@@ -5176,10 +5194,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);
+ *r = parts64_round_to_fmt(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