On 1 February 2017 at 10:49, Bharata B Rao <bhar...@linux.vnet.ibm.com> wrote: > 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 <bhar...@linux.vnet.ibm.com> > --- > fpu/softfloat.c | 65 > +++++++++++++++++++++++++++++++++++++++++++++++++ > include/fpu/softfloat.h | 2 ++ > 2 files changed, 67 insertions(+) > > diff --git a/fpu/softfloat.c b/fpu/softfloat.c > index c295f31..49a06c5 100644 > --- a/fpu/softfloat.c > +++ b/fpu/softfloat.c > @@ -6110,6 +6110,71 @@ 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. Otherwise, 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; > + int32_t aExp, shiftCount; > + uint64_t aSig0, aSig1;
I think we should have a float128_squash_input_denormal() function which we call here (compare float64_to_uint64). > + > + aSig1 = extractFloat128Frac1( a ); Can you use the QEMU coding style for this rather than following the softfloat weird one, please? > + aSig0 = extractFloat128Frac0( a ); > + aExp = extractFloat128Exp( a ); > + aSign = extractFloat128Sign( a ); > + if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); > + shiftCount = 0x402F - aExp; > + if ( shiftCount <= 0 ) { > + if ( 0x403E < aExp ) { > + float_raise(float_flag_invalid, status); > + if ( ! aSign > + || ( ( aExp == 0x7FFF ) > + && ( aSig1 || ( aSig0 != LIT64( 0x0001000000000000 ) ) > ) > + ) > + ) { > + return LIT64( 0xFFFFFFFFFFFFFFFF ); > + } > + return 0; > + } > + shortShift128Left( aSig0, aSig1, - shiftCount, &aSig0, &aSig1 ); > + } > + else { > + shift64ExtraRightJamming( aSig0, aSig1, shiftCount, &aSig0, &aSig1 ); > + } > + return roundAndPackUint64(aSign, aSig0, aSig1, status); I'm finding this a bit difficult to understand, because it doesn't follow the code pattern of (for instance) float64_to_uint64(). Is it based on some other existing function? > +} > + > +/*---------------------------------------------------------------------------- > +| 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, except that the conversion is always rounded toward zero. > +| according to the current rounding mode. If `a' is a NaN, the largest > +| positive integer is returned. Otherwise, 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_round_to_zero(float128 a, float_status *status) > +{ > + signed char current_rounding_mode = status->float_rounding_mode; > + set_float_rounding_mode(float_round_to_zero, status); > + uint64_t v = float128_to_uint64(a, status); > + set_float_rounding_mode(current_rounding_mode, status); > + return v; > +} This function is OK, though our coding style would suggest putting the declaration of 'uint64_t v;' at the top of the function. > + > +/*---------------------------------------------------------------------------- > +| 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 > | Arithmetic. > diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h > index 842ec6b..4e99253 100644 > --- a/include/fpu/softfloat.h > +++ b/include/fpu/softfloat.h > @@ -712,6 +712,8 @@ int32_t float128_to_int32(float128, float_status *status); > int32_t float128_to_int32_round_to_zero(float128, float_status *status); > int64_t float128_to_int64(float128, float_status *status); > int64_t float128_to_int64_round_to_zero(float128, float_status *status); > +uint64_t float128_to_uint64(float128, float_status *status); > +uint64_t float128_to_uint64_round_to_zero(float128, float_status *status); > float32 float128_to_float32(float128, float_status *status); > float64 float128_to_float64(float128, float_status *status); > floatx80 float128_to_floatx80(float128, float_status *status); > -- > 2.7.4 thanks -- PMM