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