On Mon, Feb 23, 2026 at 07:21:49PM +1100, Richard Henderson wrote: > Generalize arm_althp to indicate how exp==max should > be handled for the format. Reorganize canonicalize > and uncanon_normal to use a switch statement, allowing > more cases to be added trivially. > > Signed-off-by: Richard Henderson <[email protected]> > --- > fpu/softfloat.c | 17 ++++++-- > fpu/softfloat-parts.c.inc | 92 ++++++++++++++++++++++++--------------- > 2 files changed, 69 insertions(+), 40 deletions(-) > > diff --git a/fpu/softfloat.c b/fpu/softfloat.c > index 8740975348..8d8e576757 100644 > --- a/fpu/softfloat.c > +++ b/fpu/softfloat.c > @@ -522,7 +522,16 @@ typedef struct { > #define DECOMPOSED_BINARY_POINT 63 > #define DECOMPOSED_IMPLICIT_BIT (1ull << DECOMPOSED_BINARY_POINT) > > -/* Structure holding all of the relevant parameters for a format. > +/* Format-specific handling of exp == exp_max */ > +typedef enum __attribute__((__packed__)) { > + /* exp==max, frac==0 ? infinity : nan; this is ieee standard. */ > + float_expmax_ieee, > + /* exp==max is a normal number; no infinity or nan representation. */ > + float_expmax_normal, > +} FloatFmtExpMaxKind; > + > +/* > + * Structure holding all of the relevant parameters for a format. > * exp_size: the size of the exponent field > * exp_bias: the offset applied to the exponent field > * exp_max: the maximum normalised exponent > @@ -531,7 +540,7 @@ typedef struct { > * The following are computed based the size of fraction > * round_mask: bits below lsb which must be rounded > * The following optional modifiers are available: > - * arm_althp: handle ARM Alternative Half Precision > + * exp_max_kind: affects how exp == exp_max is interpreted > * has_explicit_bit: has an explicit integer bit; this affects whether > * the float_status floatx80_behaviour handling applies > */ > @@ -542,7 +551,7 @@ typedef struct { > int exp_max; > int frac_size; > int frac_shift; > - bool arm_althp; > + FloatFmtExpMaxKind exp_max_kind; > bool has_explicit_bit; > uint64_t round_mask; > } FloatFmt; > @@ -566,7 +575,7 @@ static const FloatFmt float16_params = { > > static const FloatFmt float16_params_ahp = { > FLOAT_PARAMS(5, 10), > - .arm_althp = true > + .exp_max_kind = float_expmax_normal, > }; > > static const FloatFmt bfloat16_params = { > diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc > index 79b56014ab..455bbf281e 100644 > --- a/fpu/softfloat-parts.c.inc > +++ b/fpu/softfloat-parts.c.inc > @@ -227,18 +227,30 @@ static void partsN(canonicalize)(FloatPartsN *p, > float_status *status, > p->exp = fmt->frac_shift - fmt->exp_bias > - shift + !has_pseudo_denormals; > } > - } else if (likely(p->exp < fmt->exp_max) || fmt->arm_althp) { > - p->cls = float_class_normal; > - p->exp -= fmt->exp_bias; > - frac_shl(p, fmt->frac_shift); > - p->frac_hi |= DECOMPOSED_IMPLICIT_BIT; > - } else if (likely(frac_eqz(p))) { > - p->cls = float_class_inf; > - } else { > - frac_shl(p, fmt->frac_shift); > - p->cls = (parts_is_snan_frac(p->frac_hi, status) > - ? float_class_snan : float_class_qnan); > + return; > } > + if (unlikely(p->exp == fmt->exp_max)) { > + switch (fmt->exp_max_kind) { > + case float_expmax_ieee: > + if (likely(frac_eqz(p))) { > + p->cls = float_class_inf; > + } else { > + frac_shl(p, fmt->frac_shift); > + p->cls = (parts_is_snan_frac(p->frac_hi, status) > + ? float_class_snan : float_class_qnan); > + } > + return; > + case float_expmax_normal: > + break; > + default: > + g_assert_not_reached(); > + } > + } > + > + p->cls = float_class_normal; > + p->exp -= fmt->exp_bias; > + frac_shl(p, fmt->frac_shift); > + p->frac_hi |= DECOMPOSED_IMPLICIT_BIT; > } > > /* > @@ -314,29 +326,37 @@ static void partsN(uncanon_normal)(FloatPartsN *p, > float_status *s, > p->frac_lo &= ~round_mask; > } > > - if (fmt->arm_althp) { > - /* ARM Alt HP eschews Inf and NaN for a wider exponent. */ > - if (unlikely(exp > exp_max)) { > - /* Overflow. Return the maximum normal. */ > - 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; > - if (s->rebias_overflow) { > - exp -= fmt->exp_re_bias; > - } else if (overflow_norm) { > - flags |= float_flag_inexact; > - exp = exp_max - 1; > - frac_allones(p); > - p->frac_lo &= ~round_mask; > - } else { > - flags |= float_flag_inexact; > - p->cls = float_class_inf; > - exp = exp_max; > - frac_clear(p); > + if (unlikely(exp >= exp_max)) { > + switch (fmt->exp_max_kind) { > + case float_expmax_ieee: > + flags |= float_flag_overflow; > + if (s->rebias_overflow) { > + exp -= fmt->exp_re_bias; > + } else if (overflow_norm) { > + flags |= float_flag_inexact; > + exp = exp_max - 1; > + frac_allones(p); > + p->frac_lo &= ~round_mask; > + } else { > + flags |= float_flag_inexact; > + p->cls = float_class_inf; > + exp = exp_max; > + frac_clear(p); > + } > + break; > + > + case float_expmax_normal: > + if (unlikely(exp > exp_max)) { > + /* Overflow. Return the maximum normal. */ > + flags = float_flag_invalid; > + exp = exp_max; > + frac_allones(p); > + p->frac_lo &= ~round_mask; > + } > + break; > + > + default: > + g_assert_not_reached(); > } > } > frac_shr(p, frac_shift); > @@ -434,13 +454,13 @@ static void partsN(uncanon)(FloatPartsN *p, > float_status *s, > frac_clear(p); > return; > case float_class_inf: > - g_assert(!fmt->arm_althp); > + assert(fmt->exp_max_kind == float_expmax_ieee); > p->exp = fmt->exp_max; > frac_clear(p); > return; > case float_class_qnan: > case float_class_snan: > - g_assert(!fmt->arm_althp); > + assert(fmt->exp_max_kind != float_expmax_normal); > p->exp = fmt->exp_max; > frac_shr(p, fmt->frac_shift); > return; > -- > 2.43.0 >
Reviewed-by: Chao Liu <[email protected]> Thanks, Chao
