提交 fe76d976 编写于 作者: P pbrook

Implement flush-to-zero mode (denormal results are replaced with zero).

Signed-off-by: NPaul Brook <paul@codesourcery.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6107 c046a42c-6fe2-441c-8c8c-71466251a162
上级 5c7908ed
...@@ -30,6 +30,8 @@ these four paragraphs for those parts of this code that are retained. ...@@ -30,6 +30,8 @@ these four paragraphs for those parts of this code that are retained.
=============================================================================*/ =============================================================================*/
/* FIXME: Flush-To-Zero only effects results. Denormal inputs should also
be flushed to zero. */
#include "softfloat.h" #include "softfloat.h"
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
...@@ -294,6 +296,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_P ...@@ -294,6 +296,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_P
return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 )); return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 ));
} }
if ( zExp < 0 ) { if ( zExp < 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat32( zSign, 0, 0 );
isTiny = isTiny =
( STATUS(float_detect_tininess) == float_tininess_before_rounding ) ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
|| ( zExp < -1 ) || ( zExp < -1 )
...@@ -457,6 +460,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_P ...@@ -457,6 +460,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_P
return packFloat64( zSign, 0x7FF, - ( roundIncrement == 0 )); return packFloat64( zSign, 0x7FF, - ( roundIncrement == 0 ));
} }
if ( zExp < 0 ) { if ( zExp < 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat64( zSign, 0, 0 );
isTiny = isTiny =
( STATUS(float_detect_tininess) == float_tininess_before_rounding ) ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
|| ( zExp < -1 ) || ( zExp < -1 )
...@@ -635,6 +639,7 @@ static floatx80 ...@@ -635,6 +639,7 @@ static floatx80
goto overflow; goto overflow;
} }
if ( zExp <= 0 ) { if ( zExp <= 0 ) {
if ( STATUS(flush_to_zero) ) return packFloatx80( zSign, 0, 0 );
isTiny = isTiny =
( STATUS(float_detect_tininess) == float_tininess_before_rounding ) ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
|| ( zExp < 0 ) || ( zExp < 0 )
...@@ -965,6 +970,7 @@ static float128 ...@@ -965,6 +970,7 @@ static float128
return packFloat128( zSign, 0x7FFF, 0, 0 ); return packFloat128( zSign, 0x7FFF, 0, 0 );
} }
if ( zExp < 0 ) { if ( zExp < 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat128( zSign, 0, 0, 0 );
isTiny = isTiny =
( STATUS(float_detect_tininess) == float_tininess_before_rounding ) ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
|| ( zExp < -1 ) || ( zExp < -1 )
...@@ -1637,7 +1643,10 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM) ...@@ -1637,7 +1643,10 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR ); if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
return a; return a;
} }
if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); if ( aExp == 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat32( zSign, 0, 0 );
return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
}
zSig = 0x40000000 + aSig + bSig; zSig = 0x40000000 + aSig + bSig;
zExp = aExp; zExp = aExp;
goto roundAndPack; goto roundAndPack;
...@@ -2595,7 +2604,10 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM ) ...@@ -2595,7 +2604,10 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR ); if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
return a; return a;
} }
if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); if ( aExp == 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat64( zSign, 0, 0 );
return packFloat64( zSign, 0, ( aSig + bSig )>>9 );
}
zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; zSig = LIT64( 0x4000000000000000 ) + aSig + bSig;
zExp = aExp; zExp = aExp;
goto roundAndPack; goto roundAndPack;
...@@ -4597,7 +4609,10 @@ static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM ...@@ -4597,7 +4609,10 @@ static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM
return a; return a;
} }
add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); if ( aExp == 0 ) {
if ( STATUS(flush_to_zero) ) return packFloat128( zSign, 0, 0, 0 );
return packFloat128( zSign, 0, zSig0, zSig1 );
}
zSig2 = 0; zSig2 = 0;
zSig0 |= LIT64( 0x0002000000000000 ); zSig0 |= LIT64( 0x0002000000000000 );
zExp = aExp; zExp = aExp;
......
...@@ -190,11 +190,16 @@ typedef struct float_status { ...@@ -190,11 +190,16 @@ typedef struct float_status {
#ifdef FLOATX80 #ifdef FLOATX80
signed char floatx80_rounding_precision; signed char floatx80_rounding_precision;
#endif #endif
flag flush_to_zero;
flag default_nan_mode; flag default_nan_mode;
} float_status; } float_status;
void set_float_rounding_mode(int val STATUS_PARAM); void set_float_rounding_mode(int val STATUS_PARAM);
void set_float_exception_flags(int val STATUS_PARAM); void set_float_exception_flags(int val STATUS_PARAM);
INLINE void set_flush_to_zero(flag val STATUS_PARAM)
{
STATUS(flush_to_zero) = val;
}
INLINE void set_default_nan_mode(flag val STATUS_PARAM) INLINE void set_default_nan_mode(flag val STATUS_PARAM)
{ {
STATUS(default_nan_mode) = val; STATUS(default_nan_mode) = val;
......
...@@ -2334,12 +2334,13 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val) ...@@ -2334,12 +2334,13 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
} }
set_float_rounding_mode(i, &env->vfp.fp_status); set_float_rounding_mode(i, &env->vfp.fp_status);
} }
if (changed & (1 << 24))
set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
if (changed & (1 << 25)) if (changed & (1 << 25))
set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status); set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
i = vfp_exceptbits_to_host((val >> 8) & 0x1f); i = vfp_exceptbits_to_host((val >> 8) & 0x1f);
set_float_exception_flags(i, &env->vfp.fp_status); set_float_exception_flags(i, &env->vfp.fp_status);
/* XXX: FZ and DN are not implemented. */
} }
#define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p)) #define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册