Back to home page

OSCL-LXR

 
 

    


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