Commit fe76d97653d6611df19dacc4e326fc7d3d057237
1 parent
5c7908ed
Implement flush-to-zero mode (denormal results are replaced with zero).
Signed-off-by: Paul Brook <paul@codesourcery.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6107 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
25 additions
and
4 deletions
fpu/softfloat.c
... | ... | @@ -30,6 +30,8 @@ these four paragraphs for those parts of this code that are retained. |
30 | 30 | |
31 | 31 | =============================================================================*/ |
32 | 32 | |
33 | +/* FIXME: Flush-To-Zero only effects results. Denormal inputs should also | |
34 | + be flushed to zero. */ | |
33 | 35 | #include "softfloat.h" |
34 | 36 | |
35 | 37 | /*---------------------------------------------------------------------------- |
... | ... | @@ -294,6 +296,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_P |
294 | 296 | return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 )); |
295 | 297 | } |
296 | 298 | if ( zExp < 0 ) { |
299 | + if ( STATUS(flush_to_zero) ) return packFloat32( zSign, 0, 0 ); | |
297 | 300 | isTiny = |
298 | 301 | ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) |
299 | 302 | || ( zExp < -1 ) |
... | ... | @@ -457,6 +460,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_P |
457 | 460 | return packFloat64( zSign, 0x7FF, - ( roundIncrement == 0 )); |
458 | 461 | } |
459 | 462 | if ( zExp < 0 ) { |
463 | + if ( STATUS(flush_to_zero) ) return packFloat64( zSign, 0, 0 ); | |
460 | 464 | isTiny = |
461 | 465 | ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) |
462 | 466 | || ( zExp < -1 ) |
... | ... | @@ -635,6 +639,7 @@ static floatx80 |
635 | 639 | goto overflow; |
636 | 640 | } |
637 | 641 | if ( zExp <= 0 ) { |
642 | + if ( STATUS(flush_to_zero) ) return packFloatx80( zSign, 0, 0 ); | |
638 | 643 | isTiny = |
639 | 644 | ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) |
640 | 645 | || ( zExp < 0 ) |
... | ... | @@ -965,6 +970,7 @@ static float128 |
965 | 970 | return packFloat128( zSign, 0x7FFF, 0, 0 ); |
966 | 971 | } |
967 | 972 | if ( zExp < 0 ) { |
973 | + if ( STATUS(flush_to_zero) ) return packFloat128( zSign, 0, 0, 0 ); | |
968 | 974 | isTiny = |
969 | 975 | ( STATUS(float_detect_tininess) == float_tininess_before_rounding ) |
970 | 976 | || ( zExp < -1 ) |
... | ... | @@ -1637,7 +1643,10 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM) |
1637 | 1643 | if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR ); |
1638 | 1644 | return a; |
1639 | 1645 | } |
1640 | - if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); | |
1646 | + if ( aExp == 0 ) { | |
1647 | + if ( STATUS(flush_to_zero) ) return packFloat32( zSign, 0, 0 ); | |
1648 | + return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); | |
1649 | + } | |
1641 | 1650 | zSig = 0x40000000 + aSig + bSig; |
1642 | 1651 | zExp = aExp; |
1643 | 1652 | goto roundAndPack; |
... | ... | @@ -2595,7 +2604,10 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM ) |
2595 | 2604 | if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR ); |
2596 | 2605 | return a; |
2597 | 2606 | } |
2598 | - if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); | |
2607 | + if ( aExp == 0 ) { | |
2608 | + if ( STATUS(flush_to_zero) ) return packFloat64( zSign, 0, 0 ); | |
2609 | + return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); | |
2610 | + } | |
2599 | 2611 | zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; |
2600 | 2612 | zExp = aExp; |
2601 | 2613 | goto roundAndPack; |
... | ... | @@ -4597,7 +4609,10 @@ static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM |
4597 | 4609 | return a; |
4598 | 4610 | } |
4599 | 4611 | add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); |
4600 | - if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); | |
4612 | + if ( aExp == 0 ) { | |
4613 | + if ( STATUS(flush_to_zero) ) return packFloat128( zSign, 0, 0, 0 ); | |
4614 | + return packFloat128( zSign, 0, zSig0, zSig1 ); | |
4615 | + } | |
4601 | 4616 | zSig2 = 0; |
4602 | 4617 | zSig0 |= LIT64( 0x0002000000000000 ); |
4603 | 4618 | zExp = aExp; | ... | ... |
fpu/softfloat.h
... | ... | @@ -190,11 +190,16 @@ typedef struct float_status { |
190 | 190 | #ifdef FLOATX80 |
191 | 191 | signed char floatx80_rounding_precision; |
192 | 192 | #endif |
193 | + flag flush_to_zero; | |
193 | 194 | flag default_nan_mode; |
194 | 195 | } float_status; |
195 | 196 | |
196 | 197 | void set_float_rounding_mode(int val STATUS_PARAM); |
197 | 198 | void set_float_exception_flags(int val STATUS_PARAM); |
199 | +INLINE void set_flush_to_zero(flag val STATUS_PARAM) | |
200 | +{ | |
201 | + STATUS(flush_to_zero) = val; | |
202 | +} | |
198 | 203 | INLINE void set_default_nan_mode(flag val STATUS_PARAM) |
199 | 204 | { |
200 | 205 | STATUS(default_nan_mode) = val; | ... | ... |
target-arm/helper.c
... | ... | @@ -2334,12 +2334,13 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val) |
2334 | 2334 | } |
2335 | 2335 | set_float_rounding_mode(i, &env->vfp.fp_status); |
2336 | 2336 | } |
2337 | + if (changed & (1 << 24)) | |
2338 | + set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status); | |
2337 | 2339 | if (changed & (1 << 25)) |
2338 | 2340 | set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status); |
2339 | 2341 | |
2340 | 2342 | i = vfp_exceptbits_to_host((val >> 8) & 0x1f); |
2341 | 2343 | set_float_exception_flags(i, &env->vfp.fp_status); |
2342 | - /* XXX: FZ and DN are not implemented. */ | |
2343 | 2344 | } |
2344 | 2345 | |
2345 | 2346 | #define VFP_HELPER(name, p) HELPER(glue(glue(vfp_,name),p)) | ... | ... |