Softfloat: Add support to softfloat to return floatxx_default_nan when, the corresponding target status flag is set.
PATCH v2 1/1 Softfloat: Add support to softfloat to return floatxx_default_nan when, the corresponding target status flag is set.
Some CPUs have a status flag imposing to return floatxx_default_nan whatever the input value, when converting from one FP format to another. Implement this, using the already existing default_nan_mode status flag (currently used on ARM and SH4 at the moment).
---
Note that I am unsure whether it's useful to have a default (ie non-ARM) value for float16_default_nan and if the value I've used is right.
fpu/softfloat-specialize.h | 57 ++++++++++++++++++++++++++++++++++++++++--- fpu/softfloat.c | 30 ++++++++++------------- 2 files changed, 66 insertions(+), 21 deletions(-)
fpu/softfloat-specialize.h +53 -4
@@ -144,9 +144,14 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )| precision floating-point format. *----------------------------------------------------------------------------*/ -static float32 commonNaNToFloat32 (commonNaNT a ) +static float32 commonNaNToFloat32( commonNaNT a STATUS_PARAM) {bits32 mantissa = a.high>>41 ; + +if (STATUS (default_nan_mode) ) { +return float32_default_nan; + } +if ( mantissa )return make_float32 ( ( ( (bits32 ) a.sign )<<31 ) |0x7F800000 | ( a.high>>41 ) );
@@ -398,10 +403,14 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)| precision floating-point format. *----------------------------------------------------------------------------*/ -static float64 commonNaNToFloat64 (commonNaNT a ) +static float64 commonNaNToFloat64( commonNaNT a STATUS_PARAM) {bits64 mantissa = a.high>>12 ; +if (STATUS (default_nan_mode) ) { +return float64_default_nan; + } +if ( mantissa )return make_float64 ( ( ( (bits64) a.sign )<<63 )
@@ -451,6 +460,34 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) } } +/*---------------------------------------------------------------------------- +| The pattern for a default generated haft-precision NaN. +*----------------------------------------------------------------------------*/ +#if defined(TARGET_ARM ) +#define float16_default_nan 0x7E00 +#else +#define float16_default_nan 0xFE00 +#endif + +/*---------------------------------------------------------------------------- +| Returns the result of converting the canonical NaN `a' to the half- +| precision floating-point format. +*----------------------------------------------------------------------------*/ + +static bits16 commonNaNToFloat16( commonNaNT a STATUS_PARAM) +{ +bits16 mantissa = a.high>>57 ; + +if (STATUS (default_nan_mode) ) { +return float16_default_nan; + } + +if ( mantissa ) +return (bits16 )a.sign <<15 |0x1F <<10 | mantissa; +else +return float16_default_nan; +} +#ifdef FLOATX80 /*----------------------------------------------------------------------------
@@ -551,10 +588,16 @@ static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)| double-precision floating-point format. *----------------------------------------------------------------------------*/ -static floatx80 commonNaNToFloatx80 (commonNaNT a ) +static floatx80 commonNaNToFloatx80( commonNaNT a STATUS_PARAM) {floatx80 z; +if (STATUS (default_nan_mode) ) { + z.low = floatx80_default_nan_low; + z.high = floatx80_default_nan_high; +return z; + } +if (a.high) z.low = a.high;else
@@ -699,10 +742,16 @@ static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)| precision floating-point format. *----------------------------------------------------------------------------*/ -static float128 commonNaNToFloat128 (commonNaNT a ) +static float128 commonNaNToFloat128( commonNaNT a STATUS_PARAM) {float128 z; +if (STATUS (default_nan_mode) ) { + z.low = float128_default_nan_low; + z.high = float128_default_nan_high; +return z; + } +shift128Right ( a.high, a.low,16 , &z.high, &z.low ); z.high |= ( ( (bits64 ) a.sign )<<63 ) |LIT64 (0x7FFF000000000000 );return z;
fpu/softfloat.c +13 -17
@@ -1534,7 +1534,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM ) aExp =extractFloat32Exp ( a ); aSign =extractFloat32Sign ( a );if ( aExp ==0xFF ) { - if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR )); + if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );return packFloat64 ( aSign,0x7FF ,0 ); }if ( aExp ==0 ) {
@@ -1566,7 +1566,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM ) aExp =extractFloat32Exp ( a ); aSign =extractFloat32Sign ( a );if ( aExp ==0xFF ) { - if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) ); + if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );return packFloatx80 ( aSign,0x7FFF ,LIT64 (0x8000000000000000 ) ); }if ( aExp ==0 ) {
@@ -1600,7 +1600,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM ) aExp =extractFloat32Exp ( a ); aSign =extractFloat32Sign ( a );if ( aExp ==0xFF ) { - if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) ); + if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );return packFloat128 ( aSign,0x7FFF ,0 ,0 ); }if ( aExp ==0 ) {
@@ -2689,7 +2689,7 @@ float32 float64_to_float32( float64 a STATUS_PARAM ) aExp =extractFloat64Exp ( a ); aSign =extractFloat64Sign ( a );if ( aExp ==0x7FF ) { - if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) ); + if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );return packFloat32 ( aSign,0xFF ,0 ); }shift64RightJamming ( aSig,22 , &aSig );
@@ -2767,11 +2767,7 @@ bits16 float32_to_float16( float32 a, flag ieee STATUS_PARAM) aExp =extractFloat32Exp ( a ); aSign =extractFloat32Sign ( a );if ( aExp ==0xFF ) { -if (aSig) { -/* Make sure correct exceptions are raised. */ - float32ToCommonNaN(a STATUS_VAR); - aSig |=0x00400000 ; - } + if ( aSig ) return commonNaNToFloat16( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );return packFloat16 (aSign,0x1f , aSig >>13 ); }if (aExp ==0 && aSign ==0 ) {
@@ -2861,7 +2857,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM ) aExp =extractFloat64Exp ( a ); aSign =extractFloat64Sign ( a );if ( aExp ==0x7FF ) { - if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) ); + if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );return packFloatx80 ( aSign,0x7FFF ,LIT64 (0x8000000000000000 ) ); }if ( aExp ==0 ) {
@@ -2896,7 +2892,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM ) aExp =extractFloat64Exp ( a ); aSign =extractFloat64Sign ( a );if ( aExp ==0x7FF ) { - if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) ); + if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );return packFloat128 ( aSign,0x7FFF ,0 ,0 ); }if ( aExp ==0 ) {
@@ -3843,7 +3839,7 @@ float32 floatx80_to_float32( floatx80 a STATUS_PARAM ) aSign =extractFloatx80Sign ( a );if ( aExp ==0x7FFF ) {if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); }return packFloat32 ( aSign,0xFF ,0 ); }
@@ -3871,7 +3867,7 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM ) aSign =extractFloatx80Sign ( a );if ( aExp ==0x7FFF ) {if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); }return packFloat64 ( aSign,0x7FF ,0 ); }
@@ -3900,7 +3896,7 @@ float128 floatx80_to_float128( floatx80 a STATUS_PARAM ) aExp =extractFloatx80Exp ( a ); aSign =extractFloatx80Sign ( a );if ( ( aExp ==0x7FFF ) && (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); }shift128Right ( aSig<<1 ,0 ,16 , &zSig0, &zSig1 );return packFloat128 ( aSign, aExp, zSig0, zSig1 );
@@ -4863,7 +4859,7 @@ float32 float128_to_float32( float128 a STATUS_PARAM ) aSign =extractFloat128Sign ( a );if ( aExp ==0x7FFF ) {if ( aSig0 | aSig1 ) { - return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); }return packFloat32 ( aSign,0xFF ,0 ); }
@@ -4897,7 +4893,7 @@ float64 float128_to_float64( float128 a STATUS_PARAM ) aSign =extractFloat128Sign ( a );if ( aExp ==0x7FFF ) {if ( aSig0 | aSig1 ) { - return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); }return packFloat64 ( aSign,0x7FF ,0 ); }
@@ -4932,7 +4928,7 @@ floatx80 float128_to_floatx80( float128 a STATUS_PARAM ) aSign =extractFloat128Sign ( a );if ( aExp ==0x7FFF ) {if ( aSig0 | aSig1 ) { - return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) ); + return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR ); }return packFloatx80 ( aSign,0x7FFF ,LIT64 (0x8000000000000000 ) ); }
Signature · 1 line
1.7.2.3
Quoted 1 line · Christophe Lyon
Note that I am unsure whether it's useful to have a default (ie non-ARM) value for
float16_default_nanand if the value I've used is right.
We should set the default consistent with how we do it for the other types: special cases for various architectures, default for SNAN_BIT_IS_ONE is sign=0,exp=1....1, mantissa=01.....1; default for !SNAN_BIT_IS_ONE is sign=1,exp=1.....1,mantissa=0....0. So:
#if defined(TARGET_ARM)
#define float16_default_nan 0x7E00
#elif SNAN_BIT_IS_ONE
#define float16_default_nan 0x7DFF
#else
#define float16_default_nan 0xFE00
#endif
fpu/softfloat-specialize.h static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) · line 489
Quoted 13 lines
fpu/softfloat-specialize.h +13
-0+static bits16 commonNaNToFloat16( commonNaNT a STATUS_PARAM) +{ + bits16 mantissa = a.high>>57; + + if ( STATUS(default_nan_mode) ) { + return float16_default_nan; + } + + if ( mantissa ) + return (bits16)a.sign << 15 | 0x1F << 10 | mantissa; + else + return float16_default_nan; +}
Could we have some brackets around the shifts and some braces for this if(), please? (I know most of softfloat doesn't adhere to the qemu brace-standard, and I'm not going to ask for all those other ifs to change, but since this is a new function we might as well put in the braces for this one.)
thanks
-- PMM