xref: /linux/arch/arm/nwfpe/softfloat-specialize (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds
2*1da177e4SLinus Torvalds/*
3*1da177e4SLinus Torvalds===============================================================================
4*1da177e4SLinus Torvalds
5*1da177e4SLinus TorvaldsThis C source fragment is part of the SoftFloat IEC/IEEE Floating-point
6*1da177e4SLinus TorvaldsArithmetic Package, Release 2.
7*1da177e4SLinus Torvalds
8*1da177e4SLinus TorvaldsWritten by John R. Hauser.  This work was made possible in part by the
9*1da177e4SLinus TorvaldsInternational Computer Science Institute, located at Suite 600, 1947 Center
10*1da177e4SLinus TorvaldsStreet, Berkeley, California 94704.  Funding was partially provided by the
11*1da177e4SLinus TorvaldsNational Science Foundation under grant MIP-9311980.  The original version
12*1da177e4SLinus Torvaldsof this code was written as part of a project to build a fixed-point vector
13*1da177e4SLinus Torvaldsprocessor in collaboration with the University of California at Berkeley,
14*1da177e4SLinus Torvaldsoverseen by Profs. Nelson Morgan and John Wawrzynek.  More information
15*1da177e4SLinus Torvaldsis available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
16*1da177e4SLinus Torvaldsarithmetic/softfloat.html'.
17*1da177e4SLinus Torvalds
18*1da177e4SLinus TorvaldsTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
19*1da177e4SLinus Torvaldshas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
20*1da177e4SLinus TorvaldsTIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
21*1da177e4SLinus TorvaldsPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
22*1da177e4SLinus TorvaldsAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
23*1da177e4SLinus Torvalds
24*1da177e4SLinus TorvaldsDerivative works are acceptable, even for commercial purposes, so long as
25*1da177e4SLinus Torvalds(1) they include prominent notice that the work is derivative, and (2) they
26*1da177e4SLinus Torvaldsinclude prominent notice akin to these three paragraphs for those parts of
27*1da177e4SLinus Torvaldsthis code that are retained.
28*1da177e4SLinus Torvalds
29*1da177e4SLinus Torvalds===============================================================================
30*1da177e4SLinus Torvalds*/
31*1da177e4SLinus Torvalds
32*1da177e4SLinus Torvalds/*
33*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
34*1da177e4SLinus TorvaldsUnderflow tininess-detection mode, statically initialized to default value.
35*1da177e4SLinus Torvalds(The declaration in `softfloat.h' must match the `int8' type here.)
36*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
37*1da177e4SLinus Torvalds*/
38*1da177e4SLinus Torvaldsint8 float_detect_tininess = float_tininess_after_rounding;
39*1da177e4SLinus Torvalds
40*1da177e4SLinus Torvalds/*
41*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
42*1da177e4SLinus TorvaldsRaises the exceptions specified by `flags'.  Floating-point traps can be
43*1da177e4SLinus Torvaldsdefined here if desired.  It is currently not possible for such a trap to
44*1da177e4SLinus Torvaldssubstitute a result value.  If traps are not implemented, this routine
45*1da177e4SLinus Torvaldsshould be simply `float_exception_flags |= flags;'.
46*1da177e4SLinus Torvalds
47*1da177e4SLinus TorvaldsScottB:  November 4, 1998
48*1da177e4SLinus TorvaldsMoved this function out of softfloat-specialize into fpmodule.c.
49*1da177e4SLinus TorvaldsThis effectively isolates all the changes required for integrating with the
50*1da177e4SLinus TorvaldsLinux kernel into fpmodule.c.  Porting to NetBSD should only require modifying
51*1da177e4SLinus Torvaldsfpmodule.c to integrate with the NetBSD kernel (I hope!).
52*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
53*1da177e4SLinus Torvaldsvoid float_raise( int8 flags )
54*1da177e4SLinus Torvalds{
55*1da177e4SLinus Torvalds    float_exception_flags |= flags;
56*1da177e4SLinus Torvalds}
57*1da177e4SLinus Torvalds*/
58*1da177e4SLinus Torvalds
59*1da177e4SLinus Torvalds/*
60*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
61*1da177e4SLinus TorvaldsInternal canonical NaN format.
62*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
63*1da177e4SLinus Torvalds*/
64*1da177e4SLinus Torvaldstypedef struct {
65*1da177e4SLinus Torvalds    flag sign;
66*1da177e4SLinus Torvalds    bits64 high, low;
67*1da177e4SLinus Torvalds} commonNaNT;
68*1da177e4SLinus Torvalds
69*1da177e4SLinus Torvalds/*
70*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
71*1da177e4SLinus TorvaldsThe pattern for a default generated single-precision NaN.
72*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
73*1da177e4SLinus Torvalds*/
74*1da177e4SLinus Torvalds#define float32_default_nan 0xFFFFFFFF
75*1da177e4SLinus Torvalds
76*1da177e4SLinus Torvalds/*
77*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
78*1da177e4SLinus TorvaldsReturns 1 if the single-precision floating-point value `a' is a NaN;
79*1da177e4SLinus Torvaldsotherwise returns 0.
80*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
81*1da177e4SLinus Torvalds*/
82*1da177e4SLinus Torvaldsflag float32_is_nan( float32 a )
83*1da177e4SLinus Torvalds{
84*1da177e4SLinus Torvalds
85*1da177e4SLinus Torvalds    return ( 0xFF000000 < (bits32) ( a<<1 ) );
86*1da177e4SLinus Torvalds
87*1da177e4SLinus Torvalds}
88*1da177e4SLinus Torvalds
89*1da177e4SLinus Torvalds/*
90*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
91*1da177e4SLinus TorvaldsReturns 1 if the single-precision floating-point value `a' is a signaling
92*1da177e4SLinus TorvaldsNaN; otherwise returns 0.
93*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
94*1da177e4SLinus Torvalds*/
95*1da177e4SLinus Torvaldsflag float32_is_signaling_nan( float32 a )
96*1da177e4SLinus Torvalds{
97*1da177e4SLinus Torvalds
98*1da177e4SLinus Torvalds    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
99*1da177e4SLinus Torvalds
100*1da177e4SLinus Torvalds}
101*1da177e4SLinus Torvalds
102*1da177e4SLinus Torvalds/*
103*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
104*1da177e4SLinus TorvaldsReturns the result of converting the single-precision floating-point NaN
105*1da177e4SLinus Torvalds`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
106*1da177e4SLinus Torvaldsexception is raised.
107*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
108*1da177e4SLinus Torvalds*/
109*1da177e4SLinus Torvaldsstatic commonNaNT float32ToCommonNaN( float32 a )
110*1da177e4SLinus Torvalds{
111*1da177e4SLinus Torvalds    commonNaNT z;
112*1da177e4SLinus Torvalds
113*1da177e4SLinus Torvalds    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
114*1da177e4SLinus Torvalds    z.sign = a>>31;
115*1da177e4SLinus Torvalds    z.low = 0;
116*1da177e4SLinus Torvalds    z.high = ( (bits64) a )<<41;
117*1da177e4SLinus Torvalds    return z;
118*1da177e4SLinus Torvalds
119*1da177e4SLinus Torvalds}
120*1da177e4SLinus Torvalds
121*1da177e4SLinus Torvalds/*
122*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
123*1da177e4SLinus TorvaldsReturns the result of converting the canonical NaN `a' to the single-
124*1da177e4SLinus Torvaldsprecision floating-point format.
125*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
126*1da177e4SLinus Torvalds*/
127*1da177e4SLinus Torvaldsstatic float32 commonNaNToFloat32( commonNaNT a )
128*1da177e4SLinus Torvalds{
129*1da177e4SLinus Torvalds
130*1da177e4SLinus Torvalds    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
131*1da177e4SLinus Torvalds
132*1da177e4SLinus Torvalds}
133*1da177e4SLinus Torvalds
134*1da177e4SLinus Torvalds/*
135*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
136*1da177e4SLinus TorvaldsTakes two single-precision floating-point values `a' and `b', one of which
137*1da177e4SLinus Torvaldsis a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
138*1da177e4SLinus Torvaldssignaling NaN, the invalid exception is raised.
139*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
140*1da177e4SLinus Torvalds*/
141*1da177e4SLinus Torvaldsstatic float32 propagateFloat32NaN( float32 a, float32 b )
142*1da177e4SLinus Torvalds{
143*1da177e4SLinus Torvalds    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
144*1da177e4SLinus Torvalds
145*1da177e4SLinus Torvalds    aIsNaN = float32_is_nan( a );
146*1da177e4SLinus Torvalds    aIsSignalingNaN = float32_is_signaling_nan( a );
147*1da177e4SLinus Torvalds    bIsNaN = float32_is_nan( b );
148*1da177e4SLinus Torvalds    bIsSignalingNaN = float32_is_signaling_nan( b );
149*1da177e4SLinus Torvalds    a |= 0x00400000;
150*1da177e4SLinus Torvalds    b |= 0x00400000;
151*1da177e4SLinus Torvalds    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
152*1da177e4SLinus Torvalds    if ( aIsNaN ) {
153*1da177e4SLinus Torvalds        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
154*1da177e4SLinus Torvalds    }
155*1da177e4SLinus Torvalds    else {
156*1da177e4SLinus Torvalds        return b;
157*1da177e4SLinus Torvalds    }
158*1da177e4SLinus Torvalds
159*1da177e4SLinus Torvalds}
160*1da177e4SLinus Torvalds
161*1da177e4SLinus Torvalds/*
162*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
163*1da177e4SLinus TorvaldsThe pattern for a default generated double-precision NaN.
164*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
165*1da177e4SLinus Torvalds*/
166*1da177e4SLinus Torvalds#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
167*1da177e4SLinus Torvalds
168*1da177e4SLinus Torvalds/*
169*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
170*1da177e4SLinus TorvaldsReturns 1 if the double-precision floating-point value `a' is a NaN;
171*1da177e4SLinus Torvaldsotherwise returns 0.
172*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
173*1da177e4SLinus Torvalds*/
174*1da177e4SLinus Torvaldsflag float64_is_nan( float64 a )
175*1da177e4SLinus Torvalds{
176*1da177e4SLinus Torvalds
177*1da177e4SLinus Torvalds    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
178*1da177e4SLinus Torvalds
179*1da177e4SLinus Torvalds}
180*1da177e4SLinus Torvalds
181*1da177e4SLinus Torvalds/*
182*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
183*1da177e4SLinus TorvaldsReturns 1 if the double-precision floating-point value `a' is a signaling
184*1da177e4SLinus TorvaldsNaN; otherwise returns 0.
185*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
186*1da177e4SLinus Torvalds*/
187*1da177e4SLinus Torvaldsflag float64_is_signaling_nan( float64 a )
188*1da177e4SLinus Torvalds{
189*1da177e4SLinus Torvalds
190*1da177e4SLinus Torvalds    return
191*1da177e4SLinus Torvalds           ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
192*1da177e4SLinus Torvalds        && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
193*1da177e4SLinus Torvalds
194*1da177e4SLinus Torvalds}
195*1da177e4SLinus Torvalds
196*1da177e4SLinus Torvalds/*
197*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
198*1da177e4SLinus TorvaldsReturns the result of converting the double-precision floating-point NaN
199*1da177e4SLinus Torvalds`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
200*1da177e4SLinus Torvaldsexception is raised.
201*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
202*1da177e4SLinus Torvalds*/
203*1da177e4SLinus Torvaldsstatic commonNaNT float64ToCommonNaN( float64 a )
204*1da177e4SLinus Torvalds{
205*1da177e4SLinus Torvalds    commonNaNT z;
206*1da177e4SLinus Torvalds
207*1da177e4SLinus Torvalds    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
208*1da177e4SLinus Torvalds    z.sign = a>>63;
209*1da177e4SLinus Torvalds    z.low = 0;
210*1da177e4SLinus Torvalds    z.high = a<<12;
211*1da177e4SLinus Torvalds    return z;
212*1da177e4SLinus Torvalds
213*1da177e4SLinus Torvalds}
214*1da177e4SLinus Torvalds
215*1da177e4SLinus Torvalds/*
216*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
217*1da177e4SLinus TorvaldsReturns the result of converting the canonical NaN `a' to the double-
218*1da177e4SLinus Torvaldsprecision floating-point format.
219*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
220*1da177e4SLinus Torvalds*/
221*1da177e4SLinus Torvaldsstatic float64 commonNaNToFloat64( commonNaNT a )
222*1da177e4SLinus Torvalds{
223*1da177e4SLinus Torvalds
224*1da177e4SLinus Torvalds    return
225*1da177e4SLinus Torvalds          ( ( (bits64) a.sign )<<63 )
226*1da177e4SLinus Torvalds        | LIT64( 0x7FF8000000000000 )
227*1da177e4SLinus Torvalds        | ( a.high>>12 );
228*1da177e4SLinus Torvalds
229*1da177e4SLinus Torvalds}
230*1da177e4SLinus Torvalds
231*1da177e4SLinus Torvalds/*
232*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
233*1da177e4SLinus TorvaldsTakes two double-precision floating-point values `a' and `b', one of which
234*1da177e4SLinus Torvaldsis a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
235*1da177e4SLinus Torvaldssignaling NaN, the invalid exception is raised.
236*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
237*1da177e4SLinus Torvalds*/
238*1da177e4SLinus Torvaldsstatic float64 propagateFloat64NaN( float64 a, float64 b )
239*1da177e4SLinus Torvalds{
240*1da177e4SLinus Torvalds    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
241*1da177e4SLinus Torvalds
242*1da177e4SLinus Torvalds    aIsNaN = float64_is_nan( a );
243*1da177e4SLinus Torvalds    aIsSignalingNaN = float64_is_signaling_nan( a );
244*1da177e4SLinus Torvalds    bIsNaN = float64_is_nan( b );
245*1da177e4SLinus Torvalds    bIsSignalingNaN = float64_is_signaling_nan( b );
246*1da177e4SLinus Torvalds    a |= LIT64( 0x0008000000000000 );
247*1da177e4SLinus Torvalds    b |= LIT64( 0x0008000000000000 );
248*1da177e4SLinus Torvalds    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
249*1da177e4SLinus Torvalds    if ( aIsNaN ) {
250*1da177e4SLinus Torvalds        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
251*1da177e4SLinus Torvalds    }
252*1da177e4SLinus Torvalds    else {
253*1da177e4SLinus Torvalds        return b;
254*1da177e4SLinus Torvalds    }
255*1da177e4SLinus Torvalds
256*1da177e4SLinus Torvalds}
257*1da177e4SLinus Torvalds
258*1da177e4SLinus Torvalds#ifdef FLOATX80
259*1da177e4SLinus Torvalds
260*1da177e4SLinus Torvalds/*
261*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
262*1da177e4SLinus TorvaldsThe pattern for a default generated extended double-precision NaN.  The
263*1da177e4SLinus Torvalds`high' and `low' values hold the most- and least-significant bits,
264*1da177e4SLinus Torvaldsrespectively.
265*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
266*1da177e4SLinus Torvalds*/
267*1da177e4SLinus Torvalds#define floatx80_default_nan_high 0xFFFF
268*1da177e4SLinus Torvalds#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
269*1da177e4SLinus Torvalds
270*1da177e4SLinus Torvalds/*
271*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
272*1da177e4SLinus TorvaldsReturns 1 if the extended double-precision floating-point value `a' is a
273*1da177e4SLinus TorvaldsNaN; otherwise returns 0.
274*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
275*1da177e4SLinus Torvalds*/
276*1da177e4SLinus Torvaldsflag floatx80_is_nan( floatx80 a )
277*1da177e4SLinus Torvalds{
278*1da177e4SLinus Torvalds
279*1da177e4SLinus Torvalds    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
280*1da177e4SLinus Torvalds
281*1da177e4SLinus Torvalds}
282*1da177e4SLinus Torvalds
283*1da177e4SLinus Torvalds/*
284*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
285*1da177e4SLinus TorvaldsReturns 1 if the extended double-precision floating-point value `a' is a
286*1da177e4SLinus Torvaldssignaling NaN; otherwise returns 0.
287*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
288*1da177e4SLinus Torvalds*/
289*1da177e4SLinus Torvaldsflag floatx80_is_signaling_nan( floatx80 a )
290*1da177e4SLinus Torvalds{
291*1da177e4SLinus Torvalds    //register int lr;
292*1da177e4SLinus Torvalds    bits64 aLow;
293*1da177e4SLinus Torvalds
294*1da177e4SLinus Torvalds    //__asm__("mov %0, lr" : : "g" (lr));
295*1da177e4SLinus Torvalds    //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr);
296*1da177e4SLinus Torvalds    aLow = a.low & ~ LIT64( 0x4000000000000000 );
297*1da177e4SLinus Torvalds    return
298*1da177e4SLinus Torvalds           ( ( a.high & 0x7FFF ) == 0x7FFF )
299*1da177e4SLinus Torvalds        && (bits64) ( aLow<<1 )
300*1da177e4SLinus Torvalds        && ( a.low == aLow );
301*1da177e4SLinus Torvalds
302*1da177e4SLinus Torvalds}
303*1da177e4SLinus Torvalds
304*1da177e4SLinus Torvalds/*
305*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
306*1da177e4SLinus TorvaldsReturns the result of converting the extended double-precision floating-
307*1da177e4SLinus Torvaldspoint NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
308*1da177e4SLinus Torvaldsinvalid exception is raised.
309*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
310*1da177e4SLinus Torvalds*/
311*1da177e4SLinus Torvaldsstatic commonNaNT floatx80ToCommonNaN( floatx80 a )
312*1da177e4SLinus Torvalds{
313*1da177e4SLinus Torvalds    commonNaNT z;
314*1da177e4SLinus Torvalds
315*1da177e4SLinus Torvalds    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
316*1da177e4SLinus Torvalds    z.sign = a.high>>15;
317*1da177e4SLinus Torvalds    z.low = 0;
318*1da177e4SLinus Torvalds    z.high = a.low<<1;
319*1da177e4SLinus Torvalds    return z;
320*1da177e4SLinus Torvalds
321*1da177e4SLinus Torvalds}
322*1da177e4SLinus Torvalds
323*1da177e4SLinus Torvalds/*
324*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
325*1da177e4SLinus TorvaldsReturns the result of converting the canonical NaN `a' to the extended
326*1da177e4SLinus Torvaldsdouble-precision floating-point format.
327*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
328*1da177e4SLinus Torvalds*/
329*1da177e4SLinus Torvaldsstatic floatx80 commonNaNToFloatx80( commonNaNT a )
330*1da177e4SLinus Torvalds{
331*1da177e4SLinus Torvalds    floatx80 z;
332*1da177e4SLinus Torvalds
333*1da177e4SLinus Torvalds    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
334*1da177e4SLinus Torvalds    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
335*1da177e4SLinus Torvalds    return z;
336*1da177e4SLinus Torvalds
337*1da177e4SLinus Torvalds}
338*1da177e4SLinus Torvalds
339*1da177e4SLinus Torvalds/*
340*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
341*1da177e4SLinus TorvaldsTakes two extended double-precision floating-point values `a' and `b', one
342*1da177e4SLinus Torvaldsof which is a NaN, and returns the appropriate NaN result.  If either `a' or
343*1da177e4SLinus Torvalds`b' is a signaling NaN, the invalid exception is raised.
344*1da177e4SLinus Torvalds-------------------------------------------------------------------------------
345*1da177e4SLinus Torvalds*/
346*1da177e4SLinus Torvaldsstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
347*1da177e4SLinus Torvalds{
348*1da177e4SLinus Torvalds    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
349*1da177e4SLinus Torvalds
350*1da177e4SLinus Torvalds    aIsNaN = floatx80_is_nan( a );
351*1da177e4SLinus Torvalds    aIsSignalingNaN = floatx80_is_signaling_nan( a );
352*1da177e4SLinus Torvalds    bIsNaN = floatx80_is_nan( b );
353*1da177e4SLinus Torvalds    bIsSignalingNaN = floatx80_is_signaling_nan( b );
354*1da177e4SLinus Torvalds    a.low |= LIT64( 0xC000000000000000 );
355*1da177e4SLinus Torvalds    b.low |= LIT64( 0xC000000000000000 );
356*1da177e4SLinus Torvalds    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
357*1da177e4SLinus Torvalds    if ( aIsNaN ) {
358*1da177e4SLinus Torvalds        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
359*1da177e4SLinus Torvalds    }
360*1da177e4SLinus Torvalds    else {
361*1da177e4SLinus Torvalds        return b;
362*1da177e4SLinus Torvalds    }
363*1da177e4SLinus Torvalds
364*1da177e4SLinus Torvalds}
365*1da177e4SLinus Torvalds
366*1da177e4SLinus Torvalds#endif
367