softfloat-specialize revision 1.14
1/*	$NetBSD: softfloat-specialize,v 1.14 2025/09/17 11:42:17 nat Exp $	*/
2
3/* This is a derivative work. */
4
5/*
6===============================================================================
7
8This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
9Arithmetic Package, Release 2a.
10
11Written by John R. Hauser.  This work was made possible in part by the
12International Computer Science Institute, located at Suite 600, 1947 Center
13Street, Berkeley, California 94704.  Funding was partially provided by the
14National Science Foundation under grant MIP-9311980.  The original version
15of this code was written as part of a project to build a fixed-point vector
16processor in collaboration with the University of California at Berkeley,
17overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
18is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
19arithmetic/SoftFloat.html'.
20
21THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
22has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
23TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
24PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
25AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
26
27Derivative works are acceptable, even for commercial purposes, so long as
28(1) they include prominent notice that the work is derivative, and (2) they
29include prominent notice akin to these four paragraphs for those parts of
30this code that are retained.
31
32===============================================================================
33*/
34
35#include <signal.h>
36#include <string.h>
37#include <unistd.h>
38
39#include "reentrant.h"
40
41/*
42-------------------------------------------------------------------------------
43Underflow tininess-detection mode, statically initialized to default value.
44(The declaration in `softfloat.h' must match the `int8' type here.)
45-------------------------------------------------------------------------------
46*/
47#ifdef SOFTFLOAT_FOR_GCC
48static
49#endif
50int8 float_detect_tininess = float_tininess_after_rounding;
51
52/*
53-------------------------------------------------------------------------------
54Raises the exceptions specified by `flags'.  Floating-point traps can be
55defined here if desired.  It is currently not possible for such a trap to
56substitute a result value.  If traps are not implemented, this routine
57should be simply `float_exception_flags |= flags;'.
58-------------------------------------------------------------------------------
59*/
60#ifdef SOFTFLOAT_FOR_GCC
61#ifndef set_float_exception_mask
62#define float_exception_mask	_softfloat_float_exception_mask
63#endif
64#endif
65#ifndef set_float_exception_mask
66fp_except float_exception_mask = 0;
67#endif
68void
69float_raise( fp_except newflags )
70{
71    siginfo_t info;
72    struct sigaction sa;
73    sigset_t sigmask, osigmask;
74    fp_except flags;
75
76    for (;;) {
77#ifdef set_float_exception_mask
78	flags = newflags | set_float_exception_flags(newflags, 0);
79#else
80	float_exception_flags |= newflags;
81	flags = float_exception_flags;
82#endif
83
84	/*
85	 * If none of the sticky flags are trapped (i.e., enabled in
86	 * float_exception_mask), we're done.  Trapping is unusual and
87	 * costly anyway, so take the non-trapping path as the fast
88	 * path.
89	 */
90	flags &= float_exception_mask;
91	if (__predict_true(flags == 0))
92	    break;
93
94	/*
95	 * Block all signals while we figure out how to deliver a
96	 * non-maskable (as a signal), non-ignorable SIGFPE, and obtain
97	 * the current signal mask.
98	 */
99	sigfillset(&sigmask);
100#ifdef _REENTRANT	/* XXX PR lib/59401 */
101	thr_sigsetmask(SIG_BLOCK, &sigmask, &osigmask);
102#else
103	sigprocmask(SIG_BLOCK, &sigmask, &osigmask);
104#endif
105
106	/*
107	 * Find the current signal disposition of SIGFPE.
108	 */
109	sigaction(SIGFPE, NULL, &sa);
110
111	/*
112	 * If SIGFPE is masked or ignored, unmask it and reset it to
113	 * the default disposition to deliver the signal.
114	 */
115	if (sigismember(&osigmask, SIGFPE) ||
116	    ((sa.sa_flags & SA_SIGINFO) == 0 &&
117		sa.sa_handler == SIG_IGN)) {
118		/*
119		 * Prepare to unmask SIGFPE.  This will take effect
120		 * when we use thr_sigsetmask(SIG_SETMASK, ...) below,
121		 * once the signal has been queued, so that it happens
122		 * atomically with respect to other signal delivery.
123		 */
124		sigdelset(&osigmask, SIGFPE);
125
126		/*
127		 * Reset SIGFPE to the default disposition, which is to
128		 * terminate the process.
129		 */
130		memset(&sa, 0, sizeof(sa));
131		sa.sa_handler = SIG_DFL;
132		sigemptyset(&sa.sa_mask);
133		sa.sa_flags = 0;
134		sigaction(SIGFPE, &sa, NULL);
135	}
136
137	/*
138	 * Queue the signal for delivery.  It won't trigger the signal
139	 * handler yet, because it's still masked, but as soon as we
140	 * unmask it either the process will terminate or the signal
141	 * handler will be called.
142	 */
143	memset(&info, 0, sizeof info);
144	info.si_signo = SIGFPE;
145	info.si_pid = getpid();
146	info.si_uid = geteuid();
147	if (flags & float_flag_underflow)
148	    info.si_code = FPE_FLTUND;
149	else if (flags & float_flag_overflow)
150	    info.si_code = FPE_FLTOVF;
151	else if (flags & float_flag_divbyzero)
152	    info.si_code = FPE_FLTDIV;
153	else if (flags & float_flag_invalid)
154	    info.si_code = FPE_FLTINV;
155	else if (flags & float_flag_inexact)
156	    info.si_code = FPE_FLTRES;
157	sigqueueinfo(getpid(), &info);
158
159	/*
160	 * Restore the old signal mask, except with SIGFPE unmasked
161	 * even if it was masked before.
162	 *
163	 * At this point, either the process will terminate (if SIGFPE
164	 * had or now has the default disposition) or the signal
165	 * handler will be called (if SIGFPE had a non-default,
166	 * non-ignored disposition).
167	 *
168	 * If the signal handler returns, it can't change the set of
169	 * exceptions raised by this floating-point operation -- but it
170	 * can change the sticky set from previous operations, and it
171	 * can change the set of exceptions that are trapped, so loop
172	 * around; next time we might make progress instead of calling
173	 * the signal handler again.
174	 */
175#ifdef _REENTRANT	/* XXX PR lib/59401 */
176	thr_sigsetmask(SIG_SETMASK, &osigmask, NULL);
177#else
178	sigprocmask(SIG_SETMASK, &osigmask, NULL);
179#endif
180    }
181}
182#undef float_exception_mask
183
184/*
185-------------------------------------------------------------------------------
186Internal canonical NaN format.
187-------------------------------------------------------------------------------
188*/
189typedef struct {
190    flag sign;
191    bits64 high, low;
192} commonNaNT;
193
194/*
195-------------------------------------------------------------------------------
196The pattern for a default generated single-precision NaN.
197-------------------------------------------------------------------------------
198*/
199#define float32_default_nan 0xFFFFFFFF
200
201/*
202-------------------------------------------------------------------------------
203Returns 1 if the single-precision floating-point value `a' is a NaN;
204otherwise returns 0.
205-------------------------------------------------------------------------------
206*/
207#ifdef SOFTFLOAT_FOR_GCC
208static
209#endif
210flag float32_is_nan( float32 a )
211{
212
213    return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) );
214
215}
216
217/*
218-------------------------------------------------------------------------------
219Returns 1 if the single-precision floating-point value `a' is a signaling
220NaN; otherwise returns 0.
221-------------------------------------------------------------------------------
222*/
223#if defined(SOFTFLOAT_FOR_GCC) \
224    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
225    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
226    && !defined(SOFTFLOATM68K_FOR_GCC)
227static
228#endif
229flag float32_is_signaling_nan( float32 a )
230{
231
232    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
233
234}
235
236/*
237-------------------------------------------------------------------------------
238Returns the result of converting the single-precision floating-point NaN
239`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
240exception is raised.
241-------------------------------------------------------------------------------
242*/
243static commonNaNT float32ToCommonNaN( float32 a )
244{
245    commonNaNT z;
246
247    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
248    z.sign = a>>31;
249    z.low = 0;
250    z.high = ( (bits64) a )<<41;
251    return z;
252
253}
254
255/*
256-------------------------------------------------------------------------------
257Returns the result of converting the canonical NaN `a' to the single-
258precision floating-point format.
259-------------------------------------------------------------------------------
260*/
261static float32 commonNaNToFloat32( commonNaNT a )
262{
263
264    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );
265
266}
267
268/*
269-------------------------------------------------------------------------------
270Takes two single-precision floating-point values `a' and `b', one of which
271is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
272signaling NaN, the invalid exception is raised.
273-------------------------------------------------------------------------------
274*/
275static float32 propagateFloat32NaN( float32 a, float32 b )
276{
277    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
278
279    aIsNaN = float32_is_nan( a );
280    aIsSignalingNaN = float32_is_signaling_nan( a );
281    bIsNaN = float32_is_nan( b );
282    bIsSignalingNaN = float32_is_signaling_nan( b );
283    a |= 0x00400000;
284    b |= 0x00400000;
285    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
286    if ( aIsNaN ) {
287        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
288    }
289    else {
290        return b;
291    }
292
293}
294
295/*
296-------------------------------------------------------------------------------
297The pattern for a default generated double-precision NaN.
298-------------------------------------------------------------------------------
299*/
300#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
301
302/*
303-------------------------------------------------------------------------------
304Returns 1 if the double-precision floating-point value `a' is a NaN;
305otherwise returns 0.
306-------------------------------------------------------------------------------
307*/
308#ifdef SOFTFLOAT_FOR_GCC
309static
310#endif
311flag float64_is_nan( float64 a )
312{
313
314    return ( (bits64)LIT64( 0xFFE0000000000000 ) <
315	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
316
317}
318
319/*
320-------------------------------------------------------------------------------
321Returns 1 if the double-precision floating-point value `a' is a signaling
322NaN; otherwise returns 0.
323-------------------------------------------------------------------------------
324*/
325#if defined(SOFTFLOAT_FOR_GCC) \
326    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
327    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
328    && !defined(SOFTFLOATM68K_FOR_GCC)
329static
330#endif
331flag float64_is_signaling_nan( float64 a )
332{
333
334    return
335           ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
336        && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
337
338}
339
340/*
341-------------------------------------------------------------------------------
342Returns the result of converting the double-precision floating-point NaN
343`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
344exception is raised.
345-------------------------------------------------------------------------------
346*/
347static commonNaNT float64ToCommonNaN( float64 a )
348{
349    commonNaNT z;
350
351    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
352    z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63);
353    z.low = 0;
354    z.high = FLOAT64_DEMANGLE(a)<<12;
355    return z;
356
357}
358
359/*
360-------------------------------------------------------------------------------
361Returns the result of converting the canonical NaN `a' to the double-
362precision floating-point format.
363-------------------------------------------------------------------------------
364*/
365static float64 commonNaNToFloat64( commonNaNT a )
366{
367
368    return FLOAT64_MANGLE(
369	( ( (bits64) a.sign )<<63 )
370        | LIT64( 0x7FF8000000000000 )
371        | ( a.high>>12 ) );
372
373}
374
375/*
376-------------------------------------------------------------------------------
377Takes two double-precision floating-point values `a' and `b', one of which
378is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
379signaling NaN, the invalid exception is raised.
380-------------------------------------------------------------------------------
381*/
382static float64 propagateFloat64NaN( float64 a, float64 b )
383{
384    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
385
386    aIsNaN = float64_is_nan( a );
387    aIsSignalingNaN = float64_is_signaling_nan( a );
388    bIsNaN = float64_is_nan( b );
389    bIsSignalingNaN = float64_is_signaling_nan( b );
390    a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
391    b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
392    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
393    if ( aIsNaN ) {
394        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
395    }
396    else {
397        return b;
398    }
399
400}
401
402#ifdef FLOATX80
403
404/*
405-------------------------------------------------------------------------------
406The pattern for a default generated extended double-precision NaN.  The
407`high' and `low' values hold the most- and least-significant bits,
408respectively.
409-------------------------------------------------------------------------------
410*/
411#define floatx80_default_nan_high 0xFFFF
412#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
413
414/*
415-------------------------------------------------------------------------------
416Returns 1 if the extended double-precision floating-point value `a' is a
417NaN; otherwise returns 0.
418-------------------------------------------------------------------------------
419*/
420flag floatx80_is_nan( floatx80 a )
421{
422
423    return (((a.high >> X80SHIFT) & 0x7FFF) == 0x7FFF) && (bits64)(a.low<<1);
424
425}
426
427/*
428-------------------------------------------------------------------------------
429Returns 1 if the extended double-precision floating-point value `a' is a
430signaling NaN; otherwise returns 0.
431-------------------------------------------------------------------------------
432*/
433flag floatx80_is_signaling_nan( floatx80 a )
434{
435    bits64 aLow;
436
437    aLow = a.low & ~ LIT64( 0x4000000000000000 );
438    return
439           ( ( (a.high >> X80SHIFT) & 0x7FFF ) == 0x7FFF )
440        && (bits64) ( aLow<<1 )
441        && ( a.low == aLow );
442
443}
444
445#ifndef SOFTFLOAT_BITS32
446/*
447-------------------------------------------------------------------------------
448Returns the result of converting the extended double-precision floating-
449point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
450invalid exception is raised.
451-------------------------------------------------------------------------------
452*/
453static commonNaNT floatx80ToCommonNaN( floatx80 a )
454{
455    commonNaNT z;
456
457    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
458    z.sign = a.high>>(15 + X80SHIFT);
459    z.low = a.low<<1;
460    z.high = (a.high>>X80SHIFT) & 0x7FFF;
461    return z;
462
463}
464
465/*
466-------------------------------------------------------------------------------
467Returns the result of converting the canonical NaN `a' to the extended
468double-precision floating-point format.
469-------------------------------------------------------------------------------
470*/
471static floatx80 commonNaNToFloatx80( commonNaNT a )
472{
473    floatx80 z;
474
475    z.low = LIT64( 0xC000000000000000 ) | ( a.low );
476    z.high = (( ( (bits16) a.sign )<<15 ) | 0x7FFF) << X80SHIFT;
477    return z;
478
479}
480
481/*
482-------------------------------------------------------------------------------
483Takes two extended double-precision floating-point values `a' and `b', one
484of which is a NaN, and returns the appropriate NaN result.  If either `a' or
485`b' is a signaling NaN, the invalid exception is raised.
486-------------------------------------------------------------------------------
487*/
488static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
489{
490    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
491
492    aIsNaN = floatx80_is_nan( a );
493    aIsSignalingNaN = floatx80_is_signaling_nan( a );
494    bIsNaN = floatx80_is_nan( b );
495    bIsSignalingNaN = floatx80_is_signaling_nan( b );
496    a.low |= LIT64( 0xC000000000000000 );
497    b.low |= LIT64( 0xC000000000000000 );
498    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
499    if ( aIsNaN ) {
500        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
501    }
502    else {
503        return b;
504    }
505
506}
507
508#endif
509#endif
510
511#ifdef FLOAT128
512
513/*
514-------------------------------------------------------------------------------
515The pattern for a default generated quadruple-precision NaN.  The `high' and
516`low' values hold the most- and least-significant bits, respectively.
517-------------------------------------------------------------------------------
518*/
519#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
520#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
521
522/*
523-------------------------------------------------------------------------------
524Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
525otherwise returns 0.
526-------------------------------------------------------------------------------
527*/
528flag float128_is_nan( float128 a )
529{
530
531    return
532           ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
533        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
534
535}
536
537/*
538-------------------------------------------------------------------------------
539Returns 1 if the quadruple-precision floating-point value `a' is a
540signaling NaN; otherwise returns 0.
541-------------------------------------------------------------------------------
542*/
543flag float128_is_signaling_nan( float128 a )
544{
545
546    return
547           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
548        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
549
550}
551
552/*
553-------------------------------------------------------------------------------
554Returns the result of converting the quadruple-precision floating-point NaN
555`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
556exception is raised.
557-------------------------------------------------------------------------------
558*/
559static commonNaNT float128ToCommonNaN( float128 a )
560{
561    commonNaNT z;
562
563    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
564    z.sign = (flag)(a.high>>63);
565    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
566    return z;
567
568}
569
570/*
571-------------------------------------------------------------------------------
572Returns the result of converting the canonical NaN `a' to the quadruple-
573precision floating-point format.
574-------------------------------------------------------------------------------
575*/
576static float128 commonNaNToFloat128( commonNaNT a )
577{
578    float128 z;
579
580    shift128Right( a.high, a.low, 16, &z.high, &z.low );
581    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
582    return z;
583
584}
585
586/*
587-------------------------------------------------------------------------------
588Takes two quadruple-precision floating-point values `a' and `b', one of
589which is a NaN, and returns the appropriate NaN result.  If either `a' or
590`b' is a signaling NaN, the invalid exception is raised.
591-------------------------------------------------------------------------------
592*/
593static float128 propagateFloat128NaN( float128 a, float128 b )
594{
595    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
596
597    aIsNaN = float128_is_nan( a );
598    aIsSignalingNaN = float128_is_signaling_nan( a );
599    bIsNaN = float128_is_nan( b );
600    bIsSignalingNaN = float128_is_signaling_nan( b );
601    a.high |= LIT64( 0x0000800000000000 );
602    b.high |= LIT64( 0x0000800000000000 );
603    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
604    if ( aIsNaN ) {
605        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
606    }
607    else {
608        return b;
609    }
610
611}
612
613#endif
614
615