0001
0002 /*
0003 ===============================================================================
0004
0005 This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
0006 Arithmetic Package, Release 2.
0007
0008 Written by John R. Hauser. This work was made possible in part by the
0009 International Computer Science Institute, located at Suite 600, 1947 Center
0010 Street, Berkeley, California 94704. Funding was partially provided by the
0011 National Science Foundation under grant MIP-9311980. The original version
0012 of this code was written as part of a project to build a fixed-point vector
0013 processor in collaboration with the University of California at Berkeley,
0014 overseen by Profs. Nelson Morgan and John Wawrzynek. More information
0015 is available through the Web page
0016 http://www.jhauser.us/arithmetic/SoftFloat-2b/SoftFloat-source.txt
0017
0018 THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
0019 has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
0020 TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
0021 PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
0022 AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
0023
0024 Derivative works are acceptable, even for commercial purposes, so long as
0025 (1) they include prominent notice that the work is derivative, and (2) they
0026 include prominent notice akin to these three paragraphs for those parts of
0027 this code that are retained.
0028
0029 ===============================================================================
0030 */
0031
0032 /*
0033 -------------------------------------------------------------------------------
0034 Underflow tininess-detection mode, statically initialized to default value.
0035 (The declaration in `softfloat.h' must match the `int8' type here.)
0036 -------------------------------------------------------------------------------
0037 */
0038 int8 float_detect_tininess = float_tininess_after_rounding;
0039
0040 /*
0041 -------------------------------------------------------------------------------
0042 Raises the exceptions specified by `flags'. Floating-point traps can be
0043 defined here if desired. It is currently not possible for such a trap to
0044 substitute a result value. If traps are not implemented, this routine
0045 should be simply `float_exception_flags |= flags;'.
0046
0047 ScottB: November 4, 1998
0048 Moved this function out of softfloat-specialize into fpmodule.c.
0049 This effectively isolates all the changes required for integrating with the
0050 Linux kernel into fpmodule.c. Porting to NetBSD should only require modifying
0051 fpmodule.c to integrate with the NetBSD kernel (I hope!).
0052 -------------------------------------------------------------------------------
0053 void float_raise( int8 flags )
0054 {
0055 float_exception_flags |= flags;
0056 }
0057 */
0058
0059 /*
0060 -------------------------------------------------------------------------------
0061 Internal canonical NaN format.
0062 -------------------------------------------------------------------------------
0063 */
0064 typedef struct {
0065 flag sign;
0066 bits64 high, low;
0067 } commonNaNT;
0068
0069 /*
0070 -------------------------------------------------------------------------------
0071 The pattern for a default generated single-precision NaN.
0072 -------------------------------------------------------------------------------
0073 */
0074 #define float32_default_nan 0xFFFFFFFF
0075
0076 /*
0077 -------------------------------------------------------------------------------
0078 Returns 1 if the single-precision floating-point value `a' is a NaN;
0079 otherwise returns 0.
0080 -------------------------------------------------------------------------------
0081 */
0082 flag float32_is_nan( float32 a )
0083 {
0084
0085 return ( 0xFF000000 < (bits32) ( a<<1 ) );
0086
0087 }
0088
0089 /*
0090 -------------------------------------------------------------------------------
0091 Returns 1 if the single-precision floating-point value `a' is a signaling
0092 NaN; otherwise returns 0.
0093 -------------------------------------------------------------------------------
0094 */
0095 flag float32_is_signaling_nan( float32 a )
0096 {
0097
0098 return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
0099
0100 }
0101
0102 /*
0103 -------------------------------------------------------------------------------
0104 Returns the result of converting the single-precision floating-point NaN
0105 `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
0106 exception is raised.
0107 -------------------------------------------------------------------------------
0108 */
0109 static commonNaNT float32ToCommonNaN( float32 a )
0110 {
0111 commonNaNT z;
0112
0113 if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
0114 z.sign = a>>31;
0115 z.low = 0;
0116 z.high = ( (bits64) a )<<41;
0117 return z;
0118
0119 }
0120
0121 /*
0122 -------------------------------------------------------------------------------
0123 Returns the result of converting the canonical NaN `a' to the single-
0124 precision floating-point format.
0125 -------------------------------------------------------------------------------
0126 */
0127 static float32 commonNaNToFloat32( commonNaNT a )
0128 {
0129
0130 return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
0131
0132 }
0133
0134 /*
0135 -------------------------------------------------------------------------------
0136 Takes two single-precision floating-point values `a' and `b', one of which
0137 is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
0138 signaling NaN, the invalid exception is raised.
0139 -------------------------------------------------------------------------------
0140 */
0141 static float32 propagateFloat32NaN( float32 a, float32 b )
0142 {
0143 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
0144
0145 aIsNaN = float32_is_nan( a );
0146 aIsSignalingNaN = float32_is_signaling_nan( a );
0147 bIsNaN = float32_is_nan( b );
0148 bIsSignalingNaN = float32_is_signaling_nan( b );
0149 a |= 0x00400000;
0150 b |= 0x00400000;
0151 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
0152 if ( aIsNaN ) {
0153 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
0154 }
0155 else {
0156 return b;
0157 }
0158
0159 }
0160
0161 /*
0162 -------------------------------------------------------------------------------
0163 The pattern for a default generated double-precision NaN.
0164 -------------------------------------------------------------------------------
0165 */
0166 #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
0167
0168 /*
0169 -------------------------------------------------------------------------------
0170 Returns 1 if the double-precision floating-point value `a' is a NaN;
0171 otherwise returns 0.
0172 -------------------------------------------------------------------------------
0173 */
0174 flag float64_is_nan( float64 a )
0175 {
0176
0177 return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
0178
0179 }
0180
0181 /*
0182 -------------------------------------------------------------------------------
0183 Returns 1 if the double-precision floating-point value `a' is a signaling
0184 NaN; otherwise returns 0.
0185 -------------------------------------------------------------------------------
0186 */
0187 flag float64_is_signaling_nan( float64 a )
0188 {
0189
0190 return
0191 ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
0192 && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
0193
0194 }
0195
0196 /*
0197 -------------------------------------------------------------------------------
0198 Returns the result of converting the double-precision floating-point NaN
0199 `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
0200 exception is raised.
0201 -------------------------------------------------------------------------------
0202 */
0203 static commonNaNT float64ToCommonNaN( float64 a )
0204 {
0205 commonNaNT z;
0206
0207 if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
0208 z.sign = a>>63;
0209 z.low = 0;
0210 z.high = a<<12;
0211 return z;
0212
0213 }
0214
0215 /*
0216 -------------------------------------------------------------------------------
0217 Returns the result of converting the canonical NaN `a' to the double-
0218 precision floating-point format.
0219 -------------------------------------------------------------------------------
0220 */
0221 static float64 commonNaNToFloat64( commonNaNT a )
0222 {
0223
0224 return
0225 ( ( (bits64) a.sign )<<63 )
0226 | LIT64( 0x7FF8000000000000 )
0227 | ( a.high>>12 );
0228
0229 }
0230
0231 /*
0232 -------------------------------------------------------------------------------
0233 Takes two double-precision floating-point values `a' and `b', one of which
0234 is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
0235 signaling NaN, the invalid exception is raised.
0236 -------------------------------------------------------------------------------
0237 */
0238 static float64 propagateFloat64NaN( float64 a, float64 b )
0239 {
0240 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
0241
0242 aIsNaN = float64_is_nan( a );
0243 aIsSignalingNaN = float64_is_signaling_nan( a );
0244 bIsNaN = float64_is_nan( b );
0245 bIsSignalingNaN = float64_is_signaling_nan( b );
0246 a |= LIT64( 0x0008000000000000 );
0247 b |= LIT64( 0x0008000000000000 );
0248 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
0249 if ( aIsNaN ) {
0250 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
0251 }
0252 else {
0253 return b;
0254 }
0255
0256 }
0257
0258 #ifdef FLOATX80
0259
0260 /*
0261 -------------------------------------------------------------------------------
0262 The pattern for a default generated extended double-precision NaN. The
0263 `high' and `low' values hold the most- and least-significant bits,
0264 respectively.
0265 -------------------------------------------------------------------------------
0266 */
0267 #define floatx80_default_nan_high 0xFFFF
0268 #define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
0269
0270 /*
0271 -------------------------------------------------------------------------------
0272 Returns 1 if the extended double-precision floating-point value `a' is a
0273 NaN; otherwise returns 0.
0274 -------------------------------------------------------------------------------
0275 */
0276 flag floatx80_is_nan( floatx80 a )
0277 {
0278
0279 return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
0280
0281 }
0282
0283 /*
0284 -------------------------------------------------------------------------------
0285 Returns 1 if the extended double-precision floating-point value `a' is a
0286 signaling NaN; otherwise returns 0.
0287 -------------------------------------------------------------------------------
0288 */
0289 flag floatx80_is_signaling_nan( floatx80 a )
0290 {
0291 //register int lr;
0292 bits64 aLow;
0293
0294 //__asm__("mov %0, lr" : : "g" (lr));
0295 //fp_printk("floatx80_is_signalling_nan() called from 0x%08x\n",lr);
0296 aLow = a.low & ~ LIT64( 0x4000000000000000 );
0297 return
0298 ( ( a.high & 0x7FFF ) == 0x7FFF )
0299 && (bits64) ( aLow<<1 )
0300 && ( a.low == aLow );
0301
0302 }
0303
0304 /*
0305 -------------------------------------------------------------------------------
0306 Returns the result of converting the extended double-precision floating-
0307 point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
0308 invalid exception is raised.
0309 -------------------------------------------------------------------------------
0310 */
0311 static commonNaNT floatx80ToCommonNaN( floatx80 a )
0312 {
0313 commonNaNT z;
0314
0315 if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
0316 z.sign = a.high>>15;
0317 z.low = 0;
0318 z.high = a.low<<1;
0319 return z;
0320
0321 }
0322
0323 /*
0324 -------------------------------------------------------------------------------
0325 Returns the result of converting the canonical NaN `a' to the extended
0326 double-precision floating-point format.
0327 -------------------------------------------------------------------------------
0328 */
0329 static floatx80 commonNaNToFloatx80( commonNaNT a )
0330 {
0331 floatx80 z;
0332
0333 z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
0334 z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
0335 z.__padding = 0;
0336 return z;
0337
0338 }
0339
0340 /*
0341 -------------------------------------------------------------------------------
0342 Takes two extended double-precision floating-point values `a' and `b', one
0343 of which is a NaN, and returns the appropriate NaN result. If either `a' or
0344 `b' is a signaling NaN, the invalid exception is raised.
0345 -------------------------------------------------------------------------------
0346 */
0347 static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
0348 {
0349 flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
0350
0351 aIsNaN = floatx80_is_nan( a );
0352 aIsSignalingNaN = floatx80_is_signaling_nan( a );
0353 bIsNaN = floatx80_is_nan( b );
0354 bIsSignalingNaN = floatx80_is_signaling_nan( b );
0355 a.low |= LIT64( 0xC000000000000000 );
0356 b.low |= LIT64( 0xC000000000000000 );
0357 if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
0358 if ( aIsNaN ) {
0359 return ( aIsSignalingNaN & bIsNaN ) ? b : a;
0360 }
0361 else {
0362 return b;
0363 }
0364
0365 }
0366
0367 #endif