DAZ support (still under validation)

This commit is contained in:
Stanislav Shwartsman 2003-05-17 17:45:54 +00:00
parent 7e7cbdba6f
commit 338e7b4fe2
2 changed files with 321 additions and 156 deletions

View File

@ -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;

View File

@ -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);