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
This commit is contained in:
		
							parent
							
								
									5c7908ed23
								
							
						
					
					
						commit
						fe76d97653
					
				@ -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"
 | 
			
		||||
 | 
			
		||||
/*----------------------------------------------------------------------------
 | 
			
		||||
@ -294,6 +296,7 @@ static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig STATUS_P
 | 
			
		||||
            return packFloat32( zSign, 0xFF, - ( roundIncrement == 0 ));
 | 
			
		||||
        }
 | 
			
		||||
        if ( zExp < 0 ) {
 | 
			
		||||
            if ( STATUS(flush_to_zero) ) return packFloat32( zSign, 0, 0 );
 | 
			
		||||
            isTiny =
 | 
			
		||||
                   ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
 | 
			
		||||
                || ( zExp < -1 )
 | 
			
		||||
@ -457,6 +460,7 @@ static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig STATUS_P
 | 
			
		||||
            return packFloat64( zSign, 0x7FF, - ( roundIncrement == 0 ));
 | 
			
		||||
        }
 | 
			
		||||
        if ( zExp < 0 ) {
 | 
			
		||||
            if ( STATUS(flush_to_zero) ) return packFloat64( zSign, 0, 0 );
 | 
			
		||||
            isTiny =
 | 
			
		||||
                   ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
 | 
			
		||||
                || ( zExp < -1 )
 | 
			
		||||
@ -635,6 +639,7 @@ static floatx80
 | 
			
		||||
            goto overflow;
 | 
			
		||||
        }
 | 
			
		||||
        if ( zExp <= 0 ) {
 | 
			
		||||
            if ( STATUS(flush_to_zero) ) return packFloatx80( zSign, 0, 0 );
 | 
			
		||||
            isTiny =
 | 
			
		||||
                   ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
 | 
			
		||||
                || ( zExp < 0 )
 | 
			
		||||
@ -965,6 +970,7 @@ static float128
 | 
			
		||||
            return packFloat128( zSign, 0x7FFF, 0, 0 );
 | 
			
		||||
        }
 | 
			
		||||
        if ( zExp < 0 ) {
 | 
			
		||||
            if ( STATUS(flush_to_zero) ) return packFloat128( zSign, 0, 0, 0 );
 | 
			
		||||
            isTiny =
 | 
			
		||||
                   ( STATUS(float_detect_tininess) == float_tininess_before_rounding )
 | 
			
		||||
                || ( zExp < -1 )
 | 
			
		||||
@ -1637,7 +1643,10 @@ static float32 addFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
 | 
			
		||||
            if ( aSig | bSig ) return propagateFloat32NaN( a, b STATUS_VAR );
 | 
			
		||||
            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;
 | 
			
		||||
        zExp = aExp;
 | 
			
		||||
        goto roundAndPack;
 | 
			
		||||
@ -2595,7 +2604,10 @@ static float64 addFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
 | 
			
		||||
            if ( aSig | bSig ) return propagateFloat64NaN( a, b STATUS_VAR );
 | 
			
		||||
            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;
 | 
			
		||||
        zExp = aExp;
 | 
			
		||||
        goto roundAndPack;
 | 
			
		||||
@ -4597,7 +4609,10 @@ static float128 addFloat128Sigs( float128 a, float128 b, flag zSign STATUS_PARAM
 | 
			
		||||
            return a;
 | 
			
		||||
        }
 | 
			
		||||
        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;
 | 
			
		||||
        zSig0 |= LIT64( 0x0002000000000000 );
 | 
			
		||||
        zExp = aExp;
 | 
			
		||||
 | 
			
		||||
@ -190,11 +190,16 @@ typedef struct float_status {
 | 
			
		||||
#ifdef FLOATX80
 | 
			
		||||
    signed char floatx80_rounding_precision;
 | 
			
		||||
#endif
 | 
			
		||||
    flag flush_to_zero;
 | 
			
		||||
    flag default_nan_mode;
 | 
			
		||||
} float_status;
 | 
			
		||||
 | 
			
		||||
void set_float_rounding_mode(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)
 | 
			
		||||
{
 | 
			
		||||
    STATUS(default_nan_mode) = val;
 | 
			
		||||
 | 
			
		||||
@ -2334,12 +2334,13 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
 | 
			
		||||
        }
 | 
			
		||||
        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))
 | 
			
		||||
        set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
 | 
			
		||||
 | 
			
		||||
    i = vfp_exceptbits_to_host((val >> 8) & 0x1f);
 | 
			
		||||
    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))
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user