From 4705ed6bdd7f730de08284515b2a84a593f71668 Mon Sep 17 00:00:00 2001 From: Stanislav Shwartsman Date: Mon, 20 Jan 2014 21:22:29 +0000 Subject: [PATCH] more fixes for uint conversions based on latest QEMU patches by Tom Musta --- bochs/cpu/fpu/softfloat-round-pack.cc | 28 +++++++++++++++++---------- bochs/cpu/fpu/softfloat-round-pack.h | 4 ++-- bochs/cpu/fpu/softfloat.cc | 28 +++++++++------------------ 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/bochs/cpu/fpu/softfloat-round-pack.cc b/bochs/cpu/fpu/softfloat-round-pack.cc index e995e52cf..0839fb2d2 100644 --- a/bochs/cpu/fpu/softfloat-round-pack.cc +++ b/bochs/cpu/fpu/softfloat-round-pack.cc @@ -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 diff --git a/bochs/cpu/fpu/softfloat-round-pack.h b/bochs/cpu/fpu/softfloat-round-pack.h index 9ac99c935..84e3a70d6 100644 --- a/bochs/cpu/fpu/softfloat-round-pack.h +++ b/bochs/cpu/fpu/softfloat-round-pack.h @@ -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 diff --git a/bochs/cpu/fpu/softfloat.cc b/bochs/cpu/fpu/softfloat.cc index 4ca68d956..044bdba4d 100644 --- a/bochs/cpu/fpu/softfloat.cc +++ b/bochs/cpu/fpu/softfloat.cc @@ -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); } /*----------------------------------------------------------------------------