3 ===============================================================================
5 This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
6 Arithmetic Package, Release 2.
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'.
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.
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.
29 ===============================================================================
33 -------------------------------------------------------------------------------
34 Underflow tininess-detection mode, statically initialized to default value.
35 (The declaration in `softfloat.h' must match the `int8' type here.)
36 -------------------------------------------------------------------------------
38 int8 float_detect_tininess = float_tininess_after_rounding;
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;'.
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 )
55 float_exception_flags |= flags;
60 -------------------------------------------------------------------------------
61 Internal canonical NaN format.
62 -------------------------------------------------------------------------------
70 -------------------------------------------------------------------------------
71 The pattern for a default generated single-precision NaN.
72 -------------------------------------------------------------------------------
74 #define float32_default_nan 0xFFFFFFFF
77 -------------------------------------------------------------------------------
78 Returns 1 if the single-precision floating-point value `a' is a NaN;
80 -------------------------------------------------------------------------------
82 flag float32_is_nan( float32 a )
85 return ( 0xFF000000 < (bits32) ( a<<1 ) );
90 -------------------------------------------------------------------------------
91 Returns 1 if the single-precision floating-point value `a' is a signaling
92 NaN; otherwise returns 0.
93 -------------------------------------------------------------------------------
95 flag float32_is_signaling_nan( float32 a )
98 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
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
107 -------------------------------------------------------------------------------
109 static commonNaNT float32ToCommonNaN( float32 a )
113 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
116 z.high = ( (bits64) a )<<41;
122 -------------------------------------------------------------------------------
123 Returns the result of converting the canonical NaN `a' to the single-
124 precision floating-point format.
125 -------------------------------------------------------------------------------
127 static float32 commonNaNToFloat32( commonNaNT a )
130 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
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 -------------------------------------------------------------------------------
141 static float32 propagateFloat32NaN( float32 a, float32 b )
143 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
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 );
151 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
153 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
162 -------------------------------------------------------------------------------
163 The pattern for a default generated double-precision NaN.
164 -------------------------------------------------------------------------------
166 #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
169 -------------------------------------------------------------------------------
170 Returns 1 if the double-precision floating-point value `a' is a NaN;
172 -------------------------------------------------------------------------------
174 flag float64_is_nan( float64 a )
177 return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
182 -------------------------------------------------------------------------------
183 Returns 1 if the double-precision floating-point value `a' is a signaling
184 NaN; otherwise returns 0.
185 -------------------------------------------------------------------------------
187 flag float64_is_signaling_nan( float64 a )
191 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
192 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
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
201 -------------------------------------------------------------------------------
203 static commonNaNT float64ToCommonNaN( float64 a )
207 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
216 -------------------------------------------------------------------------------
217 Returns the result of converting the canonical NaN `a' to the double-
218 precision floating-point format.
219 -------------------------------------------------------------------------------
221 static float64 commonNaNToFloat64( commonNaNT a )
225 ( ( (bits64) a.sign )<<63 )
226 | LIT64( 0x7FF8000000000000 )
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 -------------------------------------------------------------------------------
238 static float64 propagateFloat64NaN( float64 a, float64 b )
240 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
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 );
250 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
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,
265 -------------------------------------------------------------------------------
267 #define floatx80_default_nan_high 0xFFFF
268 #define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
271 -------------------------------------------------------------------------------
272 Returns 1 if the extended double-precision floating-point value `a' is a
273 NaN; otherwise returns 0.
274 -------------------------------------------------------------------------------
276 flag floatx80_is_nan( floatx80 a )
279 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
284 -------------------------------------------------------------------------------
285 Returns 1 if the extended double-precision floating-point value `a' is a
286 signaling NaN; otherwise returns 0.
287 -------------------------------------------------------------------------------
289 flag floatx80_is_signaling_nan( floatx80 a )
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 );
298 ( ( a.high & 0x7FFF ) == 0x7FFF )
299 && (bits64) ( aLow<<1 )
300 && ( a.low == aLow );
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 -------------------------------------------------------------------------------
311 static commonNaNT floatx80ToCommonNaN( floatx80 a )
315 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
324 -------------------------------------------------------------------------------
325 Returns the result of converting the canonical NaN `a' to the extended
326 double-precision floating-point format.
327 -------------------------------------------------------------------------------
329 static floatx80 commonNaNToFloatx80( commonNaNT a )
333 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
334 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
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 -------------------------------------------------------------------------------
346 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
348 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
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 );
358 return ( aIsSignalingNaN & bIsNaN ) ? b : a;