]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libc/softfloat/softfloat-specialize
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / lib / libc / softfloat / softfloat-specialize
1 /*      $NetBSD: softfloat-specialize,v 1.3 2002/05/12 13:12:45 bjh21 Exp $     */
2 /* $FreeBSD$ */
3
4 /* This is a derivative work. */
5
6 /*
7 ===============================================================================
8
9 This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
10 Arithmetic Package, Release 2a.
11
12 Written by John R. Hauser.  This work was made possible in part by the
13 International Computer Science Institute, located at Suite 600, 1947 Center
14 Street, Berkeley, California 94704.  Funding was partially provided by the
15 National Science Foundation under grant MIP-9311980.  The original version
16 of this code was written as part of a project to build a fixed-point vector
17 processor in collaboration with the University of California at Berkeley,
18 overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
19 is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
20 arithmetic/SoftFloat.html'.
21
22 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
23 has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
24 TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
25 PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
26 AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
27
28 Derivative works are acceptable, even for commercial purposes, so long as
29 (1) they include prominent notice that the work is derivative, and (2) they
30 include prominent notice akin to these four paragraphs for those parts of
31 this code that are retained.
32
33 ===============================================================================
34 */
35
36 #include <signal.h>
37
38 /*
39 -------------------------------------------------------------------------------
40 Underflow tininess-detection mode, statically initialized to default value.
41 (The declaration in `softfloat.h' must match the `int8' type here.)
42 -------------------------------------------------------------------------------
43 */
44 #ifdef SOFTFLOAT_FOR_GCC
45 static
46 #endif
47 #ifdef __sparc64__
48 int8 float_detect_tininess = float_tininess_before_rounding;
49 #else
50 int8 float_detect_tininess = float_tininess_after_rounding;
51 #endif
52
53 /*
54 -------------------------------------------------------------------------------
55 Raises the exceptions specified by `flags'.  Floating-point traps can be
56 defined here if desired.  It is currently not possible for such a trap to
57 substitute a result value.  If traps are not implemented, this routine
58 should be simply `float_exception_flags |= flags;'.
59 -------------------------------------------------------------------------------
60 */
61 fp_except float_exception_mask = 0;
62 void float_raise( fp_except flags )
63 {
64
65     float_exception_flags |= flags;
66
67     if ( flags & float_exception_mask ) {
68         raise( SIGFPE );
69     }
70 }
71
72 /*
73 -------------------------------------------------------------------------------
74 Internal canonical NaN format.
75 -------------------------------------------------------------------------------
76 */
77 typedef struct {
78     flag sign;
79     bits64 high, low;
80 } commonNaNT;
81
82 /*
83 -------------------------------------------------------------------------------
84 The pattern for a default generated single-precision NaN.
85 -------------------------------------------------------------------------------
86 */
87 #define float32_default_nan 0xFFFFFFFF
88
89 /*
90 -------------------------------------------------------------------------------
91 Returns 1 if the single-precision floating-point value `a' is a NaN;
92 otherwise returns 0.
93 -------------------------------------------------------------------------------
94 */
95 #ifdef SOFTFLOAT_FOR_GCC
96 static
97 #endif
98 flag float32_is_nan( float32 a )
99 {
100
101     return ( 0xFF000000 < (bits32) ( a<<1 ) );
102
103 }
104
105 /*
106 -------------------------------------------------------------------------------
107 Returns 1 if the single-precision floating-point value `a' is a signaling
108 NaN; otherwise returns 0.
109 -------------------------------------------------------------------------------
110 */
111 #if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC)
112 static
113 #endif
114 flag float32_is_signaling_nan( float32 a )
115 {
116
117     return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
118
119 }
120
121 /*
122 -------------------------------------------------------------------------------
123 Returns the result of converting the single-precision floating-point NaN
124 `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
125 exception is raised.
126 -------------------------------------------------------------------------------
127 */
128 static commonNaNT float32ToCommonNaN( float32 a )
129 {
130     commonNaNT z;
131
132     if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
133     z.sign = a>>31;
134     z.low = 0;
135     z.high = ( (bits64) a )<<41;
136     return z;
137
138 }
139
140 /*
141 -------------------------------------------------------------------------------
142 Returns the result of converting the canonical NaN `a' to the single-
143 precision floating-point format.
144 -------------------------------------------------------------------------------
145 */
146 static float32 commonNaNToFloat32( commonNaNT a )
147 {
148
149     return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
150
151 }
152
153 /*
154 -------------------------------------------------------------------------------
155 Takes two single-precision floating-point values `a' and `b', one of which
156 is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
157 signaling NaN, the invalid exception is raised.
158 -------------------------------------------------------------------------------
159 */
160 static float32 propagateFloat32NaN( float32 a, float32 b )
161 {
162     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
163
164     aIsNaN = float32_is_nan( a );
165     aIsSignalingNaN = float32_is_signaling_nan( a );
166     bIsNaN = float32_is_nan( b );
167     bIsSignalingNaN = float32_is_signaling_nan( b );
168     a |= 0x00400000;
169     b |= 0x00400000;
170     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
171     if ( aIsNaN ) {
172         return ( aIsSignalingNaN & bIsNaN ) ? b : a;
173     }
174     else {
175         return b;
176     }
177
178 }
179
180 /*
181 -------------------------------------------------------------------------------
182 The pattern for a default generated double-precision NaN.
183 -------------------------------------------------------------------------------
184 */
185 #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
186
187 /*
188 -------------------------------------------------------------------------------
189 Returns 1 if the double-precision floating-point value `a' is a NaN;
190 otherwise returns 0.
191 -------------------------------------------------------------------------------
192 */
193 #ifdef SOFTFLOAT_FOR_GCC
194 static
195 #endif
196 flag float64_is_nan( float64 a )
197 {
198
199     return ( LIT64( 0xFFE0000000000000 ) <
200              (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
201
202 }
203
204 /*
205 -------------------------------------------------------------------------------
206 Returns 1 if the double-precision floating-point value `a' is a signaling
207 NaN; otherwise returns 0.
208 -------------------------------------------------------------------------------
209 */
210 #if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC)
211 static
212 #endif
213 flag float64_is_signaling_nan( float64 a )
214 {
215
216     return
217            ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
218         && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
219
220 }
221
222 /*
223 -------------------------------------------------------------------------------
224 Returns the result of converting the double-precision floating-point NaN
225 `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
226 exception is raised.
227 -------------------------------------------------------------------------------
228 */
229 static commonNaNT float64ToCommonNaN( float64 a )
230 {
231     commonNaNT z;
232
233     if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
234     z.sign = FLOAT64_DEMANGLE(a)>>63;
235     z.low = 0;
236     z.high = FLOAT64_DEMANGLE(a)<<12;
237     return z;
238
239 }
240
241 /*
242 -------------------------------------------------------------------------------
243 Returns the result of converting the canonical NaN `a' to the double-
244 precision floating-point format.
245 -------------------------------------------------------------------------------
246 */
247 static float64 commonNaNToFloat64( commonNaNT a )
248 {
249
250     return FLOAT64_MANGLE(
251         ( ( (bits64) a.sign )<<63 )
252         | LIT64( 0x7FF8000000000000 )
253         | ( a.high>>12 ) );
254
255 }
256
257 /*
258 -------------------------------------------------------------------------------
259 Takes two double-precision floating-point values `a' and `b', one of which
260 is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
261 signaling NaN, the invalid exception is raised.
262 -------------------------------------------------------------------------------
263 */
264 static float64 propagateFloat64NaN( float64 a, float64 b )
265 {
266     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
267
268     aIsNaN = float64_is_nan( a );
269     aIsSignalingNaN = float64_is_signaling_nan( a );
270     bIsNaN = float64_is_nan( b );
271     bIsSignalingNaN = float64_is_signaling_nan( b );
272     a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
273     b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
274     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
275     if ( aIsNaN ) {
276         return ( aIsSignalingNaN & bIsNaN ) ? b : a;
277     }
278     else {
279         return b;
280     }
281
282 }
283
284 #ifdef FLOATX80
285
286 /*
287 -------------------------------------------------------------------------------
288 The pattern for a default generated extended double-precision NaN.  The
289 `high' and `low' values hold the most- and least-significant bits,
290 respectively.
291 -------------------------------------------------------------------------------
292 */
293 #define floatx80_default_nan_high 0xFFFF
294 #define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
295
296 /*
297 -------------------------------------------------------------------------------
298 Returns 1 if the extended double-precision floating-point value `a' is a
299 NaN; otherwise returns 0.
300 -------------------------------------------------------------------------------
301 */
302 flag floatx80_is_nan( floatx80 a )
303 {
304
305     return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
306
307 }
308
309 /*
310 -------------------------------------------------------------------------------
311 Returns 1 if the extended double-precision floating-point value `a' is a
312 signaling NaN; otherwise returns 0.
313 -------------------------------------------------------------------------------
314 */
315 flag floatx80_is_signaling_nan( floatx80 a )
316 {
317     bits64 aLow;
318
319     aLow = a.low & ~ LIT64( 0x4000000000000000 );
320     return
321            ( ( a.high & 0x7FFF ) == 0x7FFF )
322         && (bits64) ( aLow<<1 )
323         && ( a.low == aLow );
324
325 }
326
327 /*
328 -------------------------------------------------------------------------------
329 Returns the result of converting the extended double-precision floating-
330 point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
331 invalid exception is raised.
332 -------------------------------------------------------------------------------
333 */
334 static commonNaNT floatx80ToCommonNaN( floatx80 a )
335 {
336     commonNaNT z;
337
338     if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
339     z.sign = a.high>>15;
340     z.low = 0;
341     z.high = a.low<<1;
342     return z;
343
344 }
345
346 /*
347 -------------------------------------------------------------------------------
348 Returns the result of converting the canonical NaN `a' to the extended
349 double-precision floating-point format.
350 -------------------------------------------------------------------------------
351 */
352 static floatx80 commonNaNToFloatx80( commonNaNT a )
353 {
354     floatx80 z;
355
356     z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
357     z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
358     return z;
359
360 }
361
362 /*
363 -------------------------------------------------------------------------------
364 Takes two extended double-precision floating-point values `a' and `b', one
365 of which is a NaN, and returns the appropriate NaN result.  If either `a' or
366 `b' is a signaling NaN, the invalid exception is raised.
367 -------------------------------------------------------------------------------
368 */
369 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
370 {
371     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
372
373     aIsNaN = floatx80_is_nan( a );
374     aIsSignalingNaN = floatx80_is_signaling_nan( a );
375     bIsNaN = floatx80_is_nan( b );
376     bIsSignalingNaN = floatx80_is_signaling_nan( b );
377     a.low |= LIT64( 0xC000000000000000 );
378     b.low |= LIT64( 0xC000000000000000 );
379     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
380     if ( aIsNaN ) {
381         return ( aIsSignalingNaN & bIsNaN ) ? b : a;
382     }
383     else {
384         return b;
385     }
386
387 }
388
389 #endif
390
391 #ifdef FLOAT128
392
393 /*
394 -------------------------------------------------------------------------------
395 The pattern for a default generated quadruple-precision NaN.  The `high' and
396 `low' values hold the most- and least-significant bits, respectively.
397 -------------------------------------------------------------------------------
398 */
399 #define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
400 #define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
401
402 /*
403 -------------------------------------------------------------------------------
404 Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
405 otherwise returns 0.
406 -------------------------------------------------------------------------------
407 */
408 flag float128_is_nan( float128 a )
409 {
410
411     return
412            ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
413         && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
414
415 }
416
417 /*
418 -------------------------------------------------------------------------------
419 Returns 1 if the quadruple-precision floating-point value `a' is a
420 signaling NaN; otherwise returns 0.
421 -------------------------------------------------------------------------------
422 */
423 flag float128_is_signaling_nan( float128 a )
424 {
425
426     return
427            ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
428         && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
429
430 }
431
432 /*
433 -------------------------------------------------------------------------------
434 Returns the result of converting the quadruple-precision floating-point NaN
435 `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
436 exception is raised.
437 -------------------------------------------------------------------------------
438 */
439 static commonNaNT float128ToCommonNaN( float128 a )
440 {
441     commonNaNT z;
442
443     if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
444     z.sign = a.high>>63;
445     shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
446     return z;
447
448 }
449
450 /*
451 -------------------------------------------------------------------------------
452 Returns the result of converting the canonical NaN `a' to the quadruple-
453 precision floating-point format.
454 -------------------------------------------------------------------------------
455 */
456 static float128 commonNaNToFloat128( commonNaNT a )
457 {
458     float128 z;
459
460     shift128Right( a.high, a.low, 16, &z.high, &z.low );
461     z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
462     return z;
463
464 }
465
466 /*
467 -------------------------------------------------------------------------------
468 Takes two quadruple-precision floating-point values `a' and `b', one of
469 which is a NaN, and returns the appropriate NaN result.  If either `a' or
470 `b' is a signaling NaN, the invalid exception is raised.
471 -------------------------------------------------------------------------------
472 */
473 static float128 propagateFloat128NaN( float128 a, float128 b )
474 {
475     flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
476
477     aIsNaN = float128_is_nan( a );
478     aIsSignalingNaN = float128_is_signaling_nan( a );
479     bIsNaN = float128_is_nan( b );
480     bIsSignalingNaN = float128_is_signaling_nan( b );
481     a.high |= LIT64( 0x0000800000000000 );
482     b.high |= LIT64( 0x0000800000000000 );
483     if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
484     if ( aIsNaN ) {
485         return ( aIsSignalingNaN & bIsNaN ) ? b : a;
486     }
487     else {
488         return b;
489     }
490
491 }
492
493 #endif
494