softfloat-specialize revision 1.10
1/*	$NetBSD: softfloat-specialize,v 1.10 2025/04/27 15:23:27 riastradh 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	thr_sigsetmask(SIG_BLOCK, &sigmask, &osigmask);
101
102	/*
103	 * Find the current signal disposition of SIGFPE.
104	 */
105	sigaction(SIGFPE, NULL, &sa);
106
107	/*
108	 * If SIGFPE is masked or ignored, unmask it and reset it to
109	 * the default disposition to deliver the signal.
110	 */
111	if (sigismember(&osigmask, SIGFPE) ||
112	    ((sa.sa_flags & SA_SIGINFO) == 0 &&
113		sa.sa_handler == SIG_IGN)) {
114		/*
115		 * Prepare to unmask SIGFPE.  This will take effect
116		 * when we use thr_sigsetmask(SIG_SETMASK, ...) below,
117		 * once the signal has been queued, so that it happens
118		 * atomically with respect to other signal delivery.
119		 */
120		sigdelset(&osigmask, SIGFPE);
121
122		/*
123		 * Reset SIGFPE to the default disposition, which is to
124		 * terminate the process.
125		 */
126		memset(&sa, 0, sizeof(sa));
127		sa.sa_handler = SIG_DFL;
128		sigemptyset(&sa.sa_mask);
129		sa.sa_flags = 0;
130		sigaction(SIGFPE, &sa, NULL);
131	}
132
133	/*
134	 * Queue the signal for delivery.  It won't trigger the signal
135	 * handler yet, because it's still masked, but as soon as we
136	 * unmask it either the process will terminate or the signal
137	 * handler will be called.
138	 */
139	memset(&info, 0, sizeof info);
140	info.si_signo = SIGFPE;
141	info.si_pid = getpid();
142	info.si_uid = geteuid();
143	if (flags & float_flag_underflow)
144	    info.si_code = FPE_FLTUND;
145	else if (flags & float_flag_overflow)
146	    info.si_code = FPE_FLTOVF;
147	else if (flags & float_flag_divbyzero)
148	    info.si_code = FPE_FLTDIV;
149	else if (flags & float_flag_invalid)
150	    info.si_code = FPE_FLTINV;
151	else if (flags & float_flag_inexact)
152	    info.si_code = FPE_FLTRES;
153	sigqueueinfo(getpid(), &info);
154
155	/*
156	 * Restore the old signal mask, except with SIGFPE unmasked
157	 * even if it was masked before.
158	 *
159	 * At this point, either the process will terminate (if SIGFPE
160	 * had or now has the default disposition) or the signal
161	 * handler will be called (if SIGFPE had a non-default,
162	 * non-ignored disposition).
163	 *
164	 * If the signal handler returns, it can't change the set of
165	 * exceptions raised by this floating-point operation -- but it
166	 * can change the sticky set from previous operations, and it
167	 * can change the set of exceptions that are trapped, so loop
168	 * around; next time we might make progress instead of calling
169	 * the signal handler again.
170	 */
171	thr_sigsetmask(SIG_SETMASK, &osigmask, NULL);
172    }
173}
174#undef float_exception_mask
175
176/*
177-------------------------------------------------------------------------------
178Internal canonical NaN format.
179-------------------------------------------------------------------------------
180*/
181typedef struct {
182    flag sign;
183    bits64 high, low;
184} commonNaNT;
185
186/*
187-------------------------------------------------------------------------------
188The pattern for a default generated single-precision NaN.
189-------------------------------------------------------------------------------
190*/
191#define float32_default_nan 0xFFFFFFFF
192
193/*
194-------------------------------------------------------------------------------
195Returns 1 if the single-precision floating-point value `a' is a NaN;
196otherwise returns 0.
197-------------------------------------------------------------------------------
198*/
199#ifdef SOFTFLOAT_FOR_GCC
200static
201#endif
202flag float32_is_nan( float32 a )
203{
204
205    return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) );
206
207}
208
209/*
210-------------------------------------------------------------------------------
211Returns 1 if the single-precision floating-point value `a' is a signaling
212NaN; otherwise returns 0.
213-------------------------------------------------------------------------------
214*/
215#if defined(SOFTFLOAT_FOR_GCC) \
216    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
217    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
218    && !defined(SOFTFLOATM68K_FOR_GCC)
219static
220#endif
221flag float32_is_signaling_nan( float32 a )
222{
223
224    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
225
226}
227
228/*
229-------------------------------------------------------------------------------
230Returns the result of converting the single-precision floating-point NaN
231`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
232exception is raised.
233-------------------------------------------------------------------------------
234*/
235static commonNaNT float32ToCommonNaN( float32 a )
236{
237    commonNaNT z;
238
239    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
240    z.sign = a>>31;
241    z.low = 0;
242    z.high = ( (bits64) a )<<41;
243    return z;
244
245}
246
247/*
248-------------------------------------------------------------------------------
249Returns the result of converting the canonical NaN `a' to the single-
250precision floating-point format.
251-------------------------------------------------------------------------------
252*/
253static float32 commonNaNToFloat32( commonNaNT a )
254{
255
256    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );
257
258}
259
260/*
261-------------------------------------------------------------------------------
262Takes two single-precision floating-point values `a' and `b', one of which
263is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
264signaling NaN, the invalid exception is raised.
265-------------------------------------------------------------------------------
266*/
267static float32 propagateFloat32NaN( float32 a, float32 b )
268{
269    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
270
271    aIsNaN = float32_is_nan( a );
272    aIsSignalingNaN = float32_is_signaling_nan( a );
273    bIsNaN = float32_is_nan( b );
274    bIsSignalingNaN = float32_is_signaling_nan( b );
275    a |= 0x00400000;
276    b |= 0x00400000;
277    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
278    if ( aIsNaN ) {
279        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
280    }
281    else {
282        return b;
283    }
284
285}
286
287/*
288-------------------------------------------------------------------------------
289The pattern for a default generated double-precision NaN.
290-------------------------------------------------------------------------------
291*/
292#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
293
294/*
295-------------------------------------------------------------------------------
296Returns 1 if the double-precision floating-point value `a' is a NaN;
297otherwise returns 0.
298-------------------------------------------------------------------------------
299*/
300#ifdef SOFTFLOAT_FOR_GCC
301static
302#endif
303flag float64_is_nan( float64 a )
304{
305
306    return ( (bits64)LIT64( 0xFFE0000000000000 ) <
307	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
308
309}
310
311/*
312-------------------------------------------------------------------------------
313Returns 1 if the double-precision floating-point value `a' is a signaling
314NaN; otherwise returns 0.
315-------------------------------------------------------------------------------
316*/
317#if defined(SOFTFLOAT_FOR_GCC) \
318    && !defined(SOFTFLOATAARCH64_FOR_GCC) \
319    && !defined(SOFTFLOATSPARC64_FOR_GCC) \
320    && !defined(SOFTFLOATM68K_FOR_GCC)
321static
322#endif
323flag float64_is_signaling_nan( float64 a )
324{
325
326    return
327           ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
328        && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
329
330}
331
332/*
333-------------------------------------------------------------------------------
334Returns the result of converting the double-precision floating-point NaN
335`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
336exception is raised.
337-------------------------------------------------------------------------------
338*/
339static commonNaNT float64ToCommonNaN( float64 a )
340{
341    commonNaNT z;
342
343    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
344    z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63);
345    z.low = 0;
346    z.high = FLOAT64_DEMANGLE(a)<<12;
347    return z;
348
349}
350
351/*
352-------------------------------------------------------------------------------
353Returns the result of converting the canonical NaN `a' to the double-
354precision floating-point format.
355-------------------------------------------------------------------------------
356*/
357static float64 commonNaNToFloat64( commonNaNT a )
358{
359
360    return FLOAT64_MANGLE(
361	( ( (bits64) a.sign )<<63 )
362        | LIT64( 0x7FF8000000000000 )
363        | ( a.high>>12 ) );
364
365}
366
367/*
368-------------------------------------------------------------------------------
369Takes two double-precision floating-point values `a' and `b', one of which
370is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
371signaling NaN, the invalid exception is raised.
372-------------------------------------------------------------------------------
373*/
374static float64 propagateFloat64NaN( float64 a, float64 b )
375{
376    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
377
378    aIsNaN = float64_is_nan( a );
379    aIsSignalingNaN = float64_is_signaling_nan( a );
380    bIsNaN = float64_is_nan( b );
381    bIsSignalingNaN = float64_is_signaling_nan( b );
382    a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
383    b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
384    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
385    if ( aIsNaN ) {
386        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
387    }
388    else {
389        return b;
390    }
391
392}
393
394#ifdef FLOATX80
395
396/*
397-------------------------------------------------------------------------------
398The pattern for a default generated extended double-precision NaN.  The
399`high' and `low' values hold the most- and least-significant bits,
400respectively.
401-------------------------------------------------------------------------------
402*/
403#define floatx80_default_nan_high 0xFFFF
404#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
405
406/*
407-------------------------------------------------------------------------------
408Returns 1 if the extended double-precision floating-point value `a' is a
409NaN; otherwise returns 0.
410-------------------------------------------------------------------------------
411*/
412flag floatx80_is_nan( floatx80 a )
413{
414
415    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
416
417}
418
419/*
420-------------------------------------------------------------------------------
421Returns 1 if the extended double-precision floating-point value `a' is a
422signaling NaN; otherwise returns 0.
423-------------------------------------------------------------------------------
424*/
425flag floatx80_is_signaling_nan( floatx80 a )
426{
427    bits64 aLow;
428
429    aLow = a.low & ~ LIT64( 0x4000000000000000 );
430    return
431           ( ( a.high & 0x7FFF ) == 0x7FFF )
432        && (bits64) ( aLow<<1 )
433        && ( a.low == aLow );
434
435}
436
437/*
438-------------------------------------------------------------------------------
439Returns the result of converting the extended double-precision floating-
440point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
441invalid exception is raised.
442-------------------------------------------------------------------------------
443*/
444static commonNaNT floatx80ToCommonNaN( floatx80 a )
445{
446    commonNaNT z;
447
448    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
449    z.sign = a.high>>15;
450    z.low = 0;
451    z.high = a.low<<1;
452    return z;
453
454}
455
456/*
457-------------------------------------------------------------------------------
458Returns the result of converting the canonical NaN `a' to the extended
459double-precision floating-point format.
460-------------------------------------------------------------------------------
461*/
462static floatx80 commonNaNToFloatx80( commonNaNT a )
463{
464    floatx80 z;
465
466    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
467    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
468    return z;
469
470}
471
472/*
473-------------------------------------------------------------------------------
474Takes two extended double-precision floating-point values `a' and `b', one
475of which is a NaN, and returns the appropriate NaN result.  If either `a' or
476`b' is a signaling NaN, the invalid exception is raised.
477-------------------------------------------------------------------------------
478*/
479static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
480{
481    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
482
483    aIsNaN = floatx80_is_nan( a );
484    aIsSignalingNaN = floatx80_is_signaling_nan( a );
485    bIsNaN = floatx80_is_nan( b );
486    bIsSignalingNaN = floatx80_is_signaling_nan( b );
487    a.low |= LIT64( 0xC000000000000000 );
488    b.low |= LIT64( 0xC000000000000000 );
489    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
490    if ( aIsNaN ) {
491        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
492    }
493    else {
494        return b;
495    }
496
497}
498
499#endif
500
501#ifdef FLOAT128
502
503/*
504-------------------------------------------------------------------------------
505The pattern for a default generated quadruple-precision NaN.  The `high' and
506`low' values hold the most- and least-significant bits, respectively.
507-------------------------------------------------------------------------------
508*/
509#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
510#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
511
512/*
513-------------------------------------------------------------------------------
514Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
515otherwise returns 0.
516-------------------------------------------------------------------------------
517*/
518flag float128_is_nan( float128 a )
519{
520
521    return
522           ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
523        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
524
525}
526
527/*
528-------------------------------------------------------------------------------
529Returns 1 if the quadruple-precision floating-point value `a' is a
530signaling NaN; otherwise returns 0.
531-------------------------------------------------------------------------------
532*/
533flag float128_is_signaling_nan( float128 a )
534{
535
536    return
537           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
538        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
539
540}
541
542/*
543-------------------------------------------------------------------------------
544Returns the result of converting the quadruple-precision floating-point NaN
545`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
546exception is raised.
547-------------------------------------------------------------------------------
548*/
549static commonNaNT float128ToCommonNaN( float128 a )
550{
551    commonNaNT z;
552
553    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
554    z.sign = (flag)(a.high>>63);
555    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
556    return z;
557
558}
559
560/*
561-------------------------------------------------------------------------------
562Returns the result of converting the canonical NaN `a' to the quadruple-
563precision floating-point format.
564-------------------------------------------------------------------------------
565*/
566static float128 commonNaNToFloat128( commonNaNT a )
567{
568    float128 z;
569
570    shift128Right( a.high, a.low, 16, &z.high, &z.low );
571    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
572    return z;
573
574}
575
576/*
577-------------------------------------------------------------------------------
578Takes two quadruple-precision floating-point values `a' and `b', one of
579which is a NaN, and returns the appropriate NaN result.  If either `a' or
580`b' is a signaling NaN, the invalid exception is raised.
581-------------------------------------------------------------------------------
582*/
583static float128 propagateFloat128NaN( float128 a, float128 b )
584{
585    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
586
587    aIsNaN = float128_is_nan( a );
588    aIsSignalingNaN = float128_is_signaling_nan( a );
589    bIsNaN = float128_is_nan( b );
590    bIsSignalingNaN = float128_is_signaling_nan( b );
591    a.high |= LIT64( 0x0000800000000000 );
592    b.high |= LIT64( 0x0000800000000000 );
593    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
594    if ( aIsNaN ) {
595        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
596    }
597    else {
598        return b;
599    }
600
601}
602
603#endif
604
605