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