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