File: /usr/src/linux/arch/arm/nwfpe/softfloat-specialize

1     
2     /*
3     ===============================================================================
4     
5     This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
6     Arithmetic Package, Release 2.
7     
8     Written by John R. Hauser.  This work was made possible in part by the
9     International Computer Science Institute, located at Suite 600, 1947 Center
10     Street, Berkeley, California 94704.  Funding was partially provided by the
11     National Science Foundation under grant MIP-9311980.  The original version
12     of this code was written as part of a project to build a fixed-point vector
13     processor in collaboration with the University of California at Berkeley,
14     overseen by Profs. Nelson Morgan and John Wawrzynek.  More information
15     is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
16     arithmetic/softfloat.html'.
17     
18     THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE.  Although reasonable effort
19     has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
20     TIMES RESULT IN INCORRECT BEHAVIOR.  USE OF THIS SOFTWARE IS RESTRICTED TO
21     PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
22     AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
23     
24     Derivative works are acceptable, even for commercial purposes, so long as
25     (1) they include prominent notice that the work is derivative, and (2) they
26     include prominent notice akin to these three paragraphs for those parts of
27     this code that are retained.
28     
29     ===============================================================================
30     */
31     
32     /*
33     -------------------------------------------------------------------------------
34     Underflow tininess-detection mode, statically initialized to default value.
35     (The declaration in `softfloat.h' must match the `int8' type here.)
36     -------------------------------------------------------------------------------
37     */
38     int8 float_detect_tininess = float_tininess_after_rounding;
39     
40     /*
41     -------------------------------------------------------------------------------
42     Raises the exceptions specified by `flags'.  Floating-point traps can be
43     defined here if desired.  It is currently not possible for such a trap to
44     substitute a result value.  If traps are not implemented, this routine
45     should be simply `float_exception_flags |= flags;'.
46     
47     ScottB:  November 4, 1998
48     Moved this function out of softfloat-specialize into fpmodule.c.
49     This effectively isolates all the changes required for integrating with the
50     Linux kernel into fpmodule.c.  Porting to NetBSD should only require modifying
51     fpmodule.c to integrate with the NetBSD kernel (I hope!).
52     -------------------------------------------------------------------------------
53     void float_raise( int8 flags )
54     {
55         float_exception_flags |= flags;
56     }
57     */
58     
59     /*
60     -------------------------------------------------------------------------------
61     Internal canonical NaN format.
62     -------------------------------------------------------------------------------
63     */
64     typedef struct {
65         flag sign;
66         bits64 high, low;
67     } commonNaNT;
68     
69     /*
70     -------------------------------------------------------------------------------
71     The pattern for a default generated single-precision NaN.
72     -------------------------------------------------------------------------------
73     */
74     #define float32_default_nan 0xFFFFFFFF
75     
76     /*
77     -------------------------------------------------------------------------------
78     Returns 1 if the single-precision floating-point value `a' is a NaN;
79     otherwise returns 0.
80     -------------------------------------------------------------------------------
81     */
82     flag float32_is_nan( float32 a )
83     {
84     
85         return ( 0xFF000000 < (bits32) ( a<<1 ) );
86     
87     }
88     
89     /*
90     -------------------------------------------------------------------------------
91     Returns 1 if the single-precision floating-point value `a' is a signaling
92     NaN; otherwise returns 0.
93     -------------------------------------------------------------------------------
94     */
95     flag float32_is_signaling_nan( float32 a )
96     {
97     
98         return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
99     
100     }
101     
102     /*
103     -------------------------------------------------------------------------------
104     Returns the result of converting the single-precision floating-point NaN
105     `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
106     exception is raised.
107     -------------------------------------------------------------------------------
108     */
109     static commonNaNT float32ToCommonNaN( float32 a )
110     {
111         commonNaNT z;
112     
113         if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
114         z.sign = a>>31;
115         z.low = 0;
116         z.high = ( (bits64) a )<<41;
117         return z;
118     
119     }
120     
121     /*
122     -------------------------------------------------------------------------------
123     Returns the result of converting the canonical NaN `a' to the single-
124     precision floating-point format.
125     -------------------------------------------------------------------------------
126     */
127     static float32 commonNaNToFloat32( commonNaNT a )
128     {
129     
130         return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
131     
132     }
133     
134     /*
135     -------------------------------------------------------------------------------
136     Takes two single-precision floating-point values `a' and `b', one of which
137     is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
138     signaling NaN, the invalid exception is raised.
139     -------------------------------------------------------------------------------
140     */
141     static float32 propagateFloat32NaN( float32 a, float32 b )
142     {
143         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
144     
145         aIsNaN = float32_is_nan( a );
146         aIsSignalingNaN = float32_is_signaling_nan( a );
147         bIsNaN = float32_is_nan( b );
148         bIsSignalingNaN = float32_is_signaling_nan( b );
149         a |= 0x00400000;
150         b |= 0x00400000;
151         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
152         if ( aIsNaN ) {
153             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
154         }
155         else {
156             return b;
157         }
158     
159     }
160     
161     /*
162     -------------------------------------------------------------------------------
163     The pattern for a default generated double-precision NaN.
164     -------------------------------------------------------------------------------
165     */
166     #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
167     
168     /*
169     -------------------------------------------------------------------------------
170     Returns 1 if the double-precision floating-point value `a' is a NaN;
171     otherwise returns 0.
172     -------------------------------------------------------------------------------
173     */
174     flag float64_is_nan( float64 a )
175     {
176     
177         return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
178     
179     }
180     
181     /*
182     -------------------------------------------------------------------------------
183     Returns 1 if the double-precision floating-point value `a' is a signaling
184     NaN; otherwise returns 0.
185     -------------------------------------------------------------------------------
186     */
187     flag float64_is_signaling_nan( float64 a )
188     {
189     
190         return
191                ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
192             && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
193     
194     }
195     
196     /*
197     -------------------------------------------------------------------------------
198     Returns the result of converting the double-precision floating-point NaN
199     `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
200     exception is raised.
201     -------------------------------------------------------------------------------
202     */
203     static commonNaNT float64ToCommonNaN( float64 a )
204     {
205         commonNaNT z;
206     
207         if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
208         z.sign = a>>63;
209         z.low = 0;
210         z.high = a<<12;
211         return z;
212     
213     }
214     
215     /*
216     -------------------------------------------------------------------------------
217     Returns the result of converting the canonical NaN `a' to the double-
218     precision floating-point format.
219     -------------------------------------------------------------------------------
220     */
221     static float64 commonNaNToFloat64( commonNaNT a )
222     {
223     
224         return
225               ( ( (bits64) a.sign )<<63 )
226             | LIT64( 0x7FF8000000000000 )
227             | ( a.high>>12 );
228     
229     }
230     
231     /*
232     -------------------------------------------------------------------------------
233     Takes two double-precision floating-point values `a' and `b', one of which
234     is a NaN, and returns the appropriate NaN result.  If either `a' or `b' is a
235     signaling NaN, the invalid exception is raised.
236     -------------------------------------------------------------------------------
237     */
238     static float64 propagateFloat64NaN( float64 a, float64 b )
239     {
240         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
241     
242         aIsNaN = float64_is_nan( a );
243         aIsSignalingNaN = float64_is_signaling_nan( a );
244         bIsNaN = float64_is_nan( b );
245         bIsSignalingNaN = float64_is_signaling_nan( b );
246         a |= LIT64( 0x0008000000000000 );
247         b |= LIT64( 0x0008000000000000 );
248         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
249         if ( aIsNaN ) {
250             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
251         }
252         else {
253             return b;
254         }
255     
256     }
257     
258     #ifdef FLOATX80
259     
260     /*
261     -------------------------------------------------------------------------------
262     The pattern for a default generated extended double-precision NaN.  The
263     `high' and `low' values hold the most- and least-significant bits,
264     respectively.
265     -------------------------------------------------------------------------------
266     */
267     #define floatx80_default_nan_high 0xFFFF
268     #define floatx80_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
269     
270     /*
271     -------------------------------------------------------------------------------
272     Returns 1 if the extended double-precision floating-point value `a' is a
273     NaN; otherwise returns 0.
274     -------------------------------------------------------------------------------
275     */
276     flag floatx80_is_nan( floatx80 a )
277     {
278     
279         return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
280     
281     }
282     
283     /*
284     -------------------------------------------------------------------------------
285     Returns 1 if the extended double-precision floating-point value `a' is a
286     signaling NaN; otherwise returns 0.
287     -------------------------------------------------------------------------------
288     */
289     flag floatx80_is_signaling_nan( floatx80 a )
290     {
291         //register int lr;
292         bits64 aLow;
293     
294         //__asm__("mov %0, lr" : : "g" (lr));
295         //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr);
296         aLow = a.low & ~ LIT64( 0x4000000000000000 );
297         return
298                ( ( a.high & 0x7FFF ) == 0x7FFF )
299             && (bits64) ( aLow<<1 )
300             && ( a.low == aLow );
301     
302     }
303     
304     /*
305     -------------------------------------------------------------------------------
306     Returns the result of converting the extended double-precision floating-
307     point NaN `a' to the canonical NaN format.  If `a' is a signaling NaN, the
308     invalid exception is raised.
309     -------------------------------------------------------------------------------
310     */
311     static commonNaNT floatx80ToCommonNaN( floatx80 a )
312     {
313         commonNaNT z;
314     
315         if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
316         z.sign = a.high>>15;
317         z.low = 0;
318         z.high = a.low<<1;
319         return z;
320     
321     }
322     
323     /*
324     -------------------------------------------------------------------------------
325     Returns the result of converting the canonical NaN `a' to the extended
326     double-precision floating-point format.
327     -------------------------------------------------------------------------------
328     */
329     static floatx80 commonNaNToFloatx80( commonNaNT a )
330     {
331         floatx80 z;
332     
333         z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
334         z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
335         return z;
336     
337     }
338     
339     /*
340     -------------------------------------------------------------------------------
341     Takes two extended double-precision floating-point values `a' and `b', one
342     of which is a NaN, and returns the appropriate NaN result.  If either `a' or
343     `b' is a signaling NaN, the invalid exception is raised.
344     -------------------------------------------------------------------------------
345     */
346     static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
347     {
348         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
349     
350         aIsNaN = floatx80_is_nan( a );
351         aIsSignalingNaN = floatx80_is_signaling_nan( a );
352         bIsNaN = floatx80_is_nan( b );
353         bIsSignalingNaN = floatx80_is_signaling_nan( b );
354         a.low |= LIT64( 0xC000000000000000 );
355         b.low |= LIT64( 0xC000000000000000 );
356         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
357         if ( aIsNaN ) {
358             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
359         }
360         else {
361             return b;
362         }
363     
364     }
365     
366     #endif
367     
368     #ifdef FLOAT128
369     
370     /*
371     -------------------------------------------------------------------------------
372     The pattern for a default generated quadruple-precision NaN.  The `high' and
373     `low' values hold the most- and least-significant bits, respectively.
374     -------------------------------------------------------------------------------
375     */
376     #define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
377     #define float128_default_nan_low  LIT64( 0xFFFFFFFFFFFFFFFF )
378     
379     /*
380     -------------------------------------------------------------------------------
381     Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
382     otherwise returns 0.
383     -------------------------------------------------------------------------------
384     */
385     flag float128_is_nan( float128 a )
386     {
387     
388         return
389                ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
390             && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
391     
392     }
393     
394     /*
395     -------------------------------------------------------------------------------
396     Returns 1 if the quadruple-precision floating-point value `a' is a
397     signaling NaN; otherwise returns 0.
398     -------------------------------------------------------------------------------
399     */
400     flag float128_is_signaling_nan( float128 a )
401     {
402     
403         return
404                ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
405             && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
406     
407     }
408     
409     /*
410     -------------------------------------------------------------------------------
411     Returns the result of converting the quadruple-precision floating-point NaN
412     `a' to the canonical NaN format.  If `a' is a signaling NaN, the invalid
413     exception is raised.
414     -------------------------------------------------------------------------------
415     */
416     static commonNaNT float128ToCommonNaN( float128 a )
417     {
418         commonNaNT z;
419     
420         if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
421         z.sign = a.high>>63;
422         shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
423         return z;
424     
425     }
426     
427     /*
428     -------------------------------------------------------------------------------
429     Returns the result of converting the canonical NaN `a' to the quadruple-
430     precision floating-point format.
431     -------------------------------------------------------------------------------
432     */
433     static float128 commonNaNToFloat128( commonNaNT a )
434     {
435         float128 z;
436     
437         shift128Right( a.high, a.low, 16, &z.high, &z.low );
438         z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
439         return z;
440     
441     }
442     
443     /*
444     -------------------------------------------------------------------------------
445     Takes two quadruple-precision floating-point values `a' and `b', one of
446     which is a NaN, and returns the appropriate NaN result.  If either `a' or
447     `b' is a signaling NaN, the invalid exception is raised.
448     -------------------------------------------------------------------------------
449     */
450     static float128 propagateFloat128NaN( float128 a, float128 b )
451     {
452         flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
453     
454         aIsNaN = float128_is_nan( a );
455         aIsSignalingNaN = float128_is_signaling_nan( a );
456         bIsNaN = float128_is_nan( b );
457         bIsSignalingNaN = float128_is_signaling_nan( b );
458         a.high |= LIT64( 0x0000800000000000 );
459         b.high |= LIT64( 0x0000800000000000 );
460         if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
461         if ( aIsNaN ) {
462             return ( aIsSignalingNaN & bIsNaN ) ? b : a;
463         }
464         else {
465             return b;
466         }
467     
468     }
469     
470     #endif
471     
472