more fixes for uint conversions based on latest QEMU patches by Tom Musta

This commit is contained in:
Stanislav Shwartsman 2014-01-20 21:22:29 +00:00
parent 649075527e
commit 4705ed6bdd
3 changed files with 29 additions and 31 deletions

View File

@ -154,21 +154,24 @@ Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, float_status_t &
| and returns the properly rounded 64-bit unsigned integer corresponding to the | and returns the properly rounded 64-bit unsigned integer corresponding to the
| input. Ordinarily, the fixed-point input is simply rounded to an integer, | input. Ordinarily, the fixed-point input is simply rounded to an integer,
| with the inexact exception raised if the input cannot be represented exactly | with the inexact exception raised if the input cannot be represented exactly
| as an integer. However, if the fixed-point input is too large, the invalid | as an integer. However, if the fixed-point input is too large, the invalid
| exception is raised and the largest unsigned integer is returned. | exception is raised and the largest unsigned integer is returned.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
Bit64u roundAndPackUint64(Bit64u absZ0, Bit64u absZ1, float_status_t &status) Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, float_status_t &status)
{ {
int roundingMode = get_float_rounding_mode(status); int roundingMode = get_float_rounding_mode(status);
int roundNearestEven = (roundingMode == float_round_nearest_even); int roundNearestEven = (roundingMode == float_round_nearest_even);
int increment = ((Bit64s) absZ1 < 0); int increment = ((Bit64s) absZ1 < 0);
if (!roundNearestEven) { if (!roundNearestEven) {
if (roundingMode == float_round_to_zero) { if (roundingMode == float_round_to_zero) {
increment = 0; increment = 0;
} else { } else if (absZ1) {
increment = (roundingMode == float_round_up) && absZ1; if (zSign) {
increment = (roundingMode == float_round_down) && absZ1;
} else {
increment = (roundingMode == float_round_up) && absZ1;
}
} }
} }
if (increment) { if (increment) {
@ -177,13 +180,18 @@ Bit64u roundAndPackUint64(Bit64u absZ0, Bit64u absZ1, float_status_t &status)
float_raise(status, float_flag_invalid); float_raise(status, float_flag_invalid);
return uint64_indefinite; return uint64_indefinite;
} }
absZ0 &= ~(((Bit64u)(absZ1<<1) == 0) & roundNearestEven); absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven);
} }
Bit64u z = absZ0;
if (zSign && absZ0) {
float_raise(status, float_flag_invalid);
return uint64_indefinite;
}
if (absZ1) { if (absZ1) {
float_raise(status, float_flag_inexact); float_raise(status, float_flag_inexact);
} }
return z; return absZ0;
} }
#ifdef FLOAT16 #ifdef FLOAT16

View File

@ -69,11 +69,11 @@ Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, float_status_t &
| and returns the properly rounded 64-bit unsigned integer corresponding to the | and returns the properly rounded 64-bit unsigned integer corresponding to the
| input. Ordinarily, the fixed-point input is simply rounded to an integer, | input. Ordinarily, the fixed-point input is simply rounded to an integer,
| with the inexact exception raised if the input cannot be represented exactly | with the inexact exception raised if the input cannot be represented exactly
| as an integer. However, if the fixed-point input is too large, the invalid | as an integer. However, if the fixed-point input is too large, the invalid
| exception is raised and the largest unsigned integer is returned. | exception is raised and the largest unsigned integer is returned.
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
Bit64u roundAndPackUint64(Bit64u absZ0, Bit64u absZ1, float_status_t &status); Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, float_status_t &status);
#ifdef FLOAT16 #ifdef FLOAT16

View File

@ -433,13 +433,9 @@ Bit64u float32_to_uint64(float32 a, float_status_t &status)
if (aExp == 0) aSig = 0; if (aExp == 0) aSig = 0;
} }
if (aSign) { if ((aSign) && (aExp > 0x7E)) {
if (aExp > 0x7E) { float_raise(status, float_flag_invalid);
float_raise(status, float_flag_invalid); return uint64_indefinite;
return uint64_indefinite;
}
if (aExp | aSig) float_raise(status, float_flag_inexact);
return 0;
} }
shiftCount = 0xBE - aExp; shiftCount = 0xBE - aExp;
@ -454,7 +450,7 @@ Bit64u float32_to_uint64(float32 a, float_status_t &status)
aSig64 = aSig; aSig64 = aSig;
aSig64 <<= 40; aSig64 <<= 40;
shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra); shift64ExtraRightJamming(aSig64, 0, shiftCount, &aSig64, &aSigExtra);
return roundAndPackUint64(aSig64, aSigExtra, status); return roundAndPackUint64(aSign, aSig64, aSigExtra, status);
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
@ -1387,13 +1383,9 @@ Bit64u float64_to_uint64(float64 a, float_status_t &status)
if (aExp == 0) aSig = 0; if (aExp == 0) aSig = 0;
} }
if (aSign) { if (aSign && (aExp > 0x3FE)) {
if (aExp > 0x3FE) { float_raise(status, float_flag_invalid);
float_raise(status, float_flag_invalid); return uint64_indefinite;
return uint64_indefinite;
}
if (aExp | aSig) float_raise(status, float_flag_inexact);
return 0;
} }
if (aExp) { if (aExp) {
@ -1402,9 +1394,7 @@ Bit64u float64_to_uint64(float64 a, float_status_t &status)
shiftCount = 0x433 - aExp; shiftCount = 0x433 - aExp;
if (shiftCount <= 0) { if (shiftCount <= 0) {
if (0x43E < aExp) { if (0x43E < aExp) {
if ((aSig != BX_CONST64(0x0010000000000000)) || (aExp == 0x7FF)) { float_raise(status, float_flag_invalid);
float_raise(status, float_flag_invalid);
}
return uint64_indefinite; return uint64_indefinite;
} }
aSigExtra = 0; aSigExtra = 0;
@ -1413,7 +1403,7 @@ Bit64u float64_to_uint64(float64 a, float_status_t &status)
shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra); shift64ExtraRightJamming(aSig, 0, shiftCount, &aSig, &aSigExtra);
} }
return roundAndPackUint64(aSig, aSigExtra, status); return roundAndPackUint64(aSign, aSig, aSigExtra, status);
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------