@samitouri / QOSamiQemu / commits / 5146b68791

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 }