1 2/* 3=============================================================================== 4 5This C source fragment is part of the SoftFloat IEC/IEEE Floating-point 6Arithmetic Package, Release 2. 7 8Written by John R. Hauser. This work was made possible in part by the 9International Computer Science Institute, located at Suite 600, 1947 Center 10Street, Berkeley, California 94704. Funding was partially provided by the 11National Science Foundation under grant MIP-9311980. The original version 12of this code was written as part of a project to build a fixed-point vector 13processor in collaboration with the University of California at Berkeley, 14overseen by Profs. Nelson Morgan and John Wawrzynek. More information 15is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ 16arithmetic/softfloat.html'. 17 18THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 19has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 20TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 21PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 22AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 23 24Derivative works are acceptable, even for commercial purposes, so long as 25(1) they include prominent notice that the work is derivative, and (2) they 26include prominent notice akin to these three paragraphs for those parts of 27this code that are retained. 28 29=============================================================================== 30*/ 31 32/* 33------------------------------------------------------------------------------- 34Underflow tininess-detection mode, statically initialized to default value. 35(The declaration in `softfloat.h' must match the `int8' type here.) 36------------------------------------------------------------------------------- 37*/ 38int8 float_detect_tininess = float_tininess_after_rounding; 39 40/* 41------------------------------------------------------------------------------- 42Raises the exceptions specified by `flags'. Floating-point traps can be 43defined here if desired. It is currently not possible for such a trap to 44substitute a result value. If traps are not implemented, this routine 45should be simply `float_exception_flags |= flags;'. 46 47ScottB: November 4, 1998 48Moved this function out of softfloat-specialize into fpmodule.c. 49This effectively isolates all the changes required for integrating with the 50Linux kernel into fpmodule.c. Porting to NetBSD should only require modifying 51fpmodule.c to integrate with the NetBSD kernel (I hope!). 52------------------------------------------------------------------------------- 53void float_raise( int8 flags ) 54{ 55 float_exception_flags |= flags; 56} 57*/ 58 59/* 60------------------------------------------------------------------------------- 61Internal canonical NaN format. 62------------------------------------------------------------------------------- 63*/ 64typedef struct { 65 flag sign; 66 bits64 high, low; 67} commonNaNT; 68 69/* 70------------------------------------------------------------------------------- 71The pattern for a default generated single-precision NaN. 72------------------------------------------------------------------------------- 73*/ 74#define float32_default_nan 0xFFFFFFFF 75 76/* 77------------------------------------------------------------------------------- 78Returns 1 if the single-precision floating-point value `a' is a NaN; 79otherwise returns 0. 80------------------------------------------------------------------------------- 81*/ 82flag float32_is_nan( float32 a ) 83{ 84 85 return ( 0xFF000000 < (bits32) ( a<<1 ) ); 86 87} 88 89/* 90------------------------------------------------------------------------------- 91Returns 1 if the single-precision floating-point value `a' is a signaling 92NaN; otherwise returns 0. 93------------------------------------------------------------------------------- 94*/ 95flag float32_is_signaling_nan( float32 a ) 96{ 97 98 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 99 100} 101 102/* 103------------------------------------------------------------------------------- 104Returns 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 106exception is raised. 107------------------------------------------------------------------------------- 108*/ 109static 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------------------------------------------------------------------------------- 123Returns the result of converting the canonical NaN `a' to the single- 124precision floating-point format. 125------------------------------------------------------------------------------- 126*/ 127static float32 commonNaNToFloat32( commonNaNT a ) 128{ 129 130 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 131 132} 133 134/* 135------------------------------------------------------------------------------- 136Takes two single-precision floating-point values `a' and `b', one of which 137is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 138signaling NaN, the invalid exception is raised. 139------------------------------------------------------------------------------- 140*/ 141static 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------------------------------------------------------------------------------- 163The pattern for a default generated double-precision NaN. 164------------------------------------------------------------------------------- 165*/ 166#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 167 168/* 169------------------------------------------------------------------------------- 170Returns 1 if the double-precision floating-point value `a' is a NaN; 171otherwise returns 0. 172------------------------------------------------------------------------------- 173*/ 174flag float64_is_nan( float64 a ) 175{ 176 177 return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); 178 179} 180 181/* 182------------------------------------------------------------------------------- 183Returns 1 if the double-precision floating-point value `a' is a signaling 184NaN; otherwise returns 0. 185------------------------------------------------------------------------------- 186*/ 187flag float64_is_signaling_nan( float64 a ) 188{ 189 190 return 191 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) 192 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); 193 194} 195 196/* 197------------------------------------------------------------------------------- 198Returns 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 200exception is raised. 201------------------------------------------------------------------------------- 202*/ 203static 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------------------------------------------------------------------------------- 217Returns the result of converting the canonical NaN `a' to the double- 218precision floating-point format. 219------------------------------------------------------------------------------- 220*/ 221static 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------------------------------------------------------------------------------- 233Takes two double-precision floating-point values `a' and `b', one of which 234is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 235signaling NaN, the invalid exception is raised. 236------------------------------------------------------------------------------- 237*/ 238static 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------------------------------------------------------------------------------- 262The pattern for a default generated extended double-precision NaN. The 263`high' and `low' values hold the most- and least-significant bits, 264respectively. 265------------------------------------------------------------------------------- 266*/ 267#define floatx80_default_nan_high 0xFFFF 268#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 269 270/* 271------------------------------------------------------------------------------- 272Returns 1 if the extended double-precision floating-point value `a' is a 273NaN; otherwise returns 0. 274------------------------------------------------------------------------------- 275*/ 276flag floatx80_is_nan( floatx80 a ) 277{ 278 279 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 280 281} 282 283/* 284------------------------------------------------------------------------------- 285Returns 1 if the extended double-precision floating-point value `a' is a 286signaling NaN; otherwise returns 0. 287------------------------------------------------------------------------------- 288*/ 289flag 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------------------------------------------------------------------------------- 306Returns the result of converting the extended double-precision floating- 307point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 308invalid exception is raised. 309------------------------------------------------------------------------------- 310*/ 311static 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------------------------------------------------------------------------------- 325Returns the result of converting the canonical NaN `a' to the extended 326double-precision floating-point format. 327------------------------------------------------------------------------------- 328*/ 329static 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 z.__padding = 0; 336 return z; 337 338} 339 340/* 341------------------------------------------------------------------------------- 342Takes two extended double-precision floating-point values `a' and `b', one 343of which is a NaN, and returns the appropriate NaN result. If either `a' or 344`b' is a signaling NaN, the invalid exception is raised. 345------------------------------------------------------------------------------- 346*/ 347static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 348{ 349 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 350 351 aIsNaN = floatx80_is_nan( a ); 352 aIsSignalingNaN = floatx80_is_signaling_nan( a ); 353 bIsNaN = floatx80_is_nan( b ); 354 bIsSignalingNaN = floatx80_is_signaling_nan( b ); 355 a.low |= LIT64( 0xC000000000000000 ); 356 b.low |= LIT64( 0xC000000000000000 ); 357 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 358 if ( aIsNaN ) { 359 return ( aIsSignalingNaN & bIsNaN ) ? b : a; 360 } 361 else { 362 return b; 363 } 364 365} 366 367#endif 368