aboutsummaryrefslogtreecommitdiff
path: root/gcc/libgcc2.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2005-12-15 21:50:10 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2005-12-15 21:50:10 +0000
commit4a73d8657b1e02983b234533732b9dbc09c7929b (patch)
tree103ac80216ebf4fcc51f100555eacea1fd58a30f /gcc/libgcc2.c
parent4976b95c37dd8245c7565d76cfb729dc1b7f603f (diff)
downloadgcc-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.c210
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
}