fpu/softfloat: Refactor IEEE format NaN classification to share code
The floatN_is_[quiet|signaling]_nan functions for following formats (float16, bfloat16, float32, float64, float128) contain duplicated logic that should be shared. This commit introduces [float16|bfloat16|float32|float64|float128]_nan_is_snan that determine if a NaN is signaling. Suggested-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Max Chou <max.chou@sifive.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-ID: <20260204051756.667397-3-max.chou@sifive.com>
Max Chou committed
Feb 4, 2026 at 13:17 UTC
5146b68791f983a58e6d81ed0d477af7b9321d8c
1 file changed
+72
-104
fpu/softfloat-specialize.c.inc
+72
-104
@@ -227,42 +227,26 @@ floatx80 floatx80_default_inf(bool zSign, float_status *status)
227
}
228
229
/*----------------------------------------------------------------------------
230
-| Returns 1 if the half-precision floating-point value `a' is a quiet
231
-| NaN; otherwise returns 0.
230
+| Determine if a float16 NaN is signaling NaN.
231
*----------------------------------------------------------------------------*/
232
234
-bool float16_is_quiet_nan(float16 a_, float_status *status)
233
+static bool float16_nan_is_snan(float16 a, float_status *status)
234
{
235
if (no_signaling_nans(status)) {
237
- return float16_is_any_nan(a_);
238
- } else {
239
- uint16_t a = float16_val(a_);
240
- if (snan_bit_is_one(status)) {
241
- return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
242
- } else {
243
-
244
- return ((a >> 9) & 0x3F) == 0x3F;
245
- }
236
+ return false;
237
}
238
+ bool frac_msb_is_one = (a >> 9) & 1;
239
+ return frac_msb_is_one == snan_bit_is_one(status);
240
}
241
242
/*----------------------------------------------------------------------------
250
-| Returns 1 if the bfloat16 value `a' is a quiet
243
+| Returns 1 if the half-precision floating-point value `a' is a quiet
244
| NaN; otherwise returns 0.
245
*----------------------------------------------------------------------------*/
246
254
-bool bfloat16_is_quiet_nan(bfloat16 a_, float_status *status)
247
+bool float16_is_quiet_nan(float16 a_, float_status *status)
248
{
256
- if (no_signaling_nans(status)) {
257
- return bfloat16_is_any_nan(a_);
258
- } else {
259
- uint16_t a = a_;
260
- if (snan_bit_is_one(status)) {
261
- return (((a >> 6) & 0x1FF) == 0x1FE) && (a & 0x3F);
262
- } else {
263
- return ((a >> 6) & 0x1FF) == 0x1FF;
264
- }
265
- }
249
+ return float16_is_any_nan(a_) && !float16_nan_is_snan(a_, status);
250
}
251
252
/*----------------------------------------------------------------------------
@@ -271,36 +255,52 @@ bool bfloat16_is_quiet_nan(bfloat16 a_, float_status *status)
255
*----------------------------------------------------------------------------*/
256
257
bool float16_is_signaling_nan(float16 a_, float_status *status)
258
+{
259
+ return float16_is_any_nan(a_) && float16_nan_is_snan(a_, status);
260
+}
261
+
262
+/*----------------------------------------------------------------------------
263
+| Determine if a bfloat16 NaN is signaling NaN.
264
+*----------------------------------------------------------------------------*/
265
+
266
+static bool bfloat16_nan_is_snan(bfloat16 a, float_status *status)
267
{
268
if (no_signaling_nans(status)) {
276
- return 0;
277
- } else {
278
- uint16_t a = float16_val(a_);
279
- if (snan_bit_is_one(status)) {
280
- return ((a >> 9) & 0x3F) == 0x3F;
281
- } else {
282
- return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
283
- }
269
+ return false;
270
}
271
+ bool frac_msb_is_one = (a >> 6) & 1;
272
+ return frac_msb_is_one == snan_bit_is_one(status);
273
}
274
275
/*----------------------------------------------------------------------------
288
-| Returns 1 if the bfloat16 value `a' is a signaling
289
-| NaN; otherwise returns 0.
276
+| Returns 1 if the bfloat16 value `a' is a quiet NaN; otherwise returns 0.
277
+*----------------------------------------------------------------------------*/
278
+
279
+bool bfloat16_is_quiet_nan(bfloat16 a_, float_status *status)
280
+{
281
+ return bfloat16_is_any_nan(a_) && !bfloat16_nan_is_snan(a_, status);
282
+}
283
+
284
+/*----------------------------------------------------------------------------
285
+| Returns 1 if the bfloat16 value `a' is a signaling NaN; otherwise returns 0.
286
*----------------------------------------------------------------------------*/
287
288
bool bfloat16_is_signaling_nan(bfloat16 a_, float_status *status)
289
+{
290
+ return bfloat16_is_any_nan(a_) && bfloat16_nan_is_snan(a_, status);
291
+}
292
+
293
+/*----------------------------------------------------------------------------
294
+| Determine if a float32 NaN is signaling NaN.
295
+*----------------------------------------------------------------------------*/
296
+
297
+static bool float32_nan_is_snan(float32 a, float_status *status)
298
{
299
if (no_signaling_nans(status)) {
295
- return 0;
296
- } else {
297
- uint16_t a = a_;
298
- if (snan_bit_is_one(status)) {
299
- return ((a >> 6) & 0x1FF) == 0x1FF;
300
- } else {
301
- return (((a >> 6) & 0x1FF) == 0x1FE) && (a & 0x3F);
302
- }
300
+ return false;
301
}
302
+ bool frac_msb_is_one = (a >> 22) & 1;
303
+ return frac_msb_is_one == snan_bit_is_one(status);
304
}
305
306
/*----------------------------------------------------------------------------
@@ -310,16 +310,7 @@ bool bfloat16_is_signaling_nan(bfloat16 a_, float_status *status)
310
311
bool float32_is_quiet_nan(float32 a_, float_status *status)
312
{
313
- if (no_signaling_nans(status)) {
314
- return float32_is_any_nan(a_);
315
- } else {
316
- uint32_t a = float32_val(a_);
317
- if (snan_bit_is_one(status)) {
318
- return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
319
- } else {
320
- return ((uint32_t)(a << 1) >= 0xFF800000);
321
- }
322
- }
313
+ return float32_is_any_nan(a_) && !float32_nan_is_snan(a_, status);
314
}
315
316
/*----------------------------------------------------------------------------
@@ -328,17 +319,21 @@ bool float32_is_quiet_nan(float32 a_, float_status *status)
319
*----------------------------------------------------------------------------*/
320
321
bool float32_is_signaling_nan(float32 a_, float_status *status)
322
+{
323
+ return float32_is_any_nan(a_) && float32_nan_is_snan(a_, status);
324
+}
325
+
326
+/*----------------------------------------------------------------------------
327
+| Determine if a float64 NaN is signaling NaN.
328
+*----------------------------------------------------------------------------*/
329
+
330
+static bool float64_nan_is_snan(float64 a, float_status *status)
331
{
332
if (no_signaling_nans(status)) {
333
- return 0;
334
- } else {
335
- uint32_t a = float32_val(a_);
336
- if (snan_bit_is_one(status)) {
337
- return ((uint32_t)(a << 1) >= 0xFF800000);
338
- } else {
339
- return (((a >> 22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
340
- }
333
+ return false;
334
}
335
+ bool frac_msb_is_one = (a >> 51) & 1;
336
+ return frac_msb_is_one == snan_bit_is_one(status);
337
}
338
339
/*----------------------------------------------------------------------------
@@ -348,17 +343,7 @@ bool float32_is_signaling_nan(float32 a_, float_status *status)
343
344
bool float64_is_quiet_nan(float64 a_, float_status *status)
345
{
351
- if (no_signaling_nans(status)) {
352
- return float64_is_any_nan(a_);
353
- } else {
354
- uint64_t a = float64_val(a_);
355
- if (snan_bit_is_one(status)) {
356
- return (((a >> 51) & 0xFFF) == 0xFFE)
357
- && (a & 0x0007FFFFFFFFFFFFULL);
358
- } else {
359
- return ((a << 1) >= 0xFFF0000000000000ULL);
360
- }
361
- }
346
+ return float64_is_any_nan(a_) && !float64_nan_is_snan(a_, status);
347
}
348
349
/*----------------------------------------------------------------------------
@@ -368,17 +353,7 @@ bool float64_is_quiet_nan(float64 a_, float_status *status)
353
354
bool float64_is_signaling_nan(float64 a_, float_status *status)
355
{
371
- if (no_signaling_nans(status)) {
372
- return 0;
373
- } else {
374
- uint64_t a = float64_val(a_);
375
- if (snan_bit_is_one(status)) {
376
- return ((a << 1) >= 0xFFF0000000000000ULL);
377
- } else {
378
- return (((a >> 51) & 0xFFF) == 0xFFE)
379
- && (a & UINT64_C(0x0007FFFFFFFFFFFF));
380
- }
381
- }
356
+ return float64_is_any_nan(a_) && float64_nan_is_snan(a_, status);
357
}
358
359
/*----------------------------------------------------------------------------
@@ -444,6 +419,19 @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
419
return a;
420
}
421
422
+/*----------------------------------------------------------------------------
423
+| Determine if a float128 NaN is signaling NaN.
424
+*----------------------------------------------------------------------------*/
425
+
426
+static bool float128_nan_is_snan(float128 a, float_status *status)
427
+{
428
+ if (no_signaling_nans(status)) {
429
+ return false;
430
+ }
431
+ bool frac_msb_is_one = (a.high >> 47) & 1;
432
+ return frac_msb_is_one == snan_bit_is_one(status);
433
+}
434
+
435
/*----------------------------------------------------------------------------
436
| Returns 1 if the quadruple-precision floating-point value `a' is a quiet
437
| NaN; otherwise returns 0.
@@ -451,17 +439,7 @@ floatx80 floatx80_silence_nan(floatx80 a, float_status *status)
439
440
bool float128_is_quiet_nan(float128 a, float_status *status)
441
{
454
- if (no_signaling_nans(status)) {
455
- return float128_is_any_nan(a);
456
- } else {
457
- if (snan_bit_is_one(status)) {
458
- return (((a.high >> 47) & 0xFFFF) == 0xFFFE)
459
- && (a.low || (a.high & 0x00007FFFFFFFFFFFULL));
460
- } else {
461
- return ((a.high << 1) >= 0xFFFF000000000000ULL)
462
- && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL));
463
- }
464
- }
442
+ return float128_is_any_nan(a) && !float128_nan_is_snan(a, status);
443
}
444
445
/*----------------------------------------------------------------------------
@@ -471,15 +449,5 @@ bool float128_is_quiet_nan(float128 a, float_status *status)
449
450
bool float128_is_signaling_nan(float128 a, float_status *status)
451
{
474
- if (no_signaling_nans(status)) {
475
- return 0;
476
- } else {
477
- if (snan_bit_is_one(status)) {
478
- return ((a.high << 1) >= 0xFFFF000000000000ULL)
479
- && (a.low || (a.high & 0x0000FFFFFFFFFFFFULL));
480
- } else {
481
- return (((a.high >> 47) & 0xFFFF) == 0xFFFE)
482
- && (a.low || (a.high & UINT64_C(0x00007FFFFFFFFFFF)));
483
- }
484
- }
452
+ return float128_is_any_nan(a) && float128_nan_is_snan(a, status);
453
}