softfloat-specialize revision 230189
1129203Scognet/*	$NetBSD: softfloat-specialize,v 1.3 2002/05/12 13:12:45 bjh21 Exp $	*/
2129203Scognet/* $FreeBSD: head/lib/libc/softfloat/softfloat-specialize 230189 2012-01-16 04:05:53Z das $ */
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>
37129203Scognet
38129203Scognet/*
39129203Scognet-------------------------------------------------------------------------------
40129203ScognetUnderflow tininess-detection mode, statically initialized to default value.
41129203Scognet(The declaration in `softfloat.h' must match the `int8' type here.)
42129203Scognet-------------------------------------------------------------------------------
43129203Scognet*/
44129203Scognet#ifdef SOFTFLOAT_FOR_GCC
45129203Scognetstatic
46129203Scognet#endif
47206490Smarius#ifdef __sparc64__
48206490Smariusint8 float_detect_tininess = float_tininess_before_rounding;
49206490Smarius#else
50129203Scognetint8 float_detect_tininess = float_tininess_after_rounding;
51206492Smarius#endif
52129203Scognet
53129203Scognet/*
54129203Scognet-------------------------------------------------------------------------------
55129203ScognetRaises the exceptions specified by `flags'.  Floating-point traps can be
56129203Scognetdefined here if desired.  It is currently not possible for such a trap to
57129203Scognetsubstitute a result value.  If traps are not implemented, this routine
58129203Scognetshould be simply `float_exception_flags |= flags;'.
59129203Scognet-------------------------------------------------------------------------------
60129203Scognet*/
61230189Sdasint float_exception_mask = 0;
62230189Sdasvoid float_raise( int flags )
63129203Scognet{
64129203Scognet
65129203Scognet    float_exception_flags |= flags;
66129203Scognet
67129203Scognet    if ( flags & float_exception_mask ) {
68129203Scognet	raise( SIGFPE );
69129203Scognet    }
70129203Scognet}
71129203Scognet
72129203Scognet/*
73129203Scognet-------------------------------------------------------------------------------
74129203ScognetInternal canonical NaN format.
75129203Scognet-------------------------------------------------------------------------------
76129203Scognet*/
77129203Scognettypedef struct {
78129203Scognet    flag sign;
79129203Scognet    bits64 high, low;
80129203Scognet} commonNaNT;
81129203Scognet
82129203Scognet/*
83129203Scognet-------------------------------------------------------------------------------
84129203ScognetThe pattern for a default generated single-precision NaN.
85129203Scognet-------------------------------------------------------------------------------
86129203Scognet*/
87129203Scognet#define float32_default_nan 0xFFFFFFFF
88129203Scognet
89129203Scognet/*
90129203Scognet-------------------------------------------------------------------------------
91129203ScognetReturns 1 if the single-precision floating-point value `a' is a NaN;
92129203Scognetotherwise returns 0.
93129203Scognet-------------------------------------------------------------------------------
94129203Scognet*/
95129203Scognet#ifdef SOFTFLOAT_FOR_GCC
96129203Scognetstatic
97129203Scognet#endif
98129203Scognetflag float32_is_nan( float32 a )
99129203Scognet{
100129203Scognet
101129203Scognet    return ( 0xFF000000 < (bits32) ( a<<1 ) );
102129203Scognet
103129203Scognet}
104129203Scognet
105129203Scognet/*
106129203Scognet-------------------------------------------------------------------------------
107129203ScognetReturns 1 if the single-precision floating-point value `a' is a signaling
108129203ScognetNaN; otherwise returns 0.
109129203Scognet-------------------------------------------------------------------------------
110129203Scognet*/
111129203Scognet#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC)
112129203Scognetstatic
113129203Scognet#endif
114129203Scognetflag float32_is_signaling_nan( float32 a )
115129203Scognet{
116129203Scognet
117129203Scognet    return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
118129203Scognet
119129203Scognet}
120129203Scognet
121129203Scognet/*
122129203Scognet-------------------------------------------------------------------------------
123129203ScognetReturns the result of converting the single-precision floating-point NaN
124129203Scognet`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
125129203Scognetexception is raised.
126129203Scognet-------------------------------------------------------------------------------
127129203Scognet*/
128129203Scognetstatic commonNaNT float32ToCommonNaN( float32 a )
129129203Scognet{
130129203Scognet    commonNaNT z;
131129203Scognet
132129203Scognet    if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
133129203Scognet    z.sign = a>>31;
134129203Scognet    z.low = 0;
135129203Scognet    z.high = ( (bits64) a )<<41;
136129203Scognet    return z;
137129203Scognet
138129203Scognet}
139129203Scognet
140129203Scognet/*
141129203Scognet-------------------------------------------------------------------------------
142129203ScognetReturns the result of converting the canonical NaN `a' to the single-
143129203Scognetprecision floating-point format.
144129203Scognet-------------------------------------------------------------------------------
145129203Scognet*/
146129203Scognetstatic float32 commonNaNToFloat32( commonNaNT a )
147129203Scognet{
148129203Scognet
149129203Scognet    return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
150129203Scognet
151129203Scognet}
152129203Scognet
153129203Scognet/*
154129203Scognet-------------------------------------------------------------------------------
155129203ScognetTakes two single-precision floating-point values `a' and `b', one of which
156129203Scognetis a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
157129203Scognetsignaling NaN, the invalid exception is raised.
158129203Scognet-------------------------------------------------------------------------------
159129203Scognet*/
160129203Scognetstatic float32 propagateFloat32NaN( float32 a, float32 b )
161129203Scognet{
162129203Scognet    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
163129203Scognet
164129203Scognet    aIsNaN = float32_is_nan( a );
165129203Scognet    aIsSignalingNaN = float32_is_signaling_nan( a );
166129203Scognet    bIsNaN = float32_is_nan( b );
167129203Scognet    bIsSignalingNaN = float32_is_signaling_nan( b );
168129203Scognet    a |= 0x00400000;
169129203Scognet    b |= 0x00400000;
170129203Scognet    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
171129203Scognet    if ( aIsNaN ) {
172129203Scognet        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
173129203Scognet    }
174129203Scognet    else {
175129203Scognet        return b;
176129203Scognet    }
177129203Scognet
178129203Scognet}
179129203Scognet
180129203Scognet/*
181129203Scognet-------------------------------------------------------------------------------
182129203ScognetThe pattern for a default generated double-precision NaN.
183129203Scognet-------------------------------------------------------------------------------
184129203Scognet*/
185129203Scognet#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
186129203Scognet
187129203Scognet/*
188129203Scognet-------------------------------------------------------------------------------
189129203ScognetReturns 1 if the double-precision floating-point value `a' is a NaN;
190129203Scognetotherwise returns 0.
191129203Scognet-------------------------------------------------------------------------------
192129203Scognet*/
193129203Scognet#ifdef SOFTFLOAT_FOR_GCC
194129203Scognetstatic
195129203Scognet#endif
196129203Scognetflag float64_is_nan( float64 a )
197129203Scognet{
198129203Scognet
199129203Scognet    return ( LIT64( 0xFFE0000000000000 ) <
200129203Scognet	     (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
201129203Scognet
202129203Scognet}
203129203Scognet
204129203Scognet/*
205129203Scognet-------------------------------------------------------------------------------
206129203ScognetReturns 1 if the double-precision floating-point value `a' is a signaling
207129203ScognetNaN; otherwise returns 0.
208129203Scognet-------------------------------------------------------------------------------
209129203Scognet*/
210129203Scognet#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC)
211129203Scognetstatic
212129203Scognet#endif
213129203Scognetflag float64_is_signaling_nan( float64 a )
214129203Scognet{
215129203Scognet
216129203Scognet    return
217129203Scognet           ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
218129203Scognet        && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
219129203Scognet
220129203Scognet}
221129203Scognet
222129203Scognet/*
223129203Scognet-------------------------------------------------------------------------------
224129203ScognetReturns the result of converting the double-precision floating-point NaN
225129203Scognet`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
226129203Scognetexception is raised.
227129203Scognet-------------------------------------------------------------------------------
228129203Scognet*/
229129203Scognetstatic commonNaNT float64ToCommonNaN( float64 a )
230129203Scognet{
231129203Scognet    commonNaNT z;
232129203Scognet
233129203Scognet    if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
234129203Scognet    z.sign = FLOAT64_DEMANGLE(a)>>63;
235129203Scognet    z.low = 0;
236129203Scognet    z.high = FLOAT64_DEMANGLE(a)<<12;
237129203Scognet    return z;
238129203Scognet
239129203Scognet}
240129203Scognet
241129203Scognet/*
242129203Scognet-------------------------------------------------------------------------------
243129203ScognetReturns the result of converting the canonical NaN `a' to the double-
244129203Scognetprecision floating-point format.
245129203Scognet-------------------------------------------------------------------------------
246129203Scognet*/
247129203Scognetstatic float64 commonNaNToFloat64( commonNaNT a )
248129203Scognet{
249129203Scognet
250129203Scognet    return FLOAT64_MANGLE(
251129203Scognet	( ( (bits64) a.sign )<<63 )
252129203Scognet        | LIT64( 0x7FF8000000000000 )
253129203Scognet        | ( a.high>>12 ) );
254129203Scognet
255129203Scognet}
256129203Scognet
257129203Scognet/*
258129203Scognet-------------------------------------------------------------------------------
259129203ScognetTakes two double-precision floating-point values `a' and `b', one of which
260129203Scognetis a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
261129203Scognetsignaling NaN, the invalid exception is raised.
262129203Scognet-------------------------------------------------------------------------------
263129203Scognet*/
264129203Scognetstatic float64 propagateFloat64NaN( float64 a, float64 b )
265129203Scognet{
266129203Scognet    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
267129203Scognet
268129203Scognet    aIsNaN = float64_is_nan( a );
269129203Scognet    aIsSignalingNaN = float64_is_signaling_nan( a );
270129203Scognet    bIsNaN = float64_is_nan( b );
271129203Scognet    bIsSignalingNaN = float64_is_signaling_nan( b );
272129203Scognet    a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
273129203Scognet    b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
274129203Scognet    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
275129203Scognet    if ( aIsNaN ) {
276129203Scognet        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
277129203Scognet    }
278129203Scognet    else {
279129203Scognet        return b;
280129203Scognet    }
281129203Scognet
282129203Scognet}
283129203Scognet
284129203Scognet#ifdef FLOATX80
285129203Scognet
286129203Scognet/*
287129203Scognet-------------------------------------------------------------------------------
288129203ScognetThe pattern for a default generated extended double-precision NaN.  The
289129203Scognet`high' and `low' values hold the most- and least-significant bits,
290129203Scognetrespectively.
291129203Scognet-------------------------------------------------------------------------------
292129203Scognet*/
293129203Scognet#define floatx80_default_nan_high 0xFFFF
294129203Scognet#define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
295129203Scognet
296129203Scognet/*
297129203Scognet-------------------------------------------------------------------------------
298129203ScognetReturns 1 if the extended double-precision floating-point value `a' is a
299129203ScognetNaN; otherwise returns 0.
300129203Scognet-------------------------------------------------------------------------------
301129203Scognet*/
302129203Scognetflag floatx80_is_nan( floatx80 a )
303129203Scognet{
304129203Scognet
305129203Scognet    return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
306129203Scognet
307129203Scognet}
308129203Scognet
309129203Scognet/*
310129203Scognet-------------------------------------------------------------------------------
311129203ScognetReturns 1 if the extended double-precision floating-point value `a' is a
312129203Scognetsignaling NaN; otherwise returns 0.
313129203Scognet-------------------------------------------------------------------------------
314129203Scognet*/
315129203Scognetflag floatx80_is_signaling_nan( floatx80 a )
316129203Scognet{
317129203Scognet    bits64 aLow;
318129203Scognet
319129203Scognet    aLow = a.low & ~ LIT64( 0x4000000000000000 );
320129203Scognet    return
321129203Scognet           ( ( a.high & 0x7FFF ) == 0x7FFF )
322129203Scognet        && (bits64) ( aLow<<1 )
323129203Scognet        && ( a.low == aLow );
324129203Scognet
325129203Scognet}
326129203Scognet
327129203Scognet/*
328129203Scognet-------------------------------------------------------------------------------
329129203ScognetReturns the result of converting the extended double-precision floating-
330129203Scognetpoint NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
331129203Scognetinvalid exception is raised.
332129203Scognet-------------------------------------------------------------------------------
333129203Scognet*/
334129203Scognetstatic commonNaNT floatx80ToCommonNaN( floatx80 a )
335129203Scognet{
336129203Scognet    commonNaNT z;
337129203Scognet
338129203Scognet    if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
339129203Scognet    z.sign = a.high>>15;
340129203Scognet    z.low = 0;
341129203Scognet    z.high = a.low<<1;
342129203Scognet    return z;
343129203Scognet
344129203Scognet}
345129203Scognet
346129203Scognet/*
347129203Scognet-------------------------------------------------------------------------------
348129203ScognetReturns the result of converting the canonical NaN `a' to the extended
349129203Scognetdouble-precision floating-point format.
350129203Scognet-------------------------------------------------------------------------------
351129203Scognet*/
352129203Scognetstatic floatx80 commonNaNToFloatx80( commonNaNT a )
353129203Scognet{
354129203Scognet    floatx80 z;
355129203Scognet
356129203Scognet    z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
357129203Scognet    z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
358129203Scognet    return z;
359129203Scognet
360129203Scognet}
361129203Scognet
362129203Scognet/*
363129203Scognet-------------------------------------------------------------------------------
364129203ScognetTakes two extended double-precision floating-point values `a' and `b', one
365129203Scognetof which is a NaN, and returns the appropriate NaN result.  If either `a' or
366129203Scognet`b' is a signaling NaN, the invalid exception is raised.
367129203Scognet-------------------------------------------------------------------------------
368129203Scognet*/
369129203Scognetstatic floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
370129203Scognet{
371129203Scognet    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
372129203Scognet
373129203Scognet    aIsNaN = floatx80_is_nan( a );
374129203Scognet    aIsSignalingNaN = floatx80_is_signaling_nan( a );
375129203Scognet    bIsNaN = floatx80_is_nan( b );
376129203Scognet    bIsSignalingNaN = floatx80_is_signaling_nan( b );
377129203Scognet    a.low |= LIT64( 0xC000000000000000 );
378129203Scognet    b.low |= LIT64( 0xC000000000000000 );
379129203Scognet    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
380129203Scognet    if ( aIsNaN ) {
381129203Scognet        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
382129203Scognet    }
383129203Scognet    else {
384129203Scognet        return b;
385129203Scognet    }
386129203Scognet
387129203Scognet}
388129203Scognet
389129203Scognet#endif
390129203Scognet
391129203Scognet#ifdef FLOAT128
392129203Scognet
393129203Scognet/*
394129203Scognet-------------------------------------------------------------------------------
395129203ScognetThe pattern for a default generated quadruple-precision NaN.  The `high' and
396129203Scognet`low' values hold the most- and least-significant bits, respectively.
397129203Scognet-------------------------------------------------------------------------------
398129203Scognet*/
399129203Scognet#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
400129203Scognet#define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
401129203Scognet
402129203Scognet/*
403129203Scognet-------------------------------------------------------------------------------
404129203ScognetReturns 1 if the quadruple-precision floating-point value `a' is a NaN;
405129203Scognetotherwise returns 0.
406129203Scognet-------------------------------------------------------------------------------
407129203Scognet*/
408129203Scognetflag float128_is_nan( float128 a )
409129203Scognet{
410129203Scognet
411129203Scognet    return
412129203Scognet           ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
413129203Scognet        && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
414129203Scognet
415129203Scognet}
416129203Scognet
417129203Scognet/*
418129203Scognet-------------------------------------------------------------------------------
419129203ScognetReturns 1 if the quadruple-precision floating-point value `a' is a
420129203Scognetsignaling NaN; otherwise returns 0.
421129203Scognet-------------------------------------------------------------------------------
422129203Scognet*/
423129203Scognetflag float128_is_signaling_nan( float128 a )
424129203Scognet{
425129203Scognet
426129203Scognet    return
427129203Scognet           ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
428129203Scognet        && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
429129203Scognet
430129203Scognet}
431129203Scognet
432129203Scognet/*
433129203Scognet-------------------------------------------------------------------------------
434129203ScognetReturns the result of converting the quadruple-precision floating-point NaN
435129203Scognet`a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
436129203Scognetexception is raised.
437129203Scognet-------------------------------------------------------------------------------
438129203Scognet*/
439129203Scognetstatic commonNaNT float128ToCommonNaN( float128 a )
440129203Scognet{
441129203Scognet    commonNaNT z;
442129203Scognet
443129203Scognet    if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
444129203Scognet    z.sign = a.high>>63;
445129203Scognet    shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
446129203Scognet    return z;
447129203Scognet
448129203Scognet}
449129203Scognet
450129203Scognet/*
451129203Scognet-------------------------------------------------------------------------------
452129203ScognetReturns the result of converting the canonical NaN `a' to the quadruple-
453129203Scognetprecision floating-point format.
454129203Scognet-------------------------------------------------------------------------------
455129203Scognet*/
456129203Scognetstatic float128 commonNaNToFloat128( commonNaNT a )
457129203Scognet{
458129203Scognet    float128 z;
459129203Scognet
460129203Scognet    shift128Right( a.high, a.low, 16, &z.high, &z.low );
461129203Scognet    z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
462129203Scognet    return z;
463129203Scognet
464129203Scognet}
465129203Scognet
466129203Scognet/*
467129203Scognet-------------------------------------------------------------------------------
468129203ScognetTakes two quadruple-precision floating-point values `a' and `b', one of
469129203Scognetwhich is a NaN, and returns the appropriate NaN result.  If either `a' or
470129203Scognet`b' is a signaling NaN, the invalid exception is raised.
471129203Scognet-------------------------------------------------------------------------------
472129203Scognet*/
473129203Scognetstatic float128 propagateFloat128NaN( float128 a, float128 b )
474129203Scognet{
475129203Scognet    flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
476129203Scognet
477129203Scognet    aIsNaN = float128_is_nan( a );
478129203Scognet    aIsSignalingNaN = float128_is_signaling_nan( a );
479129203Scognet    bIsNaN = float128_is_nan( b );
480129203Scognet    bIsSignalingNaN = float128_is_signaling_nan( b );
481129203Scognet    a.high |= LIT64( 0x0000800000000000 );
482129203Scognet    b.high |= LIT64( 0x0000800000000000 );
483129203Scognet    if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
484129203Scognet    if ( aIsNaN ) {
485129203Scognet        return ( aIsSignalingNaN & bIsNaN ) ? b : a;
486129203Scognet    }
487129203Scognet    else {
488129203Scognet        return b;
489129203Scognet    }
490129203Scognet
491129203Scognet}
492129203Scognet
493129203Scognet#endif
494129203Scognet
495