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