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