Commit 374dfc33e260c9836e32ae7a0a90d951f3989aff
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
Showing
2 changed files
with
95 additions
and
0 deletions
fpu/softfloat.c
| @@ -2057,6 +2057,53 @@ float32 float32_sqrt( float32 a STATUS_PARAM ) | @@ -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 | | Returns 1 if the single-precision floating-point value `a' is equal to | 2107 | | Returns 1 if the single-precision floating-point value `a' is equal to |
| 2061 | | the corresponding value `b', and 0 otherwise. The comparison is performed | 2108 | | the corresponding value `b', and 0 otherwise. The comparison is performed |
| 2062 | | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. | 2109 | | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. |
| @@ -3006,6 +3053,52 @@ float64 float64_sqrt( float64 a STATUS_PARAM ) | @@ -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 | | Returns 1 if the double-precision floating-point value `a' is equal to the | 3102 | | Returns 1 if the double-precision floating-point value `a' is equal to the |
| 3010 | | corresponding value `b', and 0 otherwise. The comparison is performed | 3103 | | corresponding value `b', and 0 otherwise. The comparison is performed |
| 3011 | | according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. | 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,6 +269,7 @@ float32 float32_mul( float32, float32 STATUS_PARAM ); | ||
| 269 | float32 float32_div( float32, float32 STATUS_PARAM ); | 269 | float32 float32_div( float32, float32 STATUS_PARAM ); |
| 270 | float32 float32_rem( float32, float32 STATUS_PARAM ); | 270 | float32 float32_rem( float32, float32 STATUS_PARAM ); |
| 271 | float32 float32_sqrt( float32 STATUS_PARAM ); | 271 | float32 float32_sqrt( float32 STATUS_PARAM ); |
| 272 | +float32 float32_log2( float32 STATUS_PARAM ); | ||
| 272 | int float32_eq( float32, float32 STATUS_PARAM ); | 273 | int float32_eq( float32, float32 STATUS_PARAM ); |
| 273 | int float32_le( float32, float32 STATUS_PARAM ); | 274 | int float32_le( float32, float32 STATUS_PARAM ); |
| 274 | int float32_lt( float32, float32 STATUS_PARAM ); | 275 | int float32_lt( float32, float32 STATUS_PARAM ); |
| @@ -339,6 +340,7 @@ float64 float64_mul( float64, float64 STATUS_PARAM ); | @@ -339,6 +340,7 @@ float64 float64_mul( float64, float64 STATUS_PARAM ); | ||
| 339 | float64 float64_div( float64, float64 STATUS_PARAM ); | 340 | float64 float64_div( float64, float64 STATUS_PARAM ); |
| 340 | float64 float64_rem( float64, float64 STATUS_PARAM ); | 341 | float64 float64_rem( float64, float64 STATUS_PARAM ); |
| 341 | float64 float64_sqrt( float64 STATUS_PARAM ); | 342 | float64 float64_sqrt( float64 STATUS_PARAM ); |
| 343 | +float64 float64_log2( float64 STATUS_PARAM ); | ||
| 342 | int float64_eq( float64, float64 STATUS_PARAM ); | 344 | int float64_eq( float64, float64 STATUS_PARAM ); |
| 343 | int float64_le( float64, float64 STATUS_PARAM ); | 345 | int float64_le( float64, float64 STATUS_PARAM ); |
| 344 | int float64_lt( float64, float64 STATUS_PARAM ); | 346 | int float64_lt( float64, float64 STATUS_PARAM ); |