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