fpu: Fix NaN encoding for E4M3 in parts64_uncanon
There is only one NaN fractional encoding for E4M3. Retain the incoming sign, but force the outgoing fraction to the unique value. Reported-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Richard Henderson committed
May 19, 2026 at 09:15 UTC
ea79f8bac125554ae791a9637a94033ecc730f13
2 files changed
+26
-4
fpu/softfloat-parts.c.inc
+24
-4
@@ -278,11 +278,16 @@ static void partsN(uncanon_e4m3_overflow)(FloatPartsN *p, float_status *s,
278
const FloatFmt *fmt, bool saturate)
279
{
280
assert(N == 64);
281
+ p->exp = fmt->exp_max;
282
if (saturate) {
282
- p->exp = fmt->exp_max;
283
p->frac_hi = E4M3_NORMAL_FRAC_MAX;
284
} else {
285
- *p = partsN(default_nan)(s);
285
+ /*
286
+ * The class isn't actually used after this point in uncanon,
287
+ * but for clarity while debugging, don't leave it set to normal.
288
+ */
289
+ p->cls = float_class_qnan;
290
+ p->frac_hi = E4M3_NAN_FRAC;
291
}
292
}
293
@@ -507,9 +512,24 @@ static void partsN(uncanon)(FloatPartsN *p, float_status *s,
512
return;
513
case float_class_qnan:
514
case float_class_snan:
510
- assert(fmt->exp_max_kind != float_expmax_normal);
515
p->exp = fmt->exp_max;
512
- fracN(shr)(p, fmt->frac_shift);
516
+ switch (fmt->exp_max_kind) {
517
+ case float_expmax_e4m3:
518
+ /*
519
+ * There is only one NaN encoding for E4M3, and with a
520
+ * conversion from another format, the input NaN fraction
521
+ * may not apply.
522
+ */
523
+ assert(N == 64);
524
+ p->frac_hi = E4M3_NAN_FRAC;
525
+ /* fall through */
526
+ case float_expmax_ieee:
527
+ fracN(shr)(p, fmt->frac_shift);
528
+ break;
529
+ case float_expmax_normal:
530
+ default:
531
+ g_assert_not_reached();
532
+ }
533
return;
534
default:
535
break;
fpu/softfloat.c
+2
@@ -499,6 +499,8 @@ const FloatFmt float8_e4m3_params = {
499
500
/* 110 << frac_shift, with the implicit bit set */
501
#define E4M3_NORMAL_FRAC_MAX 0xe000000000000000ull
502
+/* 111 << frac_shift, no implicit bit */
503
+#define E4M3_NAN_FRAC 0x7000000000000000ull
504
505
const FloatFmt float8_e5m2_params = {
506
FLOAT_PARAMS(5, 2)