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