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) { 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