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 16 http://www.jhauser.us/arithmetic/SoftFloat-2b/SoftFloat-source.txt 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 z.__padding = 0; 336 return z; 337 338 } 339 340 /* 341 ------------------------------------------------------------------------------- 342 Takes two extended double-precision floating-point values `a' and `b', one 343 of 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 */ 347 static 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
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.