OSDN Git Service

* gcc.c-torture/compile/20001226-1.x: Only xfail for Xtensa
[pf3gnuchains/gcc-fork.git] / gcc / libgcc2.c
index 3d9637c..13da298 100644 (file)
 /* More subroutines needed by GCC output code on some machines.  */
 /* Compile this one with gcc.  */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001  Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file into combinations with other programs,
+and to distribute those combinations without any restriction coming
+from the use of this file.  (The General Public License restrictions
+do apply in other respects; for example, they cover modification of
+the file, and distribution when not linked into a combine
+executable.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with other files,
-   some of which are compiled with GCC, to produce an executable,
-   this library does not by itself cause the resulting executable
-   to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.  */
+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.  */
 
 /* 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 "symcat.h"
 #include "machmode.h"
-#include "defaults.h" 
-#ifndef L_trampoline
-#include <stddef.h>
-#endif
 
 /* Don't use `fancy_abort' here even if config.h says to use it.  */
 #ifdef abort
 #undef abort
 #endif
 
-#if (SUPPORTS_WEAK == 1) && defined (ASM_OUTPUT_DEF)
-#define WEAK_ALIAS
+#include "libgcc2.h"
+\f
+#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
+#if defined (L_divdi3) || defined (L_moddi3)
+static inline
 #endif
+DWtype
+__negdi2 (DWtype u)
+{
+  DWunion w;
+  DWunion uu;
+
+  uu.ll = u;
 
-/* Permit the tm.h file to select the endianness to use just for this
-   file.  This is used when the endianness is determined when the
-   compiler is run.  */
+  w.s.low = -uu.s.low;
+  w.s.high = -uu.s.high - ((UWtype) w.s.low > 0);
 
-#ifndef LIBGCC2_WORDS_BIG_ENDIAN
-#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+  return w.ll;
+}
 #endif
 
-/* In the first part of this file, we are interfacing to calls generated
-   by the compiler itself.  These calls pass values into these routines
-   which have very specific modes (rather than very specific types), and
-   these compiler-generated calls also expect any return values to have
-   very specific modes (rather than very specific types).  Thus, we need
-   to avoid using regular C language type names in this part of the file
-   because the sizes for those types can be configured to be anything.
-   Instead we use the following special type names.  */
+#ifdef L_addvsi3
+Wtype
+__addvsi3 (Wtype a, Wtype b)
+{
+  Wtype w;
 
-typedef unsigned int UQItype   __attribute__ ((mode (QI)));
-typedef         int SItype     __attribute__ ((mode (SI)));
-typedef unsigned int USItype   __attribute__ ((mode (SI)));
-typedef                 int DItype     __attribute__ ((mode (DI)));
-typedef unsigned int UDItype   __attribute__ ((mode (DI)));
+  w = a + b;
 
-typedef        float SFtype    __attribute__ ((mode (SF)));
-typedef                float DFtype    __attribute__ ((mode (DF)));
+  if (b >= 0 ? w < a : w > a)
+    abort ();
 
-#if LONG_DOUBLE_TYPE_SIZE == 96
-typedef                float XFtype    __attribute__ ((mode (XF)));
-#endif
-#if LONG_DOUBLE_TYPE_SIZE == 128
-typedef                float TFtype    __attribute__ ((mode (TF)));
+  return w;
+}
 #endif
+\f
+#ifdef L_addvdi3
+DWtype
+__addvdi3 (DWtype a, DWtype b)
+{
+  DWtype w;
 
-typedef int word_type __attribute__ ((mode (__word__)));
+  w = a + b;
 
-/* Make sure that we don't accidentally use any normal C language built-in
-   type names in the first part of this file.  Instead we want to use *only*
-   the type names defined above.  The following macro definitions insure
-   that if we *do* accidentally use some normal C language built-in type name,
-   we will get a syntax error.  */
+  if (b >= 0 ? w < a : w > a)
+    abort ();
 
-#define char bogus_type
-#define short bogus_type
-#define int bogus_type
-#define long bogus_type
-#define unsigned bogus_type
-#define float bogus_type
-#define double bogus_type
+  return w;
+}
+#endif
+\f
+#ifdef L_subvsi3
+Wtype
+__subvsi3 (Wtype a, Wtype b)
+{
+#ifdef L_addvsi3
+  return __addvsi3 (a, (-b));
+#else
+  DWtype w;
 
-#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+  w = a - b;
 
-/* DIstructs are pairs of SItype values in the order determined by
-   LIBGCC2_WORDS_BIG_ENDIAN.  */
+  if (b >= 0 ? w > a : w < a)
+    abort ();
 
-#if LIBGCC2_WORDS_BIG_ENDIAN
-  struct DIstruct {SItype high, low;};
+  return w;
+#endif
+}
+#endif
+\f
+#ifdef L_subvdi3
+DWtype
+__subvdi3 (DWtype a, DWtype b)
+{
+#ifdef L_addvdi3
+  return (a, (-b));
 #else
-  struct DIstruct {SItype low, high;};
+  DWtype w;
+
+  w = a - b;
+
+  if (b >= 0 ? w > a : w < a)
+    abort ();
+
+  return w;
+#endif
+}
 #endif
+\f
+#ifdef L_mulvsi3
+Wtype
+__mulvsi3 (Wtype a, Wtype b)
+{
+  DWtype w;
 
-/* We need this union to unpack/pack DImode values, since we don't have
-   any arithmetic yet.  Incoming DImode parameters are stored into the
-   `ll' field, and the unpacked result is read from the struct `s'.  */
+  w = a * b;
 
-typedef union
+  if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0)
+    abort ();
+
+  return w;
+}
+#endif
+\f
+#ifdef L_negvsi2
+Wtype
+__negvsi2 (Wtype a)
 {
-  struct DIstruct s;
-  DItype ll;
-} DIunion;
+  Wtype w;
 
-#if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\
-     || defined (L_divdi3) || defined (L_udivdi3) \
-     || defined (L_moddi3) || defined (L_umoddi3))
+  w  = -a;
 
-#include "longlong.h"
+  if (a >= 0 ? w > 0 : w < 0)
+    abort ();
 
-#endif /* udiv or mul */
+   return w;
+}
+#endif
+\f
+#ifdef L_negvdi2
+DWtype
+__negvdi2 (DWtype a)
+{
+  DWtype w;
+
+  w  = -a;
+
+  if (a >= 0 ? w > 0 : w < 0)
+    abort ();
+
+  return w;
+}
+#endif
+\f
+#ifdef L_absvsi2
+Wtype
+__absvsi2 (Wtype a)
+{
+  Wtype w = a;
+
+  if (a < 0)
+#ifdef L_negvsi2
+    w = __negvsi2 (a);
+#else
+    w = -a;
 
-extern DItype __fixunssfdi (SFtype a);
-extern DItype __fixunsdfdi (DFtype a);
-#if LONG_DOUBLE_TYPE_SIZE == 96
-extern DItype __fixunsxfdi (XFtype a);
+  if (w < 0)
+    abort ();
 #endif
-#if LONG_DOUBLE_TYPE_SIZE == 128
-extern DItype __fixunstfdi (TFtype a);
+
+   return w;
+}
 #endif
 \f
-#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
-#if defined (L_divdi3) || defined (L_moddi3)
-static inline
+#ifdef L_absvdi2
+DWtype
+__absvdi2 (DWtype a)
+{
+  DWtype w = a;
+
+  if (a < 0)
+#ifdef L_negvsi2
+    w = __negvsi2 (a);
+#else
+    w = -a;
+
+  if (w < 0)
+    abort ();
 #endif
-DItype
-__negdi2 (u)
-     DItype u;
+
+  return w;
+}
+#endif
+\f
+#ifdef L_mulvdi3
+DWtype
+__mulvdi3 (DWtype u, DWtype v)
 {
-  DIunion w;
-  DIunion uu;
+  DWtype w;
 
-  uu.ll = u;
+  w = u * v;
 
-  w.s.low = -uu.s.low;
-  w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
+  if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0)
+    abort ();
 
-  return w.ll;
+  return w;
 }
 #endif
 \f
+
+/* Unless shift functions are defined whith full ANSI prototypes,
+   parameter b will be promoted to int if word_type is smaller than an int.  */
 #ifdef L_lshrdi3
-DItype
-__lshrdi3 (u, b)
-     DItype u;
-     word_type b;
+DWtype
+__lshrdi3 (DWtype u, word_type b)
 {
-  DIunion w;
+  DWunion w;
   word_type bm;
-  DIunion uu;
+  DWunion uu;
 
   if (b == 0)
     return u;
 
   uu.ll = u;
 
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
+  bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
   if (bm <= 0)
     {
       w.s.high = 0;
-      w.s.low = (USItype)uu.s.high >> -bm;
+      w.s.low = (UWtype) uu.s.high >> -bm;
     }
   else
     {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = (USItype)uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
+      UWtype carries = (UWtype) uu.s.high << bm;
+
+      w.s.high = (UWtype) uu.s.high >> b;
+      w.s.low = ((UWtype) uu.s.low >> b) | carries;
     }
 
   return w.ll;
@@ -186,31 +268,30 @@ __lshrdi3 (u, b)
 #endif
 
 #ifdef L_ashldi3
-DItype
-__ashldi3 (u, b)
-     DItype u;
-     word_type b;
+DWtype
+__ashldi3 (DWtype u, word_type b)
 {
-  DIunion w;
+  DWunion w;
   word_type bm;
-  DIunion uu;
+  DWunion uu;
 
   if (b == 0)
     return u;
 
   uu.ll = u;
 
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
+  bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
   if (bm <= 0)
     {
       w.s.low = 0;
-      w.s.high = (USItype)uu.s.low << -bm;
+      w.s.high = (UWtype) uu.s.low << -bm;
     }
   else
     {
-      USItype carries = (USItype)uu.s.low >> bm;
-      w.s.low = (USItype)uu.s.low << b;
-      w.s.high = ((USItype)uu.s.high << b) | carries;
+      UWtype carries = (UWtype) uu.s.low >> bm;
+
+      w.s.low = (UWtype) uu.s.low << b;
+      w.s.high = ((UWtype) uu.s.high << b) | carries;
     }
 
   return w.ll;
@@ -218,32 +299,31 @@ __ashldi3 (u, b)
 #endif
 
 #ifdef L_ashrdi3
-DItype
-__ashrdi3 (u, b)
-     DItype u;
-     word_type b;
+DWtype
+__ashrdi3 (DWtype u, word_type b)
 {
-  DIunion w;
+  DWunion w;
   word_type bm;
-  DIunion uu;
+  DWunion uu;
 
   if (b == 0)
     return u;
 
   uu.ll = u;
 
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
+  bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
   if (bm <= 0)
     {
       /* w.s.high = 1..1 or 0..0 */
-      w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
+      w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1);
       w.s.low = uu.s.high >> -bm;
     }
   else
     {
-      USItype carries = (USItype)uu.s.high << bm;
+      UWtype carries = (UWtype) uu.s.high << bm;
+
       w.s.high = uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
+      w.s.low = ((UWtype) uu.s.low >> b) | carries;
     }
 
   return w.ll;
@@ -251,40 +331,38 @@ __ashrdi3 (u, b)
 #endif
 \f
 #ifdef L_ffsdi2
-DItype
-__ffsdi2 (u)
-     DItype u;
+DWtype
+__ffsdi2 (DWtype u)
 {
-  DIunion uu, w;
+  DWunion uu;
+  UWtype word, count, add;
+
   uu.ll = u;
-  w.s.high = 0;
-  w.s.low = ffs (uu.s.low);
-  if (w.s.low != 0)
-    return w.ll;
-  w.s.low = ffs (uu.s.high);
-  if (w.s.low != 0)
-    {
-      w.s.low += BITS_PER_UNIT * sizeof (SItype);
-      return w.ll;
-    }
-  return w.ll;
+  if (uu.s.low != 0)
+    word = uu.s.low, add = 0;
+  else if (uu.s.high != 0)
+    word = uu.s.high, add = BITS_PER_UNIT * sizeof (Wtype);
+  else
+    return 0;
+
+  count_trailing_zeros (count, word);
+  return count + add + 1;
 }
 #endif
 \f
 #ifdef L_muldi3
-DItype
-__muldi3 (u, v)
-     DItype u, v;
+DWtype
+__muldi3 (DWtype u, DWtype v)
 {
-  DIunion w;
-  DIunion uu, vv;
+  DWunion w;
+  DWunion uu, vv;
 
   uu.ll = u,
   vv.ll = v;
 
   w.ll = __umulsidi3 (uu.s.low, vv.s.low);
-  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
-              + (USItype) uu.s.high * (USItype) vv.s.low);
+  w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
+              + (UWtype) uu.s.high * (UWtype) vv.s.low);
 
   return w.ll;
 }
@@ -292,16 +370,15 @@ __muldi3 (u, v)
 \f
 #ifdef L_udiv_w_sdiv
 #if defined (sdiv_qrnnd)
-USItype
-__udiv_w_sdiv (rp, a1, a0, d)
-     USItype *rp, a1, a0, d;
+UWtype
+__udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
 {
-  USItype q, r;
-  USItype c0, c1, b1;
+  UWtype q, r;
+  UWtype c0, c1, b1;
 
-  if ((SItype) d >= 0)
+  if ((Wtype) d >= 0)
     {
-      if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
+      if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
        {
          /* dividend, divisor, and quotient are nonnegative */
          sdiv_qrnnd (q, r, a1, a0, d);
@@ -309,18 +386,18 @@ __udiv_w_sdiv (rp, a1, a0, d)
       else
        {
          /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
-         sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
+         sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
          /* Divide (c1*2^32 + c0) by d */
          sdiv_qrnnd (q, r, c1, c0, d);
          /* Add 2^31 to quotient */
-         q += (USItype) 1 << (SI_TYPE_SIZE - 1);
+         q += (UWtype) 1 << (W_TYPE_SIZE - 1);
        }
     }
   else
     {
       b1 = d >> 1;                     /* d/2, between 2^30 and 2^31 - 1 */
       c1 = a1 >> 1;                    /* A/2 */
-      c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
+      c0 = (a1 << (W_TYPE_SIZE - 1)) + (a0 >> 1);
 
       if (a1 < b1)                     /* A < 2^32*b1, so A/2 < 2^31*b1 */
        {
@@ -391,10 +468,14 @@ __udiv_w_sdiv (rp, a1, a0, d)
 }
 #else
 /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv.  */
-USItype
-__udiv_w_sdiv (rp, a1, a0, d)
-     USItype *rp, a1, a0, d;
-{}
+UWtype
+__udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
+              UWtype a1 __attribute__ ((__unused__)),
+              UWtype a0 __attribute__ ((__unused__)),
+              UWtype d __attribute__ ((__unused__)))
+{
+  return 0;
+}
 #endif
 #endif
 \f
@@ -403,8 +484,8 @@ __udiv_w_sdiv (rp, a1, a0, d)
 #define L_udivmoddi4
 #endif
 
-#ifdef L_udivmoddi4
-static const UQItype __clz_tab[] =
+#ifdef L_clz
+const UQItype __clz_tab[] =
 {
   0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
   6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
@@ -415,22 +496,23 @@ static 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,
   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
+
+#ifdef L_udivmoddi4
 
 #if (defined (L_udivdi3) || defined (L_divdi3) || \
      defined (L_umoddi3) || defined (L_moddi3))
 static inline
 #endif
-UDItype
-__udivmoddi4 (n, d, rp)
-     UDItype n, d;
-     UDItype *rp;
+UDWtype
+__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
 {
-  DIunion ww;
-  DIunion nn, dd;
-  DIunion rr;
-  USItype d0, d1, n0, n1, n2;
-  USItype q0, q1;
-  USItype b, bm;
+  DWunion ww;
+  DWunion nn, dd;
+  DWunion rr;
+  UWtype d0, d1, n0, n1, n2;
+  UWtype q0, q1;
+  UWtype b, bm;
 
   nn.ll = n;
   dd.ll = d;
@@ -489,7 +571,7 @@ __udivmoddi4 (n, d, rp)
                 denominator set.  */
 
              d0 = d0 << bm;
-             n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
+             n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
              n0 = n0 << bm;
            }
 
@@ -514,7 +596,7 @@ __udivmoddi4 (n, d, rp)
                 leading quotient digit q1 = 1).
 
                 This special case is necessary, not an optimization.
-                (Shifts counts of SI_TYPE_SIZE are undefined.)  */
+                (Shifts counts of W_TYPE_SIZE are undefined.)  */
 
              n1 -= d0;
              q1 = 1;
@@ -523,7 +605,7 @@ __udivmoddi4 (n, d, rp)
            {
              /* Normalize.  */
 
-             b = SI_TYPE_SIZE - bm;
+             b = W_TYPE_SIZE - bm;
 
              d0 = d0 << bm;
              n2 = n1 >> b;
@@ -533,7 +615,7 @@ __udivmoddi4 (n, d, rp)
              udiv_qrnnd (q1, n1, n2, n1, d0);
            }
 
-         /* n1 != d0... */
+         /* n1 != d0...  */
 
          udiv_qrnnd (q0, n0, n1, n0, d0);
 
@@ -600,10 +682,10 @@ __udivmoddi4 (n, d, rp)
            }
          else
            {
-             USItype m1, m0;
+             UWtype m1, m0;
              /* Normalize.  */
 
-             b = SI_TYPE_SIZE - bm;
+             b = W_TYPE_SIZE - bm;
 
              d1 = (d1 << bm) | (d0 >> b);
              d0 = d0 << bm;
@@ -641,15 +723,12 @@ __udivmoddi4 (n, d, rp)
 #endif
 
 #ifdef L_divdi3
-UDItype __udivmoddi4 ();
-
-DItype
-__divdi3 (u, v)
-     DItype u, v;
+DWtype
+__divdi3 (DWtype u, DWtype v)
 {
   word_type c = 0;
-  DIunion uu, vv;
-  DItype w;
+  DWunion uu, vv;
+  DWtype w;
 
   uu.ll = u;
   vv.ll = v;
@@ -661,7 +740,7 @@ __divdi3 (u, v)
     c = ~c,
     vv.ll = __negdi2 (vv.ll);
 
-  w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
+  w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
   if (c)
     w = __negdi2 (w);
 
@@ -670,14 +749,12 @@ __divdi3 (u, v)
 #endif
 
 #ifdef L_moddi3
-UDItype __udivmoddi4 ();
-DItype
-__moddi3 (u, v)
-     DItype u, v;
+DWtype
+__moddi3 (DWtype u, DWtype v)
 {
   word_type c = 0;
-  DIunion uu, vv;
-  DItype w;
+  DWunion uu, vv;
+  DWtype w;
 
   uu.ll = u;
   vv.ll = v;
@@ -697,12 +774,10 @@ __moddi3 (u, v)
 #endif
 
 #ifdef L_umoddi3
-UDItype __udivmoddi4 ();
-UDItype
-__umoddi3 (u, v)
-     UDItype u, v;
+UDWtype
+__umoddi3 (UDWtype u, UDWtype v)
 {
-  UDItype w;
+  UDWtype w;
 
   (void) __udivmoddi4 (u, v, &w);
 
@@ -711,21 +786,18 @@ __umoddi3 (u, v)
 #endif
 
 #ifdef L_udivdi3
-UDItype __udivmoddi4 ();
-UDItype
-__udivdi3 (n, d)
-     UDItype n, d;
+UDWtype
+__udivdi3 (UDWtype n, UDWtype d)
 {
-  return __udivmoddi4 (n, d, (UDItype *) 0);
+  return __udivmoddi4 (n, d, (UDWtype *) 0);
 }
 #endif
 \f
 #ifdef L_cmpdi2
 word_type
-__cmpdi2 (a, b)
-     DItype a, b;
+__cmpdi2 (DWtype a, DWtype b)
 {
-  DIunion au, bu;
+  DWunion au, bu;
 
   au.ll = a, bu.ll = b;
 
@@ -733,9 +805,9 @@ __cmpdi2 (a, b)
     return 0;
   else if (au.s.high > bu.s.high)
     return 2;
-  if ((USItype) au.s.low < (USItype) bu.s.low)
+  if ((UWtype) au.s.low < (UWtype) bu.s.low)
     return 0;
-  else if ((USItype) au.s.low > (USItype) bu.s.low)
+  else if ((UWtype) au.s.low > (UWtype) bu.s.low)
     return 2;
   return 1;
 }
@@ -743,321 +815,269 @@ __cmpdi2 (a, b)
 
 #ifdef L_ucmpdi2
 word_type
-__ucmpdi2 (a, b)
-     DItype a, b;
+__ucmpdi2 (DWtype a, DWtype b)
 {
-  DIunion au, bu;
+  DWunion au, bu;
 
   au.ll = a, bu.ll = b;
 
-  if ((USItype) au.s.high < (USItype) bu.s.high)
+  if ((UWtype) au.s.high < (UWtype) bu.s.high)
     return 0;
-  else if ((USItype) au.s.high > (USItype) bu.s.high)
+  else if ((UWtype) au.s.high > (UWtype) bu.s.high)
     return 2;
-  if ((USItype) au.s.low < (USItype) bu.s.low)
+  if ((UWtype) au.s.low < (UWtype) bu.s.low)
     return 0;
-  else if ((USItype) au.s.low > (USItype) bu.s.low)
+  else if ((UWtype) au.s.low > (UWtype) bu.s.low)
     return 2;
   return 1;
 }
 #endif
 \f
-#if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
-#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+#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)
 
-DItype
-__fixunstfdi (a)
-     TFtype a;
+DWtype
+__fixunstfDI (TFtype a)
 {
   TFtype b;
-  UDItype v;
+  UDWtype v;
 
   if (a < 0)
     return 0;
 
   /* Compute high word of result, as a flonum.  */
   b = (a / HIGH_WORD_COEFF);
-  /* Convert that to fixed (but not to DItype!),
+  /* Convert that to fixed (but not to DWtype!),
      and shift it into the high word.  */
-  v = (USItype) b;
+  v = (UWtype) b;
   v <<= WORD_SIZE;
   /* Remove high part from the TFtype, leaving the low part as flonum.  */
   a -= (TFtype)v;
-  /* Convert that to fixed (but not to DItype!) and add it in.
+  /* 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 -= (USItype) (- a);
+    v -= (UWtype) (- a);
   else
-    v += (USItype) a;
+    v += (UWtype) a;
   return v;
 }
 #endif
 
-#if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
-DItype
-__fixtfdi (a)
-     TFtype a;
+#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
+DWtype
+__fixtfdi (TFtype a)
 {
   if (a < 0)
-    return - __fixunstfdi (-a);
-  return __fixunstfdi (a);
+    return - __fixunstfDI (-a);
+  return __fixunstfDI (a);
 }
 #endif
 
-#if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
-#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
+#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
 
-DItype
-__fixunsxfdi (a)
-     XFtype a;
+DWtype
+__fixunsxfDI (XFtype a)
 {
   XFtype b;
-  UDItype v;
+  UDWtype v;
 
   if (a < 0)
     return 0;
 
   /* Compute high word of result, as a flonum.  */
   b = (a / HIGH_WORD_COEFF);
-  /* Convert that to fixed (but not to DItype!),
+  /* Convert that to fixed (but not to DWtype!),
      and shift it into the high word.  */
-  v = (USItype) b;
+  v = (UWtype) b;
   v <<= WORD_SIZE;
   /* Remove high part from the XFtype, leaving the low part as flonum.  */
   a -= (XFtype)v;
-  /* Convert that to fixed (but not to DItype!) and add it in.
+  /* 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 -= (USItype) (- a);
+    v -= (UWtype) (- a);
   else
-    v += (USItype) a;
+    v += (UWtype) a;
   return v;
 }
 #endif
 
-#if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
-DItype
-__fixxfdi (a)
-     XFtype a;
+#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+DWtype
+__fixxfdi (XFtype a)
 {
   if (a < 0)
-    return - __fixunsxfdi (-a);
-  return __fixunsxfdi (a);
+    return - __fixunsxfDI (-a);
+  return __fixunsxfDI (a);
 }
 #endif
 
 #ifdef L_fixunsdfdi
-#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
+#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
 
-DItype
-__fixunsdfdi (a)
-     DFtype a;
+DWtype
+__fixunsdfDI (DFtype a)
 {
   DFtype b;
-  UDItype v;
+  UDWtype v;
 
   if (a < 0)
     return 0;
 
   /* Compute high word of result, as a flonum.  */
   b = (a / HIGH_WORD_COEFF);
-  /* Convert that to fixed (but not to DItype!),
+  /* Convert that to fixed (but not to DWtype!),
      and shift it into the high word.  */
-  v = (USItype) b;
+  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 DItype!) and add it in.
+  /* 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 -= (USItype) (- a);
+    v -= (UWtype) (- a);
   else
-    v += (USItype) a;
+    v += (UWtype) a;
   return v;
 }
 #endif
 
 #ifdef L_fixdfdi
-DItype
-__fixdfdi (a)
-     DFtype a;
+DWtype
+__fixdfdi (DFtype a)
 {
   if (a < 0)
-    return - __fixunsdfdi (-a);
-  return __fixunsdfdi (a);
+    return - __fixunsdfDI (-a);
+  return __fixunsdfDI (a);
 }
 #endif
 
 #ifdef L_fixunssfdi
-#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
-#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
+#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
 
-DItype
-__fixunssfdi (SFtype original_a)
+DWtype
+__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;
-  UDItype v;
+  UDWtype v;
 
   if (a < 0)
     return 0;
 
   /* Compute high word of result, as a flonum.  */
   b = (a / HIGH_WORD_COEFF);
-  /* Convert that to fixed (but not to DItype!),
+  /* Convert that to fixed (but not to DWtype!),
      and shift it into the high word.  */
-  v = (USItype) b;
+  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 DItype!) and add it in.
+  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 -= (USItype) (- a);
+    v -= (UWtype) (- a);
   else
-    v += (USItype) a;
+    v += (UWtype) a;
   return v;
 }
 #endif
 
 #ifdef L_fixsfdi
-DItype
+DWtype
 __fixsfdi (SFtype a)
 {
   if (a < 0)
-    return - __fixunssfdi (-a);
-  return __fixunssfdi (a);
+    return - __fixunssfDI (-a);
+  return __fixunssfDI (a);
 }
 #endif
 
-#if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
-#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+#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)
 
 XFtype
-__floatdixf (u)
-     DItype u;
+__floatdixf (DWtype u)
 {
   XFtype d;
-  SItype negate = 0;
 
-  if (u < 0)
-    u = -u, negate = 1;
-
-  d = (USItype) (u >> WORD_SIZE);
+  d = (Wtype) (u >> WORD_SIZE);
   d *= HIGH_HALFWORD_COEFF;
   d *= HIGH_HALFWORD_COEFF;
-  d += (USItype) (u & (HIGH_WORD_COEFF - 1));
+  d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
 
-  return (negate ? -d : d);
+  return d;
 }
 #endif
 
-#if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
-#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+#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)
 
 TFtype
-__floatditf (u)
-     DItype u;
+__floatditf (DWtype u)
 {
   TFtype d;
-  SItype negate = 0;
-
-  if (u < 0)
-    u = -u, negate = 1;
 
-  d = (USItype) (u >> WORD_SIZE);
+  d = (Wtype) (u >> WORD_SIZE);
   d *= HIGH_HALFWORD_COEFF;
   d *= HIGH_HALFWORD_COEFF;
-  d += (USItype) (u & (HIGH_WORD_COEFF - 1));
+  d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
 
-  return (negate ? -d : d);
+  return d;
 }
 #endif
 
 #ifdef L_floatdidf
-#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
+#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)
 
 DFtype
-__floatdidf (u)
-     DItype u;
+__floatdidf (DWtype u)
 {
   DFtype d;
-  SItype negate = 0;
-
-  if (u < 0)
-    u = -u, negate = 1;
 
-  d = (USItype) (u >> WORD_SIZE);
+  d = (Wtype) (u >> WORD_SIZE);
   d *= HIGH_HALFWORD_COEFF;
   d *= HIGH_HALFWORD_COEFF;
-  d += (USItype) (u & (HIGH_WORD_COEFF - 1));
+  d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
 
-  return (negate ? -d : d);
+  return d;
 }
 #endif
 
 #ifdef L_floatdisf
-#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
-#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
-#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
-#define DI_SIZE (sizeof (DItype) * 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
+#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 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 (u)
-     DItype u;
+__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;
-  SItype negate = 0;
-
-  if (u < 0)
-    u = -u, negate = 1;
 
   /* Protect against double-rounding error.
      Represent any low-order bits, that might be truncated in DFmode,
@@ -1068,23 +1088,24 @@ __floatdisf (u)
   if (DF_SIZE < DI_SIZE
       && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
     {
-#define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
-      if (u >= ((UDItype) 1 << DF_SIZE))
+#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
+      if (! (- ((DWtype) 1 << DF_SIZE) < u
+            && u < ((DWtype) 1 << DF_SIZE)))
        {
-         if ((USItype) u & (REP_BIT - 1))
+         if ((UDWtype) u & (REP_BIT - 1))
            u |= REP_BIT;
        }
     }
-  f = (USItype) (u >> WORD_SIZE);
+  f = (Wtype) (u >> WORD_SIZE);
   f *= HIGH_HALFWORD_COEFF;
   f *= HIGH_HALFWORD_COEFF;
-  f += (USItype) (u & (HIGH_WORD_COEFF - 1));
+  f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
 
-  return (SFtype) (negate ? -f : f);
+  return (SFtype) f;
 }
 #endif
 
-#if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
+#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
 /* Reenable the normal types, in case limits.h needs them.  */
 #undef char
 #undef short
@@ -1093,15 +1114,16 @@ __floatdisf (u)
 #undef unsigned
 #undef float
 #undef double
+#undef MIN
+#undef MAX
 #include <limits.h>
 
-USItype
-__fixunsxfsi (a)
-     XFtype a;
+UWtype
+__fixunsxfSI (XFtype a)
 {
-  if (a >= - (DFtype) LONG_MIN)
-    return (SItype) (a + LONG_MIN) - LONG_MIN;
-  return (SItype) a;
+  if (a >= - (DFtype) Wtype_MIN)
+    return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
+  return (Wtype) a;
 }
 #endif
 
@@ -1114,15 +1136,16 @@ __fixunsxfsi (a)
 #undef unsigned
 #undef float
 #undef double
+#undef MIN
+#undef MAX
 #include <limits.h>
 
-USItype
-__fixunsdfsi (a)
-     DFtype a;
+UWtype
+__fixunsdfSI (DFtype a)
 {
-  if (a >= - (DFtype) LONG_MIN)
-    return (SItype) (a + LONG_MIN) - LONG_MIN;
-  return (SItype) a;
+  if (a >= - (DFtype) Wtype_MIN)
+    return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
+  return (Wtype) a;
 }
 #endif
 
@@ -1135,14 +1158,16 @@ __fixunsdfsi (a)
 #undef unsigned
 #undef float
 #undef double
+#undef MIN
+#undef MAX
 #include <limits.h>
 
-USItype
-__fixunssfsi (SFtype a)
+UWtype
+__fixunssfSI (SFtype a)
 {
-  if (a >= - (SFtype) LONG_MIN)
-    return (SItype) (a + LONG_MIN) - LONG_MIN;
-  return (SItype) a;
+  if (a >= - (SFtype) Wtype_MIN)
+    return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
+  return (Wtype) a;
 }
 #endif
 \f
@@ -1154,6 +1179,12 @@ __fixunssfsi (SFtype a)
 #define UDItype bogus_type
 #define SFtype bogus_type
 #define DFtype bogus_type
+#undef Wtype
+#undef UWtype
+#undef HWtype
+#undef UHWtype
+#undef DWtype
+#undef UDWtype
 
 #undef char
 #undef short
@@ -1170,9 +1201,7 @@ __fixunssfsi (SFtype a)
    positive if S1 is greater, 0 if S1 and S2 are equal.  */
 
 int
-__gcc_bcmp (s1, s2, size)
-     unsigned char *s1, *s2;
-     size_t size;
+__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
 {
   while (size > 0)
     {
@@ -1185,239 +1214,20 @@ __gcc_bcmp (s1, s2, size)
 }
 
 #endif
-\f\f
-#ifdef L_varargs
-#ifdef __i860__
-#if defined(__svr4__) || defined(__alliant__)
-       asm ("  .text");
-       asm ("  .align  4");
-
-/* The Alliant needs the added underscore.  */
-       asm (".globl    __builtin_saveregs");
-asm ("__builtin_saveregs:");
-       asm (".globl    ___builtin_saveregs");
-asm ("___builtin_saveregs:");
-
-        asm (" andnot  0x0f,%sp,%sp"); /* round down to 16-byte boundary */
-       asm ("  adds    -96,%sp,%sp");  /* allocate stack space for reg save
-                                          area and also for a new va_list
-                                          structure */
-       /* Save all argument registers in the arg reg save area.  The
-          arg reg save area must have the following layout (according
-          to the svr4 ABI):
-
-               struct {
-                 union  {
-                   float freg[8];
-                   double dreg[4];
-                 } float_regs;
-                 long  ireg[12];
-               };
-       */
-
-       asm ("  fst.q   %f8,  0(%sp)"); /* save floating regs (f8-f15)  */
-       asm ("  fst.q   %f12,16(%sp)"); 
-
-       asm ("  st.l    %r16,32(%sp)"); /* save integer regs (r16-r27) */
-       asm ("  st.l    %r17,36(%sp)"); 
-       asm ("  st.l    %r18,40(%sp)");
-       asm ("  st.l    %r19,44(%sp)");
-       asm ("  st.l    %r20,48(%sp)");
-       asm ("  st.l    %r21,52(%sp)");
-       asm ("  st.l    %r22,56(%sp)");
-       asm ("  st.l    %r23,60(%sp)");
-       asm ("  st.l    %r24,64(%sp)");
-       asm ("  st.l    %r25,68(%sp)");
-       asm ("  st.l    %r26,72(%sp)");
-       asm ("  st.l    %r27,76(%sp)");
-
-       asm ("  adds    80,%sp,%r16");  /* compute the address of the new
-                                          va_list structure.  Put in into
-                                          r16 so that it will be returned
-                                          to the caller.  */
-
-       /* Initialize all fields of the new va_list structure.  This
-          structure looks like:
-
-               typedef struct {
-                   unsigned long       ireg_used;
-                   unsigned long       freg_used;
-                   long                *reg_base;
-                   long                *mem_ptr;
-               } va_list;
-       */
-
-       asm ("  st.l    %r0, 0(%r16)"); /* nfixed */
-       asm ("  st.l    %r0, 4(%r16)"); /* nfloating */
-       asm ("  st.l    %sp, 8(%r16)"); /* __va_ctl points to __va_struct.  */
-       asm ("  bri     %r1");          /* delayed return */
-       asm ("  st.l    %r28,12(%r16)"); /* pointer to overflow args */
-
-#else /* not __svr4__ */
-#if defined(__PARAGON__)
-       /*
-        *      we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
-        *      and we stand a better chance of hooking into libraries
-        *      compiled by PGI.  [andyp@ssd.intel.com]
-        */
-       asm ("  .text");
-       asm ("  .align  4");
-       asm (".globl    __builtin_saveregs");
-asm ("__builtin_saveregs:");
-       asm (".globl    ___builtin_saveregs");
-asm ("___builtin_saveregs:");
-
-        asm (" andnot  0x0f,sp,sp");   /* round down to 16-byte boundary */
-       asm ("  adds    -96,sp,sp");    /* allocate stack space for reg save
-                                          area and also for a new va_list
-                                          structure */
-       /* Save all argument registers in the arg reg save area.  The
-          arg reg save area must have the following layout (according
-          to the svr4 ABI):
-
-               struct {
-                 union  {
-                   float freg[8];
-                   double dreg[4];
-                 } float_regs;
-                 long  ireg[12];
-               };
-       */
-
-       asm ("  fst.q   f8,  0(sp)");
-       asm ("  fst.q   f12,16(sp)"); 
-       asm ("  st.l    r16,32(sp)");
-       asm ("  st.l    r17,36(sp)"); 
-       asm ("  st.l    r18,40(sp)");
-       asm ("  st.l    r19,44(sp)");
-       asm ("  st.l    r20,48(sp)");
-       asm ("  st.l    r21,52(sp)");
-       asm ("  st.l    r22,56(sp)");
-       asm ("  st.l    r23,60(sp)");
-       asm ("  st.l    r24,64(sp)");
-       asm ("  st.l    r25,68(sp)");
-       asm ("  st.l    r26,72(sp)");
-       asm ("  st.l    r27,76(sp)");
-
-       asm ("  adds    80,sp,r16");  /* compute the address of the new
-                                          va_list structure.  Put in into
-                                          r16 so that it will be returned
-                                          to the caller.  */
-
-       /* Initialize all fields of the new va_list structure.  This
-          structure looks like:
-
-               typedef struct {
-                   unsigned long       ireg_used;
-                   unsigned long       freg_used;
-                   long                *reg_base;
-                   long                *mem_ptr;
-               } va_list;
-       */
-
-       asm ("  st.l    r0, 0(r16)"); /* nfixed */
-       asm ("  st.l    r0, 4(r16)"); /* nfloating */
-       asm ("  st.l    sp, 8(r16)"); /* __va_ctl points to __va_struct.  */
-       asm ("  bri     r1");           /* delayed return */
-       asm ("   st.l   r28,12(r16)"); /* pointer to overflow args */
-#else /* not __PARAGON__ */
-       asm ("  .text");
-       asm ("  .align  4");
-
-       asm (".globl    ___builtin_saveregs");
-       asm ("___builtin_saveregs:");
-       asm ("  mov     sp,r30");
-       asm ("  andnot  0x0f,sp,sp");
-       asm ("  adds    -96,sp,sp");  /* allocate sufficient space on the stack */
-
-/* Fill in the __va_struct.  */
-       asm ("  st.l    r16, 0(sp)"); /* save integer regs (r16-r27) */
-       asm ("  st.l    r17, 4(sp)"); /* int    fixed[12] */
-       asm ("  st.l    r18, 8(sp)");
-       asm ("  st.l    r19,12(sp)");
-       asm ("  st.l    r20,16(sp)");
-       asm ("  st.l    r21,20(sp)");
-       asm ("  st.l    r22,24(sp)");
-       asm ("  st.l    r23,28(sp)");
-       asm ("  st.l    r24,32(sp)");
-       asm ("  st.l    r25,36(sp)");
-       asm ("  st.l    r26,40(sp)");
-       asm ("  st.l    r27,44(sp)");
-
-       asm ("  fst.q   f8, 48(sp)"); /* save floating regs (f8-f15) */
-       asm ("  fst.q   f12,64(sp)"); /* int floating[8] */
-
-/* Fill in the __va_ctl.  */
-       asm ("  st.l    sp, 80(sp)"); /* __va_ctl points to __va_struct.  */
-       asm ("  st.l    r28,84(sp)"); /* pointer to more args */
-       asm ("  st.l    r0, 88(sp)"); /* nfixed */
-       asm ("  st.l    r0, 92(sp)"); /* nfloating */
-
-       asm ("  adds    80,sp,r16");  /* return address of the __va_ctl.  */
-       asm ("  bri     r1");
-       asm ("  mov     r30,sp");
-                               /* recover stack and pass address to start 
-                                  of data.  */
-#endif /* not __PARAGON__ */
-#endif /* not __svr4__ */
-#else /* not __i860__ */
-#ifdef __sparc__
-       asm (".global __builtin_saveregs");
-       asm ("__builtin_saveregs:");
-       asm (".global ___builtin_saveregs");
-       asm ("___builtin_saveregs:");
-#ifdef NEED_PROC_COMMAND
-       asm (".proc 020");
-#endif
-       asm ("st %i0,[%fp+68]");
-       asm ("st %i1,[%fp+72]");
-       asm ("st %i2,[%fp+76]");
-       asm ("st %i3,[%fp+80]");
-       asm ("st %i4,[%fp+84]");
-       asm ("retl");
-       asm ("st %i5,[%fp+88]");
-#ifdef NEED_TYPE_COMMAND
-       asm (".type __builtin_saveregs,#function");
-       asm (".size __builtin_saveregs,.-__builtin_saveregs");
-#endif
-#else /* not __sparc__ */
-#if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
-
-  asm ("       .text");
-  asm ("       .ent __builtin_saveregs");
-  asm ("       .globl __builtin_saveregs");
-  asm ("__builtin_saveregs:");
-  asm ("       sw      $4,0($30)");
-  asm ("       sw      $5,4($30)");
-  asm ("       sw      $6,8($30)");
-  asm ("       sw      $7,12($30)");
-  asm ("       j       $31");
-  asm ("       .end __builtin_saveregs");
-#else /* not __mips__, etc. */
-
-void *
-__builtin_saveregs ()
-{
-  abort ();
-}
-
-#endif /* not __mips__ */
-#endif /* not __sparc__ */
-#endif /* not __i860__ */
-#endif
 \f
+/* __eprintf used to be used by GCC's private version of <assert.h>.
+   We no longer provide that header, but this routine remains in libgcc.a
+   for binary backward compatibility.  Note that it is not included in
+   the shared version of libgcc.  */
 #ifdef L_eprintf
 #ifndef inhibit_libc
 
 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
 #include <stdio.h>
-/* This is used by the `assert' macro.  */
+
 void
-__eprintf (string, expression, line, filename)
-     const char *string;
-     const char *expression;
-     int line;
-     const char *filename;
+__eprintf (const char *string, const char *expression,
+          unsigned int line, const char *filename)
 {
   fprintf (stderr, string, expression, line, filename);
   fflush (stderr);
@@ -1429,26 +1239,26 @@ __eprintf (string, expression, line, filename)
 
 #ifdef L_bb
 
+struct bb_function_info {
+  long checksum;
+  int arc_count;
+  const char *name;
+};
+
 /* Structure emitted by -a  */
 struct bb
 {
   long zero_word;
   const char *filename;
-  long *counts;
+  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;
+  long sizeof_bb;
+  struct bb_function_info *function_infos;
 };
 
-#ifdef BLOCK_PROFILER_CODE
-BLOCK_PROFILER_CODE
-#else
 #ifndef inhibit_libc
 
 /* Simple minded basic block profiling output dumper for
@@ -1457,151 +1267,189 @@ BLOCK_PROFILER_CODE
 
 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
 #include <stdio.h>
-char *ctime ();
 
-#ifdef HAVE_ATEXIT
-#ifdef WINNT
-extern int atexit (void (*) (void));
-#else
-extern void atexit (void (*) (void));
-#endif
-#define ON_EXIT(FUNC,ARG) atexit ((FUNC))
-#else
-#ifdef sun
-extern void on_exit (void*, void*);
-#define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
-#endif
+#include "gbl-ctors.h"
+#include "gcov-io.h"
+#include <string.h>
+#ifdef TARGET_HAS_F_SETLKW
+#include <fcntl.h>
+#include <errno.h>
 #endif
 
+#include <gthr.h>
+
 static struct bb *bb_head;
 
-/* Return the number of digits needed to print a value */
-/* __inline__ */ static int num_digits (long value, int base)
+int __global_counters = 0, __gthreads_active = 0;
+
+void
+__bb_exit_func (void)
 {
-  int minus = (value < 0 && base != 16);
-  unsigned long v = (minus) ? -value : value;
-  int ret = minus;
+  FILE *da_file;
+  struct bb *ptr;
+  long n_counters_p = 0;
+  gcov_type max_counter_p = 0;
+  gcov_type sum_counters_p = 0;
 
-  do
+  if (bb_head == 0)
+    return;
+
+  /* Calculate overall "statistics".  */
+
+  for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
     {
-      v /= base;
-      ret++;
-    }
-  while (v);
+      int i;
 
-  return ret;
-}
+      n_counters_p += ptr->ncounts;
 
-void
-__bb_exit_func (void)
-{
-  FILE *file = fopen ("bb.out", "a");
-  long time_value;
+      for (i = 0; i < ptr->ncounts; i++)
+       {
+         sum_counters_p += ptr->counts[i];
 
-  if (!file)
-    perror ("bb.out");
+         if (ptr->counts[i] > max_counter_p)
+           max_counter_p = ptr->counts[i];
+       }
+    }
 
-  else
+  for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
     {
-      struct bb *ptr;
+      gcov_type max_counter_o = 0;
+      gcov_type sum_counters_o = 0;
+      int i;
 
-      /* 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.  */
+      /* Calculate the per-object statistics.  */
 
-      time((void *) &time_value);
-      fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
+      for (i = 0; i < ptr->ncounts; i++)
+       {
+         sum_counters_o += ptr->counts[i];
 
-      /* We check the length field explicitly in order to allow compatibility
-        with older GCC's which did not provide it.  */
+         if (ptr->counts[i] > max_counter_o)
+           max_counter_o = ptr->counts[i];
+       }
 
-      for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
+      /* open the file for appending, creating it if necessary.  */
+      da_file = fopen (ptr->filename, "ab");
+      /* 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, "a");
+      if (da_file == 0)
        {
-         int i;
-         int func_p    = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
-         int line_p    = (func_p && ptr->line_nums);
-         int file_p    = (func_p && ptr->filenames);
-         long ncounts  = ptr->ncounts;
-         long 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;
+         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;
 
-             if (cnt_max < ptr->counts[i])
-               cnt_max = ptr->counts[i];
+       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 ();
 
-             if (addr_max < ptr->addresses[i])
-               addr_max = ptr->addresses[i];
+       while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
+              && errno == EINTR);
+      }
+#endif
 
-             if (line_p && line_max < ptr->line_nums[i])
-               line_max = ptr->line_nums[i];
+      if (__write_long (-123, da_file, 4) != 0)        /* magic */
+       {
+         fprintf (stderr, "arc profiling: Error writing output file %s.\n",
+                  ptr->filename);
+       }
+      else
+       {
 
-             if (func_p)
+         struct bb_function_info *fn_info;
+         gcov_type *count_ptr = ptr->counts;
+         int i;
+         int count_functions = 0;
+
+         for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
+              fn_info++)
+           count_functions++;
+
+         /* number of functions in this block.  */
+         __write_long (count_functions, da_file, 4);
+
+         /* length of extra data in bytes.  */
+         __write_long ((4 + 8 + 8) + (4 + 8 + 8), da_file, 4);
+
+         /* overall statistics.  */
+         /* number of counters.  */
+         __write_long (n_counters_p, da_file, 4);
+         /* sum of counters.  */
+         __write_gcov_type (sum_counters_p, da_file, 8);
+         /* maximal counter.  */
+         __write_gcov_type (max_counter_p, da_file, 8);
+
+         /* per-object statistics.  */
+         /* number of counters.  */
+         __write_long (ptr->ncounts, da_file, 4);
+         /* sum of counters.  */
+         __write_gcov_type (sum_counters_o, da_file, 8);
+         /* maximal counter.  */
+         __write_gcov_type (max_counter_o, da_file, 8);
+
+         /* write execution counts for each function.  */
+
+         for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
+              fn_info++)
+           {
+             /* new function.  */
+             if (__write_gcov_string
+                 (fn_info->name, strlen (fn_info->name), da_file, -1) != 0)
                {
-                 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
-                 len = strlen (p);
-                 if (func_len < len)
-                   func_len = len;
+                 fprintf (stderr,
+                          "arc profiling: Error writing output file %s.\n",
+                          ptr->filename);
+                 break;
                }
 
-             if (file_p)
+             if (__write_long (fn_info->checksum, da_file, 4) != 0)
                {
-                 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
-                 len = strlen (p);
-                 if (file_len < len)
-                   file_len = len;
+                 fprintf (stderr,
+                          "arc profiling: Error writing output file %s.\n",
+                          ptr->filename);
+                 break;
                }
-           }
-
-         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++)
-           {
-             fprintf (file,
-                      "    Block #%*d: executed %*ld time(s) address= 0x%.*lx",
-                      blk_len, i+1,
-                      cnt_len, ptr->counts[i],
-                      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 (__write_long (fn_info->arc_count, da_file, 4) != 0)
+               {
+                 fprintf (stderr,
+                          "arc profiling: Error writing output file %s.\n",
+                          ptr->filename);
+                 break;
+               }
 
-             if (file_p)
-               fprintf (file, " file= %s",
-                        (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
+             for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
+               {
+                 if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
+                   break;
+               }
 
-             fprintf (file, "\n");
+             if (i)            /* there was an error */
+               {
+                 fprintf (stderr,
+                          "arc profiling: Error writing output file %s.\n",
+                          ptr->filename);
+                 break;
+               }
            }
-
-         fprintf (file, "\n");
-         fflush (file);
        }
 
-      fprintf (file, "\n\n");
-      fclose (file);
+      if (fclose (da_file) != 0)
+       fprintf (stderr, "arc profiling: Error closing output file %s.\n",
+                ptr->filename);
     }
 }
 
@@ -1609,16 +1457,14 @@ void
 __bb_init_func (struct bb *blocks)
 {
   /* User is supposed to check whether the first word is non-0,
-     but just in case.... */
+     but just in case....  */
 
   if (blocks->zero_word)
     return;
 
-#ifdef ON_EXIT
-  /* Initialize destructor.  */
+  /* Initialize destructor and per-thread data.  */
   if (!bb_head)
-    ON_EXIT (__bb_exit_func, 0);
-#endif
+    atexit (__bb_exit_func);
 
   /* Set up linked list.  */
   blocks->zero_word = 1;
@@ -1626,173 +1472,25 @@ __bb_init_func (struct bb *blocks)
   bb_head = blocks;
 }
 
-#endif /* not inhibit_libc */
-#endif /* not BLOCK_PROFILER_CODE */
-#endif /* L_bb */
-\f
-/* Default free-store management functions for C++, per sections 12.5 and
-   17.3.3 of the Working Paper. */
-
-#ifdef L_op_new
-/* operator new (size_t), described in 17.3.3.5.  This function is used by
-   C++ programs to allocate a block of memory to hold a single object. */
-
-typedef void (*vfp)(void);
-extern vfp __new_handler;
-extern void __default_new_handler (void);
-
-#ifdef WEAK_ALIAS
-void * __builtin_new (size_t sz)
-     __attribute__ ((weak, alias ("___builtin_new")));
-void *
-___builtin_new (size_t sz)
-#else
-void *
-__builtin_new (size_t sz)
-#endif
-{
-  void *p;
-  vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
-
-  /* malloc (0) is unpredictable; avoid it.  */
-  if (sz == 0)
-    sz = 1;
-  p = (void *) malloc (sz);
-  while (p == 0)
-    {
-      (*handler) ();
-      p = (void *) malloc (sz);
-    }
-  
-  return p;
-}
-#endif /* L_op_new */
-
-#ifdef L_op_vnew
-/* void * operator new [] (size_t), described in 17.3.3.6.  This function
-   is used by C++ programs to allocate a block of memory for an array.  */
-
-extern void * __builtin_new (size_t);
-
-#ifdef WEAK_ALIAS
-void * __builtin_vec_new (size_t sz)
-     __attribute__ ((weak, alias ("___builtin_vec_new")));
-void *
-___builtin_vec_new (size_t sz)
-#else
-void *
-__builtin_vec_new (size_t sz)
-#endif
-{
-  return __builtin_new (sz);
-}
-#endif /* L_op_vnew */
-
-#ifdef L_new_handler
-/* set_new_handler (fvoid_t *) and the default new handler, described in
-   17.3.3.2 and 17.3.3.5.  These functions define the result of a failure
-   to allocate the amount of memory requested from operator new or new []. */
-
-#ifndef inhibit_libc
-/* This gets us __GNU_LIBRARY__.  */
-#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
-#include <stdio.h>
-
-#ifdef __GNU_LIBRARY__
-  /* Avoid forcing the library's meaning of `write' on the user program
-     by using the "internal" name (for use within the library)  */
-#define write(fd, buf, n)      __write((fd), (buf), (n))
-#endif
-#endif /* inhibit_libc */
-
-typedef void (*vfp)(void);
-void __default_new_handler (void);
-
-vfp __new_handler = (vfp)0;
-
-vfp
-set_new_handler (vfp handler)
-{
-  vfp prev_handler;
-
-  prev_handler = __new_handler;
-  if (handler == 0) handler = __default_new_handler;
-  __new_handler = handler;
-  return prev_handler;
-}
-
-#define MESSAGE "Virtual memory exceeded in `new'\n"
-
-void
-__default_new_handler ()
-{
-#ifndef inhibit_libc
-  /* don't use fprintf (stderr, ...) because it may need to call malloc.  */
-  /* This should really print the name of the program, but that is hard to
-     do.  We need a standard, clean way to get at the name.  */
-  write (2, MESSAGE, sizeof (MESSAGE));
-#endif
-  /* don't call exit () because that may call global destructors which
-     may cause a loop.  */
-  _exit (-1);
-}
-#endif
-
-#ifdef L_op_delete
-/* operator delete (void *), described in 17.3.3.3.  This function is used
-   by C++ programs to return to the free store a block of memory allocated
-   as a single object. */
-
-#ifdef WEAK_ALIAS
-void __builtin_delete (void *ptr)
-     __attribute__ ((weak, alias ("___builtin_delete")));
-void
-___builtin_delete (void *ptr)
-#else
+/* 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
-__builtin_delete (void *ptr)
-#endif
+__bb_fork_func (void)
 {
-  if (ptr)
-    free (ptr);
-}
-#endif
+  struct bb *ptr;
 
-#ifdef L_op_vdel
-/* operator delete [] (void *), described in 17.3.3.4.  This function is
-   used by C++ programs to return to the free store a block of memory
-   allocated as an array. */
-
-extern void __builtin_delete (void *);
-
-#ifdef WEAK_ALIAS
-void __builtin_vec_delete (void *ptr)
-     __attribute__ ((weak, alias ("___builtin_vec_delete")));
-void
-___builtin_vec_delete (void *ptr)
-#else
-void
-__builtin_vec_delete (void *ptr)
-#endif
-{
-  __builtin_delete (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;
+    }
 }
-#endif
 
-/* End of C++ free-store management functions */
-\f
-#ifdef L_shtab
-unsigned int __shtab[] = {
-    0x00000001, 0x00000002, 0x00000004, 0x00000008,
-    0x00000010, 0x00000020, 0x00000040, 0x00000080,
-    0x00000100, 0x00000200, 0x00000400, 0x00000800,
-    0x00001000, 0x00002000, 0x00004000, 0x00008000,
-    0x00010000, 0x00020000, 0x00040000, 0x00080000,
-    0x00100000, 0x00200000, 0x00400000, 0x00800000,
-    0x01000000, 0x02000000, 0x04000000, 0x08000000,
-    0x10000000, 0x20000000, 0x40000000, 0x80000000
-  };
-#endif
+#endif /* not inhibit_libc */
+#endif /* L_bb */
 \f
 #ifdef L_clear_cache
 /* Clear part of an instruction cache.  */
@@ -1800,10 +1498,10 @@ unsigned int __shtab[] = {
 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
 
 void
-__clear_cache (beg, end)
-     char *beg, *end;
+__clear_cache (char *beg __attribute__((__unused__)),
+              char *end __attribute__((__unused__)))
 {
-#ifdef CLEAR_INSN_CACHE 
+#ifdef CLEAR_INSN_CACHE
   CLEAR_INSN_CACHE (beg, end);
 #else
 #ifdef INSN_CACHE_SIZE
@@ -1812,7 +1510,7 @@ __clear_cache (beg, end)
   int offset;
   void *start_addr
   void *end_addr;
-  typedef (*function_ptr) ();
+  typedef (*function_ptr) (void);
 
 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
   /* It's cheaper to clear the whole cache.
@@ -1831,7 +1529,7 @@ __clear_cache (beg, end)
            = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
          ptr += INSN_CACHE_LINE_WIDTH;
        }
-      *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
+      *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
 
       initialized = 1;
     }
@@ -1867,7 +1565,7 @@ __clear_cache (beg, end)
   /* 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.  */ 
+     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)
@@ -1913,8 +1611,50 @@ __clear_cache (beg, end)
 
 /* Jump to a trampoline, loading the static chain address.  */
 
-#ifdef TRANSFER_FROM_TRAMPOLINE 
-TRANSFER_FROM_TRAMPOLINE 
+#if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
+
+long
+getpagesize (void)
+{
+#ifdef _ALPHA_
+  return 8192;
+#else
+  return 4096;
+#endif
+}
+
+#ifdef __i386__
+extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
+#endif
+
+int
+mprotect (char *addr, int len, int prot)
+{
+  int np, op;
+
+  if (prot == 7)
+    np = 0x40;
+  else if (prot == 5)
+    np = 0x20;
+  else if (prot == 4)
+    np = 0x10;
+  else if (prot == 3)
+    np = 0x04;
+  else if (prot == 1)
+    np = 0x02;
+  else if (prot == 0)
+    np = 0x01;
+
+  if (VirtualProtect (addr, len, np, &op))
+    return 0;
+  else
+    return -1;
+}
+
+#endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
+
+#ifdef TRANSFER_FROM_TRAMPOLINE
+TRANSFER_FROM_TRAMPOLINE
 #endif
 
 #if defined (NeXT) && defined (__MACH__)
@@ -1928,8 +1668,7 @@ TRANSFER_FROM_TRAMPOLINE
 #endif
 
 void
-__enable_execute_stack (addr)
-     char *addr;
+__enable_execute_stack (char *addr)
 {
   kern_return_t r;
   char *eaddr = addr + TRAMPOLINE_SIZE;
@@ -1950,7 +1689,7 @@ __enable_execute_stack (addr)
 #else
   __clear_cache ((int) addr, (int) eaddr);
 #endif
-} 
+}
 
 #endif /* defined (NeXT) && defined (__MACH__) */
 
@@ -1964,7 +1703,7 @@ __enable_execute_stack (addr)
 #include <machine/machparam.h>
 
 void
-__enable_execute_stack ()
+__enable_execute_stack (void)
 {
   int fp;
   static unsigned lowest = USRSTACK;
@@ -1977,28 +1716,28 @@ __enable_execute_stack ()
       lowest = current;
     }
 
-  /* Clear instruction cache in case an old trampoline is in it. */
+  /* Clear instruction cache in case an old trampoline is in it.  */
   asm ("pich");
 }
 #endif /* __convex__ */
 
-#ifdef __DOLPHIN__
+#ifdef __sysV88__
 
-/* Modified from the convex -code above. */
+/* Modified from the convex -code above.  */
 
 #include <sys/param.h>
 #include <errno.h>
 #include <sys/m88kbcs.h>
 
 void
-__enable_execute_stack ()
+__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.   */
+     address is seen as 'negative'. That is the case with the stack.  */
 
   save_errno=errno;
   if (lowest > current)
@@ -2012,7 +1751,52 @@ __enable_execute_stack ()
   errno=save_errno;
 }
 
-#endif /* __DOLPHIN__ */
+#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__
 
@@ -2024,10 +1808,10 @@ __enable_execute_stack ()
 #include <sys/vmmac.h>
 
 /* Modified from the convex -code above.
-   mremap promises to clear the i-cache. */
+   mremap promises to clear the i-cache.  */
 
 void
-__enable_execute_stack ()
+__enable_execute_stack (void)
 {
   int fp;
   if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
@@ -2039,59 +1823,107 @@ __enable_execute_stack ()
     }
 }
 #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__
 #ifdef L__main
 
 #include "gbl-ctors.h"
 /* Some systems use __main in a way incompatible with its use in gcc, in these
    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
    give the same symbol without quotes for an alternative entry point.  You
-   must define both, or neither. */
+   must define both, or neither.  */
 #ifndef NAME__MAIN
 #define NAME__MAIN "__main"
 #define SYMBOL__MAIN __main
 #endif
 
-#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
+#ifdef INIT_SECTION_ASM_OP
+#undef HAS_INIT_SECTION
+#define HAS_INIT_SECTION
+#endif
+
+#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
+
+/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
+   code to run constructors.  In that case, we need to handle EH here, too.  */
+
+#ifdef EH_FRAME_SECTION_NAME
+#include "unwind-dw2-fde.h"
+extern unsigned char __EH_FRAME_BEGIN__[];
+#endif
+
 /* Run all the global destructors on exit from the program.  */
 
 void
-__do_global_dtors ()
+__do_global_dtors (void)
 {
 #ifdef DO_GLOBAL_DTORS_BODY
   DO_GLOBAL_DTORS_BODY;
 #else
-  func_ptr *p;
-  for (p = __DTOR_LIST__ + 1; *p; )
-    (*p++) ();
+  static func_ptr *p = __DTOR_LIST__ + 1;
+  while (*p)
+    {
+      p++;
+      (*(p-1)) ();
+    }
+#endif
+#if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
+  {
+    static int completed = 0;
+    if (! completed)
+      {
+       completed = 1;
+       __deregister_frame_info (__EH_FRAME_BEGIN__);
+      }
+  }
 #endif
 }
 #endif
 
-#ifndef INIT_SECTION_ASM_OP
+#ifndef HAS_INIT_SECTION
 /* Run all the global constructors on entry to the program.  */
 
-#ifndef ON_EXIT
-#define ON_EXIT(a, b)
-#else
-/* Make sure the exit routine is pulled in to define the globals as
-   bss symbols, just in case the linker does not automatically pull
-   bss definitions from the library.  */
-
-extern int _exit_dummy_decl;
-int *_exit_dummy_ref = &_exit_dummy_decl;
-#endif /* ON_EXIT */
-
 void
-__do_global_ctors ()
+__do_global_ctors (void)
 {
+#ifdef EH_FRAME_SECTION_NAME
+  {
+    static struct object object;
+    __register_frame_info (__EH_FRAME_BEGIN__, &object);
+  }
+#endif
   DO_GLOBAL_CTORS_BODY;
-  ON_EXIT (__do_global_dtors, 0);
+  atexit (__do_global_dtors);
 }
-#endif /* no INIT_SECTION_ASM_OP */
+#endif /* no HAS_INIT_SECTION */
 
-#if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
+#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
 /* Subroutine called automatically by `main'.
    Compiling a global function named `main'
    produces an automatic call to this function at the beginning.
@@ -2111,9 +1943,10 @@ SYMBOL__MAIN ()
       __do_global_ctors ();
     }
 }
-#endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
+#endif /* no HAS_INIT_SECTION or INVOKE__main */
 
 #endif /* L__main */
+#endif /* __CYGWIN__ */
 \f
 #ifdef L_ctors
 
@@ -2125,10 +1958,15 @@ SYMBOL__MAIN ()
    the right values.  */
 
 /* We declare the lists here with two elements each,
-   so that they are valid empty lists if no other definition is loaded.  */
+   so that they are valid empty lists if no other definition is loaded.
+
+   If we are using the old "set" extensions to have the gnu linker
+   collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
+   must be in the bss/common section.
+
+   Long term no port should use those extensions.  But many still do.  */
 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
-#ifdef __NeXT__
-/* After 2.3, try this definition on all systems.  */
+#if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
 func_ptr __CTOR_LIST__[2] = {0, 0};
 func_ptr __DTOR_LIST__[2] = {0, 0};
 #else
@@ -2142,276 +1980,74 @@ func_ptr __DTOR_LIST__[2];
 
 #include "gbl-ctors.h"
 
-#ifndef ON_EXIT
-
-/* If we have no known way of registering our own __do_global_dtors
-   routine so that it will be invoked at program exit time, then we
-   have to define our own exit routine which will get this to happen.  */
+#ifdef NEED_ATEXIT
 
-extern void __do_global_dtors ();
-extern void _cleanup ();
-extern void _exit () __attribute__ ((noreturn));
-
-void 
-exit (status)
-     int status;
-{
-#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
-  __do_global_dtors ();
-#endif
-#ifdef EXIT_BODY
-  EXIT_BODY;
-#else
-  _cleanup ();
-#endif
-  _exit (status);
-}
-
-#else
-int _exit_dummy_decl = 0;      /* prevent compiler & linker warnings */
-#endif
+#ifndef ON_EXIT
 
-#endif /* L_exit */
-\f
-#ifdef L_eh
-typedef struct {
-  void *start;
-  void *end;
-  void *exception_handler;
-} exception_table;
-
-struct exception_table_node {
-  exception_table *table;
-  void *start;
-  void *end;
-  struct exception_table_node *next;
-};
+# include <errno.h>
 
-static int except_table_pos;
-static void *except_pc;
-static struct exception_table_node *exception_table_list;
+static func_ptr *atexit_chain = 0;
+static long atexit_chain_length = 0;
+static volatile long last_atexit_chain_slot = -1;
 
-static exception_table *
-find_exception_table (pc)
-     void* pc;
+int
+atexit (func_ptr func)
 {
-  register struct exception_table_node *table = exception_table_list;
-  for ( ; table != 0; table = table->next)
+  if (++last_atexit_chain_slot == atexit_chain_length)
     {
-      if (table->start <= pc && table->end > pc)
-       return table->table;
+      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);
+       }
     }
-  return 0;
+  atexit_chain[last_atexit_chain_slot] = func;
+  return (0);
 }
 
-/* this routine takes a pc, and the address of the exception handler associated
-   with the closest exception table handler entry associated with that PC,
-   or 0 if there are no table entries the PC fits in.  The algorithm works
-   something like this:
-
-    while(current_entry exists) {
-        if(current_entry.start < pc )
-            current_entry = next_entry;
-        else {
-            if(prev_entry.start <= pc && prev_entry.end > pc) {
-                save pointer to prev_entry;
-                return prev_entry.exception_handler;
-             }
-            else return 0;
-         }
-     }
-    return 0;
-
-   Assuming a correctly sorted table (ascending order) this routine should
-   return the tightest match...
+extern void _cleanup (void);
+extern void _exit (int) __attribute__ ((__noreturn__));
 
-   In the advent of a tie, we have to give the last entry, as it represents
-   an inner block.
- */
-
-
-void *
-__find_first_exception_table_match(pc)
-void *pc;
+void
+exit (int status)
 {
-  exception_table *table = find_exception_table (pc);
-  int pos = 0;
-  int best = 0;
-  if (table == 0)
-    return (void*)0;
-#if 0
-  printf("find_first_exception_table_match(): pc = %x!\n",pc);
-#endif
-
-  except_pc = pc;
-
-#if 0
-  /* We can't do this yet, as we don't know that the table is sorted.  */
-  do {
-    ++pos;
-    if (table[pos].start > except_pc)
-      /* found the first table[pos].start > except_pc, so the previous
-        entry better be the one we want! */
-      break;
-  } while(table[pos].exception_handler != (void*)-1);
-
-  --pos;
-  if (table[pos].start <= except_pc && table[pos].end > except_pc)
+  if (atexit_chain)
     {
-      except_table_pos = pos;
-#if 0
-      printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
-#endif
-      return table[pos].exception_handler;
+      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
-  while (table[++pos].exception_handler != (void*)-1) {
-    if (table[pos].start <= except_pc && table[pos].end > except_pc)
-      {
-       /* This can apply.  Make sure it is better or as good as the previous
-          best.  */
-       /* The best one ends first. */
-       if (best == 0 || (table[pos].end <= table[best].end
-                         /* The best one starts last.  */
-                         && table[pos].start >= table[best].start))
-         best = pos;
-      }
-  }
-  if (best != 0)
-    return table[best].exception_handler;
-#endif
-
-#if 0
-  printf("find_first_eh_table_match(): else: returning NULL!\n");
-#endif
-  return (void*)0;
-}
-
-void *
-__throw_type_match (void *catch_type, void *throw_type, void* obj)
-{
-#if 0
- printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
-       catch_type, throw_type);
+  _cleanup ();
 #endif
- if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
-   return obj;
- return 0;
-}
-
-void
-__register_exceptions (exception_table *table)
-{
-  struct exception_table_node *node;
-  exception_table *range = table + 1;
-
-  if (range->start == (void*)-1)
-    return;
-
-  node = (struct exception_table_node*)
-    malloc (sizeof (struct exception_table_node));
-  node->table = table;
-
-  /* This look can be optimized away either if the table
-     is sorted, or if we pass in extra parameters. */
-  node->start = range->start;
-  node->end = range->end;
-  for (range++ ; range->start != (void*)(-1); range++)
-    {
-      if (range->start < node->start)
-       node->start = range->start;
-      if (range->end > node->end)
-       node->end = range->end;
-    }
-
-  node->next = exception_table_list;
-  exception_table_list = node;
+  _exit (status);
 }
 
-#if #machine(i386)
-void
-__unwind_function(void *ptr)
-{
-  asm("movl 8(%esp),%ecx");
-  /* Undo current frame */
-  asm("movl %ebp,%esp");
-  asm("popl %ebp");
-  /* like ret, but stay here */
-  asm("addl $4,%esp");
-  
-  /* Now, undo previous frame. */
-  /* This is a test routine, as we have to dynamically probe to find out
-     what to pop for certain, this is just a guess. */
-  asm("leal -16(%ebp),%esp");
-  asm("pop %eax"); /* really for popl %ebx */
-  asm("pop %eax"); /* really for popl %esi */
-  asm("pop %eax"); /* really for popl %edi */
-  asm("movl %ebp,%esp");
-  asm("popl %ebp");
-
-  asm("movl %ecx,0(%esp)");
-  asm("ret");
-}
-#endif
+#else /* ON_EXIT */
 
-#if #machine(rs6000)
-__unwind_function(void *ptr)
+/* Simple; we just need a wrapper for ON_EXIT.  */
+int
+atexit (func_ptr func)
 {
-  asm("mr 31,1");
-  asm("l 1,0(1)");
-  asm("l 31,-4(1)");
-  asm("# br");
-
-  asm("mr 31,1");
-  asm("l 1,0(1)");
-  /* use 31 as a scratch register to restore the link register. */
-  asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
-  asm("l 31,-4(1)");
-  asm("# br");
-  asm("mtctr 3;bctr # b 3");
+  return ON_EXIT (func);
 }
-#endif /* rs6000 */
 
-#if #machine(powerpc)
-__unwind_function(void *ptr)
-{
-  asm("mr 31,1");
-  asm("lwz 1,0(1)");
-  asm("lwz 31,-4(1)");
-  asm("# br");
-
-  asm("mr 31,1");
-  asm("lwz 1,0(1)");
-  /* use 31 as a scratch register to restore the link register. */
-  asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
-  asm("lwz 31,-4(1)");
-  asm("# br");
-  asm("mtctr 3;bctr # b 3");
-}
-#endif /* powerpc */
-#endif /* L_eh */
-\f
-#ifdef L_pure
-#ifndef inhibit_libc
-/* This gets us __GNU_LIBRARY__.  */
-#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
-#include <stdio.h>
-
-#ifdef __GNU_LIBRARY__
-  /* Avoid forcing the library's meaning of `write' on the user program
-     by using the "internal" name (for use within the library)  */
-#define write(fd, buf, n)      __write((fd), (buf), (n))
-#endif
-#endif /* inhibit_libc */
-
-#define MESSAGE "pure virtual method called\n"
+#endif /* ON_EXIT */
+#endif /* NEED_ATEXIT */
 
-void
-__pure_virtual ()
-{
-#ifndef inhibit_libc
-  write (2, MESSAGE, sizeof (MESSAGE) - 1);
-#endif
-  _exit (-1);
-}
-#endif
+#endif /* L_exit */