softfloat-specialize revision 1.8 1 /* $NetBSD: softfloat-specialize,v 1.8 2013/01/10 08:16:10 matt 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 /*
40 -------------------------------------------------------------------------------
41 Underflow tininess-detection mode, statically initialized to default value.
42 (The declaration in `softfloat.h' must match the `int8' type here.)
43 -------------------------------------------------------------------------------
44 */
45 #ifdef SOFTFLOAT_FOR_GCC
46 static
47 #endif
48 int8 float_detect_tininess = float_tininess_after_rounding;
49
50 /*
51 -------------------------------------------------------------------------------
52 Raises the exceptions specified by `flags'. Floating-point traps can be
53 defined here if desired. It is currently not possible for such a trap to
54 substitute a result value. If traps are not implemented, this routine
55 should be simply `float_exception_flags |= flags;'.
56 -------------------------------------------------------------------------------
57 */
58 #ifdef SOFTFLOAT_FOR_GCC
59 #ifndef set_float_exception_mask
60 #define float_exception_mask _softfloat_float_exception_mask
61 #endif
62 #endif
63 #ifndef set_float_exception_mask
64 fp_except float_exception_mask = 0;
65 #endif
66 void
67 float_raise( fp_except flags )
68 {
69 siginfo_t info;
70 fp_except mask = float_exception_mask;
71
72 #ifdef set_float_exception_mask
73 flags |= set_float_exception_flags(flags, 0);
74 #else
75 float_exception_flags |= flags;
76 flags = float_exception_flags;
77 #endif
78
79 flags &= mask;
80 if ( flags ) {
81 memset(&info, 0, sizeof info);
82 info.si_signo = SIGFPE;
83 info.si_pid = getpid();
84 info.si_uid = geteuid();
85 if (flags & float_flag_underflow)
86 info.si_code = FPE_FLTUND;
87 else if (flags & float_flag_overflow)
88 info.si_code = FPE_FLTOVF;
89 else if (flags & float_flag_divbyzero)
90 info.si_code = FPE_FLTDIV;
91 else if (flags & float_flag_invalid)
92 info.si_code = FPE_FLTINV;
93 else if (flags & float_flag_inexact)
94 info.si_code = FPE_FLTRES;
95 sigqueueinfo(getpid(), &info);
96 }
97 }
98 #undef float_exception_mask
99
100 /*
101 -------------------------------------------------------------------------------
102 Internal canonical NaN format.
103 -------------------------------------------------------------------------------
104 */
105 typedef struct {
106 flag sign;
107 bits64 high, low;
108 } commonNaNT;
109
110 /*
111 -------------------------------------------------------------------------------
112 The pattern for a default generated single-precision NaN.
113 -------------------------------------------------------------------------------
114 */
115 #define float32_default_nan 0xFFFFFFFF
116
117 /*
118 -------------------------------------------------------------------------------
119 Returns 1 if the single-precision floating-point value `a' is a NaN;
120 otherwise returns 0.
121 -------------------------------------------------------------------------------
122 */
123 #ifdef SOFTFLOAT_FOR_GCC
124 static
125 #endif
126 flag float32_is_nan( float32 a )
127 {
128
129 return ( (bits32)0xFF000000 < (bits32) ( a<<1 ) );
130
131 }
132
133 /*
134 -------------------------------------------------------------------------------
135 Returns 1 if the single-precision floating-point value `a' is a signaling
136 NaN; otherwise returns 0.
137 -------------------------------------------------------------------------------
138 */
139 #if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
140 !defined(SOFTFLOAT_M68K_FOR_GCC)
141 static
142 #endif
143 flag float32_is_signaling_nan( float32 a )
144 {
145
146 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
147
148 }
149
150 /*
151 -------------------------------------------------------------------------------
152 Returns the result of converting the single-precision floating-point NaN
153 `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
154 exception is raised.
155 -------------------------------------------------------------------------------
156 */
157 static commonNaNT float32ToCommonNaN( float32 a )
158 {
159 commonNaNT z;
160
161 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
162 z.sign = a>>31;
163 z.low = 0;
164 z.high = ( (bits64) a )<<41;
165 return z;
166
167 }
168
169 /*
170 -------------------------------------------------------------------------------
171 Returns the result of converting the canonical NaN `a' to the single-
172 precision floating-point format.
173 -------------------------------------------------------------------------------
174 */
175 static float32 commonNaNToFloat32( commonNaNT a )
176 {
177
178 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | (bits32)( a.high>>41 );
179
180 }
181
182 /*
183 -------------------------------------------------------------------------------
184 Takes two single-precision floating-point values `a' and `b', one of which
185 is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
186 signaling NaN, the invalid exception is raised.
187 -------------------------------------------------------------------------------
188 */
189 static float32 propagateFloat32NaN( float32 a, float32 b )
190 {
191 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
192
193 aIsNaN = float32_is_nan( a );
194 aIsSignalingNaN = float32_is_signaling_nan( a );
195 bIsNaN = float32_is_nan( b );
196 bIsSignalingNaN = float32_is_signaling_nan( b );
197 a |= 0x00400000;
198 b |= 0x00400000;
199 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
200 if ( aIsNaN ) {
201 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
202 }
203 else {
204 return b;
205 }
206
207 }
208
209 /*
210 -------------------------------------------------------------------------------
211 The pattern for a default generated double-precision NaN.
212 -------------------------------------------------------------------------------
213 */
214 #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
215
216 /*
217 -------------------------------------------------------------------------------
218 Returns 1 if the double-precision floating-point value `a' is a NaN;
219 otherwise returns 0.
220 -------------------------------------------------------------------------------
221 */
222 #ifdef SOFTFLOAT_FOR_GCC
223 static
224 #endif
225 flag float64_is_nan( float64 a )
226 {
227
228 return ( (bits64)LIT64( 0xFFE0000000000000 ) <
229 (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
230
231 }
232
233 /*
234 -------------------------------------------------------------------------------
235 Returns 1 if the double-precision floating-point value `a' is a signaling
236 NaN; otherwise returns 0.
237 -------------------------------------------------------------------------------
238 */
239 #if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
240 !defined(SOFTFLOATM68K_FOR_GCC)
241 static
242 #endif
243 flag float64_is_signaling_nan( float64 a )
244 {
245
246 return
247 ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
248 && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
249
250 }
251
252 /*
253 -------------------------------------------------------------------------------
254 Returns the result of converting the double-precision floating-point NaN
255 `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
256 exception is raised.
257 -------------------------------------------------------------------------------
258 */
259 static commonNaNT float64ToCommonNaN( float64 a )
260 {
261 commonNaNT z;
262
263 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
264 z.sign = (flag)(FLOAT64_DEMANGLE(a)>>63);
265 z.low = 0;
266 z.high = FLOAT64_DEMANGLE(a)<<12;
267 return z;
268
269 }
270
271 /*
272 -------------------------------------------------------------------------------
273 Returns the result of converting the canonical NaN `a' to the double-
274 precision floating-point format.
275 -------------------------------------------------------------------------------
276 */
277 static float64 commonNaNToFloat64( commonNaNT a )
278 {
279
280 return FLOAT64_MANGLE(
281 ( ( (bits64) a.sign )<<63 )
282 | LIT64( 0x7FF8000000000000 )
283 | ( a.high>>12 ) );
284
285 }
286
287 /*
288 -------------------------------------------------------------------------------
289 Takes two double-precision floating-point values `a' and `b', one of which
290 is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
291 signaling NaN, the invalid exception is raised.
292 -------------------------------------------------------------------------------
293 */
294 static float64 propagateFloat64NaN( float64 a, float64 b )
295 {
296 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
297
298 aIsNaN = float64_is_nan( a );
299 aIsSignalingNaN = float64_is_signaling_nan( a );
300 bIsNaN = float64_is_nan( b );
301 bIsSignalingNaN = float64_is_signaling_nan( b );
302 a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
303 b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
304 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
305 if ( aIsNaN ) {
306 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
307 }
308 else {
309 return b;
310 }
311
312 }
313
314 #ifdef FLOATX80
315
316 /*
317 -------------------------------------------------------------------------------
318 The pattern for a default generated extended double-precision NaN. The
319 `high' and `low' values hold the most- and least-significant bits,
320 respectively.
321 -------------------------------------------------------------------------------
322 */
323 #define floatx80_default_nan_high 0xFFFF
324 #define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
325
326 /*
327 -------------------------------------------------------------------------------
328 Returns 1 if the extended double-precision floating-point value `a' is a
329 NaN; otherwise returns 0.
330 -------------------------------------------------------------------------------
331 */
332 flag floatx80_is_nan( floatx80 a )
333 {
334
335 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
336
337 }
338
339 /*
340 -------------------------------------------------------------------------------
341 Returns 1 if the extended double-precision floating-point value `a' is a
342 signaling NaN; otherwise returns 0.
343 -------------------------------------------------------------------------------
344 */
345 flag floatx80_is_signaling_nan( floatx80 a )
346 {
347 bits64 aLow;
348
349 aLow = a.low & ~ LIT64( 0x4000000000000000 );
350 return
351 ( ( a.high & 0x7FFF ) == 0x7FFF )
352 && (bits64) ( aLow<<1 )
353 && ( a.low == aLow );
354
355 }
356
357 /*
358 -------------------------------------------------------------------------------
359 Returns the result of converting the extended double-precision floating-
360 point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
361 invalid exception is raised.
362 -------------------------------------------------------------------------------
363 */
364 static commonNaNT floatx80ToCommonNaN( floatx80 a )
365 {
366 commonNaNT z;
367
368 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
369 z.sign = a.high>>15;
370 z.low = 0;
371 z.high = a.low<<1;
372 return z;
373
374 }
375
376 /*
377 -------------------------------------------------------------------------------
378 Returns the result of converting the canonical NaN `a' to the extended
379 double-precision floating-point format.
380 -------------------------------------------------------------------------------
381 */
382 static floatx80 commonNaNToFloatx80( commonNaNT a )
383 {
384 floatx80 z;
385
386 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
387 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
388 return z;
389
390 }
391
392 /*
393 -------------------------------------------------------------------------------
394 Takes two extended double-precision floating-point values `a' and `b', one
395 of which is a NaN, and returns the appropriate NaN result. If either `a' or
396 `b' is a signaling NaN, the invalid exception is raised.
397 -------------------------------------------------------------------------------
398 */
399 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
400 {
401 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
402
403 aIsNaN = floatx80_is_nan( a );
404 aIsSignalingNaN = floatx80_is_signaling_nan( a );
405 bIsNaN = floatx80_is_nan( b );
406 bIsSignalingNaN = floatx80_is_signaling_nan( b );
407 a.low |= LIT64( 0xC000000000000000 );
408 b.low |= LIT64( 0xC000000000000000 );
409 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
410 if ( aIsNaN ) {
411 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
412 }
413 else {
414 return b;
415 }
416
417 }
418
419 #endif
420
421 #ifdef FLOAT128
422
423 /*
424 -------------------------------------------------------------------------------
425 The pattern for a default generated quadruple-precision NaN. The `high' and
426 `low' values hold the most- and least-significant bits, respectively.
427 -------------------------------------------------------------------------------
428 */
429 #define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
430 #define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
431
432 /*
433 -------------------------------------------------------------------------------
434 Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
435 otherwise returns 0.
436 -------------------------------------------------------------------------------
437 */
438 flag float128_is_nan( float128 a )
439 {
440
441 return
442 ( (bits64)LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
443 && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
444
445 }
446
447 /*
448 -------------------------------------------------------------------------------
449 Returns 1 if the quadruple-precision floating-point value `a' is a
450 signaling NaN; otherwise returns 0.
451 -------------------------------------------------------------------------------
452 */
453 flag float128_is_signaling_nan( float128 a )
454 {
455
456 return
457 ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
458 && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
459
460 }
461
462 /*
463 -------------------------------------------------------------------------------
464 Returns the result of converting the quadruple-precision floating-point NaN
465 `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
466 exception is raised.
467 -------------------------------------------------------------------------------
468 */
469 static commonNaNT float128ToCommonNaN( float128 a )
470 {
471 commonNaNT z;
472
473 if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
474 z.sign = (flag)(a.high>>63);
475 shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
476 return z;
477
478 }
479
480 /*
481 -------------------------------------------------------------------------------
482 Returns the result of converting the canonical NaN `a' to the quadruple-
483 precision floating-point format.
484 -------------------------------------------------------------------------------
485 */
486 static float128 commonNaNToFloat128( commonNaNT a )
487 {
488 float128 z;
489
490 shift128Right( a.high, a.low, 16, &z.high, &z.low );
491 z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
492 return z;
493
494 }
495
496 /*
497 -------------------------------------------------------------------------------
498 Takes two quadruple-precision floating-point values `a' and `b', one of
499 which is a NaN, and returns the appropriate NaN result. If either `a' or
500 `b' is a signaling NaN, the invalid exception is raised.
501 -------------------------------------------------------------------------------
502 */
503 static float128 propagateFloat128NaN( float128 a, float128 b )
504 {
505 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
506
507 aIsNaN = float128_is_nan( a );
508 aIsSignalingNaN = float128_is_signaling_nan( a );
509 bIsNaN = float128_is_nan( b );
510 bIsSignalingNaN = float128_is_signaling_nan( b );
511 a.high |= LIT64( 0x0000800000000000 );
512 b.high |= LIT64( 0x0000800000000000 );
513 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
514 if ( aIsNaN ) {
515 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
516 }
517 else {
518 return b;
519 }
520
521 }
522
523 #endif
524
525