diff options
author | Bharata B Rao <bharata@linux.vnet.ibm.com> | 2017-02-10 12:53:06 +0530 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2017-02-22 11:28:28 +1100 |
commit | 2e6d85683576c970c714c1cc071dca742835b9d4 (patch) | |
tree | c710cafe62acfe91b6778c35a632f82dfaf2f21f /fpu | |
parent | 9ee6f678f473007e252934d6acd09c24490d9d42 (diff) |
softfloat: Add float128_to_uint64_round_to_zero()
Implement float128_to_uint64() and use that to implement
float128_to_uint64_round_to_zero()
This is required by xscvqpudz instruction of PowerPC ISA 3.0.
Signed-off-by: Bharata B Rao <bharata@linux.vnet.ibm.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'fpu')
-rw-r--r-- | fpu/softfloat.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 5ccba76481..47e4646570 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -6128,6 +6128,65 @@ int64_t float128_to_int64_round_to_zero(float128 a, float_status *status) } /*---------------------------------------------------------------------------- +| Returns the result of converting the quadruple-precision floating-point value +| `a' to the 64-bit unsigned integer format. The conversion is +| performed according to the IEC/IEEE Standard for Binary Floating-Point +| Arithmetic---which means in particular that the conversion is rounded +| according to the current rounding mode. If `a' is a NaN, the largest +| positive integer is returned. If the conversion overflows, the +| largest unsigned integer is returned. If 'a' is negative, the value is +| rounded and zero is returned; negative values that do not round to zero +| will raise the inexact exception. +*----------------------------------------------------------------------------*/ + +uint64_t float128_to_uint64(float128 a, float_status *status) +{ + flag aSign; + int aExp; + int shiftCount; + uint64_t aSig0, aSig1; + + aSig0 = extractFloat128Frac0(a); + aSig1 = extractFloat128Frac1(a); + aExp = extractFloat128Exp(a); + aSign = extractFloat128Sign(a); + if (aSign && (aExp > 0x3FFE)) { + float_raise(float_flag_invalid, status); + if (float128_is_any_nan(a)) { + return LIT64(0xFFFFFFFFFFFFFFFF); + } else { + return 0; + } + } + if (aExp) { + aSig0 |= LIT64(0x0001000000000000); + } + shiftCount = 0x402F - aExp; + if (shiftCount <= 0) { + if (0x403E < aExp) { + float_raise(float_flag_invalid, status); + return LIT64(0xFFFFFFFFFFFFFFFF); + } + shortShift128Left(aSig0, aSig1, -shiftCount, &aSig0, &aSig1); + } else { + shift64ExtraRightJamming(aSig0, aSig1, shiftCount, &aSig0, &aSig1); + } + return roundAndPackUint64(aSign, aSig0, aSig1, status); +} + +uint64_t float128_to_uint64_round_to_zero(float128 a, float_status *status) +{ + uint64_t v; + signed char current_rounding_mode = status->float_rounding_mode; + + set_float_rounding_mode(float_round_to_zero, status); + v = float128_to_uint64(a, status); + set_float_rounding_mode(current_rounding_mode, status); + + return v; +} + +/*---------------------------------------------------------------------------- | Returns the result of converting the quadruple-precision floating-point | value `a' to the single-precision floating-point format. The conversion | is performed according to the IEC/IEEE Standard for Binary Floating-Point |