more fixes for uint conversions based on latest QEMU patches by Tom Musta
This commit is contained in:
parent
649075527e
commit
4705ed6bdd
@ -147,28 +147,31 @@ Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, float_status_t &
|
|||||||
}
|
}
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
|
| 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),
|
| `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
|
| 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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------
|
/*----------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user