re PR middle-end/19920 (build broken on several targets due to recent 'DC' type updat...
authorRichard Henderson <rth@redhat.com>
Wed, 16 Feb 2005 22:55:33 +0000 (14:55 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Wed, 16 Feb 2005 22:55:33 +0000 (14:55 -0800)
        PR 19920
        * libgcc2.c (WORD_SIZE): Remove all definitions; replace uses
        with W_TYPE_SIZE.
        (HIGH_WORD_COEFF, HIGH_HALFWORD_COEFF): Remove all definitions;
        replace uses with Wtype_MAXp1_F.
        (L_fixunstfdi, L_fixtfdi, L_floatditf, L_fixunsxfdi, L_fixxfdi,
        L_floatdixf, L_fixunsxfsi, L_fixunsdfdi, L_floatdidf, L_fixunsdfsi,
        L_powidf2, L_powixf2, L_powitf2, L_muldc3, L_divdc3, L_mulxc3,
        L_divxc3, L_multc3, L_divtc3): Protect with HAVE_DFMODE, HAVE_XFMODE,
        and HAVE_TFMODE as appropriate.
        (__fixunssfDI): Provide an implementation that doesn't need DFmode.
        (__floatdisf): Likewise.
        * libgcc2.h (LIBGCC2_DOUBLE_TYPE_SIZE): New.
        (HAVE_DFMODE, HAVE_XFMODE, HAVE_TFMODE): New.
        (Wtype_MAXp1_F): New.
        (DFtype, DCtype, __fixdfdi, __floatdidf, __fixunsdfSI, __fixunsdfDI,
        __powidf2, __divdc3, __muldc3): Protect with HAVE_DFMODE.

From-SVN: r95121

gcc/ChangeLog
gcc/libgcc2.c
gcc/libgcc2.h

index 379b422014ac3318e2e8de2d280502aa33769063..ea3a1c6618529506517668e6b8c26c6aee13237b 100644 (file)
@@ -1,3 +1,23 @@
+2005-02-16  Richard Henderson  <rth@redhat.com>
+
+       PR 19920
+       * libgcc2.c (WORD_SIZE): Remove all definitions; replace uses
+       with W_TYPE_SIZE.
+       (HIGH_WORD_COEFF, HIGH_HALFWORD_COEFF): Remove all definitions;
+       replace uses with Wtype_MAXp1_F.
+       (L_fixunstfdi, L_fixtfdi, L_floatditf, L_fixunsxfdi, L_fixxfdi,
+       L_floatdixf, L_fixunsxfsi, L_fixunsdfdi, L_floatdidf, L_fixunsdfsi,
+       L_powidf2, L_powixf2, L_powitf2, L_muldc3, L_divdc3, L_mulxc3,
+       L_divxc3, L_multc3, L_divtc3): Protect with HAVE_DFMODE, HAVE_XFMODE,
+       and HAVE_TFMODE as appropriate.
+       (__fixunssfDI): Provide an implementation that doesn't need DFmode.
+       (__floatdisf): Likewise.
+       * libgcc2.h (LIBGCC2_DOUBLE_TYPE_SIZE): New.
+       (HAVE_DFMODE, HAVE_XFMODE, HAVE_TFMODE): New.
+       (Wtype_MAXp1_F): New.
+       (DFtype, DCtype, __fixdfdi, __floatdidf, __fixunsdfSI, __fixunsdfDI,
+       __powidf2, __divdc3, __muldc3): Protect with HAVE_DFMODE.
+
 2005-02-16  Richard Earnshaw  <rearnsha@arm.com>
 
        * PR target/19162
index 56a9bc4e87a3dffd9c49a7e6025fa584af4450a6..9bdb1c71228ffa3b072a2f4ef04e3c348dc26783 100644 (file)
@@ -148,13 +148,12 @@ __subvDI3 (DWtype a, DWtype b)
 #endif
 \f
 #ifdef L_mulvsi3
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
 Wtype
 __mulvSI3 (Wtype a, Wtype b)
 {
   const DWtype w = (DWtype) a * (DWtype) b;
 
-  if ((Wtype) (w >> WORD_SIZE) != (Wtype) w >> (WORD_SIZE - 1))
+  if ((Wtype) (w >> W_TYPE_SIZE) != (Wtype) w >> (W_TYPE_SIZE - 1))
     abort ();
 
   return w;
@@ -273,7 +272,6 @@ __absvDI2 (DWtype a)
 #endif
 \f
 #ifdef L_mulvdi3
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
 DWtype
 __mulvDI3 (DWtype u, DWtype v)
 {
@@ -282,10 +280,10 @@ __mulvDI3 (DWtype u, DWtype v)
   const DWunion uu = {.ll = u};
   const DWunion vv = {.ll = v};
 
-  if (__builtin_expect (uu.s.high == uu.s.low >> (WORD_SIZE - 1), 1))
+  if (__builtin_expect (uu.s.high == uu.s.low >> (W_TYPE_SIZE - 1), 1))
     {
       /* u fits in a single Wtype.  */
-      if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1))
+      if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1))
        {
          /* v fits in a single Wtype as well.  */
          /* A single multiplication.  No overflow risk.  */
@@ -304,7 +302,7 @@ __mulvDI3 (DWtype u, DWtype v)
          if (uu.s.low < 0)
            w1.ll -= vv.ll;
          w1.ll += (UWtype) w0.s.high;
-         if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1))
+         if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1))
            {
              w0.s.high = w1.s.low;
              return w0.ll;
@@ -313,7 +311,7 @@ __mulvDI3 (DWtype u, DWtype v)
     }
   else
     {
-      if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1))
+      if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1))
        {
          /* v fits into a single Wtype.  */
          /* Two multiplications.  */
@@ -327,7 +325,7 @@ __mulvDI3 (DWtype u, DWtype v)
          if (vv.s.low < 0)
            w1.ll -= uu.ll;
          w1.ll += (UWtype) w0.s.high;
-         if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1))
+         if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1))
            {
              w0.s.high = w1.s.low;
              return w0.ll;
@@ -1157,10 +1155,7 @@ __ucmpdi2 (DWtype a, DWtype b)
 }
 #endif
 \f
-#if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_fixunstfdi) && defined(HAVE_TFMODE)
 DWtype
 __fixunstfDI (TFtype a)
 {
@@ -1168,11 +1163,11 @@ __fixunstfDI (TFtype a)
     return 0;
 
   /* Compute high word of result, as a flonum.  */
-  const TFtype b = (a / HIGH_WORD_COEFF);
+  const TFtype b = (a / Wtype_MAXp1_F);
   /* Convert that to fixed (but not to DWtype!),
      and shift it into the high word.  */
   UDWtype v = (UWtype) b;
-  v <<= WORD_SIZE;
+  v <<= W_TYPE_SIZE;
   /* Remove high part from the TFtype, leaving the low part as flonum.  */
   a -= (TFtype)v;
   /* Convert that to fixed (but not to DWtype!) and add it in.
@@ -1186,7 +1181,7 @@ __fixunstfDI (TFtype a)
 }
 #endif
 
-#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
+#if defined(L_fixtfdi) && defined(HAVE_TFMODE)
 DWtype
 __fixtfdi (TFtype a)
 {
@@ -1196,10 +1191,7 @@ __fixtfdi (TFtype a)
 }
 #endif
 
-#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_fixunsxfdi) && defined(HAVE_XFMODE)
 DWtype
 __fixunsxfDI (XFtype a)
 {
@@ -1207,11 +1199,11 @@ __fixunsxfDI (XFtype a)
     return 0;
 
   /* Compute high word of result, as a flonum.  */
-  const XFtype b = (a / HIGH_WORD_COEFF);
+  const XFtype b = (a / Wtype_MAXp1_F);
   /* Convert that to fixed (but not to DWtype!),
      and shift it into the high word.  */
   UDWtype v = (UWtype) b;
-  v <<= WORD_SIZE;
+  v <<= W_TYPE_SIZE;
   /* Remove high part from the XFtype, leaving the low part as flonum.  */
   a -= (XFtype)v;
   /* Convert that to fixed (but not to DWtype!) and add it in.
@@ -1225,7 +1217,7 @@ __fixunsxfDI (XFtype a)
 }
 #endif
 
-#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
+#if defined(L_fixxfdi) && defined(HAVE_XFMODE)
 DWtype
 __fixxfdi (XFtype a)
 {
@@ -1235,29 +1227,26 @@ __fixxfdi (XFtype a)
 }
 #endif
 
-#ifdef L_fixunsdfdi
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_fixunsdfdi) && defined(HAVE_DFMODE)
 DWtype
 __fixunsdfDI (DFtype a)
 {
   /* Get high part of result.  The division here will just moves the radix
      point and will not cause any rounding.  Then the conversion to integral
      type chops result as desired.  */
-  const UWtype hi = a / HIGH_WORD_COEFF;
+  const UWtype hi = a / Wtype_MAXp1_F;
 
   /* Get low part of result.  Convert `hi' to floating type and scale it back,
      then subtract this from the number being converted.  This leaves the low
      part.  Convert that to integral type.  */
-  const UWtype lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
+  const UWtype lo = a - (DFtype) hi * Wtype_MAXp1_F;
 
   /* Assemble result from the two parts.  */
-  return ((UDWtype) hi << WORD_SIZE) | lo;
+  return ((UDWtype) hi << W_TYPE_SIZE) | lo;
 }
 #endif
 
-#ifdef L_fixdfdi
+#if defined(L_fixdfdi) && defined(HAVE_DFMODE)
 DWtype
 __fixdfdi (DFtype a)
 {
@@ -1268,29 +1257,66 @@ __fixdfdi (DFtype a)
 #endif
 
 #ifdef L_fixunssfdi
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
 DWtype
-__fixunssfDI (SFtype original_a)
+__fixunssfDI (SFtype a)
 {
+#if defined(HAVE_DFMODE)
   /* Convert the SFtype to a DFtype, because that is surely not going
      to lose any bits.  Some day someone else can write a faster version
      that avoids converting to DFtype, and verify it really works right.  */
-  const DFtype a = original_a;
+  const DFtype dfa = a;
 
   /* Get high part of result.  The division here will just moves the radix
      point and will not cause any rounding.  Then the conversion to integral
      type chops result as desired.  */
-  const UWtype hi = a / HIGH_WORD_COEFF;
+  const UWtype hi = dfa / Wtype_MAXp1_F;
 
   /* Get low part of result.  Convert `hi' to floating type and scale it back,
      then subtract this from the number being converted.  This leaves the low
      part.  Convert that to integral type.  */
-  const UWtype lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
+  const UWtype lo = dfa - (DFtype) hi * Wtype_MAXp1_F;
 
   /* Assemble result from the two parts.  */
-  return ((UDWtype) hi << WORD_SIZE) | lo;
+  return ((UDWtype) hi << W_TYPE_SIZE) | lo;
+#elif FLT_MANT_DIG < W_TYPE_SIZE
+  if (a < 1)
+    return 0;
+  if (a < Wtype_MAXp1_F)
+    return (UWtype)a;
+  if (a < Wtype_MAXp1_F * Wtype_MAXp1_F)
+    {
+      /* Since we know that there are fewer significant bits in the SFmode
+        quantity than in a word, we know that we can convert out all the
+        signficant bits in one step, and thus avoid losing bits.  */
+
+      /* ??? This following loop essentially performs frexpf.  If we could
+        use the real libm function, or poke at the actual bits of the fp
+        format, it would be significantly faster.  */
+
+      UWtype shift = 0, counter;
+      SFtype msb;
+
+      a /= Wtype_MAXp1_F;
+      for (counter = W_TYPE_SIZE / 2; counter != 0; counter >>= 1)
+       {
+         SFtype counterf = (UWtype)1 << counter;
+         if (a >= counterf)
+           {
+             shift |= counter;
+             a /= counterf;
+           }
+       }
+
+      /* Rescale into the range of one word, extract the bits of that
+        one word, and shift the result into position.  */
+      a *= Wtype_MAXp1_F;
+      counter = a;
+      return (DWtype)counter << shift;
+    }
+  return -1;
+#else
+# error
+#endif
 }
 #endif
 
@@ -1304,79 +1330,72 @@ __fixsfdi (SFtype a)
 }
 #endif
 
-#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_floatdixf) && defined(HAVE_XFMODE)
 XFtype
 __floatdixf (DWtype u)
 {
-  XFtype d = (Wtype) (u >> WORD_SIZE);
-  d *= HIGH_HALFWORD_COEFF;
-  d *= HIGH_HALFWORD_COEFF;
-  d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
-
+  XFtype d = (Wtype) (u >> W_TYPE_SIZE);
+  d *= Wtype_MAXp1_F;
+  d += (UWtype)u;
   return d;
 }
 #endif
 
-#if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_floatditf) && defined(HAVE_TFMODE)
 TFtype
 __floatditf (DWtype u)
 {
-  TFtype d = (Wtype) (u >> WORD_SIZE);
-  d *= HIGH_HALFWORD_COEFF;
-  d *= HIGH_HALFWORD_COEFF;
-  d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
-
+  TFtype d = (Wtype) (u >> W_TYPE_SIZE);
+  d *= Wtype_MAXp1_F;
+  d += (UWtype)u;
   return d;
 }
 #endif
 
-#ifdef L_floatdidf
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
+#if defined(L_floatdidf) && defined(HAVE_DFMODE)
 DFtype
 __floatdidf (DWtype u)
 {
-  DFtype d = (Wtype) (u >> WORD_SIZE);
-  d *= HIGH_HALFWORD_COEFF;
-  d *= HIGH_HALFWORD_COEFF;
-  d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
-
+  DFtype d = (Wtype) (u >> W_TYPE_SIZE);
+  d *= Wtype_MAXp1_F;
+  d += (UWtype)u;
   return d;
 }
 #endif
 
 #ifdef L_floatdisf
-#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
-
-#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
-#define DF_SIZE DBL_MANT_DIG
+#define DI_SIZE (W_TYPE_SIZE * 2)
 #define SF_SIZE FLT_MANT_DIG
 
 SFtype
 __floatdisf (DWtype u)
 {
+#if SF_SIZE >= W_TYPE_SIZE
+  /* When the word size is small, we never get any rounding error.  */
+  SFtype f = (Wtype) (u >> W_TYPE_SIZE);
+  f *= Wtype_MAXp1_F;
+  f += (UWtype)u;
+  return f;
+#elif defined(HAVE_DFMODE)
+
+#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
+# error
+#endif
+
+#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
+
   /* Protect against double-rounding error.
-     Represent any low-order bits, that might be truncated in DFmode,
-     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.  */
+     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))
     {
-#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
       if (! (- ((DWtype) 1 << DF_SIZE) < u
             && u < ((DWtype) 1 << DF_SIZE)))
        {
@@ -1387,19 +1406,52 @@ __floatdisf (DWtype u)
            }
        }
     }
-  /* 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 >> WORD_SIZE);
-  f *= HIGH_HALFWORD_COEFF;
-  f *= HIGH_HALFWORD_COEFF;
-  f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
 
+  /* 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);
+  f *= Wtype_MAXp1_F;
+  f += (UWtype)u;
   return (SFtype) 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 there are no high bits set, fall back to one conversion.  */
+  if ((Wtype)u == u)
+    return (SFtype)(Wtype)u;
+
+  /* Otherwise, find the power of two.  */
+  Wtype hi = u >> W_TYPE_SIZE;
+  if (hi < 0)
+    hi = -hi;
+
+  UWtype count, shift;
+  count_leading_zeros (count, hi);
+
+  /* No leading bits means u == minimum.  */
+  if (count == 0)
+    return -(Wtype_MAXp1_F * Wtype_MAXp1_F / 2);
+
+  shift = 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))
+    hi |= 1;
+
+  /* Convert the one word of data, and rescale.  */
+  SFtype f = hi;
+  f *= (UWtype)1 << shift;
+  return f;
+#endif
 }
 #endif
 
-#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80
+#if defined(L_fixunsxfsi) && defined(HAVE_XFMODE)
 /* Reenable the normal types, in case limits.h needs them.  */
 #undef char
 #undef short
@@ -1421,7 +1473,7 @@ __fixunsxfSI (XFtype a)
 }
 #endif
 
-#ifdef L_fixunsdfsi
+#if defined(L_fixunsdfsi) && defined(HAVE_DFMODE)
 /* Reenable the normal types, in case limits.h needs them.  */
 #undef char
 #undef short
@@ -1468,9 +1520,10 @@ __fixunssfSI (SFtype a)
 /* Integer power helper used from __builtin_powi for non-constant
    exponents.  */
 
-#if defined(L_powisf2) || defined(L_powidf2) \
-    || (defined(L_powixf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) \
-    || (defined(L_powitf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
+#if defined(L_powisf2) \
+    || (defined(L_powidf2) && defined(HAVE_DFMODE)) \
+    || (defined(L_powixf2) && defined(HAVE_XFMODE)) \
+    || (defined(L_powitf2) && defined(HAVE_TFMODE))
 # if defined(L_powisf2)
 #  define TYPE SFtype
 #  define NAME __powisf2
@@ -1502,11 +1555,9 @@ NAME (TYPE x, Wtype m)
 #endif
 \f
 #if defined(L_mulsc3) || defined(L_divsc3) \
-    || defined(L_muldc3) || defined(L_divdc3) \
-    || (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80 \
-       && (defined(L_mulxc3) || defined(L_divxc3))) \
-    || (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 \
-       && (defined(L_multc3) || defined(L_divtc3)))
+    || ((defined(L_muldc3) || defined(L_divdc3)) && defined(HAVE_DFMODE)) \
+    || ((defined(L_mulxc3) || defined(L_divxc3)) && defined(HAVE_XFMODE)) \
+    || ((defined(L_multc3) || defined(L_divtc3)) && defined(HAVE_TFMODE))
 
 #undef float
 #undef double
index 165787316364e970491a751a9b8e514276f699d4..0a08f51195ed522f0ce65f40d9634e1e1a804993 100644 (file)
@@ -51,6 +51,9 @@ extern short int __get_eh_table_version (struct exception_descriptor *);
 #define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
 #endif
 
+#ifndef LIBGCC2_DOUBLE_TYPE_SIZE
+#define LIBGCC2_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
+#endif
 #ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
 #endif
@@ -91,15 +94,20 @@ typedef unsigned int UTItype        __attribute__ ((mode (TI)));
 #if BITS_PER_UNIT == 8
 
 typedef        float SFtype    __attribute__ ((mode (SF)));
-typedef                float DFtype    __attribute__ ((mode (DF)));
 typedef _Complex float SCtype  __attribute__ ((mode (SC)));
-typedef _Complex float DCtype  __attribute__ ((mode (DC)));
 
+#if LIBGCC2_DOUBLE_TYPE_SIZE == 64 || LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64
+#define HAVE_DFMODE
+typedef                float DFtype    __attribute__ ((mode (DF)));
+typedef _Complex float DCtype  __attribute__ ((mode (DC)));
+#endif
 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80
+#define HAVE_XFMODE
 typedef                float XFtype    __attribute__ ((mode (XF)));
 typedef _Complex float XCtype  __attribute__ ((mode (XC)));
 #endif
 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
+#define HAVE_TFMODE
 typedef                float TFtype    __attribute__ ((mode (TF)));
 typedef _Complex float TCtype  __attribute__ ((mode (TC)));
 #endif
@@ -200,6 +208,18 @@ typedef int word_type __attribute__ ((mode (__word__)));
 #define Wtype_MAX ((Wtype)(((UWtype)1 << (W_TYPE_SIZE - 1)) - 1))
 #define Wtype_MIN (- Wtype_MAX - 1)
 
+#if W_TYPE_SIZE == 8
+# define Wtype_MAXp1_F 0x1p8f
+#elif W_TYPE_SIZE == 16
+# define Wtype_MAXp1_F 0x1p16f
+#elif W_TYPE_SIZE == 32
+# define Wtype_MAXp1_F 0x1p32f
+#elif W_TYPE_SIZE == 64
+# define Wtype_MAXp1_F 0x1p64f
+#else
+# error "expand the table"
+#endif
+
 #define __muldi3       __NDW(mul,3)
 #define __divdi3       __NDW(div,3)
 #define __udivdi3      __NDW(udiv,3)
@@ -301,23 +321,25 @@ extern SItype __negvsi2 (SItype);
 #endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
 
 #if BITS_PER_UNIT == 8
-extern DWtype __fixdfdi (DFtype);
 extern DWtype __fixsfdi (SFtype);
-extern DFtype __floatdidf (DWtype);
 extern SFtype __floatdisf (DWtype);
-extern UWtype __fixunsdfSI (DFtype);
 extern UWtype __fixunssfSI (SFtype);
-extern DWtype __fixunsdfDI (DFtype);
 extern DWtype __fixunssfDI (SFtype);
 extern SFtype __powisf2 (SFtype, Wtype);
-extern DFtype __powidf2 (DFtype, Wtype);
-
 extern SCtype __divsc3 (SFtype, SFtype, SFtype, SFtype);
 extern SCtype __mulsc3 (SFtype, SFtype, SFtype, SFtype);
+
+#ifdef HAVE_DFMODE
+extern DWtype __fixdfdi (DFtype);
+extern DFtype __floatdidf (DWtype);
+extern UWtype __fixunsdfSI (DFtype);
+extern DWtype __fixunsdfDI (DFtype);
+extern DFtype __powidf2 (DFtype, Wtype);
 extern DCtype __divdc3 (DFtype, DFtype, DFtype, DFtype);
 extern DCtype __muldc3 (DFtype, DFtype, DFtype, DFtype);
+#endif
 
-#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80
+#ifdef HAVE_XFMODE
 extern DWtype __fixxfdi (XFtype);
 extern DWtype __fixunsxfDI (XFtype);
 extern XFtype __floatdixf (DWtype);
@@ -327,7 +349,7 @@ extern XCtype __divxc3 (XFtype, XFtype, XFtype, XFtype);
 extern XCtype __mulxc3 (XFtype, XFtype, XFtype, XFtype);
 #endif
 
-#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
+#ifdef HAVE_TFMODE
 extern DWtype __fixunstfDI (TFtype);
 extern DWtype __fixtfdi (TFtype);
 extern TFtype __floatditf (DWtype);