fpu: Introduce FloatFmtExpMaxKind
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. Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Richard Henderson committed
Feb 5, 2026 at 15:21 UTC
a4aa765c9ed5350133c3f5bd4b985f81f7871f84
2 files changed
+69
-40
fpu/softfloat-parts.c.inc
+56
-36
@@ -227,18 +227,30 @@ static void partsN(canonicalize)(FloatPartsN *p, float_status *status,
227
p->exp = fmt->frac_shift - fmt->exp_bias
228
- shift + !has_pseudo_denormals;
229
}
230
- } else if (likely(p->exp < fmt->exp_max) || fmt->arm_althp) {
231
- p->cls = float_class_normal;
232
- p->exp -= fmt->exp_bias;
233
- frac_shl(p, fmt->frac_shift);
234
- p->frac_hi |= DECOMPOSED_IMPLICIT_BIT;
235
- } else if (likely(frac_eqz(p))) {
236
- p->cls = float_class_inf;
237
- } else {
238
- frac_shl(p, fmt->frac_shift);
239
- p->cls = (parts_is_snan_frac(p->frac_hi, status)
240
- ? float_class_snan : float_class_qnan);
230
+ return;
231
}
232
+ if (unlikely(p->exp == fmt->exp_max)) {
233
+ switch (fmt->exp_max_kind) {
234
+ case float_expmax_ieee:
235
+ if (likely(frac_eqz(p))) {
236
+ p->cls = float_class_inf;
237
+ } else {
238
+ frac_shl(p, fmt->frac_shift);
239
+ p->cls = (parts_is_snan_frac(p->frac_hi, status)
240
+ ? float_class_snan : float_class_qnan);
241
+ }
242
+ return;
243
+ case float_expmax_normal:
244
+ break;
245
+ default:
246
+ g_assert_not_reached();
247
+ }
248
+ }
249
+
250
+ p->cls = float_class_normal;
251
+ p->exp -= fmt->exp_bias;
252
+ frac_shl(p, fmt->frac_shift);
253
+ p->frac_hi |= DECOMPOSED_IMPLICIT_BIT;
254
}
255
256
/*
@@ -314,29 +326,37 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s,
326
p->frac_lo &= ~round_mask;
327
}
328
317
- if (fmt->arm_althp) {
318
- /* ARM Alt HP eschews Inf and NaN for a wider exponent. */
319
- if (unlikely(exp > exp_max)) {
320
- /* Overflow. Return the maximum normal. */
321
- flags = float_flag_invalid;
322
- exp = exp_max;
323
- frac_allones(p);
324
- p->frac_lo &= ~round_mask;
325
- }
326
- } else if (unlikely(exp >= exp_max)) {
327
- flags |= float_flag_overflow;
328
- if (s->rebias_overflow) {
329
- exp -= fmt->exp_re_bias;
330
- } else if (overflow_norm) {
331
- flags |= float_flag_inexact;
332
- exp = exp_max - 1;
333
- frac_allones(p);
334
- p->frac_lo &= ~round_mask;
335
- } else {
336
- flags |= float_flag_inexact;
337
- p->cls = float_class_inf;
338
- exp = exp_max;
339
- frac_clear(p);
329
+ if (unlikely(exp >= exp_max)) {
330
+ switch (fmt->exp_max_kind) {
331
+ case float_expmax_ieee:
332
+ flags |= float_flag_overflow;
333
+ if (s->rebias_overflow) {
334
+ exp -= fmt->exp_re_bias;
335
+ } else if (overflow_norm) {
336
+ flags |= float_flag_inexact;
337
+ exp = exp_max - 1;
338
+ frac_allones(p);
339
+ p->frac_lo &= ~round_mask;
340
+ } else {
341
+ flags |= float_flag_inexact;
342
+ p->cls = float_class_inf;
343
+ exp = exp_max;
344
+ frac_clear(p);
345
+ }
346
+ break;
347
+
348
+ case float_expmax_normal:
349
+ if (unlikely(exp > exp_max)) {
350
+ /* Overflow. Return the maximum normal. */
351
+ flags = float_flag_invalid;
352
+ exp = exp_max;
353
+ frac_allones(p);
354
+ p->frac_lo &= ~round_mask;
355
+ }
356
+ break;
357
+
358
+ default:
359
+ g_assert_not_reached();
360
}
361
}
362
frac_shr(p, frac_shift);
@@ -434,13 +454,13 @@ static void partsN(uncanon)(FloatPartsN *p, float_status *s,
454
frac_clear(p);
455
return;
456
case float_class_inf:
437
- g_assert(!fmt->arm_althp);
457
+ assert(fmt->exp_max_kind == float_expmax_ieee);
458
p->exp = fmt->exp_max;
459
frac_clear(p);
460
return;
461
case float_class_qnan:
462
case float_class_snan:
443
- g_assert(!fmt->arm_althp);
463
+ assert(fmt->exp_max_kind != float_expmax_normal);
464
p->exp = fmt->exp_max;
465
frac_shr(p, fmt->frac_shift);
466
return;
fpu/softfloat.c
+13
-4
@@ -522,7 +522,16 @@ typedef struct {
522
#define DECOMPOSED_BINARY_POINT 63
523
#define DECOMPOSED_IMPLICIT_BIT (1ull << DECOMPOSED_BINARY_POINT)
524
525
-/* Structure holding all of the relevant parameters for a format.
525
+/* Format-specific handling of exp == exp_max */
526
+typedef enum __attribute__((__packed__)) {
527
+ /* exp==max, frac==0 ? infinity : nan; this is ieee standard. */
528
+ float_expmax_ieee,
529
+ /* exp==max is a normal number; no infinity or nan representation. */
530
+ float_expmax_normal,
531
+} FloatFmtExpMaxKind;
532
+
533
+/*
534
+ * Structure holding all of the relevant parameters for a format.
535
* exp_size: the size of the exponent field
536
* exp_bias: the offset applied to the exponent field
537
* exp_max: the maximum normalised exponent
@@ -531,7 +540,7 @@ typedef struct {
540
* The following are computed based the size of fraction
541
* round_mask: bits below lsb which must be rounded
542
* The following optional modifiers are available:
534
- * arm_althp: handle ARM Alternative Half Precision
543
+ * exp_max_kind: affects how exp == exp_max is interpreted
544
* has_explicit_bit: has an explicit integer bit; this affects whether
545
* the float_status floatx80_behaviour handling applies
546
*/
@@ -542,7 +551,7 @@ typedef struct {
551
int exp_max;
552
int frac_size;
553
int frac_shift;
545
- bool arm_althp;
554
+ FloatFmtExpMaxKind exp_max_kind;
555
bool has_explicit_bit;
556
uint64_t round_mask;
557
} FloatFmt;
@@ -566,7 +575,7 @@ static const FloatFmt float16_params = {
575
576
static const FloatFmt float16_params_ahp = {
577
FLOAT_PARAMS(5, 10),
569
- .arm_althp = true
578
+ .exp_max_kind = float_expmax_normal,
579
};
580
581
static const FloatFmt bfloat16_params = {