OSDN Git Service

* libsupc++/del_op.cc: Don't include cstdlib when !_GLIBCXX_HOSTED.
[pf3gnuchains/gcc-fork.git] / gcc / libgcc2.c
index 0f007ec..9d12d32 100644 (file)
@@ -1,7 +1,7 @@
 /* More subroutines needed by GCC output code on some machines.  */
 /* Compile this one with gcc.  */
 /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001  Free Software Foundation, Inc.
+   2000, 2001, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -29,36 +29,43 @@ along with GCC; see the file COPYING.  If not, write to the Free
 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 02111-1307, USA.  */
 
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN.  This is
+   supposedly valid even though this is a "target" file.  */
+#include "auto-host.h"
+
 /* It is incorrect to include config.h here, because this file is being
    compiled for the target, and hence definitions concerning only the host
    do not apply.  */
-
 #include "tconfig.h"
 #include "tsystem.h"
-
-#include "machmode.h"
+#include "coretypes.h"
+#include "tm.h"
 
 /* Don't use `fancy_abort' here even if config.h says to use it.  */
 #ifdef abort
 #undef abort
 #endif
 
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
 #include "libgcc2.h"
 \f
-#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
-#if defined (L_divdi3) || defined (L_moddi3)
-static inline
+#ifdef DECLARE_LIBRARY_RENAMES
+  DECLARE_LIBRARY_RENAMES
 #endif
+
+#if defined (L_negdi2)
 DWtype
 __negdi2 (DWtype u)
 {
-  DWunion w;
-  DWunion uu;
-
-  uu.ll = u;
-
-  w.s.low = -uu.s.low;
-  w.s.high = -uu.s.high - ((UWtype) w.s.low > 0);
+  const DWunion uu = {.ll = u};
+  const DWunion w = { {.low = -uu.s.low,
+                      .high = -uu.s.high - ((UWtype) -uu.s.low > 0) } };
 
   return w.ll;
 }
@@ -66,26 +73,34 @@ __negdi2 (DWtype u)
 
 #ifdef L_addvsi3
 Wtype
-__addvsi3 (Wtype a, Wtype b)
+__addvSI3 (Wtype a, Wtype b)
 {
-  Wtype w;
+  const Wtype w = a + b;
+
+  if (b >= 0 ? w < a : w > a)
+    abort ();
 
-  w = a + b;
+  return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__addvsi3 (SItype a, SItype b)
+{
+  const SItype w = a + b;
 
   if (b >= 0 ? w < a : w > a)
     abort ();
 
   return w;
 }
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
 #endif
 \f
 #ifdef L_addvdi3
 DWtype
-__addvdi3 (DWtype a, DWtype b)
+__addvDI3 (DWtype a, DWtype b)
 {
-  DWtype w;
-
-  w = a + b;
+  const DWtype w = a + b;
 
   if (b >= 0 ? w < a : w > a)
     abort ();
@@ -96,159 +111,306 @@ __addvdi3 (DWtype a, DWtype b)
 \f
 #ifdef L_subvsi3
 Wtype
-__subvsi3 (Wtype a, Wtype b)
+__subvSI3 (Wtype a, Wtype b)
 {
-#ifdef L_addvsi3
-  return __addvsi3 (a, (-b));
-#else
-  DWtype w;
+  const Wtype w = a - b;
+
+  if (b >= 0 ? w > a : w < a)
+    abort ();
 
-  w = a - b;
+  return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__subvsi3 (SItype a, SItype b)
+{
+  const SItype w = a - b;
 
   if (b >= 0 ? w > a : w < a)
     abort ();
 
   return w;
-#endif
 }
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
 #endif
 \f
 #ifdef L_subvdi3
 DWtype
-__subvdi3 (DWtype a, DWtype b)
+__subvDI3 (DWtype a, DWtype b)
 {
-#ifdef L_addvdi3
-  return (a, (-b));
-#else
-  DWtype w;
-
-  w = a - b;
+  const DWtype w = a - b;
 
   if (b >= 0 ? w > a : w < a)
     abort ();
 
   return w;
-#endif
 }
 #endif
 \f
 #ifdef L_mulvsi3
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
 Wtype
-__mulvsi3 (Wtype a, Wtype b)
+__mulvSI3 (Wtype a, Wtype b)
 {
-  DWtype w;
+  const DWtype w = (DWtype) a * (DWtype) b;
 
-  w = a * b;
+  if ((Wtype) (w >> WORD_SIZE) != (Wtype) w >> (WORD_SIZE - 1))
+    abort ();
+
+  return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+#undef WORD_SIZE
+#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+SItype
+__mulvsi3 (SItype a, SItype b)
+{
+  const DItype w = (DItype) a * (DItype) b;
 
-  if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0)
+  if ((SItype) (w >> WORD_SIZE) != (SItype) w >> (WORD_SIZE-1))
     abort ();
 
   return w;
 }
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
 #endif
 \f
 #ifdef L_negvsi2
 Wtype
-__negvsi2 (Wtype a)
+__negvSI2 (Wtype a)
 {
-   Wtype w;
+  const Wtype w = -a;
+
+  if (a >= 0 ? w > 0 : w < 0)
+    abort ();
 
-   w  = -a;
+   return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__negvsi2 (SItype a)
+{
+  const SItype w = -a;
 
   if (a >= 0 ? w > 0 : w < 0)
     abort ();
 
    return w;
 }
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
 #endif
 \f
 #ifdef L_negvdi2
 DWtype
-__negvdi2 (DWtype a)
+__negvDI2 (DWtype a)
 {
-   DWtype w;
-
-   w  = -a;
+  const DWtype w = -a;
 
   if (a >= 0 ? w > 0 : w < 0)
     abort ();
 
-   return w;
+  return w;
 }
 #endif
 \f
 #ifdef L_absvsi2
 Wtype
-__absvsi2 (Wtype a)
+__absvSI2 (Wtype a)
+{
+  Wtype w = a;
+
+  if (a < 0)
+#ifdef L_negvsi2
+    w = __negvSI2 (a);
+#else
+    w = -a;
+
+  if (w < 0)
+    abort ();
+#endif
+
+   return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__absvsi2 (SItype a)
 {
-   Wtype w = a;
+  SItype w = a;
 
-   if (a < 0)
+  if (a < 0)
 #ifdef L_negvsi2
-     w = __negvsi2 (a);
+    w = __negvsi2 (a);
 #else
-     w = -a;
+    w = -a;
 
-   if (w < 0)
-     abort ();
+  if (w < 0)
+    abort ();
 #endif
 
    return w;
 }
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
 #endif
 \f
 #ifdef L_absvdi2
 DWtype
-__absvdi2 (DWtype a)
+__absvDI2 (DWtype a)
 {
-   DWtype w = a;
+  DWtype w = a;
 
-   if (a < 0)
-#ifdef L_negvsi2
-     w = __negvsi2 (a);
+  if (a < 0)
+#ifdef L_negvdi2
+    w = __negvDI2 (a);
 #else
-     w = -a;
+    w = -a;
 
-   if (w < 0)
-     abort ();
+  if (w < 0)
+    abort ();
 #endif
 
-   return w;
+  return w;
 }
 #endif
 \f
 #ifdef L_mulvdi3
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
 DWtype
-__mulvdi3 (DWtype u, DWtype v)
+__mulvDI3 (DWtype u, DWtype v)
 {
-   DWtype w;
+  /* The unchecked multiplication needs 3 Wtype x Wtype multiplications,
+     but the checked multiplication needs only two.  */
+  const DWunion uu = {.ll = u};
+  const DWunion vv = {.ll = v};
 
-  w = u * v;
+  if (__builtin_expect (uu.s.high == uu.s.low >> (WORD_SIZE - 1), 1))
+    {
+      /* u fits in a single Wtype.  */
+      if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1))
+       {
+         /* v fits in a single Wtype as well.  */
+         /* A single multiplication.  No overflow risk.  */
+         return (DWtype) uu.s.low * (DWtype) vv.s.low;
+       }
+      else
+       {
+         /* Two multiplications.  */
+         DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
+                       * (UDWtype) (UWtype) vv.s.low};
+         DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.low
+                       * (UDWtype) (UWtype) vv.s.high};
+
+         if (vv.s.high < 0)
+           w1.s.high -= uu.s.low;
+         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))
+           {
+             w0.s.high = w1.s.low;
+             return w0.ll;
+           }
+       }
+    }
+  else
+    {
+      if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1))
+       {
+         /* v fits into a single Wtype.  */
+         /* Two multiplications.  */
+         DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
+                       * (UDWtype) (UWtype) vv.s.low};
+         DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.high
+                       * (UDWtype) (UWtype) vv.s.low};
+
+         if (uu.s.high < 0)
+           w1.s.high -= vv.s.low;
+         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))
+           {
+             w0.s.high = w1.s.low;
+             return w0.ll;
+           }
+       }
+      else
+       {
+         /* A few sign checks and a single multiplication.  */
+         if (uu.s.high >= 0)
+           {
+             if (vv.s.high >= 0)
+               {
+                 if (uu.s.high == 0 && vv.s.high == 0)
+                   {
+                     const DWtype w = (UDWtype) (UWtype) uu.s.low
+                       * (UDWtype) (UWtype) vv.s.low;
+                     if (__builtin_expect (w >= 0, 1))
+                       return w;
+                   }
+               }
+             else
+               {
+                 if (uu.s.high == 0 && vv.s.high == (Wtype) -1)
+                   {
+                     DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+                                   * (UDWtype) (UWtype) vv.s.low};
 
-  if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0)
-    abort ();
+                     ww.s.high -= uu.s.low;
+                     if (__builtin_expect (ww.s.high < 0, 1))
+                       return ww.ll;
+                   }
+               }
+           }
+         else
+           {
+             if (vv.s.high >= 0)
+               {
+                 if (uu.s.high == (Wtype) -1 && vv.s.high == 0)
+                   {
+                     DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+                                   * (UDWtype) (UWtype) vv.s.low};
 
-  return w;
+                     ww.s.high -= vv.s.low;
+                     if (__builtin_expect (ww.s.high < 0, 1))
+                       return ww.ll;
+                   }
+               }
+             else
+               {
+                 if (uu.s.high == (Wtype) -1 && vv.s.high == (Wtype) - 1)
+                   {
+                     DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+                                   * (UDWtype) (UWtype) vv.s.low};
+
+                     ww.s.high -= uu.s.low;
+                     ww.s.high -= vv.s.low;
+                     if (__builtin_expect (ww.s.high >= 0, 1))
+                       return ww.ll;
+                   }
+               }
+           }
+       }
+    }
+
+  /* Overflow.  */
+  abort ();
 }
 #endif
 \f
 
-/* Unless shift functions are defined whith full ANSI prototypes,
+/* Unless shift functions are defined with full ANSI prototypes,
    parameter b will be promoted to int if word_type is smaller than an int.  */
 #ifdef L_lshrdi3
 DWtype
 __lshrdi3 (DWtype u, word_type b)
 {
-  DWunion w;
-  word_type bm;
-  DWunion uu;
-
   if (b == 0)
     return u;
 
-  uu.ll = u;
+  const DWunion uu = {.ll = u};
+  const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+  DWunion w;
 
-  bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
   if (bm <= 0)
     {
       w.s.high = 0;
@@ -256,7 +418,7 @@ __lshrdi3 (DWtype u, word_type b)
     }
   else
     {
-      UWtype carries = (UWtype) uu.s.high << bm;
+      const UWtype carries = (UWtype) uu.s.high << bm;
 
       w.s.high = (UWtype) uu.s.high >> b;
       w.s.low = ((UWtype) uu.s.low >> b) | carries;
@@ -270,16 +432,13 @@ __lshrdi3 (DWtype u, word_type b)
 DWtype
 __ashldi3 (DWtype u, word_type b)
 {
-  DWunion w;
-  word_type bm;
-  DWunion uu;
-
   if (b == 0)
     return u;
 
-  uu.ll = u;
+  const DWunion uu = {.ll = u};
+  const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+  DWunion w;
 
-  bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
   if (bm <= 0)
     {
       w.s.low = 0;
@@ -287,7 +446,7 @@ __ashldi3 (DWtype u, word_type b)
     }
   else
     {
-      UWtype carries = (UWtype) uu.s.low >> bm;
+      const UWtype carries = (UWtype) uu.s.low >> bm;
 
       w.s.low = (UWtype) uu.s.low << b;
       w.s.high = ((UWtype) uu.s.high << b) | carries;
@@ -301,16 +460,13 @@ __ashldi3 (DWtype u, word_type b)
 DWtype
 __ashrdi3 (DWtype u, word_type b)
 {
-  DWunion w;
-  word_type bm;
-  DWunion uu;
-
   if (b == 0)
     return u;
 
-  uu.ll = u;
+  const DWunion uu = {.ll = u};
+  const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+  DWunion w;
 
-  bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
   if (bm <= 0)
     {
       /* w.s.high = 1..1 or 0..0 */
@@ -319,7 +475,7 @@ __ashrdi3 (DWtype u, word_type b)
     }
   else
     {
-      UWtype carries = (UWtype) uu.s.high << bm;
+      const UWtype carries = (UWtype) uu.s.high << bm;
 
       w.s.high = uu.s.high >> b;
       w.s.low = ((UWtype) uu.s.low >> b) | carries;
@@ -329,14 +485,29 @@ __ashrdi3 (DWtype u, word_type b)
 }
 #endif
 \f
+#ifdef L_ffssi2
+#undef int
+int
+__ffsSI2 (UWtype u)
+{
+  UWtype count;
+
+  if (u == 0)
+    return 0;
+
+  count_trailing_zeros (count, u);
+  return count + 1;
+}
+#endif
+\f
 #ifdef L_ffsdi2
-DWtype
-__ffsdi2 (DWtype u)
+#undef int
+int
+__ffsDI2 (DWtype u)
 {
-  DWunion uu;
+  const DWunion uu = {.ll = u};
   UWtype word, count, add;
 
-  uu.ll = u;
   if (uu.s.low != 0)
     word = uu.s.low, add = 0;
   else if (uu.s.high != 0)
@@ -353,13 +524,10 @@ __ffsdi2 (DWtype u)
 DWtype
 __muldi3 (DWtype u, DWtype v)
 {
-  DWunion w;
-  DWunion uu, vv;
-
-  uu.ll = u,
-  vv.ll = v;
+  const DWunion uu = {.ll = u};
+  const DWunion vv = {.ll = v};
+  DWunion w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)};
 
-  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
   w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
               + (UWtype) uu.s.high * (UWtype) vv.s.low);
 
@@ -367,8 +535,19 @@ __muldi3 (DWtype u, DWtype v)
 }
 #endif
 \f
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+     defined (L_umoddi3) || defined (L_moddi3))
+#if defined (sdiv_qrnnd)
+#define L_udiv_w_sdiv
+#endif
+#endif
+
 #ifdef L_udiv_w_sdiv
 #if defined (sdiv_qrnnd)
+#if (defined (L_udivdi3) || defined (L_divdi3) || \
+     defined (L_umoddi3) || defined (L_moddi3))
+static inline __attribute__ ((__always_inline__))
+#endif
 UWtype
 __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
 {
@@ -379,16 +558,16 @@ __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
     {
       if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
        {
-         /* dividend, divisor, and quotient are nonnegative */
+         /* Dividend, divisor, and quotient are nonnegative.  */
          sdiv_qrnnd (q, r, a1, a0, d);
        }
       else
        {
-         /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
+         /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
          sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
-         /* Divide (c1*2^32 + c0) by d */
+         /* Divide (c1*2^32 + c0) by d */
          sdiv_qrnnd (q, r, c1, c0, d);
-         /* Add 2^31 to quotient */
+         /* Add 2^31 to quotient */
          q += (UWtype) 1 << (W_TYPE_SIZE - 1);
        }
     }
@@ -496,26 +675,179 @@ const UQItype __clz_tab[] =
   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
 };
 #endif
+\f
+#ifdef L_clzsi2
+#undef int
+int
+__clzSI2 (UWtype x)
+{
+  Wtype ret;
+
+  count_leading_zeros (ret, x);
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_clzdi2
+#undef int
+int
+__clzDI2 (UDWtype x)
+{
+  const DWunion uu = {.ll = x};
+  UWtype word;
+  Wtype ret, add;
+
+  if (uu.s.high)
+    word = uu.s.high, add = 0;
+  else
+    word = uu.s.low, add = W_TYPE_SIZE;
+
+  count_leading_zeros (ret, word);
+  return ret + add;
+}
+#endif
+\f
+#ifdef L_ctzsi2
+#undef int
+int
+__ctzSI2 (UWtype x)
+{
+  Wtype ret;
+
+  count_trailing_zeros (ret, x);
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_ctzdi2
+#undef int
+int
+__ctzDI2 (UDWtype x)
+{
+  const DWunion uu = {.ll = x};
+  UWtype word;
+  Wtype ret, add;
+
+  if (uu.s.low)
+    word = uu.s.low, add = 0;
+  else
+    word = uu.s.high, add = W_TYPE_SIZE;
+
+  count_trailing_zeros (ret, word);
+  return ret + add;
+}
+#endif
+
+#if (defined (L_popcountsi2) || defined (L_popcountdi2)        \
+     || defined (L_popcount_tab))
+extern const UQItype __popcount_tab[] ATTRIBUTE_HIDDEN;
+#endif
+
+#ifdef L_popcount_tab
+const UQItype __popcount_tab[] =
+{
+    0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+    3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
+};
+#endif
+\f
+#ifdef L_popcountsi2
+#undef int
+int
+__popcountSI2 (UWtype x)
+{
+  UWtype i, ret = 0;
+
+  for (i = 0; i < W_TYPE_SIZE; i += 8)
+    ret += __popcount_tab[(x >> i) & 0xff];
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_popcountdi2
+#undef int
+int
+__popcountDI2 (UDWtype x)
+{
+  UWtype i, ret = 0;
+
+  for (i = 0; i < 2*W_TYPE_SIZE; i += 8)
+    ret += __popcount_tab[(x >> i) & 0xff];
+
+  return ret;
+}
+#endif
+\f
+#ifdef L_paritysi2
+#undef int
+int
+__paritySI2 (UWtype x)
+{
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+  x ^= x >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+  x ^= x >> 16;
+#endif
+  x ^= x >> 8;
+  x ^= x >> 4;
+  x &= 0xf;
+  return (0x6996 >> x) & 1;
+}
+#endif
+\f
+#ifdef L_paritydi2
+#undef int
+int
+__parityDI2 (UDWtype x)
+{
+  const DWunion uu = {.ll = x};
+  UWtype nx = uu.s.low ^ uu.s.high;
+
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+  nx ^= nx >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+  nx ^= nx >> 16;
+#endif
+  nx ^= nx >> 8;
+  nx ^= nx >> 4;
+  nx &= 0xf;
+  return (0x6996 >> nx) & 1;
+}
+#endif
 
 #ifdef L_udivmoddi4
 
 #if (defined (L_udivdi3) || defined (L_divdi3) || \
      defined (L_umoddi3) || defined (L_moddi3))
-static inline
+static inline __attribute__ ((__always_inline__))
 #endif
 UDWtype
 __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
 {
-  DWunion ww;
-  DWunion nn, dd;
+  const DWunion nn = {.ll = n};
+  const DWunion dd = {.ll = d};
   DWunion rr;
   UWtype d0, d1, n0, n1, n2;
   UWtype q0, q1;
   UWtype b, bm;
 
-  nn.ll = n;
-  dd.ll = d;
-
   d0 = dd.s.low;
   d1 = dd.s.high;
   n0 = nn.s.low;
@@ -715,8 +1047,7 @@ __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
        }
     }
 
-  ww.s.low = q0;
-  ww.s.high = q1;
+  const DWunion ww = {{.low = q0, .high = q1}};
   return ww.ll;
 }
 #endif
@@ -726,22 +1057,20 @@ DWtype
 __divdi3 (DWtype u, DWtype v)
 {
   word_type c = 0;
-  DWunion uu, vv;
+  DWunion uu = {.ll = u};
+  DWunion vv = {.ll = v};
   DWtype w;
 
-  uu.ll = u;
-  vv.ll = v;
-
   if (uu.s.high < 0)
     c = ~c,
-    uu.ll = __negdi2 (uu.ll);
+    uu.ll = -uu.ll;
   if (vv.s.high < 0)
     c = ~c,
-    vv.ll = __negdi2 (vv.ll);
+    vv.ll = -vv.ll;
 
   w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
   if (c)
-    w = __negdi2 (w);
+    w = -w;
 
   return w;
 }
@@ -752,21 +1081,19 @@ DWtype
 __moddi3 (DWtype u, DWtype v)
 {
   word_type c = 0;
-  DWunion uu, vv;
+  DWunion uu = {.ll = u};
+  DWunion vv = {.ll = v};
   DWtype w;
 
-  uu.ll = u;
-  vv.ll = v;
-
   if (uu.s.high < 0)
     c = ~c,
-    uu.ll = __negdi2 (uu.ll);
+    uu.ll = -uu.ll;
   if (vv.s.high < 0)
-    vv.ll = __negdi2 (vv.ll);
+    vv.ll = -vv.ll;
 
-  (void) __udivmoddi4 (uu.ll, vv.ll, &w);
+  (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
   if (c)
-    w = __negdi2 (w);
+    w = -w;
 
   return w;
 }
@@ -796,9 +1123,8 @@ __udivdi3 (UDWtype n, UDWtype d)
 word_type
 __cmpdi2 (DWtype a, DWtype b)
 {
-  DWunion au, bu;
-
-  au.ll = a, bu.ll = b;
+  const DWunion au = {.ll = a};
+  const DWunion bu = {.ll = b};
 
   if (au.s.high < bu.s.high)
     return 0;
@@ -816,9 +1142,8 @@ __cmpdi2 (DWtype a, DWtype b)
 word_type
 __ucmpdi2 (DWtype a, DWtype b)
 {
-  DWunion au, bu;
-
-  au.ll = a, bu.ll = b;
+  const DWunion au = {.ll = a};
+  const DWunion bu = {.ll = b};
 
   if ((UWtype) au.s.high < (UWtype) bu.s.high)
     return 0;
@@ -839,17 +1164,14 @@ __ucmpdi2 (DWtype a, DWtype b)
 DWtype
 __fixunstfDI (TFtype a)
 {
-  TFtype b;
-  UDWtype v;
-
   if (a < 0)
     return 0;
 
   /* Compute high word of result, as a flonum.  */
-  b = (a / HIGH_WORD_COEFF);
+  const TFtype b = (a / HIGH_WORD_COEFF);
   /* Convert that to fixed (but not to DWtype!),
      and shift it into the high word.  */
-  v = (UWtype) b;
+  UDWtype v = (UWtype) b;
   v <<= WORD_SIZE;
   /* Remove high part from the TFtype, leaving the low part as flonum.  */
   a -= (TFtype)v;
@@ -874,24 +1196,21 @@ __fixtfdi (TFtype a)
 }
 #endif
 
-#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+#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)
 
 DWtype
 __fixunsxfDI (XFtype a)
 {
-  XFtype b;
-  UDWtype v;
-
   if (a < 0)
     return 0;
 
   /* Compute high word of result, as a flonum.  */
-  b = (a / HIGH_WORD_COEFF);
+  const XFtype b = (a / HIGH_WORD_COEFF);
   /* Convert that to fixed (but not to DWtype!),
      and shift it into the high word.  */
-  v = (UWtype) b;
+  UDWtype v = (UWtype) b;
   v <<= WORD_SIZE;
   /* Remove high part from the XFtype, leaving the low part as flonum.  */
   a -= (XFtype)v;
@@ -906,7 +1225,7 @@ __fixunsxfDI (XFtype a)
 }
 #endif
 
-#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
 DWtype
 __fixxfdi (XFtype a)
 {
@@ -923,28 +1242,18 @@ __fixxfdi (XFtype a)
 DWtype
 __fixunsdfDI (DFtype a)
 {
-  DFtype b;
-  UDWtype v;
+  /* 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;
 
-  if (a < 0)
-    return 0;
+  /* 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);
 
-  /* Compute high word of result, as a flonum.  */
-  b = (a / HIGH_WORD_COEFF);
-  /* Convert that to fixed (but not to DWtype!),
-     and shift it into the high word.  */
-  v = (UWtype) b;
-  v <<= WORD_SIZE;
-  /* Remove high part from the DFtype, leaving the low part as flonum.  */
-  a -= (DFtype)v;
-  /* Convert that to fixed (but not to DWtype!) and add it in.
-     Sometimes A comes out negative.  This is significant, since
-     A has more bits than a long int does.  */
-  if (a < 0)
-    v -= (UWtype) (- a);
-  else
-    v += (UWtype) a;
-  return v;
+  /* Assemble result from the two parts.  */
+  return ((UDWtype) hi << WORD_SIZE) | lo;
 }
 #endif
 
@@ -968,29 +1277,20 @@ __fixunssfDI (SFtype original_a)
   /* 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.  */
-  DFtype a = original_a;
-  DFtype b;
-  UDWtype v;
+  const DFtype a = original_a;
 
-  if (a < 0)
-    return 0;
+  /* 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;
 
-  /* Compute high word of result, as a flonum.  */
-  b = (a / HIGH_WORD_COEFF);
-  /* Convert that to fixed (but not to DWtype!),
-     and shift it into the high word.  */
-  v = (UWtype) b;
-  v <<= WORD_SIZE;
-  /* Remove high part from the DFtype, leaving the low part as flonum.  */
-  a -= (DFtype) v;
-  /* Convert that to fixed (but not to DWtype!) and add it in.
-     Sometimes A comes out negative.  This is significant, since
-     A has more bits than a long int does.  */
-  if (a < 0)
-    v -= (UWtype) (- a);
-  else
-    v += (UWtype) a;
-  return v;
+  /* 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);
+
+  /* Assemble result from the two parts.  */
+  return ((UDWtype) hi << WORD_SIZE) | lo;
 }
 #endif
 
@@ -1004,7 +1304,7 @@ __fixsfdi (SFtype a)
 }
 #endif
 
-#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+#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)
@@ -1012,9 +1312,7 @@ __fixsfdi (SFtype a)
 XFtype
 __floatdixf (DWtype u)
 {
-  XFtype d;
-
-  d = (Wtype) (u >> WORD_SIZE);
+  XFtype d = (Wtype) (u >> WORD_SIZE);
   d *= HIGH_HALFWORD_COEFF;
   d *= HIGH_HALFWORD_COEFF;
   d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
@@ -1031,9 +1329,7 @@ __floatdixf (DWtype u)
 TFtype
 __floatditf (DWtype u)
 {
-  TFtype d;
-
-  d = (Wtype) (u >> WORD_SIZE);
+  TFtype d = (Wtype) (u >> WORD_SIZE);
   d *= HIGH_HALFWORD_COEFF;
   d *= HIGH_HALFWORD_COEFF;
   d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
@@ -1050,9 +1346,7 @@ __floatditf (DWtype u)
 DFtype
 __floatdidf (DWtype u)
 {
-  DFtype d;
-
-  d = (Wtype) (u >> WORD_SIZE);
+  DFtype d = (Wtype) (u >> WORD_SIZE);
   d *= HIGH_HALFWORD_COEFF;
   d *= HIGH_HALFWORD_COEFF;
   d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
@@ -1065,44 +1359,14 @@ __floatdidf (DWtype u)
 #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 codes for all the float formats that we know of.  Note
-   that this is copied from real.h.  */
-
-#define UNKNOWN_FLOAT_FORMAT 0
-#define IEEE_FLOAT_FORMAT 1
-#define VAX_FLOAT_FORMAT 2
-#define IBM_FLOAT_FORMAT 3
-
-/* Default to IEEE float if not specified.  Nearly all machines use it.  */
-#ifndef HOST_FLOAT_FORMAT
-#define        HOST_FLOAT_FORMAT       IEEE_FLOAT_FORMAT
-#endif
-
-#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
-#define DF_SIZE 53
-#define SF_SIZE 24
-#endif
-
-#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
-#define DF_SIZE 56
-#define SF_SIZE 24
-#endif
 
-#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
-#define DF_SIZE 56
-#define SF_SIZE 24
-#endif
+#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+#define DF_SIZE DBL_MANT_DIG
+#define SF_SIZE FLT_MANT_DIG
 
 SFtype
 __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;
-
   /* 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
@@ -1117,10 +1381,16 @@ __floatdisf (DWtype u)
             && u < ((DWtype) 1 << DF_SIZE)))
        {
          if ((UDWtype) u & (REP_BIT - 1))
-           u |= REP_BIT;
+           {
+             u &= ~ (REP_BIT - 1);
+             u |= REP_BIT;
+           }
        }
     }
-  f = (Wtype) (u >> WORD_SIZE);
+  /* 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));
@@ -1129,7 +1399,7 @@ __floatdisf (DWtype u)
 }
 #endif
 
-#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
+#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80
 /* Reenable the normal types, in case limits.h needs them.  */
 #undef char
 #undef short
@@ -1195,6 +1465,42 @@ __fixunssfSI (SFtype a)
 }
 #endif
 \f
+/* 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)
+#  define TYPE SFtype
+#  define NAME __powisf2
+# elif defined(L_powidf2)
+#  define TYPE DFtype
+#  define NAME __powidf2
+# elif defined(L_powixf2)
+#  define TYPE XFtype
+#  define NAME __powixf2
+# elif defined(L_powitf2)
+#  define TYPE TFtype
+#  define NAME __powitf2
+# endif
+
+TYPE
+NAME (TYPE x, Wtype m)
+{
+  UWtype n = m < 0 ? -m : m;
+  TYPE y = n % 2 ? x : 1;
+  while (n >>= 1)
+    {
+      x = x * x;
+      if (n % 2)
+       y = y * x;
+    }
+  return m < 0 ? 1/y : y;
+}
+
+#endif
+\f
 /* From here on down, the routines use normal data types.  */
 
 #define SItype bogus_type
@@ -1229,7 +1535,7 @@ __gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
 {
   while (size > 0)
     {
-      unsigned char c1 = *s1++, c2 = *s2++;
+      const unsigned char c1 = *s1++, c2 = *s2++;
       if (c1 != c2)
        return c1 - c2;
       size--;
@@ -1261,1227 +1567,41 @@ __eprintf (const char *string, const char *expression,
 #endif
 #endif
 
-#ifdef L_bb
-
-#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
-typedef long gcov_type;
-#else
-typedef long long gcov_type;
-#endif
-
-
-/* Structure emitted by -a  */
-struct bb
-{
-  long zero_word;
-  const char *filename;
-  gcov_type *counts;
-  long ncounts;
-  struct bb *next;
-  const unsigned long *addresses;
-
-  /* Older GCC's did not emit these fields.  */
-  long nwords;
-  const char **functions;
-  const long *line_nums;
-  const char **filenames;
-  char *flags;
-};
-
-#ifdef BLOCK_PROFILER_CODE
-BLOCK_PROFILER_CODE
-#else
-#ifndef inhibit_libc
-
-/* Simple minded basic block profiling output dumper for
-   systems that don't provide tcov support.  At present,
-   it requires atexit and stdio.  */
-
-#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
-#include <stdio.h>
-char *ctime PARAMS ((const time_t *));
-
-#include "gbl-ctors.h"
-#include "gcov-io.h"
-#include <string.h>
-#ifdef TARGET_HAS_F_SETLKW
-#include <fcntl.h>
-#include <errno.h>
-#endif
-
-static struct bb *bb_head;
-
-static int num_digits (long long value, int base) __attribute__ ((const));
-
-/* Return the number of digits needed to print a value */
-/* __inline__ */ static int num_digits (long long value, int base)
-{
-  int minus = (value < 0 && base != 16);
-  unsigned long long v = (minus) ? -value : value;
-  int ret = minus;
-
-  do
-    {
-      v /= base;
-      ret++;
-    }
-  while (v);
-
-  return ret;
-}
-
-void
-__bb_exit_func (void)
-{
-  FILE *da_file, *file;
-  long time_value;
-  int i;
-
-  if (bb_head == 0)
-    return;
-
-  i = strlen (bb_head->filename) - 3;
-
-  if (!strcmp (bb_head->filename+i, ".da"))
-    {
-      /* Must be -fprofile-arcs not -a.
-        Dump data in a form that gcov expects.  */
-
-      struct bb *ptr;
-
-      for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
-       {
-         int firstchar;
-
-         /* Make sure the output file exists -
-            but don't clobber exiting data.  */
-         if ((da_file = fopen (ptr->filename, "a")) != 0)
-           fclose (da_file);
-
-         /* Need to re-open in order to be able to write from the start.  */
-         da_file = fopen (ptr->filename, "r+b");
-         /* Some old systems might not allow the 'b' mode modifier.
-            Therefore, try to open without it.  This can lead to a race
-            condition so that when you delete and re-create the file, the
-            file might be opened in text mode, but then, you shouldn't
-            delete the file in the first place.  */
-         if (da_file == 0)
-           da_file = fopen (ptr->filename, "r+");
-         if (da_file == 0)
-           {
-             fprintf (stderr, "arc profiling: Can't open output file %s.\n",
-                      ptr->filename);
-             continue;
-           }
-
-         /* After a fork, another process might try to read and/or write
-            the same file simultanously.  So if we can, lock the file to
-            avoid race conditions.  */
-#if defined (TARGET_HAS_F_SETLKW)
-         {
-           struct flock s_flock;
-
-           s_flock.l_type = F_WRLCK;
-           s_flock.l_whence = SEEK_SET;
-           s_flock.l_start = 0;
-           s_flock.l_len = 1;
-           s_flock.l_pid = getpid ();
-
-           while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
-                  && errno == EINTR);
-         }
-#endif
-
-         /* If the file is not empty, and the number of counts in it is the
-            same, then merge them in.  */
-         firstchar = fgetc (da_file);
-         if (firstchar == EOF)
-           {
-             if (ferror (da_file))
-               {
-                 fprintf (stderr, "arc profiling: Can't read output file ");
-                 perror (ptr->filename);
-               }
-           }
-         else
-           {
-             long n_counts = 0;
-
-             if (ungetc (firstchar, da_file) == EOF)
-               rewind (da_file);
-             if (__read_long (&n_counts, da_file, 8) != 0)
-               {
-                 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
-                          ptr->filename);
-                 continue;
-               }
-
-             if (n_counts == ptr->ncounts)
-               {
-                 int i;
-
-                 for (i = 0; i < n_counts; i++)
-                   {
-                     gcov_type v = 0;
-
-                     if (__read_gcov_type (&v, da_file, 8) != 0)
-                       {
-                         fprintf (stderr, "arc profiling: Can't read output file %s.\n",
-                                  ptr->filename);
-                         break;
-                       }
-                     ptr->counts[i] += v;
-                   }
-               }
-
-           }
-
-         rewind (da_file);
-
-         /* ??? Should first write a header to the file.  Preferably, a 4 byte
-            magic number, 4 bytes containing the time the program was
-            compiled, 4 bytes containing the last modification time of the
-            source file, and 4 bytes indicating the compiler options used.
-
-            That way we can easily verify that the proper source/executable/
-            data file combination is being used from gcov.  */
-
-         if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0)
-           {
-
-             fprintf (stderr, "arc profiling: Error writing output file %s.\n",
-                      ptr->filename);
-           }
-         else
-           {
-             int j;
-             gcov_type *count_ptr = ptr->counts;
-             int ret = 0;
-             for (j = ptr->ncounts; j > 0; j--)
-               {
-                 if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
-                   {
-                     ret=1;
-                     break;
-                   }
-                 count_ptr++;
-               }
-             if (ret)
-               fprintf (stderr, "arc profiling: Error writing output file %s.\n",
-                        ptr->filename);
-           }
-
-         if (fclose (da_file) == EOF)
-           fprintf (stderr, "arc profiling: Error closing output file %s.\n",
-                    ptr->filename);
-       }
-
-      return;
-    }
-
-  /* Must be basic block profiling.  Emit a human readable output file.  */
-
-  file = fopen ("bb.out", "a");
-
-  if (!file)
-    perror ("bb.out");
-
-  else
-    {
-      struct bb *ptr;
-
-      /* This is somewhat type incorrect, but it avoids worrying about
-        exactly where time.h is included from.  It should be ok unless
-        a void * differs from other pointer formats, or if sizeof (long)
-        is < sizeof (time_t).  It would be nice if we could assume the
-        use of rationale standards here.  */
-
-      time ((void *) &time_value);
-      fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
-
-      /* We check the length field explicitly in order to allow compatibility
-        with older GCC's which did not provide it.  */
-
-      for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
-       {
-         int i;
-         int func_p    = (ptr->nwords >= (long) sizeof (struct bb)
-                          && ptr->nwords <= 1000
-                          && ptr->functions);
-         int line_p    = (func_p && ptr->line_nums);
-         int file_p    = (func_p && ptr->filenames);
-         int addr_p    = (ptr->addresses != 0);
-         long ncounts  = ptr->ncounts;
-         gcov_type cnt_max  = 0;
-         long line_max = 0;
-         long addr_max = 0;
-         int file_len  = 0;
-         int func_len  = 0;
-         int blk_len   = num_digits (ncounts, 10);
-         int cnt_len;
-         int line_len;
-         int addr_len;
-
-         fprintf (file, "File %s, %ld basic blocks \n\n",
-                  ptr->filename, ncounts);
-
-         /* Get max values for each field.  */
-         for (i = 0; i < ncounts; i++)
-           {
-             const char *p;
-             int len;
-
-             if (cnt_max < ptr->counts[i])
-               cnt_max = ptr->counts[i];
-
-             if (addr_p && (unsigned long) addr_max < ptr->addresses[i])
-               addr_max = ptr->addresses[i];
-
-             if (line_p && line_max < ptr->line_nums[i])
-               line_max = ptr->line_nums[i];
-
-             if (func_p)
-               {
-                 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
-                 len = strlen (p);
-                 if (func_len < len)
-                   func_len = len;
-               }
-
-             if (file_p)
-               {
-                 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
-                 len = strlen (p);
-                 if (file_len < len)
-                   file_len = len;
-               }
-           }
-
-         addr_len = num_digits (addr_max, 16);
-         cnt_len  = num_digits (cnt_max, 10);
-         line_len = num_digits (line_max, 10);
-
-         /* Now print out the basic block information.  */
-         for (i = 0; i < ncounts; i++)
-           {
-#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
-             fprintf (file,
-                      "    Block #%*d: executed %*ld time(s)",
-                      blk_len, i+1,
-                      cnt_len, ptr->counts[i]);
-#else
-             fprintf (file,
-                      "    Block #%*d: executed %*lld time(s)",
-                      blk_len, i+1,
-                      cnt_len, ptr->counts[i]);
-#endif
-
-             if (addr_p)
-               fprintf (file, " address= 0x%.*lx", addr_len,
-                        ptr->addresses[i]);
-
-             if (func_p)
-               fprintf (file, " function= %-*s", func_len,
-                        (ptr->functions[i]) ? ptr->functions[i] : "<none>");
-
-             if (line_p)
-               fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
-
-             if (file_p)
-               fprintf (file, " file= %s",
-                        (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
-
-             fprintf (file, "\n");
-           }
-
-         fprintf (file, "\n");
-         fflush (file);
-       }
-
-      fprintf (file, "\n\n");
-      fclose (file);
-    }
-}
-
-void
-__bb_init_func (struct bb *blocks)
-{
-  /* User is supposed to check whether the first word is non-0,
-     but just in case....  */
-
-  if (blocks->zero_word)
-    return;
-
-  /* Initialize destructor.  */
-  if (!bb_head)
-    atexit (__bb_exit_func);
-
-  /* Set up linked list.  */
-  blocks->zero_word = 1;
-  blocks->next = bb_head;
-  bb_head = blocks;
-}
-
-/* Called before fork or exec - write out profile information gathered so
-   far and reset it to zero.  This avoids duplication or loss of the
-   profile information gathered so far.  */
-void
-__bb_fork_func (void)
-{
-  struct bb *ptr;
-
-  __bb_exit_func ();
-  for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
-    {
-      long i;
-      for (i = ptr->ncounts - 1; i >= 0; i--)
-       ptr->counts[i] = 0;
-    }
-}
-
-#ifndef MACHINE_STATE_SAVE
-#define MACHINE_STATE_SAVE(ID)
-#endif
-#ifndef MACHINE_STATE_RESTORE
-#define MACHINE_STATE_RESTORE(ID)
-#endif
-
-/* Number of buckets in hashtable of basic block addresses.  */
-
-#define BB_BUCKETS 311
-
-/* Maximum length of string in file bb.in.  */
-
-#define BBINBUFSIZE 500
-
-struct bb_edge
-{
-  struct bb_edge *next;
-  unsigned long src_addr;
-  unsigned long dst_addr;
-  unsigned long count;
-};
-
-enum bb_func_mode
-{
-  TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
-};
-
-struct bb_func
-{
-  struct bb_func *next;
-  char *funcname;
-  char *filename;
-  enum bb_func_mode mode;
-};
-
-/* This is the connection to the outside world.
-   The BLOCK_PROFILER macro must set __bb.blocks
-   and __bb.blockno.  */
-
-struct {
-  unsigned long blockno;
-  struct bb *blocks;
-} __bb;
-
-/* Vars to store addrs of source and destination basic blocks
-   of a jump.  */
-
-static unsigned long bb_src = 0;
-static unsigned long bb_dst = 0;
-
-static FILE *bb_tracefile = (FILE *) 0;
-static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
-static struct bb_func *bb_func_head = (struct bb_func *) 0;
-static unsigned long bb_callcount = 0;
-static int bb_mode = 0;
-
-static unsigned long *bb_stack = (unsigned long *) 0;
-static size_t bb_stacksize = 0;
-
-static int reported = 0;
-
-/* Trace modes:
-Always             :   Print execution frequencies of basic blocks
-                       to file bb.out.
-bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
-bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
-bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
-bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
-*/
-
-#ifdef HAVE_POPEN
-
-/*#include <sys/types.h>*/
-#include <sys/stat.h>
-/*#include <malloc.h>*/
-
-/* Commands executed by gopen.  */
-
-#define GOPENDECOMPRESS "gzip -cd "
-#define GOPENCOMPRESS "gzip -c >"
-
-/* Like fopen but pipes through gzip.  mode may only be "r" or "w".
-   If it does not compile, simply replace gopen by fopen and delete
-   '.gz' from any first parameter to gopen.  */
-
-static FILE *
-gopen (char *fn, char *mode)
-{
-  int use_gzip;
-  char *p;
-
-  if (mode[1])
-    return (FILE *) 0;
-
-  if (mode[0] != 'r' && mode[0] != 'w')
-    return (FILE *) 0;
-
-  p = fn + strlen (fn)-1;
-  use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
-             || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
-
-  if (use_gzip)
-    {
-      if (mode[0]=='r')
-        {
-          FILE *f;
-          char *s = (char *) malloc (sizeof (char) * strlen (fn)
-                                    + sizeof (GOPENDECOMPRESS));
-          strcpy (s, GOPENDECOMPRESS);
-          strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
-          f = popen (s, mode);
-          free (s);
-          return f;
-        }
-
-      else
-        {
-          FILE *f;
-          char *s = (char *) malloc (sizeof (char) * strlen (fn)
-                                    + sizeof (GOPENCOMPRESS));
-          strcpy (s, GOPENCOMPRESS);
-          strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
-          if (!(f = popen (s, mode)))
-            f = fopen (s, mode);
-          free (s);
-          return f;
-        }
-    }
-
-  else
-    return fopen (fn, mode);
-}
-
-static int
-gclose (FILE *f)
-{
-  struct stat buf;
-
-  if (f != 0)
-    {
-      if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
-        return pclose (f);
-
-      return fclose (f);
-    }
-  return 0;
-}
-
-#endif /* HAVE_POPEN */
-
-/* Called once per program.  */
-
-static void
-__bb_exit_trace_func (void)
-{
-  FILE *file = fopen ("bb.out", "a");
-  struct bb_func *f;
-  struct bb *b;
-
-  if (!file)
-    perror ("bb.out");
-
-  if (bb_mode & 1)
-    {
-      if (!bb_tracefile)
-        perror ("bbtrace");
-      else
-#ifdef HAVE_POPEN
-        gclose (bb_tracefile);
-#else
-        fclose (bb_tracefile);
-#endif /* HAVE_POPEN */
-    }
-
-  /* Check functions in `bb.in'.  */
-
-  if (file)
-    {
-      long time_value;
-      const struct bb_func *p;
-      int printed_something = 0;
-      struct bb *ptr;
-      long blk;
-
-      /* This is somewhat type incorrect.  */
-      time ((void *) &time_value);
-
-      for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
-        {
-          for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
-            {
-              if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
-                continue;
-              for (blk = 0; blk < ptr->ncounts; blk++)
-                {
-                  if (!strcmp (p->funcname, ptr->functions[blk]))
-                    goto found;
-                }
-            }
-
-          if (!printed_something)
-            {
-              fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
-              printed_something = 1;
-            }
-
-          fprintf (file, "\tFunction %s", p->funcname);
-          if (p->filename)
-              fprintf (file, " of file %s", p->filename);
-          fprintf (file, "\n" );
-
-found:        ;
-        }
-
-      if (printed_something)
-       fprintf (file, "\n");
-
-    }
-
-  if (bb_mode & 2)
-    {
-      if (!bb_hashbuckets)
-        {
-          if (!reported)
-            {
-              fprintf (stderr, "Profiler: out of memory\n");
-              reported = 1;
-            }
-          return;
-        }
-
-      else if (file)
-        {
-          long time_value;
-          int i;
-          unsigned long addr_max = 0;
-          unsigned long cnt_max  = 0;
-          int cnt_len;
-          int addr_len;
-
-          /* This is somewhat type incorrect, but it avoids worrying about
-             exactly where time.h is included from.  It should be ok unless
-             a void * differs from other pointer formats, or if sizeof (long)
-             is < sizeof (time_t).  It would be nice if we could assume the
-             use of rationale standards here.  */
-
-          time ((void *) &time_value);
-          fprintf (file, "Basic block jump tracing");
-
-          switch (bb_mode & 12)
-            {
-              case 0:
-                fprintf (file, " (with call)");
-              break;
-
-              case 4:
-               /* Print nothing.  */
-              break;
-
-              case 8:
-                fprintf (file, " (with call & ret)");
-              break;
-
-              case 12:
-                fprintf (file, " (with ret)");
-              break;
-            }
-
-          fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
-
-          for (i = 0; i < BB_BUCKETS; i++)
-            {
-               struct bb_edge *bucket = bb_hashbuckets[i];
-               for ( ; bucket; bucket = bucket->next )
-                 {
-                   if (addr_max < bucket->src_addr)
-                     addr_max = bucket->src_addr;
-                   if (addr_max < bucket->dst_addr)
-                     addr_max = bucket->dst_addr;
-                   if (cnt_max < bucket->count)
-                     cnt_max = bucket->count;
-                 }
-            }
-          addr_len = num_digits (addr_max, 16);
-          cnt_len  = num_digits (cnt_max, 10);
-
-          for ( i = 0; i < BB_BUCKETS; i++)
-            {
-               struct bb_edge *bucket = bb_hashbuckets[i];
-               for ( ; bucket; bucket = bucket->next )
-                 {
-                   fprintf (file,
-       "Jump from block 0x%.*lx to block 0x%.*lx executed %*lu time(s)\n",
-                            addr_len, bucket->src_addr,
-                            addr_len, bucket->dst_addr,
-                            cnt_len, bucket->count);
-                 }
-            }
-
-          fprintf (file, "\n");
-
-        }
-    }
-
-   if (file)
-     fclose (file);
-
-   /* Free allocated memory.  */
-
-   f = bb_func_head;
-   while (f)
-     {
-       struct bb_func *old = f;
-
-       f = f->next;
-       if (old->funcname) free (old->funcname);
-       if (old->filename) free (old->filename);
-       free (old);
-     }
-
-   if (bb_stack)
-     free (bb_stack);
-
-   if (bb_hashbuckets)
-     {
-       int i;
-
-       for (i = 0; i < BB_BUCKETS; i++)
-         {
-           struct bb_edge *old, *bucket = bb_hashbuckets[i];
-
-           while (bucket)
-             {
-               old = bucket;
-               bucket = bucket->next;
-               free (old);
-             }
-         }
-       free (bb_hashbuckets);
-     }
-
-   for (b = bb_head; b; b = b->next)
-     if (b->flags) free (b->flags);
-}
-
-/* Called once per program.  */
-
-static void
-__bb_init_prg (void)
-{
-  FILE *file;
-  char buf[BBINBUFSIZE];
-  const char *p;
-  const char *pos;
-  enum bb_func_mode m;
-  int i;
-
-  /* Initialize destructor.  */
-  atexit (__bb_exit_func);
-
-  if (!(file = fopen ("bb.in", "r")))
-    return;
-
-  while(fgets (buf, BBINBUFSIZE, file) != 0)
-    {
-      i = strlen (buf);
-      if (buf[i] == '\n')
-       buf[i--] = '\0';
-
-      p = buf;
-      if (*p == '-')
-        {
-          m = TRACE_OFF;
-          p++;
-        }
-      else
-        {
-          m = TRACE_ON;
-        }
-      if (!strcmp (p, "__bb_trace__"))
-        bb_mode |= 1;
-      else if (!strcmp (p, "__bb_jumps__"))
-        bb_mode |= 2;
-      else if (!strcmp (p, "__bb_hidecall__"))
-        bb_mode |= 4;
-      else if (!strcmp (p, "__bb_showret__"))
-        bb_mode |= 8;
-      else
-        {
-          struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
-          if (f)
-            {
-              unsigned long l;
-              f->next = bb_func_head;
-              if ((pos = strchr (p, ':')))
-                {
-                  if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
-                    continue;
-                  strcpy (f->funcname, pos+1);
-                  l = pos-p;
-                  if ((f->filename = (char *) malloc (l+1)))
-                    {
-                      strncpy (f->filename, p, l);
-                      f->filename[l] = '\0';
-                    }
-                  else
-                    f->filename = (char *) 0;
-                }
-              else
-                {
-                  if (!(f->funcname = (char *) malloc (strlen (p)+1)))
-                    continue;
-                  strcpy (f->funcname, p);
-                  f->filename = (char *) 0;
-                }
-              f->mode = m;
-              bb_func_head = f;
-           }
-         }
-    }
-  fclose (file);
-
-#ifdef HAVE_POPEN
-
-  if (bb_mode & 1)
-      bb_tracefile = gopen ("bbtrace.gz", "w");
-
-#else
-
-  if (bb_mode & 1)
-      bb_tracefile = fopen ("bbtrace", "w");
-
-#endif /* HAVE_POPEN */
-
-  if (bb_mode & 2)
-    {
-      bb_hashbuckets = (struct bb_edge **)
-                   malloc (BB_BUCKETS * sizeof (struct bb_edge *));
-      if (bb_hashbuckets)
-       /* Use a loop here rather than calling bzero to avoid having to
-          conditionalize its existance.  */
-       for (i = 0; i < BB_BUCKETS; i++)
-         bb_hashbuckets[i] = 0;
-    }
-
-  if (bb_mode & 12)
-    {
-      bb_stacksize = 10;
-      bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
-    }
-
-  /* Initialize destructor.  */
-  atexit (__bb_exit_trace_func);
-}
-
-/* Called upon entering a basic block.  */
-
-void
-__bb_trace_func (void)
-{
-  struct bb_edge *bucket;
-
-  MACHINE_STATE_SAVE("1")
-
-  if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
-    goto skip;
-
-  bb_dst = __bb.blocks->addresses[__bb.blockno];
-  __bb.blocks->counts[__bb.blockno]++;
-
-  if (bb_tracefile)
-    {
-      fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
-    }
-
-  if (bb_hashbuckets)
-    {
-      struct bb_edge **startbucket, **oldnext;
-
-      oldnext = startbucket
-       = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
-      bucket = *startbucket;
-
-      for (bucket = *startbucket; bucket;
-           oldnext = &(bucket->next), bucket = *oldnext)
-        {
-          if (bucket->src_addr == bb_src
-             && bucket->dst_addr == bb_dst)
-            {
-              bucket->count++;
-              *oldnext = bucket->next;
-              bucket->next = *startbucket;
-              *startbucket = bucket;
-              goto ret;
-            }
-        }
-
-      bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
-
-      if (!bucket)
-        {
-          if (!reported)
-            {
-              fprintf (stderr, "Profiler: out of memory\n");
-              reported = 1;
-            }
-        }
-
-      else
-        {
-          bucket->src_addr = bb_src;
-          bucket->dst_addr = bb_dst;
-          bucket->next = *startbucket;
-          *startbucket = bucket;
-          bucket->count = 1;
-        }
-    }
-
-ret:
-  bb_src = bb_dst;
-
-skip:
-  ;
-
-  MACHINE_STATE_RESTORE("1")
-
-}
-
-/* Called when returning from a function and `__bb_showret__' is set.  */
-
-static void
-__bb_trace_func_ret (void)
-{
-  struct bb_edge *bucket;
-
-  if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
-    goto skip;
-
-  if (bb_hashbuckets)
-    {
-      struct bb_edge **startbucket, **oldnext;
-
-      oldnext = startbucket
-       = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
-      bucket = *startbucket;
-
-      for (bucket = *startbucket; bucket;
-           oldnext = &(bucket->next), bucket = *oldnext)
-        {
-          if (bucket->src_addr == bb_dst
-              && bucket->dst_addr == bb_src)
-            {
-              bucket->count++;
-              *oldnext = bucket->next;
-              bucket->next = *startbucket;
-              *startbucket = bucket;
-              goto ret;
-            }
-        }
-
-      bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
-
-      if (!bucket)
-        {
-          if (!reported)
-            {
-              fprintf (stderr, "Profiler: out of memory\n");
-              reported = 1;
-            }
-        }
-
-      else
-        {
-          bucket->src_addr = bb_dst;
-          bucket->dst_addr = bb_src;
-          bucket->next = *startbucket;
-          *startbucket = bucket;
-          bucket->count = 1;
-        }
-    }
-
-ret:
-  bb_dst = bb_src;
-
-skip:
-  ;
-
-}
-
-/* Called upon entering the first function of a file.  */
-
-static void
-__bb_init_file (struct bb *blocks)
-{
-
-  const struct bb_func *p;
-  long blk, ncounts = blocks->ncounts;
-  const char **functions = blocks->functions;
-
-  /* Set up linked list.  */
-  blocks->zero_word = 1;
-  blocks->next = bb_head;
-  bb_head = blocks;
-
-  blocks->flags = 0;
-  if (!bb_func_head
-      || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
-    return;
-
-  for (blk = 0; blk < ncounts; blk++)
-    blocks->flags[blk] = 0;
-
-  for (blk = 0; blk < ncounts; blk++)
-    {
-      for (p = bb_func_head; p; p = p->next)
-        {
-          if (!strcmp (p->funcname, functions[blk])
-             && (!p->filename || !strcmp (p->filename, blocks->filename)))
-            {
-              blocks->flags[blk] |= p->mode;
-            }
-        }
-    }
-
-}
-
-/* Called when exiting from a function.  */
-
-void
-__bb_trace_ret (void)
-{
-
-  MACHINE_STATE_SAVE("2")
-
-  if (bb_callcount)
-    {
-      if ((bb_mode & 12) && bb_stacksize > bb_callcount)
-        {
-          bb_src = bb_stack[bb_callcount];
-          if (bb_mode & 8)
-            __bb_trace_func_ret ();
-        }
-
-      bb_callcount -= 1;
-    }
-
-  MACHINE_STATE_RESTORE("2")
-
-}
-
-/* Called when entering a function.  */
-
-void
-__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
-{
-  static int trace_init = 0;
-
-  MACHINE_STATE_SAVE("3")
-
-  if (!blocks->zero_word)
-    {
-      if (!trace_init)
-        {
-          trace_init = 1;
-          __bb_init_prg ();
-        }
-      __bb_init_file (blocks);
-    }
-
-  if (bb_callcount)
-    {
-
-      bb_callcount += 1;
-
-      if (bb_mode & 12)
-        {
-          if (bb_callcount >= bb_stacksize)
-            {
-              size_t newsize = bb_callcount + 100;
-
-              bb_stack = (unsigned long *) realloc (bb_stack, newsize);
-              if (! bb_stack)
-                {
-                  if (!reported)
-                    {
-                      fprintf (stderr, "Profiler: out of memory\n");
-                      reported = 1;
-                    }
-                  bb_stacksize = 0;
-                  goto stack_overflow;
-                }
-             bb_stacksize = newsize;
-            }
-          bb_stack[bb_callcount] = bb_src;
-
-          if (bb_mode & 4)
-            bb_src = 0;
-
-        }
-
-stack_overflow:;
-
-    }
-
-  else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
-    {
-      bb_callcount = 1;
-      bb_src = 0;
-
-      if (bb_stack)
-          bb_stack[bb_callcount] = bb_src;
-    }
-
-  MACHINE_STATE_RESTORE("3")
-}
-
-#endif /* not inhibit_libc */
-#endif /* not BLOCK_PROFILER_CODE */
-#endif /* L_bb */
 \f
 #ifdef L_clear_cache
 /* Clear part of an instruction cache.  */
 
-#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
-
 void
 __clear_cache (char *beg __attribute__((__unused__)),
               char *end __attribute__((__unused__)))
 {
 #ifdef CLEAR_INSN_CACHE
   CLEAR_INSN_CACHE (beg, end);
-#else
-#ifdef INSN_CACHE_SIZE
-  static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
-  static int initialized;
-  int offset;
-  void *start_addr
-  void *end_addr;
-  typedef (*function_ptr) (void);
-
-#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
-  /* It's cheaper to clear the whole cache.
-     Put in a series of jump instructions so that calling the beginning
-     of the cache will clear the whole thing.  */
-
-  if (! initialized)
-    {
-      int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
-                & -INSN_CACHE_LINE_WIDTH);
-      int end_ptr = ptr + INSN_CACHE_SIZE;
-
-      while (ptr < end_ptr)
-       {
-         *(INSTRUCTION_TYPE *)ptr
-           = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
-         ptr += INSN_CACHE_LINE_WIDTH;
-       }
-      *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
-
-      initialized = 1;
-    }
-
-  /* Call the beginning of the sequence.  */
-  (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
-                   & -INSN_CACHE_LINE_WIDTH))
-   ());
-
-#else /* Cache is large.  */
-
-  if (! initialized)
-    {
-      int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
-                & -INSN_CACHE_LINE_WIDTH);
-
-      while (ptr < (int) array + sizeof array)
-       {
-         *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
-         ptr += INSN_CACHE_LINE_WIDTH;
-       }
-
-      initialized = 1;
-    }
-
-  /* Find the location in array that occupies the same cache line as BEG.  */
-
-  offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
-  start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
-                & -INSN_CACHE_PLANE_SIZE)
-               + offset);
-
-  /* Compute the cache alignment of the place to stop clearing.  */
-#if 0  /* This is not needed for gcc's purposes.  */
-  /* If the block to clear is bigger than a cache plane,
-     we clear the entire cache, and OFFSET is already correct.  */
-  if (end < beg + INSN_CACHE_PLANE_SIZE)
-#endif
-    offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
-              & -INSN_CACHE_LINE_WIDTH)
-             & (INSN_CACHE_PLANE_SIZE - 1));
-
-#if INSN_CACHE_DEPTH > 1
-  end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
-  if (end_addr <= start_addr)
-    end_addr += INSN_CACHE_PLANE_SIZE;
-
-  for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
-    {
-      int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
-      int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
-
-      while (addr != stop)
-       {
-         /* Call the return instruction at ADDR.  */
-         ((function_ptr) addr) ();
-
-         addr += INSN_CACHE_LINE_WIDTH;
-       }
-    }
-#else /* just one plane */
-  do
-    {
-      /* Call the return instruction at START_ADDR.  */
-      ((function_ptr) start_addr) ();
-
-      start_addr += INSN_CACHE_LINE_WIDTH;
-    }
-  while ((start_addr % INSN_CACHE_SIZE) != offset);
-#endif /* just one plane */
-#endif /* Cache is large */
-#endif /* Cache exists */
 #endif /* CLEAR_INSN_CACHE */
 }
 
 #endif /* L_clear_cache */
 \f
+#ifdef L_enable_execute_stack
+/* Attempt to turn on execute permission for the stack.  */
+
+#ifdef ENABLE_EXECUTE_STACK
+  ENABLE_EXECUTE_STACK
+#else
+void
+__enable_execute_stack (void *addr __attribute__((__unused__)))
+{}
+#endif /* ENABLE_EXECUTE_STACK */
+
+#endif /* L_enable_execute_stack */
+\f
 #ifdef L_trampoline
 
 /* Jump to a trampoline, loading the static chain address.  */
 
 #if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
 
-long
+int
 getpagesize (void)
 {
 #ifdef _ALPHA_
@@ -2524,198 +1644,6 @@ mprotect (char *addr, int len, int prot)
 #ifdef TRANSFER_FROM_TRAMPOLINE
 TRANSFER_FROM_TRAMPOLINE
 #endif
-
-#if defined (NeXT) && defined (__MACH__)
-
-/* Make stack executable so we can call trampolines on stack.
-   This is called from INITIALIZE_TRAMPOLINE in next.h.  */
-#ifdef NeXTStep21
- #include <mach.h>
-#else
- #include <mach/mach.h>
-#endif
-
-void
-__enable_execute_stack (char *addr)
-{
-  kern_return_t r;
-  char *eaddr = addr + TRAMPOLINE_SIZE;
-  vm_address_t a = (vm_address_t) addr;
-
-  /* turn on execute access on stack */
-  r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
-  if (r != KERN_SUCCESS)
-    {
-      mach_error("vm_protect VM_PROT_ALL", r);
-      exit(1);
-    }
-
-  /* We inline the i-cache invalidation for speed */
-
-#ifdef CLEAR_INSN_CACHE
-  CLEAR_INSN_CACHE (addr, eaddr);
-#else
-  __clear_cache ((int) addr, (int) eaddr);
-#endif
-}
-
-#endif /* defined (NeXT) && defined (__MACH__) */
-
-#ifdef __convex__
-
-/* Make stack executable so we can call trampolines on stack.
-   This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
-
-#include <sys/mman.h>
-#include <sys/vmparam.h>
-#include <machine/machparam.h>
-
-void
-__enable_execute_stack (void)
-{
-  int fp;
-  static unsigned lowest = USRSTACK;
-  unsigned current = (unsigned) &fp & -NBPG;
-
-  if (lowest > current)
-    {
-      unsigned len = lowest - current;
-      mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
-      lowest = current;
-    }
-
-  /* Clear instruction cache in case an old trampoline is in it.  */
-  asm ("pich");
-}
-#endif /* __convex__ */
-
-#ifdef __sysV88__
-
-/* Modified from the convex -code above.  */
-
-#include <sys/param.h>
-#include <errno.h>
-#include <sys/m88kbcs.h>
-
-void
-__enable_execute_stack (void)
-{
-  int save_errno;
-  static unsigned long lowest = USRSTACK;
-  unsigned long current = (unsigned long) &save_errno & -NBPC;
-
-  /* Ignore errno being set. memctl sets errno to EINVAL whenever the
-     address is seen as 'negative'. That is the case with the stack.   */
-
-  save_errno=errno;
-  if (lowest > current)
-    {
-      unsigned len=lowest-current;
-      memctl(current,len,MCT_TEXT);
-      lowest = current;
-    }
-  else
-    memctl(current,NBPC,MCT_TEXT);
-  errno=save_errno;
-}
-
-#endif /* __sysV88__ */
-
-#ifdef __sysV68__
-
-#include <sys/signal.h>
-#include <errno.h>
-
-/* Motorola forgot to put memctl.o in the libp version of libc881.a,
-   so define it here, because we need it in __clear_insn_cache below */
-/* On older versions of this OS, no memctl or MCT_TEXT are defined;
-   hence we enable this stuff only if MCT_TEXT is #define'd.  */
-
-#ifdef MCT_TEXT
-asm("\n\
-       global memctl\n\
-memctl:\n\
-       movq &75,%d0\n\
-       trap &0\n\
-       bcc.b noerror\n\
-       jmp cerror%\n\
-noerror:\n\
-       movq &0,%d0\n\
-       rts");
-#endif
-
-/* Clear instruction cache so we can call trampolines on stack.
-   This is called from FINALIZE_TRAMPOLINE in mot3300.h.  */
-
-void
-__clear_insn_cache (void)
-{
-#ifdef MCT_TEXT
-  int save_errno;
-
-  /* Preserve errno, because users would be surprised to have
-  errno changing without explicitly calling any system-call.  */
-  save_errno = errno;
-
-  /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
-     No need to use an address derived from _start or %sp, as 0 works also.  */
-  memctl(0, 4096, MCT_TEXT);
-  errno = save_errno;
-#endif
-}
-
-#endif /* __sysV68__ */
-
-#ifdef __pyr__
-
-#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
-#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/vmmac.h>
-
-/* Modified from the convex -code above.
-   mremap promises to clear the i-cache.  */
-
-void
-__enable_execute_stack (void)
-{
-  int fp;
-  if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
-               PROT_READ|PROT_WRITE|PROT_EXEC))
-    {
-      perror ("mprotect in __enable_execute_stack");
-      fflush (stderr);
-      abort ();
-    }
-}
-#endif /* __pyr__ */
-
-#if defined (sony_news) && defined (SYSTYPE_BSD)
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <syscall.h>
-#include <machine/sysnews.h>
-
-/* cacheflush function for NEWS-OS 4.2.
-   This function is called from trampoline-initialize code
-   defined in config/mips/mips.h.  */
-
-void
-cacheflush (char *beg, int size, int flag)
-{
-  if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
-    {
-      perror ("cache_flush");
-      fflush (stderr);
-      abort ();
-    }
-}
-
-#endif /* sony_news */
 #endif /* L_trampoline */
 \f
 #ifndef __CYGWIN__
@@ -2800,8 +1728,9 @@ __do_global_ctors (void)
    For systems which support a .init section we use the .init section
    to run __do_global_ctors, so we need not do anything here.  */
 
+extern void SYMBOL__MAIN (void);
 void
-SYMBOL__MAIN ()
+SYMBOL__MAIN (void)
 {
   /* Support recursive calls to `main': run initializers just once.  */
   static int initialized;
@@ -2834,7 +1763,7 @@ SYMBOL__MAIN ()
 
    Long term no port should use those extensions.  But many still do.  */
 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
-#if defined (ASM_OUTPUT_CONSTRUCTOR) || defined (USE_COLLECT2)
+#if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
 func_ptr __CTOR_LIST__[2] = {0, 0};
 func_ptr __DTOR_LIST__[2] = {0, 0};
 #else
@@ -2843,79 +1772,4 @@ func_ptr __DTOR_LIST__[2];
 #endif
 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
 #endif /* L_ctors */
-\f
-#ifdef L_exit
-
-#include "gbl-ctors.h"
-
-#ifdef NEED_ATEXIT
-
-#ifndef ON_EXIT
-
-# include <errno.h>
-
-static func_ptr *atexit_chain = 0;
-static long atexit_chain_length = 0;
-static volatile long last_atexit_chain_slot = -1;
-
-int
-atexit (func_ptr func)
-{
-  if (++last_atexit_chain_slot == atexit_chain_length)
-    {
-      atexit_chain_length += 32;
-      if (atexit_chain)
-       atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
-                                            * sizeof (func_ptr));
-      else
-       atexit_chain = (func_ptr *) malloc (atexit_chain_length
-                                           * sizeof (func_ptr));
-      if (! atexit_chain)
-       {
-         atexit_chain_length = 0;
-         last_atexit_chain_slot = -1;
-         errno = ENOMEM;
-         return (-1);
-       }
-    }
-  atexit_chain[last_atexit_chain_slot] = func;
-  return (0);
-}
-
-extern void _cleanup (void);
-extern void _exit (int) __attribute__ ((__noreturn__));
-
-void
-exit (int status)
-{
-  if (atexit_chain)
-    {
-      for ( ; last_atexit_chain_slot-- >= 0; )
-       {
-         (*atexit_chain[last_atexit_chain_slot + 1]) ();
-         atexit_chain[last_atexit_chain_slot + 1] = 0;
-       }
-      free (atexit_chain);
-      atexit_chain = 0;
-    }
-#ifdef EXIT_BODY
-  EXIT_BODY;
-#else
-  _cleanup ();
-#endif
-  _exit (status);
-}
-
-#else /* ON_EXIT */
-
-/* Simple; we just need a wrapper for ON_EXIT.  */
-int
-atexit (func_ptr func)
-{
-  return ON_EXIT (func);
-}
-
-#endif /* ON_EXIT */
-#endif /* NEED_ATEXIT */
 
-#endif /* L_exit */