Commit 374dfc33e260c9836e32ae7a0a90d951f3989aff

Authored by aurel32
1 parent 7344da06

soft-float: add float32_log2() and float64_log2()

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6518 c046a42c-6fe2-441c-8c8c-71466251a162
fpu/softfloat.c
... ... @@ -2057,6 +2057,53 @@ float32 float32_sqrt( float32 a STATUS_PARAM )
2057 2057 }
2058 2058  
2059 2059 /*----------------------------------------------------------------------------
  2060 +| Returns the binary log of the single-precision floating-point value `a'.
  2061 +| The operation is performed according to the IEC/IEEE Standard for Binary
  2062 +| Floating-Point Arithmetic.
  2063 +*----------------------------------------------------------------------------*/
  2064 +float32 float32_log2( float32 a STATUS_PARAM )
  2065 +{
  2066 + flag aSign, zSign;
  2067 + int16 aExp;
  2068 + bits32 aSig, zSig, i;
  2069 +
  2070 + aSig = extractFloat32Frac( a );
  2071 + aExp = extractFloat32Exp( a );
  2072 + aSign = extractFloat32Sign( a );
  2073 +
  2074 + if ( aExp == 0 ) {
  2075 + if ( aSig == 0 ) return packFloat32( 1, 0xFF, 0 );
  2076 + normalizeFloat32Subnormal( aSig, &aExp, &aSig );
  2077 + }
  2078 + if ( aSign ) {
  2079 + float_raise( float_flag_invalid STATUS_VAR);
  2080 + return float32_default_nan;
  2081 + }
  2082 + if ( aExp == 0xFF ) {
  2083 + if ( aSig ) return propagateFloat32NaN( a, float32_zero STATUS_VAR );
  2084 + return a;
  2085 + }
  2086 +
  2087 + aExp -= 0x7F;
  2088 + aSig |= 0x00800000;
  2089 + zSign = aExp < 0;
  2090 + zSig = aExp << 23;
  2091 +
  2092 + for (i = 1 << 22; i > 0; i >>= 1) {
  2093 + aSig = ( (bits64)aSig * aSig ) >> 23;
  2094 + if ( aSig & 0x01000000 ) {
  2095 + aSig >>= 1;
  2096 + zSig |= i;
  2097 + }
  2098 + }
  2099 +
  2100 + if ( zSign )
  2101 + zSig = -zSig;
  2102 +
  2103 + return normalizeRoundAndPackFloat32( zSign, 0x85, zSig STATUS_VAR );
  2104 +}
  2105 +
  2106 +/*----------------------------------------------------------------------------
2060 2107 | Returns 1 if the single-precision floating-point value `a' is equal to
2061 2108 | the corresponding value `b', and 0 otherwise. The comparison is performed
2062 2109 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
... ... @@ -3006,6 +3053,52 @@ float64 float64_sqrt( float64 a STATUS_PARAM )
3006 3053 }
3007 3054  
3008 3055 /*----------------------------------------------------------------------------
  3056 +| Returns the binary log of the double-precision floating-point value `a'.
  3057 +| The operation is performed according to the IEC/IEEE Standard for Binary
  3058 +| Floating-Point Arithmetic.
  3059 +*----------------------------------------------------------------------------*/
  3060 +float64 float64_log2( float64 a STATUS_PARAM )
  3061 +{
  3062 + flag aSign, zSign;
  3063 + int16 aExp;
  3064 + bits64 aSig, aSig0, aSig1, zSig, i;
  3065 +
  3066 + aSig = extractFloat64Frac( a );
  3067 + aExp = extractFloat64Exp( a );
  3068 + aSign = extractFloat64Sign( a );
  3069 +
  3070 + if ( aExp == 0 ) {
  3071 + if ( aSig == 0 ) return packFloat64( 1, 0x7FF, 0 );
  3072 + normalizeFloat64Subnormal( aSig, &aExp, &aSig );
  3073 + }
  3074 + if ( aSign ) {
  3075 + float_raise( float_flag_invalid STATUS_VAR);
  3076 + return float64_default_nan;
  3077 + }
  3078 + if ( aExp == 0x7FF ) {
  3079 + if ( aSig ) return propagateFloat64NaN( a, float64_zero STATUS_VAR );
  3080 + return a;
  3081 + }
  3082 +
  3083 + aExp -= 0x3FF;
  3084 + aSig |= LIT64( 0x0010000000000000 );
  3085 + zSign = aExp < 0;
  3086 + zSig = (bits64)aExp << 52;
  3087 + for (i = 1LL << 51; i > 0; i >>= 1) {
  3088 + mul64To128( aSig, aSig, &aSig0, &aSig1 );
  3089 + aSig = ( aSig0 << 12 ) | ( aSig1 >> 52 );
  3090 + if ( aSig & LIT64( 0x0020000000000000 ) ) {
  3091 + aSig >>= 1;
  3092 + zSig |= i;
  3093 + }
  3094 + }
  3095 +
  3096 + if ( zSign )
  3097 + zSig = -zSig;
  3098 + return normalizeRoundAndPackFloat64( zSign, 0x408, zSig STATUS_VAR );
  3099 +}
  3100 +
  3101 +/*----------------------------------------------------------------------------
3009 3102 | Returns 1 if the double-precision floating-point value `a' is equal to the
3010 3103 | corresponding value `b', and 0 otherwise. The comparison is performed
3011 3104 | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
... ...
fpu/softfloat.h
... ... @@ -269,6 +269,7 @@ float32 float32_mul( float32, float32 STATUS_PARAM );
269 269 float32 float32_div( float32, float32 STATUS_PARAM );
270 270 float32 float32_rem( float32, float32 STATUS_PARAM );
271 271 float32 float32_sqrt( float32 STATUS_PARAM );
  272 +float32 float32_log2( float32 STATUS_PARAM );
272 273 int float32_eq( float32, float32 STATUS_PARAM );
273 274 int float32_le( float32, float32 STATUS_PARAM );
274 275 int float32_lt( float32, float32 STATUS_PARAM );
... ... @@ -339,6 +340,7 @@ float64 float64_mul( float64, float64 STATUS_PARAM );
339 340 float64 float64_div( float64, float64 STATUS_PARAM );
340 341 float64 float64_rem( float64, float64 STATUS_PARAM );
341 342 float64 float64_sqrt( float64 STATUS_PARAM );
  343 +float64 float64_log2( float64 STATUS_PARAM );
342 344 int float64_eq( float64, float64 STATUS_PARAM );
343 345 int float64_le( float64, float64 STATUS_PARAM );
344 346 int float64_lt( float64, float64 STATUS_PARAM );
... ...