OSDN Git Service

PR other/25028
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 15 Dec 2005 21:50:10 +0000 (21:50 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 15 Dec 2005 21:50:10 +0000 (21:50 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@108598 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/ia64/hpux.h
gcc/config/ia64/ia64.c
gcc/doc/tm.texi
gcc/libgcc2.c
gcc/libgcc2.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/fp-int-convert-timode.c

index 208beb2..4170cbc 100644 (file)
@@ -1,3 +1,22 @@
+2005-12-15  Joseph S. Myers  <joseph@codesourcery.com>
+
+       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.
+
 2005-12-14  Craig Rodrigues  <rodrigc@gcc.gnu.org>
 
        * freebsd-spec.h (FBSD_TARGET_OS_CPP_BUILTINS):
index 512f7c8..9ffe1fd 100644 (file)
@@ -195,10 +195,12 @@ do {                                                              \
 /* Put all *xf routines in libgcc, regardless of long double size.  */
 #undef LIBGCC2_HAS_XF_MODE
 #define LIBGCC2_HAS_XF_MODE 1
+#define XF_SIZE 64
 
 /* Put all *tf routines in libgcc, regardless of long double size.  */
 #undef LIBGCC2_HAS_TF_MODE
 #define LIBGCC2_HAS_TF_MODE 1
+#define TF_SIZE 113
 
 /* HP-UX headers are C++-compatible.  */
 #define NO_IMPLICIT_EXTERN_C
index 2da3383..e676753 100644 (file)
@@ -8437,11 +8437,13 @@ ia64_init_libfuncs (void)
 
   set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
   set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
+  set_conv_libfunc (sfix_optab, TImode, TFmode, "_U_Qfcnvfxt_quad_to_quad");
   set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl");
   set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl");
 
   set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
   set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
+  set_conv_libfunc (sfloat_optab, TFmode, TImode, "_U_Qfcnvxf_quad_to_quad");
   /* HP-UX 11.23 libc does not have a function for unsigned
      SImode-to-TFmode conversion.  */
   set_conv_libfunc (ufloat_optab, TFmode, DImode, "_U_Qfcnvxuf_dbl_to_quad");
index 64a1a22..b0dd8e1 100644 (file)
@@ -1548,6 +1548,20 @@ anyway.  If you don't define this and @code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE}
 is 128 then the default is 1, otherwise it is 0.
 @end defmac
 
+@defmac SF_SIZE
+@defmacx DF_SIZE
+@defmacx XF_SIZE
+@defmacx TF_SIZE
+Define these macros to be the size in bits of the mantissa of
+@code{SFmode}, @code{DFmode}, @code{XFmode} and @code{TFmode} values,
+if the defaults in @file{libgcc2.h} are inappropriate.  By default,
+@code{FLT_MANT_DIG} is used for @code{SF_SIZE}, @code{LDBL_MANT_DIG}
+for @code{XF_SIZE} and @code{TF_SIZE}, and @code{DBL_MANT_DIG} or
+@code{LDBL_MANT_DIG} for @code{DF_SIZE} according to whether
+@code{LIBGCC2_DOUBLE_TYPE_SIZE} or
+@code{LIBGCC2_LONG_DOUBLE_TYPE_SIZE} is 64.
+@end defmac
+
 @defmac TARGET_FLT_EVAL_METHOD
 A C expression for the value for @code{FLT_EVAL_METHOD} in @file{float.h},
 assuming, if applicable, that the floating-point control word is in its
index d6bd872..03cc448 100644 (file)
@@ -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
 }
index 11a1d9a..f8056d6 100644 (file)
@@ -79,6 +79,44 @@ extern short int __get_eh_table_version (struct exception_descriptor *);
   (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
 #endif
 
+#ifndef SF_SIZE
+#if LIBGCC2_HAS_SF_MODE
+#define SF_SIZE FLT_MANT_DIG
+#else
+#define SF_SIZE 0
+#endif
+#endif
+
+#ifndef DF_SIZE
+#if 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
+#else
+#define DF_SIZE 0
+#endif
+#else
+#define DF_SIZE 0
+#endif
+#endif
+
+#ifndef XF_SIZE
+#if LIBGCC2_HAS_XF_MODE
+#define XF_SIZE LDBL_MANT_DIG
+#else
+#define XF_SIZE 0
+#endif
+#endif
+
+#ifndef TF_SIZE
+#if LIBGCC2_HAS_TF_MODE
+#define TF_SIZE LDBL_MANT_DIG
+#else
+#define TF_SIZE 0
+#endif
+#endif
+
 #ifndef MIN_UNITS_PER_WORD
 #define MIN_UNITS_PER_WORD UNITS_PER_WORD
 #endif
index efeb2a5..39fa89c 100644 (file)
@@ -1,3 +1,9 @@
+2005-12-15  Joseph S. Myers  <joseph@codesourcery.com>
+
+       PR other/25028
+       * gcc.dg/torture/fp-int-convert-timode.c: Only XFAIL for LP64 IA64
+       HP-UX.
+
 2005-12-15  Richard Sandiford  <richard@codesourcery.com>
 
        * gcc.dg/20051215-1.c: New file.
index e60b540..244fc31 100644 (file)
@@ -1,6 +1,6 @@
 /* Test floating-point conversions.  TImode types.  */
 /* Origin: Joseph Myers <joseph@codesourcery.com> */
-/* { dg-do run { xfail lp64 } } */
+/* { dg-do run { xfail { ia64-*-hpux* && lp64 } } } */
 /* { dg-options "" } */
 
 #include <float.h>