On Mon, Feb 23, 2026 at 07:21:51PM +1100, Richard Henderson wrote: > From: Max Chou <[email protected]> > > The OCP FP8 conversion operations have a parameter to control > saturate vs overflow. Add a parameter, currently always false. > > Signed-off-by: Max Chou <[email protected]> > [rth: Split out of a larger patch] > Signed-off-by: Richard Henderson <[email protected]> > --- > fpu/softfloat.c | 46 +++++++++++++++++++-------------------- > fpu/softfloat-parts.c.inc | 15 ++++++++----- > 2 files changed, 32 insertions(+), 29 deletions(-) > > diff --git a/fpu/softfloat.c b/fpu/softfloat.c > index 9d06a1bb59..b3c4104854 100644 > --- a/fpu/softfloat.c > +++ b/fpu/softfloat.c > @@ -771,20 +771,20 @@ static void parts128_canonicalize(FloatParts128 *p, > float_status *status, > PARTS_GENERIC_64_128(canonicalize, A)(A, S, F) > > static void parts64_uncanon_normal(FloatParts64 *p, float_status *status, > - const FloatFmt *fmt); > + const FloatFmt *fmt, bool saturate); > static void parts128_uncanon_normal(FloatParts128 *p, float_status *status, > - const FloatFmt *fmt); > + const FloatFmt *fmt, bool saturate); > > -#define parts_uncanon_normal(A, S, F) \ > - PARTS_GENERIC_64_128(uncanon_normal, A)(A, S, F) > +#define parts_uncanon_normal(A, S, F, X) \ > + PARTS_GENERIC_64_128(uncanon_normal, A)(A, S, F, X) > > static void parts64_uncanon(FloatParts64 *p, float_status *status, > - const FloatFmt *fmt); > + const FloatFmt *fmt, bool saturate); > static void parts128_uncanon(FloatParts128 *p, float_status *status, > - const FloatFmt *fmt); > + const FloatFmt *fmt, bool saturate); > > -#define parts_uncanon(A, S, F) \ > - PARTS_GENERIC_64_128(uncanon, A)(A, S, F) > +#define parts_uncanon(A, S, F, X) \ > + PARTS_GENERIC_64_128(uncanon, A)(A, S, F, X) > > static void parts64_add_normal(FloatParts64 *a, FloatParts64 *b); > static void parts128_add_normal(FloatParts128 *a, FloatParts128 *b); > @@ -1699,7 +1699,7 @@ static float16 > float16a_round_pack_canonical(FloatParts64 *p, > float_status *s, > const FloatFmt *params) > { > - parts_uncanon(p, s, params); > + parts_uncanon(p, s, params, false); > return float16_pack_raw(p); > } > > @@ -1712,7 +1712,7 @@ static float16 > float16_round_pack_canonical(FloatParts64 *p, > static bfloat16 bfloat16_round_pack_canonical(FloatParts64 *p, > float_status *s) > { > - parts_uncanon(p, s, &bfloat16_params); > + parts_uncanon(p, s, &bfloat16_params, false); > return bfloat16_pack_raw(p); > } > > @@ -1726,7 +1726,7 @@ static void float32_unpack_canonical(FloatParts64 *p, > float32 f, > static float32 float32_round_pack_canonical(FloatParts64 *p, > float_status *s) > { > - parts_uncanon(p, s, &float32_params); > + parts_uncanon(p, s, &float32_params, false); > return float32_pack_raw(p); > } > > @@ -1740,7 +1740,7 @@ static void float64_unpack_canonical(FloatParts64 *p, > float64 f, > static float64 float64_round_pack_canonical(FloatParts64 *p, > float_status *s) > { > - parts_uncanon(p, s, &float64_params); > + parts_uncanon(p, s, &float64_params, false); > return float64_pack_raw(p); > } > > @@ -1789,7 +1789,7 @@ static float64 float64r32_pack_raw(FloatParts64 *p) > static float64 float64r32_round_pack_canonical(FloatParts64 *p, > float_status *s) > { > - parts_uncanon(p, s, &float32_params); > + parts_uncanon(p, s, &float32_params, false); > return float64r32_pack_raw(p); > } > > @@ -1803,7 +1803,7 @@ static void float128_unpack_canonical(FloatParts128 *p, > float128 f, > static float128 float128_round_pack_canonical(FloatParts128 *p, > float_status *s) > { > - parts_uncanon(p, s, &float128_params); > + parts_uncanon(p, s, &float128_params, false); > return float128_pack_raw(p); > } > > @@ -1851,7 +1851,7 @@ static floatx80 > floatx80_round_pack_canonical(FloatParts128 *p, > case float_class_normal: > case float_class_denormal: > if (s->floatx80_rounding_precision == floatx80_precision_x) { > - parts_uncanon_normal(p, s, fmt); > + parts_uncanon_normal(p, s, fmt, false); > frac = p->frac_hi; > exp = p->exp; > } else { > @@ -1860,7 +1860,7 @@ static floatx80 > floatx80_round_pack_canonical(FloatParts128 *p, > p64.sign = p->sign; > p64.exp = p->exp; > frac_truncjam(&p64, p); > - parts_uncanon_normal(&p64, s, fmt); > + parts_uncanon_normal(&p64, s, fmt, false); > frac = p64.frac; > exp = p64.exp; > } > @@ -2258,7 +2258,7 @@ float16_muladd_scalbn(float16 a, float16 b, float16 c, > pr = parts_muladd_scalbn(&pa, &pb, &pc, scale, flags, status); > > /* Round before applying negate result. */ > - parts_uncanon(pr, status, &float16_params); > + parts_uncanon(pr, status, &float16_params, false); > if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) { > pr->sign ^= 1; > } > @@ -2283,7 +2283,7 @@ float32_muladd_scalbn(float32 a, float32 b, float32 c, > pr = parts_muladd_scalbn(&pa, &pb, &pc, scale, flags, status); > > /* Round before applying negate result. */ > - parts_uncanon(pr, status, &float32_params); > + parts_uncanon(pr, status, &float32_params, false); > if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) { > pr->sign ^= 1; > } > @@ -2302,7 +2302,7 @@ float64_muladd_scalbn(float64 a, float64 b, float64 c, > pr = parts_muladd_scalbn(&pa, &pb, &pc, scale, flags, status); > > /* Round before applying negate result. */ > - parts_uncanon(pr, status, &float64_params); > + parts_uncanon(pr, status, &float64_params, false); > if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) { > pr->sign ^= 1; > } > @@ -2461,7 +2461,7 @@ float64 float64r32_muladd(float64 a, float64 b, float64 > c, > pr = parts_muladd_scalbn(&pa, &pb, &pc, 0, flags, status); > > /* Round before applying negate result. */ > - parts_uncanon(pr, status, &float32_params); > + parts_uncanon(pr, status, &float32_params, false); > if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) { > pr->sign ^= 1; > } > @@ -2479,7 +2479,7 @@ bfloat16 QEMU_FLATTEN bfloat16_muladd(bfloat16 a, > bfloat16 b, bfloat16 c, > pr = parts_muladd_scalbn(&pa, &pb, &pc, 0, flags, status); > > /* Round before applying negate result. */ > - parts_uncanon(pr, status, &bfloat16_params); > + parts_uncanon(pr, status, &bfloat16_params, false); > if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) { > pr->sign ^= 1; > } > @@ -2497,7 +2497,7 @@ float128 QEMU_FLATTEN float128_muladd(float128 a, > float128 b, float128 c, > pr = parts_muladd_scalbn(&pa, &pb, &pc, 0, flags, status); > > /* Round before applying negate result. */ > - parts_uncanon(pr, status, &float128_params); > + parts_uncanon(pr, status, &float128_params, false); > if ((flags & float_muladd_negate_result) && !is_nan(pr->cls)) { > pr->sign ^= 1; > } > @@ -5435,7 +5435,7 @@ 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; > - parts_uncanon(r, status, fmt); > + parts_uncanon(r, status, fmt, false); > r_flags = status->float_exception_flags; > r->frac &= (1ULL << fmt->frac_size) - 1; > parts_canonicalize(r, status, fmt); > diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc > index 4909ff7418..09be686645 100644 > --- a/fpu/softfloat-parts.c.inc > +++ b/fpu/softfloat-parts.c.inc > @@ -258,9 +258,12 @@ static void partsN(canonicalize)(FloatPartsN *p, > float_status *status, > * are FRAC_SHIFT bits that may require rounding at the bottom of the > * fraction; these bits will be removed. The exponent will be biased > * by EXP_BIAS and must be bounded by [EXP_MAX-1, 0]. > + * > + * The saturate parameter controls saturation behavior for formats that > + * support it -- when true, overflow produces max normal instead of infinity. > */ > static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s, > - const FloatFmt *fmt) > + const FloatFmt *fmt, bool saturate) > { > const int exp_max = fmt->exp_max; > const int frac_shift = fmt->frac_shift; > @@ -269,7 +272,7 @@ static void partsN(uncanon_normal)(FloatPartsN *p, > float_status *s, > const uint64_t frac_lsbm1 = round_mask ^ (round_mask >> 1); > const uint64_t roundeven_mask = round_mask | frac_lsb; > uint64_t inc; > - bool overflow_norm = false; > + bool overflow_norm = saturate; > int exp, flags = 0; > > switch (s->float_rounding_mode) { > @@ -294,11 +297,11 @@ static void partsN(uncanon_normal)(FloatPartsN *p, > float_status *s, > break; > case float_round_up: > inc = p->sign ? 0 : round_mask; > - overflow_norm = p->sign; > + overflow_norm |= p->sign; > break; > case float_round_down: > inc = p->sign ? round_mask : 0; > - overflow_norm = !p->sign; > + overflow_norm |= !p->sign; > break; > case float_round_to_odd: > overflow_norm = true; > @@ -445,10 +448,10 @@ static void partsN(uncanon_normal)(FloatPartsN *p, > float_status *s, > } > > static void partsN(uncanon)(FloatPartsN *p, float_status *s, > - const FloatFmt *fmt) > + const FloatFmt *fmt, bool saturate) > { > if (likely(is_anynorm(p->cls))) { > - parts_uncanon_normal(p, s, fmt); > + parts_uncanon_normal(p, s, fmt, saturate); > } else { > switch (p->cls) { > case float_class_zero: > -- > 2.43.0 >
Reviewed-by: Chao Liu <[email protected]> Thanks, Chao
