1129203Scognet/* $FreeBSD: releng/11.0/lib/libc/softfloat/templates/softfloat-specialize 129203 2004-05-14 12:13:06Z cognet $ */
2129203Scognet
3129203Scognet/*
4129203Scognet===============================================================================
5129203Scognet
6129203ScognetThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point
7129203ScognetArithmetic Package, Release 2a.
8129203Scognet
9129203ScognetWritten by John R. Hauser.  This work was made possible in part by the
10129203ScognetInternational Computer Science Institute, located at Suite 600, 1947 Center
11129203ScognetStreet, Berkeley, California 94704.  Funding was partially provided by the
12129203ScognetNational Science Foundation under grant MIP-9311980.  The original version
13129203Scognetof this code was written as part of a project to build a fixed-point vector
14129203Scognetprocessor in collaboration with the University of California at Berkeley,
15129203Scognetoverseen by Profs. Nelson Morgan and John Wawrzynek.  More information
16129203Scognetis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
17129203Scognetarithmetic/SoftFloat.html'.
18129203Scognet
19129203ScognetTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
20129203Scognethas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
21129203ScognetTIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
22129203ScognetPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
23129203ScognetAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
24129203Scognet
25129203ScognetDerivative works are acceptable, even for commercial purposes, so long as
26129203Scognet(1) they include prominent notice that the work is derivative, and (2) they
27129203Scognetinclude prominent notice akin to these four paragraphs for those parts of
28129203Scognetthis code that are retained.
29129203Scognet
30129203Scognet===============================================================================
31129203Scognet*/
32129203Scognet
33129203Scognet/*
34129203Scognet-------------------------------------------------------------------------------
35129203ScognetUnderflow tininess-detection mode, statically initialized to default value.
36129203Scognet(The declaration in `softfloat.h' must match the `int8' type here.)
37129203Scognet-------------------------------------------------------------------------------
38129203Scognet*/
39129203Scognetint8 float_detect_tininess = float_tininess_after_rounding;
40129203Scognet
41129203Scognet/*
42129203Scognet-------------------------------------------------------------------------------
43129203ScognetRaises the exceptions specified by `flags'.  Floating-point traps can be
44129203Scognetdefined here if desired.  It is currently not possible for such a trap to
45129203Scognetsubstitute a result value.  If traps are not implemented, this routine
46129203Scognetshould be simply `float_exception_flags |= flags;'.
47129203Scognet-------------------------------------------------------------------------------
48129203Scognet*/
49129203Scognetvoid float_raise( int8 flags )
50129203Scognet{
51129203Scognet
52129203Scognet    float_exception_flags |= flags;
53129203Scognet
54129203Scognet}
55129203Scognet
56129203Scognet/*
57129203Scognet-------------------------------------------------------------------------------
58129203ScognetInternal canonical NaN format.
59129203Scognet-------------------------------------------------------------------------------
60129203Scognet*/
61129203Scognettypedef struct {
62129203Scognet    flag sign;
63129203Scognet    bits64 high, low;
64129203Scognet} commonNaNT;
65129203Scognet
66129203Scognet/*
67129203Scognet-------------------------------------------------------------------------------
68129203ScognetThe pattern for a default generated single-precision NaN.
69129203Scognet-------------------------------------------------------------------------------
70129203Scognet*/
71129203Scognet#define float32_default_nan 0xFFFFFFFF
72129203Scognet
73129203Scognet/*
74129203Scognet-------------------------------------------------------------------------------
75129203ScognetReturns 1 if the single-precision floating-point value `a' is a NaN;
76129203Scognetotherwise returns 0.
77129203Scognet-------------------------------------------------------------------------------
78129203Scognet*/
79129203Scognetflag float32_is_nan( float32 a )
80129203Scognet{
81129203Scognet
82129203Scognet    return ( 0xFF000000 < (bits32) ( a<<1 ) );
83129203Scognet
84129203Scognet}
85129203Scognet
86129203Scognet/*
87129203Scognet-------------------------------------------------------------------------------
88129203ScognetReturns 1 if the single-precision floating-point value `a' is a signaling
89129203ScognetNaN; otherwise returns 0.
90129203Scognet-------------------------------------------------------------------------------
91129203Scognet*/
92129203Scognetflag float32_is_signaling_nan( float32 a )
93129203Scognet{
94129203Scognet
95129203Scognet    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
96129203Scognet
97129203Scognet}
98129203Scognet
99129203Scognet/*
100129203Scognet-------------------------------------------------------------------------------
101129203ScognetReturns the result of converting the single-precision floating-point NaN
102129203Scognet`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
103129203Scognetexception is raised.
104129203Scognet-------------------------------------------------------------------------------
105129203Scognet*/
106129203Scognetstatic commonNaNT float32ToCommonNaN( float32 a )
107129203Scognet{
108129203Scognet    commonNaNT z;
109129203Scognet
110129203Scognet    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
111129203Scognet    z.sign = a>>31;
112129203Scognet    z.low = 0;
113129203Scognet    z.high = ( (bits64) a )<<41;
114129203Scognet    return z;
115129203Scognet
116129203Scognet}
117129203Scognet
118129203Scognet/*
119129203Scognet-------------------------------------------------------------------------------
120129203ScognetReturns the result of converting the canonical NaN `a' to the single-
121129203Scognetprecision floating-point format.
122129203Scognet-------------------------------------------------------------------------------
123129203Scognet*/
124129203Scognetstatic float32 commonNaNToFloat32( commonNaNT a )
125129203Scognet{
126129203Scognet
127129203Scognet    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
128129203Scognet
129129203Scognet}
130129203Scognet
131129203Scognet/*
132129203Scognet-------------------------------------------------------------------------------
133129203ScognetTakes two single-precision floating-point values `a' and `b', one of which
134129203Scognetis a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
135129203Scognetsignaling NaN, the invalid exception is raised.
136129203Scognet-------------------------------------------------------------------------------
137129203Scognet*/
138129203Scognetstatic float32 propagateFloat32NaN( float32 a, float32 b )
139129203Scognet{
140129203Scognet    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
141129203Scognet
142129203Scognet    aIsNaN = float32_is_nan( a );
143129203Scognet    aIsSignalingNaN = float32_is_signaling_nan( a );
144129203Scognet    bIsNaN = float32_is_nan( b );
145129203Scognet    bIsSignalingNaN = float32_is_signaling_nan( b );
146129203Scognet    a |= 0x00400000;
147129203Scognet    b |= 0x00400000;
148129203Scognet    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
149129203Scognet    if ( aIsNaN ) {
150129203Scognet        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
151129203Scognet    }
152129203Scognet    else {
153129203Scognet        return b;
154129203Scognet    }
155129203Scognet
156129203Scognet}
157129203Scognet
158129203Scognet/*
159129203Scognet-------------------------------------------------------------------------------
160129203ScognetThe pattern for a default generated double-precision NaN.
161129203Scognet-------------------------------------------------------------------------------
162129203Scognet*/
163129203Scognet#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
164129203Scognet
165129203Scognet/*
166129203Scognet-------------------------------------------------------------------------------
167129203ScognetReturns 1 if the double-precision floating-point value `a' is a NaN;
168129203Scognetotherwise returns 0.
169129203Scognet-------------------------------------------------------------------------------
170129203Scognet*/
171129203Scognetflag float64_is_nan( float64 a )
172129203Scognet{
173129203Scognet
174129203Scognet    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
175129203Scognet
176129203Scognet}
177129203Scognet
178129203Scognet/*
179129203Scognet-------------------------------------------------------------------------------
180129203ScognetReturns 1 if the double-precision floating-point value `a' is a signaling
181129203ScognetNaN; otherwise returns 0.
182129203Scognet-------------------------------------------------------------------------------
183129203Scognet*/
184129203Scognetflag float64_is_signaling_nan( float64 a )
185129203Scognet{
186129203Scognet
187129203Scognet    return
188129203Scognet           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
189129203Scognet        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
190129203Scognet
191129203Scognet}
192129203Scognet
193129203Scognet/*
194129203Scognet-------------------------------------------------------------------------------
195129203ScognetReturns the result of converting the double-precision floating-point NaN
196129203Scognet`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
197129203Scognetexception is raised.
198129203Scognet-------------------------------------------------------------------------------
199129203Scognet*/
200129203Scognetstatic commonNaNT float64ToCommonNaN( float64 a )
201129203Scognet{
202129203Scognet    commonNaNT z;
203129203Scognet
204129203Scognet    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
205129203Scognet    z.sign = a>>63;
206129203Scognet    z.low = 0;
207129203Scognet    z.high = a<<12;
208129203Scognet    return z;
209129203Scognet
210129203Scognet}
211129203Scognet
212129203Scognet/*
213129203Scognet-------------------------------------------------------------------------------
214129203ScognetReturns the result of converting the canonical NaN `a' to the double-
215129203Scognetprecision floating-point format.
216129203Scognet-------------------------------------------------------------------------------
217129203Scognet*/
218129203Scognetstatic float64 commonNaNToFloat64( commonNaNT a )
219129203Scognet{
220129203Scognet
221129203Scognet    return
222129203Scognet          ( ( (bits64) a.sign )<<63 )
223129203Scognet        | LIT64( 0x7FF8000000000000 )
224129203Scognet        | ( a.high>>12 );
225129203Scognet
226129203Scognet}
227129203Scognet
228129203Scognet/*
229129203Scognet-------------------------------------------------------------------------------
230129203ScognetTakes two double-precision floating-point values `a' and `b', one of which
231129203Scognetis a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
232129203Scognetsignaling NaN, the invalid exception is raised.
233129203Scognet-------------------------------------------------------------------------------
234129203Scognet*/
235129203Scognetstatic float64 propagateFloat64NaN( float64 a, float64 b )
236129203Scognet{
237129203Scognet    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
238129203Scognet
239129203Scognet    aIsNaN = float64_is_nan( a );
240129203Scognet    aIsSignalingNaN = float64_is_signaling_nan( a );
241129203Scognet    bIsNaN = float64_is_nan( b );
242129203Scognet    bIsSignalingNaN = float64_is_signaling_nan( b );
243129203Scognet    a |= LIT64( 0x0008000000000000 );
244129203Scognet    b |= LIT64( 0x0008000000000000 );
245129203Scognet    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
246129203Scognet    if ( aIsNaN ) {
247129203Scognet        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
248129203Scognet    }
249129203Scognet    else {
250129203Scognet        return b;
251129203Scognet    }
252129203Scognet
253129203Scognet}
254129203Scognet
255129203Scognet#ifdef FLOATX80
256129203Scognet
257129203Scognet/*
258129203Scognet-------------------------------------------------------------------------------
259129203ScognetThe pattern for a default generated extended double-precision NaN.  The
260129203Scognet`high' and `low' values hold the most- and least-significant bits,
261129203Scognetrespectively.
262129203Scognet-------------------------------------------------------------------------------
263129203Scognet*/
264129203Scognet#define floatx80_default_nan_high 0xFFFF
265129203Scognet#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
266129203Scognet
267129203Scognet/*
268129203Scognet-------------------------------------------------------------------------------
269129203ScognetReturns 1 if the extended double-precision floating-point value `a' is a
270129203ScognetNaN; otherwise returns 0.
271129203Scognet-------------------------------------------------------------------------------
272129203Scognet*/
273129203Scognetflag floatx80_is_nan( floatx80 a )
274129203Scognet{
275129203Scognet
276129203Scognet    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
277129203Scognet
278129203Scognet}
279129203Scognet
280129203Scognet/*
281129203Scognet-------------------------------------------------------------------------------
282129203ScognetReturns 1 if the extended double-precision floating-point value `a' is a
283129203Scognetsignaling NaN; otherwise returns 0.
284129203Scognet-------------------------------------------------------------------------------
285129203Scognet*/
286129203Scognetflag floatx80_is_signaling_nan( floatx80 a )
287129203Scognet{
288129203Scognet    bits64 aLow;
289129203Scognet
290129203Scognet    aLow = a.low & ~ LIT64( 0x4000000000000000 );
291129203Scognet    return
292129203Scognet           ( ( a.high & 0x7FFF ) == 0x7FFF )
293129203Scognet        && (bits64) ( aLow<<1 )
294129203Scognet        && ( a.low == aLow );
295129203Scognet
296129203Scognet}
297129203Scognet
298129203Scognet/*
299129203Scognet-------------------------------------------------------------------------------
300129203ScognetReturns the result of converting the extended double-precision floating-
301129203Scognetpoint NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
302129203Scognetinvalid exception is raised.
303129203Scognet-------------------------------------------------------------------------------
304129203Scognet*/
305129203Scognetstatic commonNaNT floatx80ToCommonNaN( floatx80 a )
306129203Scognet{
307129203Scognet    commonNaNT z;
308129203Scognet
309129203Scognet    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
310129203Scognet    z.sign = a.high>>15;
311129203Scognet    z.low = 0;
312129203Scognet    z.high = a.low<<1;
313129203Scognet    return z;
314129203Scognet
315129203Scognet}
316129203Scognet
317129203Scognet/*
318129203Scognet-------------------------------------------------------------------------------
319129203ScognetReturns the result of converting the canonical NaN `a' to the extended
320129203Scognetdouble-precision floating-point format.
321129203Scognet-------------------------------------------------------------------------------
322129203Scognet*/
323129203Scognetstatic floatx80 commonNaNToFloatx80( commonNaNT a )
324129203Scognet{
325129203Scognet    floatx80 z;
326129203Scognet
327129203Scognet    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
328129203Scognet    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
329129203Scognet    return z;
330129203Scognet
331129203Scognet}
332129203Scognet
333129203Scognet/*
334129203Scognet-------------------------------------------------------------------------------
335129203ScognetTakes two extended double-precision floating-point values `a' and `b', one
336129203Scognetof which is a NaN, and returns the appropriate NaN result.  If either `a' or
337129203Scognet`b' is a signaling NaN, the invalid exception is raised.
338129203Scognet-------------------------------------------------------------------------------
339129203Scognet*/
340129203Scognetstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
341129203Scognet{
342129203Scognet    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
343129203Scognet
344129203Scognet    aIsNaN = floatx80_is_nan( a );
345129203Scognet    aIsSignalingNaN = floatx80_is_signaling_nan( a );
346129203Scognet    bIsNaN = floatx80_is_nan( b );
347129203Scognet    bIsSignalingNaN = floatx80_is_signaling_nan( b );
348129203Scognet    a.low |= LIT64( 0xC000000000000000 );
349129203Scognet    b.low |= LIT64( 0xC000000000000000 );
350129203Scognet    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
351129203Scognet    if ( aIsNaN ) {
352129203Scognet        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
353129203Scognet    }
354129203Scognet    else {
355129203Scognet        return b;
356129203Scognet    }
357129203Scognet
358129203Scognet}
359129203Scognet
360129203Scognet#endif
361129203Scognet
362129203Scognet#ifdef FLOAT128
363129203Scognet
364129203Scognet/*
365129203Scognet-------------------------------------------------------------------------------
366129203ScognetThe pattern for a default generated quadruple-precision NaN.  The `high' and
367129203Scognet`low' values hold the most- and least-significant bits, respectively.
368129203Scognet-------------------------------------------------------------------------------
369129203Scognet*/
370129203Scognet#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
371129203Scognet#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
372129203Scognet
373129203Scognet/*
374129203Scognet-------------------------------------------------------------------------------
375129203ScognetReturns 1 if the quadruple-precision floating-point value `a' is a NaN;
376129203Scognetotherwise returns 0.
377129203Scognet-------------------------------------------------------------------------------
378129203Scognet*/
379129203Scognetflag float128_is_nan( float128 a )
380129203Scognet{
381129203Scognet
382129203Scognet    return
383129203Scognet           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
384129203Scognet        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
385129203Scognet
386129203Scognet}
387129203Scognet
388129203Scognet/*
389129203Scognet-------------------------------------------------------------------------------
390129203ScognetReturns 1 if the quadruple-precision floating-point value `a' is a
391129203Scognetsignaling NaN; otherwise returns 0.
392129203Scognet-------------------------------------------------------------------------------
393129203Scognet*/
394129203Scognetflag float128_is_signaling_nan( float128 a )
395129203Scognet{
396129203Scognet
397129203Scognet    return
398129203Scognet           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
399129203Scognet        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
400129203Scognet
401129203Scognet}
402129203Scognet
403129203Scognet/*
404129203Scognet-------------------------------------------------------------------------------
405129203ScognetReturns the result of converting the quadruple-precision floating-point NaN
406129203Scognet`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
407129203Scognetexception is raised.
408129203Scognet-------------------------------------------------------------------------------
409129203Scognet*/
410129203Scognetstatic commonNaNT float128ToCommonNaN( float128 a )
411129203Scognet{
412129203Scognet    commonNaNT z;
413129203Scognet
414129203Scognet    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
415129203Scognet    z.sign = a.high>>63;
416129203Scognet    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
417129203Scognet    return z;
418129203Scognet
419129203Scognet}
420129203Scognet
421129203Scognet/*
422129203Scognet-------------------------------------------------------------------------------
423129203ScognetReturns the result of converting the canonical NaN `a' to the quadruple-
424129203Scognetprecision floating-point format.
425129203Scognet-------------------------------------------------------------------------------
426129203Scognet*/
427129203Scognetstatic float128 commonNaNToFloat128( commonNaNT a )
428129203Scognet{
429129203Scognet    float128 z;
430129203Scognet
431129203Scognet    shift128Right( a.high, a.low, 16, &z.high, &z.low );
432129203Scognet    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
433129203Scognet    return z;
434129203Scognet
435129203Scognet}
436129203Scognet
437129203Scognet/*
438129203Scognet-------------------------------------------------------------------------------
439129203ScognetTakes two quadruple-precision floating-point values `a' and `b', one of
440129203Scognetwhich is a NaN, and returns the appropriate NaN result.  If either `a' or
441129203Scognet`b' is a signaling NaN, the invalid exception is raised.
442129203Scognet-------------------------------------------------------------------------------
443129203Scognet*/
444129203Scognetstatic float128 propagateFloat128NaN( float128 a, float128 b )
445129203Scognet{
446129203Scognet    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
447129203Scognet
448129203Scognet    aIsNaN = float128_is_nan( a );
449129203Scognet    aIsSignalingNaN = float128_is_signaling_nan( a );
450129203Scognet    bIsNaN = float128_is_nan( b );
451129203Scognet    bIsSignalingNaN = float128_is_signaling_nan( b );
452129203Scognet    a.high |= LIT64( 0x0000800000000000 );
453129203Scognet    b.high |= LIT64( 0x0000800000000000 );
454129203Scognet    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
455129203Scognet    if ( aIsNaN ) {
456129203Scognet        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
457129203Scognet    }
458129203Scognet    else {
459129203Scognet        return b;
460129203Scognet    }
461129203Scognet
462129203Scognet}
463129203Scognet
464129203Scognet#endif
465129203Scognet
466