diff --git a/bochs/cpu/softfloat.cc b/bochs/cpu/softfloat.cc index ad835e454..fb4bc9fc1 100755 --- a/bochs/cpu/softfloat.cc +++ b/bochs/cpu/softfloat.cc @@ -178,6 +178,33 @@ BX_CPP_INLINE flag extractFloat32Sign(float32 a) return a>>31; } +/*---------------------------------------------------------------------------- +| Determine single-precision floating-point number class +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float_class_t float32_class(float32 a) +{ + Bit16s aExp = extractFloat32Exp(a); + Bit32u aSig = extractFloat32Frac(a); + flag aSign = extractFloat32Sign(a); + + if(aExp == 0xFF) { + if (aSig == 0) { + return (aSign) ? float_negative_inf : float_positive_inf; + } + return float_NaN; + } + + if(aExp == 0) { + if (aSig == 0) { + return (aSign) ? float_negative_zero : float_positive_zero; + } + return float_denormal; + } + + return float_normalized; +} + /*---------------------------------------------------------------------------- | Normalizes the subnormal single-precision floating-point value represented | by the denormalized significand `aSig'. The normalized exponent and @@ -331,6 +358,33 @@ BX_CPP_INLINE flag extractFloat64Sign(float64 a) return a>>63; } +/*---------------------------------------------------------------------------- +| Determine double-precision floating-point number class +*----------------------------------------------------------------------------*/ + +BX_CPP_INLINE float_class_t float64_class(float64 a) +{ + Bit16s aExp = extractFloat64Exp(a); + Bit64u aSig = extractFloat64Frac(a); + flag aSign = extractFloat64Sign(a); + + if(aExp == 0x7FF) { + if (aSig == 0) { + return (aSign) ? float_negative_inf : float_positive_inf; + } + return float_NaN; + } + + if(aExp == 0) { + if (aSig == 0) { + return (aSign) ? float_negative_zero : float_positive_zero; + } + return float_denormal; + } + + return float_normalized; +} + /*---------------------------------------------------------------------------- | Normalizes the subnormal double-precision floating-point value represented | by the denormalized significand `aSig'. The normalized exponent and @@ -703,19 +757,16 @@ Bit64s float32_to_int64_round_to_zero(float32 a, float_status_t &status) float64 float32_to_float64(float32 a, float_status_t &status) { - flag aSign; - Bit16s aExp; - Bit32u aSig; + Bit32u aSig = extractFloat32Frac(a); + Bit16s aExp = extractFloat32Exp(a); + flag aSign = extractFloat32Sign(a); - aSig = extractFloat32Frac(a); - aExp = extractFloat32Exp(a); - aSign = extractFloat32Sign(a); if (aExp == 0xFF) { if (aSig) return commonNaNToFloat64(float32ToCommonNaN(a, status)); return packFloat64(aSign, 0x7FF, 0); } if (aExp == 0) { - if (aSig == 0) return packFloat64(aSign, 0, 0); + if (aSig == 0 || get_DAZ(status)) return packFloat64(aSign, 0, 0); float_raise(status, float_flag_denormal); normalizeFloat32Subnormal(aSig, &aExp, &aSig); --aExp; @@ -800,9 +851,20 @@ static float32 addFloat32Sigs(float32 a, float32 b, flag zSign, float_status_t & bSig = extractFloat32Frac(b); bExp = extractFloat32Exp(b); - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); - } + if ((aExp == 0) && aSig) { + if (get_DAZ(status)) { + aExp = 0; + aSig = 0; + } + else float_raise(status, float_flag_denormal); + } + if ((bExp == 0) && bSig) { + if (get_DAZ(status)) { + bExp = 0; + bSig = 0; + } + else float_raise(status, float_flag_denormal); + } expDiff = aExp - bExp; aSig <<= 6; @@ -876,9 +938,20 @@ static float32 subFloat32Sigs(float32 a, float32 b, flag zSign, float_status_t & bSig = extractFloat32Frac(b); bExp = extractFloat32Exp(b); - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); - } + if ((aExp == 0) && aSig) { + if (get_DAZ(status)) { + aExp = 0; + aSig = 0; + } + else float_raise(status, float_flag_denormal); + } + if ((bExp == 0) && bSig) { + if (get_DAZ(status)) { + bExp = 0; + bSig = 0; + } + else float_raise(status, float_flag_denormal); + } expDiff = aExp - bExp; aSig <<= 7; @@ -1016,12 +1089,12 @@ float32 float32_mul(float32 a, float32 b, float_status_t &status) return packFloat32(zSign, 0xFF, 0); } if (aExp == 0) { - if (aSig == 0) return packFloat32(zSign, 0, 0); + if (aSig == 0 || get_DAZ(status)) return packFloat32(zSign, 0, 0); float_raise(status, float_flag_denormal); normalizeFloat32Subnormal(aSig, &aExp, &aSig); } if (bExp == 0) { - if (bSig == 0) return packFloat32(zSign, 0, 0); + if (bSig == 0 || get_DAZ(status)) return packFloat32(zSign, 0, 0); float_raise(status, float_flag_denormal); normalizeFloat32Subnormal(bSig, &bExp, &bSig); } @@ -1070,10 +1143,12 @@ float32 float32_div(float32 a, float32 b, float_status_t &status) return packFloat32(zSign, 0, 0); } if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return float32_default_nan; + if (bSig == 0 || get_DAZ(status)) { + if (aExp == 0) { + if (aSig == 0 || get_DAZ(status)) { + float_raise(status, float_flag_invalid); + return float32_default_nan; + } } float_raise(status, float_flag_divbyzero); return packFloat32(zSign, 0xFF, 0); @@ -1082,7 +1157,7 @@ float32 float32_div(float32 a, float32 b, float_status_t &status) normalizeFloat32Subnormal(bSig, &bExp, &bSig); } if (aExp == 0) { - if (aSig == 0) return packFloat32(zSign, 0, 0); + if (aSig == 0 || get_DAZ(status)) return packFloat32(zSign, 0, 0); float_raise(status, float_flag_denormal); normalizeFloat32Subnormal(aSig, &aExp, &aSig); } @@ -1134,7 +1209,7 @@ float32 float32_rem(float32 a, float32 b, float_status_t &status) return a; } if (bExp == 0) { - if (bSig == 0) { + if (bSig == 0 || get_DAZ(status)) { float_raise(status, float_flag_invalid); return float32_default_nan; } @@ -1142,7 +1217,7 @@ float32 float32_rem(float32 a, float32 b, float_status_t &status) normalizeFloat32Subnormal(bSig, &bExp, &bSig); } if (aExp == 0) { - if (aSig == 0) return a; + if (aSig == 0 || get_DAZ(status)) return packFloat32(aSign, 0, 0); float_raise(status, float_flag_denormal); normalizeFloat32Subnormal(aSig, &aExp, &aSig); } @@ -1224,12 +1299,14 @@ float32 float32_sqrt(float32 a, float_status_t &status) return float32_default_nan; } if (aSign) { - if ((aExp | aSig) == 0) return a; + if (aExp == 0) { + if (aSig == 0 || get_DAZ(status)) return packFloat32(aSign, 0, 0); + } float_raise(status, float_flag_invalid); return float32_default_nan; } if (aExp == 0) { - if (aSig == 0) return 0; + if (aSig == 0 || get_DAZ(status)) return 0; float_raise(status, float_flag_denormal); normalizeFloat32Subnormal(aSig, &aExp, &aSig); } @@ -1263,12 +1340,10 @@ float32 float32_sqrt(float32 a, float_status_t &status) int float32_eq(float32 a, float32 b, float_status_t &status) { - Bit16s aExp = extractFloat32Exp(a); - Bit16s bExp = extractFloat32Exp(b); - Bit32u aSig = extractFloat32Frac(a); - Bit32u bSig = extractFloat32Frac(b); + float_class_t aClass = float32_class(a); + float_class_t bClass = float32_class(b); - if (((aExp == 0xFF) && aSig) || ((bExp == 0xFF) && bSig)) + if (aClass == float_NaN || bClass == float_NaN) { if (float32_is_signaling_nan(a) || float32_is_signaling_nan(b)) { @@ -1277,8 +1352,13 @@ int float32_eq(float32 a, float32 b, float_status_t &status) return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } return (a == b) || ((Bit32u) ((a | b)<<1) == 0); @@ -1293,18 +1373,21 @@ int float32_eq(float32 a, float32 b, float_status_t &status) int float32_le(float32 a, float32 b, float_status_t &status) { - Bit16s aExp = extractFloat32Exp(a); - Bit16s bExp = extractFloat32Exp(b); - Bit32u aSig = extractFloat32Frac(a); - Bit32u bSig = extractFloat32Frac(b); + float_class_t aClass = float32_class(a); + float_class_t bClass = float32_class(b); - if (((aExp == 0xFF) && aSig) || ((bExp == 0xFF) && bSig)) { + if (aClass == float_NaN || bClass == float_NaN) { float_raise(status, float_flag_invalid); return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } flag aSign = extractFloat32Sign(a); @@ -1321,18 +1404,21 @@ int float32_le(float32 a, float32 b, float_status_t &status) int float32_lt(float32 a, float32 b, float_status_t &status) { - Bit16s aExp = extractFloat32Exp(a); - Bit16s bExp = extractFloat32Exp(b); - Bit32u aSig = extractFloat32Frac(a); - Bit32u bSig = extractFloat32Frac(b); + float_class_t aClass = float32_class(a); + float_class_t bClass = float32_class(b); - if (((aExp == 0xFF) && aSig) || ((bExp == 0xFF) && bSig)) { + if (aClass == float_NaN || bClass == float_NaN) { float_raise(status, float_flag_invalid); return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } flag aSign = extractFloat32Sign(a); @@ -1350,18 +1436,21 @@ int float32_lt(float32 a, float32 b, float_status_t &status) int float32_eq_signaling(float32 a, float32 b, float_status_t &status) { - Bit16s aExp = extractFloat32Exp(a); - Bit16s bExp = extractFloat32Exp(b); - Bit32u aSig = extractFloat32Frac(a); - Bit32u bSig = extractFloat32Frac(b); + float_class_t aClass = float32_class(a); + float_class_t bClass = float32_class(b); - if (((aExp == 0xFF) && aSig) || ((bExp == 0xFF) && bSig)) { + if (aClass == float_NaN || bClass == float_NaN) { float_raise(status, float_flag_invalid); return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } return (a == b) || ((Bit32u) ((a | b)<<1) == 0); @@ -1376,12 +1465,10 @@ int float32_eq_signaling(float32 a, float32 b, float_status_t &status) int float32_le_quiet(float32 a, float32 b, float_status_t &status) { - Bit16s aExp = extractFloat32Exp(a); - Bit16s bExp = extractFloat32Exp(b); - Bit32u aSig = extractFloat32Frac(a); - Bit32u bSig = extractFloat32Frac(b); + float_class_t aClass = float32_class(a); + float_class_t bClass = float32_class(b); - if (((aExp == 0xFF) && aSig) || ((bExp == 0xFF) && bSig)) + if (aClass == float_NaN || bClass == float_NaN) { if (float32_is_signaling_nan(a) || float32_is_signaling_nan(b)) { @@ -1390,8 +1477,13 @@ int float32_le_quiet(float32 a, float32 b, float_status_t &status) return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } flag aSign = extractFloat32Sign(a); @@ -1409,12 +1501,10 @@ int float32_le_quiet(float32 a, float32 b, float_status_t &status) int float32_lt_quiet(float32 a, float32 b, float_status_t &status) { - Bit16s aExp = extractFloat32Exp(a); - Bit16s bExp = extractFloat32Exp(b); - Bit32u aSig = extractFloat32Frac(a); - Bit32u bSig = extractFloat32Frac(b); + float_class_t aClass = float32_class(a); + float_class_t bClass = float32_class(b); - if (((aExp == 0xFF) && aSig) || ((bExp == 0xFF) && bSig)) + if (aClass == float_NaN || bClass == float_NaN) { if (float32_is_signaling_nan(a) || float32_is_signaling_nan(b)) { @@ -1423,8 +1513,13 @@ int float32_lt_quiet(float32 a, float32 b, float_status_t &status) return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } flag aSign = extractFloat32Sign(a); @@ -1461,18 +1556,21 @@ int float32_unordered(float32 a, float32 b, float_status_t &status) int float32_compare(float32 a, float32 b, float_status_t &status) { - Bit16s aExp = extractFloat32Exp(a); - Bit16s bExp = extractFloat32Exp(b); - Bit32u aSig = extractFloat32Frac(a); - Bit32u bSig = extractFloat32Frac(b); + float_class_t aClass = float32_class(a); + float_class_t bClass = float32_class(b); - if (((aExp == 0xFF) && aSig) || ((bExp == 0xFF) && bSig)) { + if (aClass == float_NaN || bClass == float_NaN) { float_raise(status, float_flag_invalid); return float_relation_unordered; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } if ((a == b) || ((Bit32u) ((a | b)<<1) == 0)) return float_relation_equal; @@ -1497,12 +1595,10 @@ int float32_compare(float32 a, float32 b, float_status_t &status) int float32_compare_quiet(float32 a, float32 b, float_status_t &status) { - Bit16s aExp = extractFloat32Exp(a); - Bit16s bExp = extractFloat32Exp(b); - Bit32u aSig = extractFloat32Frac(a); - Bit32u bSig = extractFloat32Frac(b); + float_class_t aClass = float32_class(a); + float_class_t bClass = float32_class(b); - if (((aExp == 0xFF) && aSig) || ((bExp == 0xFF) && bSig)) + if (aClass == float_NaN || bClass == float_NaN) { if (float32_is_signaling_nan(a) || float32_is_signaling_nan(b)) { @@ -1511,8 +1607,13 @@ int float32_compare_quiet(float32 a, float32 b, float_status_t &status) return float_relation_unordered; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } if ((a == b) || ((Bit32u) ((a | b)<<1) == 0)) return float_relation_equal; @@ -1709,7 +1810,7 @@ float32 float64_to_float32(float64 a, float_status_t &status) return packFloat32(aSign, 0xFF, 0); } if (aExp == 0) { - if (aSig == 0) return packFloat32(aSign, 0, 0); + if (aSig == 0 || get_DAZ(status)) return packFloat32(aSign, 0, 0); float_raise(status, float_flag_denormal); } shift64RightJamming(aSig, 22, &aSig); @@ -1799,9 +1900,20 @@ static float64 addFloat64Sigs(float64 a, float64 b, flag zSign, float_status_t & bSig = extractFloat64Frac(b); bExp = extractFloat64Exp(b); - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); - } + if ((aExp == 0) && aSig) { + if (get_DAZ(status)) { + aExp = 0; + aSig = 0; + } + else float_raise(status, float_flag_denormal); + } + if ((bExp == 0) && bSig) { + if (get_DAZ(status)) { + bExp = 0; + bSig = 0; + } + else float_raise(status, float_flag_denormal); + } expDiff = aExp - bExp; aSig <<= 9; @@ -1874,9 +1986,20 @@ static float64 subFloat64Sigs(float64 a, float64 b, flag zSign, float_status_t & bSig = extractFloat64Frac(b); bExp = extractFloat64Exp(b); - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); - } + if ((aExp == 0) && aSig) { + if (get_DAZ(status)) { + aExp = 0; + aSig = 0; + } + else float_raise(status, float_flag_denormal); + } + if ((bExp == 0) && bSig) { + if (get_DAZ(status)) { + bExp = 0; + bSig = 0; + } + else float_raise(status, float_flag_denormal); + } expDiff = aExp - bExp; aSig <<= 10; @@ -2012,12 +2135,12 @@ float64 float64_mul(float64 a, float64 b, float_status_t &status) return packFloat64(zSign, 0x7FF, 0); } if (aExp == 0) { - if (aSig == 0) return packFloat64(zSign, 0, 0); + if (aSig == 0 || get_DAZ(status)) return packFloat64(zSign, 0, 0); float_raise(status, float_flag_denormal); normalizeFloat64Subnormal(aSig, &aExp, &aSig); } if (bExp == 0) { - if (bSig == 0) return packFloat64(zSign, 0, 0); + if (bSig == 0 || get_DAZ(status)) return packFloat64(zSign, 0, 0); float_raise(status, float_flag_denormal); normalizeFloat64Subnormal(bSig, &bExp, &bSig); } @@ -2068,10 +2191,12 @@ float64 float64_div(float64 a, float64 b, float_status_t &status) return packFloat64(zSign, 0, 0); } if (bExp == 0) { - if (bSig == 0) { - if ((aExp | aSig) == 0) { - float_raise(status, float_flag_invalid); - return float64_default_nan; + if (bSig == 0 || get_DAZ(status)) { + if (aExp == 0) { + if (aSig == 0 || get_DAZ(status)) { + float_raise(status, float_flag_invalid); + return float64_default_nan; + } } float_raise(status, float_flag_divbyzero); return packFloat64(zSign, 0x7FF, 0); @@ -2080,7 +2205,7 @@ float64 float64_div(float64 a, float64 b, float_status_t &status) normalizeFloat64Subnormal(bSig, &bExp, &bSig); } if (aExp == 0) { - if (aSig == 0) return packFloat64(zSign, 0, 0); + if (aSig == 0 || get_DAZ(status)) return packFloat64(zSign, 0, 0); float_raise(status, float_flag_denormal); normalizeFloat64Subnormal(aSig, &aExp, &aSig); } @@ -2136,7 +2261,7 @@ float64 float64_rem(float64 a, float64 b, float_status_t &status) return a; } if (bExp == 0) { - if (bSig == 0) { + if (bSig == 0 || get_DAZ(status)) { float_raise(status, float_flag_invalid); return float64_default_nan; } @@ -2144,7 +2269,7 @@ float64 float64_rem(float64 a, float64 b, float_status_t &status) normalizeFloat64Subnormal(bSig, &bExp, &bSig); } if (aExp == 0) { - if (aSig == 0) return a; + if (aSig == 0 || get_DAZ(status)) return packFloat64(aSign, 0, 0); float_raise(status, float_flag_denormal); normalizeFloat64Subnormal(aSig, &aExp, &aSig); } @@ -2214,12 +2339,14 @@ float64 float64_sqrt(float64 a, float_status_t &status) return float64_default_nan; } if (aSign) { - if ((aExp | aSig) == 0) return a; + if (aExp == 0) { + if (aSig == 0 || get_DAZ(status)) return packFloat64(aSign, 0, 0); + } float_raise(status, float_flag_invalid); return float64_default_nan; } if (aExp == 0) { - if (aSig == 0) return 0; + if (aSig == 0 || get_DAZ(status)) return 0; float_raise(status, float_flag_denormal); normalizeFloat64Subnormal(aSig, &aExp, &aSig); } @@ -2250,12 +2377,10 @@ float64 float64_sqrt(float64 a, float_status_t &status) int float64_eq(float64 a, float64 b, float_status_t &status) { - Bit16s aExp = extractFloat64Exp(a); - Bit16s bExp = extractFloat64Exp(b); - Bit64u aSig = extractFloat64Frac(a); - Bit64u bSig = extractFloat64Frac(b); + float_class_t aClass = float64_class(a); + float_class_t bClass = float64_class(b); - if (((aExp == 0x7FF) && aSig) || ((bExp == 0x7FF) && bSig)) + if (aClass == float_NaN || bClass == float_NaN) { if (float64_is_signaling_nan(a) || float64_is_signaling_nan(b)) { @@ -2264,8 +2389,13 @@ int float64_eq(float64 a, float64 b, float_status_t &status) return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } return (a == b) || ((Bit64u) ((a | b)<<1) == 0); @@ -2280,18 +2410,21 @@ int float64_eq(float64 a, float64 b, float_status_t &status) int float64_le(float64 a, float64 b, float_status_t &status) { - Bit16s aExp = extractFloat64Exp(a); - Bit16s bExp = extractFloat64Exp(b); - Bit64u aSig = extractFloat64Frac(a); - Bit64u bSig = extractFloat64Frac(b); + float_class_t aClass = float64_class(a); + float_class_t bClass = float64_class(b); - if (((aExp == 0x7FF) && aSig) || ((bExp == 0x7FF) && bSig)) { + if (aClass == float_NaN || bClass == float_NaN) { float_raise(status, float_flag_invalid); return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } flag aSign = extractFloat64Sign(a); @@ -2308,18 +2441,21 @@ int float64_le(float64 a, float64 b, float_status_t &status) int float64_lt(float64 a, float64 b, float_status_t &status) { - Bit16s aExp = extractFloat64Exp(a); - Bit16s bExp = extractFloat64Exp(b); - Bit64u aSig = extractFloat64Frac(a); - Bit64u bSig = extractFloat64Frac(b); + float_class_t aClass = float64_class(a); + float_class_t bClass = float64_class(b); - if (((aExp == 0x7FF) && aSig) || ((bExp == 0x7FF) && bSig)) { + if (aClass == float_NaN || bClass == float_NaN) { float_raise(status, float_flag_invalid); return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } flag aSign = extractFloat64Sign(a); @@ -2337,18 +2473,21 @@ int float64_lt(float64 a, float64 b, float_status_t &status) int float64_eq_signaling(float64 a, float64 b, float_status_t &status) { - Bit16s aExp = extractFloat64Exp(a); - Bit16s bExp = extractFloat64Exp(b); - Bit64u aSig = extractFloat64Frac(a); - Bit64u bSig = extractFloat64Frac(b); + float_class_t aClass = float64_class(a); + float_class_t bClass = float64_class(b); - if (((aExp == 0x7FF) && aSig) || ((bExp == 0x7FF) && bSig)) { + if (aClass == float_NaN || bClass == float_NaN) { float_raise(status, float_flag_invalid); return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } return (a == b) || ((Bit64u) ((a | b)<<1) == 0); @@ -2363,12 +2502,10 @@ int float64_eq_signaling(float64 a, float64 b, float_status_t &status) int float64_le_quiet(float64 a, float64 b, float_status_t &status) { - Bit16s aExp = extractFloat64Exp(a); - Bit16s bExp = extractFloat64Exp(b); - Bit64u aSig = extractFloat64Frac(a); - Bit64u bSig = extractFloat64Frac(b); + float_class_t aClass = float64_class(a); + float_class_t bClass = float64_class(b); - if (((aExp == 0x7FF) && aSig) || ((bExp == 0x7FF) && bSig)) + if (aClass == float_NaN || bClass == float_NaN) { if (float64_is_signaling_nan(a) || float64_is_signaling_nan(b)) { @@ -2377,8 +2514,13 @@ int float64_le_quiet(float64 a, float64 b, float_status_t &status) return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } flag aSign = extractFloat64Sign(a); @@ -2396,12 +2538,10 @@ int float64_le_quiet(float64 a, float64 b, float_status_t &status) int float64_lt_quiet(float64 a, float64 b, float_status_t &status) { - Bit16s aExp = extractFloat64Exp(a); - Bit16s bExp = extractFloat64Exp(b); - Bit64u aSig = extractFloat64Frac(a); - Bit64u bSig = extractFloat64Frac(b); + float_class_t aClass = float64_class(a); + float_class_t bClass = float64_class(b); - if (((aExp == 0x7FF) && aSig) || ((bExp == 0x7FF) && bSig)) + if (aClass == float_NaN || bClass == float_NaN) { if (float64_is_signaling_nan(a) || float64_is_signaling_nan(b)) { @@ -2410,8 +2550,13 @@ int float64_lt_quiet(float64 a, float64 b, float_status_t &status) return 0; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } flag aSign = extractFloat64Sign(a); @@ -2449,18 +2594,21 @@ int float64_unordered(float64 a, float64 b, float_status_t &status) int float64_compare(float64 a, float64 b, float_status_t &status) { - Bit16s aExp = extractFloat64Exp(a); - Bit16s bExp = extractFloat64Exp(b); - Bit64u aSig = extractFloat64Frac(a); - Bit64u bSig = extractFloat64Frac(b); + float_class_t aClass = float64_class(a); + float_class_t bClass = float64_class(b); - if (((aExp == 0x7FF) && aSig) || ((bExp == 0x7FF) && bSig)) { + if (aClass == float_NaN || bClass == float_NaN) { float_raise(status, float_flag_invalid); return float_relation_unordered; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } if ((a == b) || ((Bit64u) ((a | b)<<1) == 0)) return float_relation_equal; @@ -2485,22 +2633,25 @@ int float64_compare(float64 a, float64 b, float_status_t &status) int float64_compare_quiet(float64 a, float64 b, float_status_t &status) { - Bit16s aExp = extractFloat64Exp(a); - Bit16s bExp = extractFloat64Exp(b); - Bit64u aSig = extractFloat64Frac(a); - Bit64u bSig = extractFloat64Frac(b); + float_class_t aClass = float64_class(a); + float_class_t bClass = float64_class(b); - if (((aExp == 0x7FF) && aSig) || ((bExp == 0x7FF) && bSig)) + if (aClass == float_NaN || bClass == float_NaN) { - if (float64_is_signaling_nan(a) || float64_is_signaling_nan(b)) + if (float64_is_signaling_nan(a) || float64_is_signaling_nan(b)) { float_raise(status, float_flag_invalid); } return float_relation_unordered; } - if (((aExp == 0) && aSig) || ((bExp == 0) && bSig)) { - float_raise(status, float_flag_denormal); + if (aClass == float_denormal) { + if (get_DAZ(status)) a = 0; + else float_raise(status, float_flag_denormal); + } + if (bClass == float_denormal) { + if (get_DAZ(status)) b = 0; + else float_raise(status, float_flag_denormal); } if ((a == b) || ((Bit64u) ((a | b)<<1) == 0)) return float_relation_equal; diff --git a/bochs/cpu/softfloat.h b/bochs/cpu/softfloat.h index 024d30db6..d6e1bae6e 100755 --- a/bochs/cpu/softfloat.h +++ b/bochs/cpu/softfloat.h @@ -49,6 +49,19 @@ these four paragraphs for those parts of this code that are retained. typedef Bit32u float32, Float32; typedef Bit64u float64, Float64; +/*---------------------------------------------------------------------------- +| Software IEC/IEEE floating-point class. +*----------------------------------------------------------------------------*/ +typedef enum { + float_negative_zero, + float_positive_zero, + float_NaN, + float_negative_inf, + float_positive_inf, + float_denormal, + float_normalized, +} float_class_t; + /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point underflow tininess-detection mode. *----------------------------------------------------------------------------*/ @@ -90,7 +103,6 @@ enum float_exception_flag_t { /*---------------------------------------------------------------------------- | Software IEC/IEEE floating-point ordering relations *----------------------------------------------------------------------------*/ - enum { float_relation_less = -1, float_relation_equal = 0, @@ -162,6 +174,7 @@ int float32_unordered(float32, float32, float_status_t &status); int float32_compare(float32, float32, float_status_t &status); int float32_compare_quiet(float32, float32, float_status_t &status); +float_class_t float32_class(float32); int float32_is_signaling_nan(float32); int float32_is_zero(float32); @@ -196,5 +209,6 @@ int float64_unordered(float64, float64, float_status_t &status); int float64_compare(float64, float64, float_status_t &status); int float64_compare_quiet(float64, float64, float_status_t &status); +float_class_t float64_class(float64); int float64_is_signaling_nan(float64); int float64_is_zero(float64);