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