diff options
author | Joseph Myers <joseph@codesourcery.com> | 2005-12-15 21:50:10 +0000 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2005-12-15 21:50:10 +0000 |
commit | 4a73d8657b1e02983b234533732b9dbc09c7929b (patch) | |
tree | 103ac80216ebf4fcc51f100555eacea1fd58a30f /gcc/libgcc2.c | |
parent | 4976b95c37dd8245c7565d76cfb729dc1b7f603f (diff) | |
download | gcc-4a73d8657b1e02983b234533732b9dbc09c7929b.zip gcc-4a73d8657b1e02983b234533732b9dbc09c7929b.tar.gz gcc-4a73d8657b1e02983b234533732b9dbc09c7929b.tar.bz2 |
re PR other/25028 (TImode-to-floating conversions broken)
PR other/25028
* libgcc2.h (SF_SIZE, DF_SIZE, XF_SIZE, TF_SIZE): Define.
* libgcc2.c (__floatdixf, __floatundixf, __floatditf,
__floatunditf): Use #error if type sizes don't match requirements
of implementation.
(__floatdisf, __floatdidf): Unify. Possibly use XFmode or TFmode
as wider floating-point type. Use #error if type sizes don't
match requirements of implementation. Avoid overflow in computing
Wtype_MAXp1_F * Wtype_MAXp1_F. When special casing conversion,
shift one more bit. Cast 1 to DWtype or UDWtype for shifting.
(__floatundisf, __floatundidf): Likewise.
* config/ia64/hpux.h (XF_SIZE, TF_SIZE): Define.
* config/ia64/ia64.c (ia64_init_libfuncs): Use
_U_Qfcnvfxt_quad_to_quad and _U_Qfcnvxf_quad_to_quad for
TFmode-TImode conversions.
* doc/tm.texi (SF_SIZE, DF_SIZE, XF_SIZE, TF_SIZE): Document.
testsuite:
* gcc.dg/torture/fp-int-convert-timode.c: Only XFAIL for LP64 IA64
HP-UX.
From-SVN: r108598
Diffstat (limited to 'gcc/libgcc2.c')
-rw-r--r-- | gcc/libgcc2.c | 210 |
1 files changed, 117 insertions, 93 deletions
diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index d6bd872..03cc448 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -1316,6 +1316,9 @@ __fixsfdi (SFtype a) XFtype __floatdixf (DWtype u) { +#if W_TYPE_SIZE > XF_SIZE +# error +#endif XFtype d = (Wtype) (u >> W_TYPE_SIZE); d *= Wtype_MAXp1_F; d += (UWtype)u; @@ -1327,6 +1330,9 @@ __floatdixf (DWtype u) XFtype __floatundixf (UDWtype u) { +#if W_TYPE_SIZE > XF_SIZE +# error +#endif XFtype d = (UWtype) (u >> W_TYPE_SIZE); d *= Wtype_MAXp1_F; d += (UWtype)u; @@ -1338,6 +1344,9 @@ __floatundixf (UDWtype u) TFtype __floatditf (DWtype u) { +#if W_TYPE_SIZE > TF_SIZE +# error +#endif TFtype d = (Wtype) (u >> W_TYPE_SIZE); d *= Wtype_MAXp1_F; d += (UWtype)u; @@ -1349,93 +1358,91 @@ __floatditf (DWtype u) TFtype __floatunditf (UDWtype u) { - TFtype d = (UWtype) (u >> W_TYPE_SIZE); - d *= Wtype_MAXp1_F; - d += (UWtype)u; - return d; -} -#endif - -#if defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE -DFtype -__floatdidf (DWtype u) -{ - DFtype d = (Wtype) (u >> W_TYPE_SIZE); - d *= Wtype_MAXp1_F; - d += (UWtype)u; - return d; -} +#if W_TYPE_SIZE > TF_SIZE +# error #endif - -#if defined(L_floatundidf) && LIBGCC2_HAS_DF_MODE -DFtype -__floatundidf (UDWtype u) -{ - DFtype d = (UWtype) (u >> W_TYPE_SIZE); + TFtype d = (UWtype) (u >> W_TYPE_SIZE); d *= Wtype_MAXp1_F; d += (UWtype)u; return d; } #endif -#if defined(L_floatdisf) && LIBGCC2_HAS_SF_MODE +#if (defined(L_floatdisf) && LIBGCC2_HAS_SF_MODE) \ + || (defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE) #define DI_SIZE (W_TYPE_SIZE * 2) -#define SF_SIZE FLT_MANT_DIG +#define F_MODE_OK(SIZE) (SIZE < DI_SIZE && SIZE > (DI_SIZE - SIZE + FSSIZE)) +#if defined(L_floatdisf) +#define FUNC __floatdisf +#define FSTYPE SFtype +#define FSSIZE SF_SIZE +#else +#define FUNC __floatdidf +#define FSTYPE DFtype +#define FSSIZE DF_SIZE +#endif -SFtype -__floatdisf (DWtype u) +FSTYPE +FUNC (DWtype u) { -#if SF_SIZE >= W_TYPE_SIZE +#if FSSIZE >= W_TYPE_SIZE /* When the word size is small, we never get any rounding error. */ - SFtype f = (Wtype) (u >> W_TYPE_SIZE); + FSTYPE f = (Wtype) (u >> W_TYPE_SIZE); f *= Wtype_MAXp1_F; f += (UWtype)u; return f; -#elif LIBGCC2_HAS_DF_MODE - -#if LIBGCC2_DOUBLE_TYPE_SIZE == 64 -#define DF_SIZE DBL_MANT_DIG -#elif LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64 -#define DF_SIZE LDBL_MANT_DIG +#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \ + || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \ + || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) + +#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) +# define FSIZE DF_SIZE +# define FTYPE DFtype +#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) +# define FSIZE XF_SIZE +# define FTYPE XFtype +#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) +# define FSIZE TF_SIZE +# define FTYPE TFtype #else # error #endif -#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE)) +#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE)) /* Protect against double-rounding error. Represent any low-order bits, that might be truncated by a bit that won't be lost. The bit can go in anywhere below the rounding position - of the SFmode. A fixed mask and bit position handles all usual - configurations. It doesn't handle the case of 128-bit DImode, however. */ - if (DF_SIZE < DI_SIZE - && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE)) + of the FSTYPE. A fixed mask and bit position handles all usual + configurations. */ + if (! (- ((DWtype) 1 << FSIZE) < u + && u < ((DWtype) 1 << FSIZE))) { - if (! (- ((DWtype) 1 << DF_SIZE) < u - && u < ((DWtype) 1 << DF_SIZE))) + if ((UDWtype) u & (REP_BIT - 1)) { - if ((UDWtype) u & (REP_BIT - 1)) - { - u &= ~ (REP_BIT - 1); - u |= REP_BIT; - } + u &= ~ (REP_BIT - 1); + u |= REP_BIT; } } - /* Do the calculation in DFmode so that we don't lose any of the - precision of the high word while multiplying it. */ - DFtype f = (Wtype) (u >> W_TYPE_SIZE); + /* Do the calculation in a wider type so that we don't lose any of + the precision of the high word while multiplying it. */ + FTYPE f = (Wtype) (u >> W_TYPE_SIZE); f *= Wtype_MAXp1_F; f += (UWtype)u; - return (SFtype) f; + return (FSTYPE) f; #else - /* Finally, the word size is larger than the number of bits in SFmode, - and we've got no DFmode. The only way to avoid double rounding is - to special case the extraction. */ +#if FSSIZE >= W_TYPE_SIZE - 2 +# error +#endif + /* Finally, the word size is larger than the number of bits in the + required FSTYPE, and we've got no suitable wider type. The only + way to avoid double rounding is to special case the + extraction. */ /* If there are no high bits set, fall back to one conversion. */ if ((Wtype)u == u) - return (SFtype)(Wtype)u; + return (FSTYPE)(Wtype)u; /* Otherwise, find the power of two. */ Wtype hi = u >> W_TYPE_SIZE; @@ -1447,82 +1454,99 @@ __floatdisf (DWtype u) /* No leading bits means u == minimum. */ if (count == 0) - return -(Wtype_MAXp1_F * Wtype_MAXp1_F / 2); + return -(Wtype_MAXp1_F * (Wtype_MAXp1_F / 2)); - shift = W_TYPE_SIZE - count; + shift = 1 + W_TYPE_SIZE - count; /* Shift down the most significant bits. */ hi = u >> shift; /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */ - if (u & ((1 << shift) - 1)) + if (u & (((DWtype)1 << shift) - 1)) hi |= 1; /* Convert the one word of data, and rescale. */ - SFtype f = hi; - f *= (UWtype)1 << shift; + FSTYPE f = hi; + f *= (UDWtype)1 << shift; return f; #endif } #endif -#if defined(L_floatundisf) && LIBGCC2_HAS_SF_MODE +#if (defined(L_floatundisf) && LIBGCC2_HAS_SF_MODE) \ + || (defined(L_floatundidf) && LIBGCC2_HAS_DF_MODE) #define DI_SIZE (W_TYPE_SIZE * 2) -#define SF_SIZE FLT_MANT_DIG +#define F_MODE_OK(SIZE) (SIZE < DI_SIZE && SIZE > (DI_SIZE - SIZE + FSSIZE)) +#if defined(L_floatundisf) +#define FUNC __floatundisf +#define FSTYPE SFtype +#define FSSIZE SF_SIZE +#else +#define FUNC __floatundidf +#define FSTYPE DFtype +#define FSSIZE DF_SIZE +#endif -SFtype -__floatundisf (UDWtype u) +FSTYPE +FUNC (UDWtype u) { -#if SF_SIZE >= W_TYPE_SIZE +#if FSSIZE >= W_TYPE_SIZE /* When the word size is small, we never get any rounding error. */ - SFtype f = (UWtype) (u >> W_TYPE_SIZE); + FSTYPE f = (UWtype) (u >> W_TYPE_SIZE); f *= Wtype_MAXp1_F; f += (UWtype)u; return f; -#elif LIBGCC2_HAS_DF_MODE - -#if LIBGCC2_DOUBLE_TYPE_SIZE == 64 -#define DF_SIZE DBL_MANT_DIG -#elif LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64 -#define DF_SIZE LDBL_MANT_DIG +#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \ + || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \ + || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) + +#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) +# define FSIZE DF_SIZE +# define FTYPE DFtype +#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) +# define FSIZE XF_SIZE +# define FTYPE XFtype +#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) +# define FSIZE TF_SIZE +# define FTYPE TFtype #else # error #endif -#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE)) +#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE)) /* Protect against double-rounding error. Represent any low-order bits, that might be truncated by a bit that won't be lost. The bit can go in anywhere below the rounding position - of the SFmode. A fixed mask and bit position handles all usual - configurations. It doesn't handle the case of 128-bit DImode, however. */ - if (DF_SIZE < DI_SIZE - && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE)) + of the FSTYPE. A fixed mask and bit position handles all usual + configurations. */ + if (u >= ((UDWtype) 1 << FSIZE)) { - if (u >= ((UDWtype) 1 << DF_SIZE)) + if ((UDWtype) u & (REP_BIT - 1)) { - if ((UDWtype) u & (REP_BIT - 1)) - { - u &= ~ (REP_BIT - 1); - u |= REP_BIT; - } + u &= ~ (REP_BIT - 1); + u |= REP_BIT; } } - /* Do the calculation in DFmode so that we don't lose any of the - precision of the high word while multiplying it. */ - DFtype f = (UWtype) (u >> W_TYPE_SIZE); + /* Do the calculation in a wider type so that we don't lose any of + the precision of the high word while multiplying it. */ + FTYPE f = (UWtype) (u >> W_TYPE_SIZE); f *= Wtype_MAXp1_F; f += (UWtype)u; - return (SFtype) f; + return (FSTYPE) f; #else - /* Finally, the word size is larger than the number of bits in SFmode, - and we've got no DFmode. The only way to avoid double rounding is - to special case the extraction. */ +#if FSSIZE == W_TYPE_SIZE - 1 +# error +#endif + /* Finally, the word size is larger than the number of bits in the + required FSTYPE, and we've got no suitable wider type. The only + way to avoid double rounding is to special case the + extraction. */ /* If there are no high bits set, fall back to one conversion. */ if ((UWtype)u == u) - return (SFtype)(UWtype)u; + return (FSTYPE)(UWtype)u; /* Otherwise, find the power of two. */ UWtype hi = u >> W_TYPE_SIZE; @@ -1536,12 +1560,12 @@ __floatundisf (UDWtype u) hi = u >> shift; /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */ - if (u & ((1 << shift) - 1)) + if (u & (((UDWtype)1 << shift) - 1)) hi |= 1; /* Convert the one word of data, and rescale. */ - SFtype f = hi; - f *= (UWtype)1 << shift; + FSTYPE f = hi; + f *= (UDWtype)1 << shift; return f; #endif } |