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

@ -147,28 +147,31 @@ Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, float_status_t &
}
return z;
}
/*----------------------------------------------------------------------------
| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
| `absZ1', with binary point between bits 63 and 64 (between the input words),
| and returns the properly rounded 64-bit unsigned integer corresponding to the
| input. Ordinarily, the fixed-point input is simply rounded to an integer,
| 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.
*----------------------------------------------------------------------------*/
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 roundNearestEven = (roundingMode == float_round_nearest_even);
int increment = ((Bit64s) absZ1 < 0);
int increment = ((Bit64s) absZ1 < 0);
if (!roundNearestEven) {
if (roundingMode == float_round_to_zero) {
increment = 0;
} else {
increment = (roundingMode == float_round_up) && absZ1;
} else if (absZ1) {
if (zSign) {
increment = (roundingMode == float_round_down) && absZ1;
} else {
increment = (roundingMode == float_round_up) && absZ1;
}
}
}
if (increment) {
@ -177,13 +180,18 @@ Bit64u roundAndPackUint64(Bit64u absZ0, Bit64u absZ1, float_status_t &status)
float_raise(status, float_flag_invalid);
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) {
float_raise(status, float_flag_inexact);
}
return z;
return absZ0;
}
#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
| input. Ordinarily, the fixed-point input is simply rounded to an integer,
| 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.
*----------------------------------------------------------------------------*/
Bit64u roundAndPackUint64(Bit64u absZ0, Bit64u absZ1, float_status_t &status);
Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, float_status_t &status);
#ifdef FLOAT16

View File

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