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
8 This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
9 Arithmetic Package, Release 2a.
10
11 Written by John R. Hauser. This work was made possible in part by the
12 International Computer Science Institute, located at Suite 600, 1947 Center
13 Street, Berkeley, California 94704. Funding was partially provided by the
14 National Science Foundation under grant MIP-9311980. The original version
15 of this code was written as part of a project to build a fixed-point vector
16 processor in collaboration with the University of California at Berkeley,
17 overseen by Profs. Nelson Morgan and John Wawrzynek. More information
18 is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
19 arithmetic/SoftFloat.html'.
20
21 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
22 has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
23 TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
24 PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
25 AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
26
27 Derivative works are acceptable, even for commercial purposes, so long as
28 (1) they include prominent notice that the work is derivative, and (2) they
29 include prominent notice akin to these four paragraphs for those parts of
30 this 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 -------------------------------------------------------------------------------
43 Underflow 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
48 static
49 #endif
50 int8 float_detect_tininess = float_tininess_after_rounding;
51
52 /*
53 -------------------------------------------------------------------------------
54 Raises the exceptions specified by `flags'. Floating-point traps can be
55 defined here if desired. It is currently not possible for such a trap to
56 substitute a result value. If traps are not implemented, this routine
57 should 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
66 fp_except float_exception_mask = 0;
67 #endif
68 void
69 float_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 -------------------------------------------------------------------------------
178 Internal canonical NaN format.
179 -------------------------------------------------------------------------------
180 */
181 typedef struct {
182 flag sign;
183 bits64 high, low;
184 } commonNaNT;
185
186 /*
187 -------------------------------------------------------------------------------
188 The pattern for a default generated single-precision NaN.
189 -------------------------------------------------------------------------------
190 */
191 #define float32_default_nan 0xFFFFFFFF
192
193 /*
194 -------------------------------------------------------------------------------
195 Returns 1 if the single-precision floating-point value `a' is a NaN;
196 otherwise returns 0.
197 -------------------------------------------------------------------------------
198 */
199 #ifdef SOFTFLOAT_FOR_GCC
200 static
201 #endif
202 flag float32_is_nan( float32 a )
203 {
204
205 return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) );
206
207 }
208
209 /*
210 -------------------------------------------------------------------------------
211 Returns 1 if the single-precision floating-point value `a' is a signaling
212 NaN; 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)
219 static
220 #endif
221 flag float32_is_signaling_nan( float32 a )
222 {
223
224 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
225
226 }
227
228 /*
229 -------------------------------------------------------------------------------
230 Returns 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
232 exception is raised.
233 -------------------------------------------------------------------------------
234 */
235 static 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 -------------------------------------------------------------------------------
249 Returns the result of converting the canonical NaN `a' to the single-
250 precision floating-point format.
251 -------------------------------------------------------------------------------
252 */
253 static float32 commonNaNToFloat32( commonNaNT a )
254 {
255
256 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );
257
258 }
259
260 /*
261 -------------------------------------------------------------------------------
262 Takes two single-precision floating-point values `a' and `b', one of which
263 is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
264 signaling NaN, the invalid exception is raised.
265 -------------------------------------------------------------------------------
266 */
267 static 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 -------------------------------------------------------------------------------
289 The pattern for a default generated double-precision NaN.
290 -------------------------------------------------------------------------------
291 */
292 #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
293
294 /*
295 -------------------------------------------------------------------------------
296 Returns 1 if the double-precision floating-point value `a' is a NaN;
297 otherwise returns 0.
298 -------------------------------------------------------------------------------
299 */
300 #ifdef SOFTFLOAT_FOR_GCC
301 static
302 #endif
303 flag float64_is_nan( float64 a )
304 {
305
306 return ( (bits64)LIT64( 0xFFE0000000000000 ) <
307 (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
308
309 }
310
311 /*
312 -------------------------------------------------------------------------------
313 Returns 1 if the double-precision floating-point value `a' is a signaling
314 NaN; 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)
321 static
322 #endif
323 flag 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 -------------------------------------------------------------------------------
334 Returns 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
336 exception is raised.
337 -------------------------------------------------------------------------------
338 */
339 static 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 -------------------------------------------------------------------------------
353 Returns the result of converting the canonical NaN `a' to the double-
354 precision floating-point format.
355 -------------------------------------------------------------------------------
356 */
357 static 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 -------------------------------------------------------------------------------
369 Takes two double-precision floating-point values `a' and `b', one of which
370 is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
371 signaling NaN, the invalid exception is raised.
372 -------------------------------------------------------------------------------
373 */
374 static 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 -------------------------------------------------------------------------------
398 The pattern for a default generated extended double-precision NaN. The
399 `high' and `low' values hold the most- and least-significant bits,
400 respectively.
401 -------------------------------------------------------------------------------
402 */
403 #define floatx80_default_nan_high 0xFFFF
404 #define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
405
406 /*
407 -------------------------------------------------------------------------------
408 Returns 1 if the extended double-precision floating-point value `a' is a
409 NaN; otherwise returns 0.
410 -------------------------------------------------------------------------------
411 */
412 flag floatx80_is_nan( floatx80 a )
413 {
414
415 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
416
417 }
418
419 /*
420 -------------------------------------------------------------------------------
421 Returns 1 if the extended double-precision floating-point value `a' is a
422 signaling NaN; otherwise returns 0.
423 -------------------------------------------------------------------------------
424 */
425 flag 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 -------------------------------------------------------------------------------
439 Returns the result of converting the extended double-precision floating-
440 point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
441 invalid exception is raised.
442 -------------------------------------------------------------------------------
443 */
444 static 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 -------------------------------------------------------------------------------
458 Returns the result of converting the canonical NaN `a' to the extended
459 double-precision floating-point format.
460 -------------------------------------------------------------------------------
461 */
462 static 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 -------------------------------------------------------------------------------
474 Takes two extended double-precision floating-point values `a' and `b', one
475 of 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 */
479 static 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 -------------------------------------------------------------------------------
505 The 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 -------------------------------------------------------------------------------
514 Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
515 otherwise returns 0.
516 -------------------------------------------------------------------------------
517 */
518 flag 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 -------------------------------------------------------------------------------
529 Returns 1 if the quadruple-precision floating-point value `a' is a
530 signaling NaN; otherwise returns 0.
531 -------------------------------------------------------------------------------
532 */
533 flag 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 -------------------------------------------------------------------------------
544 Returns 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
546 exception is raised.
547 -------------------------------------------------------------------------------
548 */
549 static 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 -------------------------------------------------------------------------------
562 Returns the result of converting the canonical NaN `a' to the quadruple-
563 precision floating-point format.
564 -------------------------------------------------------------------------------
565 */
566 static 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 -------------------------------------------------------------------------------
578 Takes two quadruple-precision floating-point values `a' and `b', one of
579 which 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 */
583 static 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