diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h index 166b913696..d279210ae8 100644 --- a/fpu/softfloat-specialize.h +++ b/fpu/softfloat-specialize.h @@ -144,6 +144,9 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM) flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; bits32 av, bv, res; + if ( STATUS(default_nan_mode) ) + return float32_default_nan; + aIsNaN = float32_is_nan( a ); aIsSignalingNaN = float32_is_signaling_nan( a ); bIsNaN = float32_is_nan( b ); @@ -276,6 +279,9 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM) flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; bits64 av, bv, res; + if ( STATUS(default_nan_mode) ) + return float64_default_nan; + aIsNaN = float64_is_nan( a ); aIsSignalingNaN = float64_is_signaling_nan( a ); bIsNaN = float64_is_nan( b ); @@ -412,6 +418,12 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM) { flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + if ( STATUS(default_nan_mode) ) { + a.low = floatx80_default_nan_low; + a.high = floatx80_default_nan_high; + return a; + } + aIsNaN = floatx80_is_nan( a ); aIsSignalingNaN = floatx80_is_signaling_nan( a ); bIsNaN = floatx80_is_nan( b ); @@ -532,6 +544,12 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM) { flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; + if ( STATUS(default_nan_mode) ) { + a.low = float128_default_nan_low; + a.high = float128_default_nan_high; + return a; + } + aIsNaN = float128_is_nan( a ); aIsSignalingNaN = float128_is_signaling_nan( a ); bIsNaN = float128_is_nan( b ); diff --git a/fpu/softfloat.h b/fpu/softfloat.h index 9061f03be1..6cd4facc88 100644 --- a/fpu/softfloat.h +++ b/fpu/softfloat.h @@ -190,10 +190,15 @@ typedef struct float_status { #ifdef FLOATX80 signed char floatx80_rounding_precision; #endif + 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_default_nan_mode(flag val STATUS_PARAM) +{ + STATUS(default_nan_mode) = val; +} INLINE int get_float_exception_flags(float_status *status) { return STATUS(float_exception_flags); diff --git a/target-arm/helper.c b/target-arm/helper.c index 14f19a93f7..79163b8287 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2334,6 +2334,8 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val) } set_float_rounding_mode(i, &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);