OSDN Git Service

* POTFILES.in: Remove dyn-string.[ch].
[pf3gnuchains/gcc-fork.git] / gcc / libgcc2.c
index aa8839b..305d7f0 100644 (file)
@@ -1,6 +1,7 @@
 /* More subroutines needed by GCC output code on some machines.  */
 /* Compile this one with gcc.  */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
+/* Copyright (C) 1989, 92, 93, 94, 95, 96, 97, 98, 1999, 2000
+   Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -9,6 +10,15 @@ 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.)
+
 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
@@ -19,152 +29,37 @@ 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.  */
-
 /* 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"
-
-/* We disable this when inhibit_libc, so that gcc can still be built without
-   needing header files first.  */
-/* ??? This is not a good solution, since prototypes may be required in
-   some cases for correct code.  See also frame.c.  */
-#ifndef inhibit_libc
-/* fixproto guarantees these system headers exist. */
-#include <stdlib.h>
-#include <unistd.h>
-#endif
+#include "tsystem.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
 
-/* In a cross-compilation situation, default to inhibiting compilation
-   of routines that use libc.  */
-
-#if defined(CROSS_COMPILE) && !defined(inhibit_libc)
-#define inhibit_libc
-#endif
-
-/* 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.  */
-
-#ifndef LIBGCC2_WORDS_BIG_ENDIAN
-#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
-#endif
-
-#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
-#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.  */
-
-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)));
-
-typedef        float SFtype    __attribute__ ((mode (SF)));
-typedef                float DFtype    __attribute__ ((mode (DF)));
-
-#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
-typedef                float XFtype    __attribute__ ((mode (XF)));
-#endif
-#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
-typedef                float TFtype    __attribute__ ((mode (TF)));
-#endif
-
-typedef int word_type __attribute__ ((mode (__word__)));
-
-/* 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.  */
-
-#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
-
-#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
-
-/* DIstructs are pairs of SItype values in the order determined by
-   LIBGCC2_WORDS_BIG_ENDIAN.  */
-
-#if LIBGCC2_WORDS_BIG_ENDIAN
-  struct DIstruct {SItype high, low;};
-#else
-  struct DIstruct {SItype low, high;};
-#endif
-
-/* 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'.  */
-
-typedef union
-{
-  struct DIstruct s;
-  DItype ll;
-} DIunion;
-
-#if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\
-     || defined (L_divdi3) || defined (L_udivdi3) \
-     || defined (L_moddi3) || defined (L_umoddi3))
-
-#include "longlong.h"
-
-#endif /* udiv or mul */
-
-extern DItype __fixunssfdi (SFtype a);
-extern DItype __fixunsdfdi (DFtype a);
-#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
-extern DItype __fixunsxfdi (XFtype a);
-#endif
-#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
-extern DItype __fixunstfdi (TFtype a);
-#endif
+#include "libgcc2.h"
 \f
 #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
 #if defined (L_divdi3) || defined (L_moddi3)
 static inline
 #endif
-DItype
-__negdi2 (DItype u)
+DWtype
+__negdi2 (DWtype u)
 {
-  DIunion w;
-  DIunion uu;
+  DWunion w;
+  DWunion uu;
 
   uu.ll = u;
 
   w.s.low = -uu.s.low;
-  w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
+  w.s.high = -uu.s.high - ((UWtype) w.s.low > 0);
 
   return w.ll;
 }
@@ -173,29 +68,30 @@ __negdi2 (DItype u)
 /* 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 (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;
@@ -203,29 +99,30 @@ __lshrdi3 (DItype u, word_type b)
 #endif
 
 #ifdef L_ashldi3
-DItype
-__ashldi3 (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;
@@ -233,30 +130,31 @@ __ashldi3 (DItype u, word_type b)
 #endif
 
 #ifdef L_ashrdi3
-DItype
-__ashrdi3 (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;
@@ -264,10 +162,10 @@ __ashrdi3 (DItype u, word_type b)
 #endif
 \f
 #ifdef L_ffsdi2
-DItype
-__ffsdi2 (DItype u)
+DWtype
+__ffsdi2 (DWtype u)
 {
-  DIunion uu, w;
+  DWunion uu, w;
   uu.ll = u;
   w.s.high = 0;
   w.s.low = ffs (uu.s.low);
@@ -276,7 +174,7 @@ __ffsdi2 (DItype u)
   w.s.low = ffs (uu.s.high);
   if (w.s.low != 0)
     {
-      w.s.low += BITS_PER_UNIT * sizeof (SItype);
+      w.s.low += BITS_PER_UNIT * sizeof (Wtype);
       return w.ll;
     }
   return w.ll;
@@ -284,18 +182,18 @@ __ffsdi2 (DItype u)
 #endif
 \f
 #ifdef L_muldi3
-DItype
-__muldi3 (DItype u, DItype 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;
 }
@@ -303,15 +201,15 @@ __muldi3 (DItype u, DItype v)
 \f
 #ifdef L_udiv_w_sdiv
 #if defined (sdiv_qrnnd)
-USItype
-__udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype 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);
@@ -319,18 +217,18 @@ __udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype 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 */
        {
@@ -401,11 +299,11 @@ __udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
 }
 #else
 /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv.  */
-USItype
-__udiv_w_sdiv (USItype *rp __attribute__ ((__unused__)),
-              USItype a1 __attribute__ ((__unused__)),
-              USItype a0 __attribute__ ((__unused__)),
-              USItype d __attribute__ ((__unused__)))
+UWtype
+__udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
+              UWtype a1 __attribute__ ((__unused__)),
+              UWtype a0 __attribute__ ((__unused__)),
+              UWtype d __attribute__ ((__unused__)))
 {
   return 0;
 }
@@ -434,15 +332,15 @@ static const UQItype __clz_tab[] =
      defined (L_umoddi3) || defined (L_moddi3))
 static inline
 #endif
-UDItype
-__udivmoddi4 (UDItype n, UDItype 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;
@@ -501,7 +399,7 @@ __udivmoddi4 (UDItype n, UDItype d, UDItype *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;
            }
 
@@ -526,7 +424,7 @@ __udivmoddi4 (UDItype n, UDItype d, UDItype *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;
@@ -535,7 +433,7 @@ __udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
            {
              /* Normalize.  */
 
-             b = SI_TYPE_SIZE - bm;
+             b = W_TYPE_SIZE - bm;
 
              d0 = d0 << bm;
              n2 = n1 >> b;
@@ -612,10 +510,10 @@ __udivmoddi4 (UDItype n, UDItype d, UDItype *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;
@@ -653,14 +551,12 @@ __udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
 #endif
 
 #ifdef L_divdi3
-UDItype __udivmoddi4 ();
-
-DItype
-__divdi3 (DItype u, DItype 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;
@@ -672,7 +568,7 @@ __divdi3 (DItype u, DItype 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);
 
@@ -681,13 +577,12 @@ __divdi3 (DItype u, DItype v)
 #endif
 
 #ifdef L_moddi3
-UDItype __udivmoddi4 ();
-DItype
-__moddi3 (DItype u, DItype 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;
@@ -707,11 +602,10 @@ __moddi3 (DItype u, DItype v)
 #endif
 
 #ifdef L_umoddi3
-UDItype __udivmoddi4 ();
-UDItype
-__umoddi3 (UDItype u, UDItype v)
+UDWtype
+__umoddi3 (UDWtype u, UDWtype v)
 {
-  UDItype w;
+  UDWtype w;
 
   (void) __udivmoddi4 (u, v, &w);
 
@@ -720,19 +614,18 @@ __umoddi3 (UDItype u, UDItype v)
 #endif
 
 #ifdef L_udivdi3
-UDItype __udivmoddi4 ();
-UDItype
-__udivdi3 (UDItype n, UDItype 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 (DItype a, DItype b)
+__cmpdi2 (DWtype a, DWtype b)
 {
-  DIunion au, bu;
+  DWunion au, bu;
 
   au.ll = a, bu.ll = b;
 
@@ -740,9 +633,9 @@ __cmpdi2 (DItype a, DItype 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;
 }
@@ -750,258 +643,258 @@ __cmpdi2 (DItype a, DItype b)
 
 #ifdef L_ucmpdi2
 word_type
-__ucmpdi2 (DItype a, DItype 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) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
-#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
-__fixunstfdi (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) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
-DItype
+DWtype
 __fixtfdi (TFtype a)
 {
   if (a < 0)
-    return - __fixunstfdi (-a);
-  return __fixunstfdi (a);
+    return - __fixunstfDI (-a);
+  return __fixunstfDI (a);
 }
 #endif
 
 #if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
-#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
-__fixunsxfdi (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) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
-DItype
+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 (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
+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) && (LIBGCC2_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)
+#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 (DItype u)
+__floatdixf (DWtype u)
 {
   XFtype d;
 
-  d = (SItype) (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 d;
 }
 #endif
 
 #if defined(L_floatditf) && (LIBGCC2_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)
+#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 (DItype u)
+__floatditf (DWtype u)
 {
   TFtype d;
 
-  d = (SItype) (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 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 (DItype u)
+__floatdidf (DWtype u)
 {
   DFtype d;
 
-  d = (SItype) (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 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 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.  */
@@ -1032,7 +925,7 @@ __floatdidf (DItype u)
 #endif
 
 SFtype
-__floatdisf (DItype u)
+__floatdisf (DWtype u)
 {
   /* Do the calculation in DFmode
      so that we don't lose any of the precision of the high word
@@ -1048,18 +941,18 @@ __floatdisf (DItype u)
   if (DF_SIZE < DI_SIZE
       && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
     {
-#define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
-      if (! (- ((DItype) 1 << DF_SIZE) < u
-            && u < ((DItype) 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 = (SItype) (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) f;
 }
@@ -1078,12 +971,12 @@ __floatdisf (DItype u)
 #undef MAX
 #include <limits.h>
 
-USItype
-__fixunsxfsi (XFtype a)
+UWtype
+__fixunsxfSI (XFtype a)
 {
   if (a >= - (DFtype) LONG_MIN)
-    return (SItype) (a + LONG_MIN) - LONG_MIN;
-  return (SItype) a;
+    return (Wtype) (a + LONG_MIN) - LONG_MIN;
+  return (Wtype) a;
 }
 #endif
 
@@ -1100,12 +993,12 @@ __fixunsxfsi (XFtype a)
 #undef MAX
 #include <limits.h>
 
-USItype
-__fixunsdfsi (DFtype a)
+UWtype
+__fixunsdfSI (DFtype a)
 {
   if (a >= - (DFtype) LONG_MIN)
-    return (SItype) (a + LONG_MIN) - LONG_MIN;
-  return (SItype) a;
+    return (Wtype) (a + LONG_MIN) - LONG_MIN;
+  return (Wtype) a;
 }
 #endif
 
@@ -1122,12 +1015,12 @@ __fixunsdfsi (DFtype a)
 #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;
+    return (Wtype) (a + LONG_MIN) - LONG_MIN;
+  return (Wtype) a;
 }
 #endif
 \f
@@ -1139,6 +1032,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
@@ -1155,7 +1054,7 @@ __fixunssfsi (SFtype a)
    positive if S1 is greater, 0 if S1 and S2 are equal.  */
 
 int
-__gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size)
+__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
 {
   while (size > 0)
     {
@@ -1171,7 +1070,7 @@ __gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size)
 \f\f
 #ifdef L__dummy
 void
-__dummy () {}
+__dummy (void) {}
 #endif
 
 #ifdef L_varargs
@@ -1386,8 +1285,8 @@ asm ("___builtin_saveregs:");
   asm ("       .end __builtin_saveregs");
 #else /* not __mips__, etc.  */
 
-void *
-__builtin_saveregs ()
+void * __attribute__ ((__noreturn__))
+__builtin_saveregs (void)
 {
   abort ();
 }
@@ -1403,9 +1302,6 @@ __builtin_saveregs ()
 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
 #include <stdio.h>
 /* This is used by the `assert' macro.  */
-extern void __eprintf (const char *, const char *, unsigned int, const char *)
-  __attribute__ ((__noreturn__));
-
 void
 __eprintf (const char *string, const char *expression,
           unsigned int line, const char *filename)
@@ -1454,6 +1350,10 @@ char *ctime ();
 #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;
 
@@ -1497,13 +1397,64 @@ __bb_exit_func (void)
 
       for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
        {
-         /* If the file exists, and the number of counts in it is the same,
-            then merge them in.  */
-            
-         if ((da_file = fopen (ptr->filename, "r")) != 0)
+         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",
@@ -1529,17 +1480,10 @@ __bb_exit_func (void)
                    }
                }
 
-             if (fclose (da_file) == EOF)
-               fprintf (stderr, "arc profiling: Error closing output file %s.\n",
-                        ptr->filename);
-           }
-         if ((da_file = fopen (ptr->filename, "w")) == 0)
-           {
-             fprintf (stderr, "arc profiling: Can't open output file %s.\n",
-                      ptr->filename);
-             continue;
            }
 
+         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
@@ -1607,7 +1551,7 @@ __bb_exit_func (void)
       for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
        {
          int i;
-         int func_p    = (ptr->nwords >= sizeof (struct bb)
+         int func_p    = (ptr->nwords >= (long) sizeof (struct bb)
                           && ptr->nwords <= 1000
                           && ptr->functions);
          int line_p    = (func_p && ptr->line_nums);
@@ -1636,7 +1580,7 @@ __bb_exit_func (void)
              if (cnt_max < ptr->counts[i])
                cnt_max = ptr->counts[i];
 
-             if (addr_p && addr_max < ptr->addresses[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])
@@ -1717,6 +1661,23 @@ __bb_init_func (struct bb *blocks)
   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
@@ -1732,11 +1693,6 @@ __bb_init_func (struct bb *blocks)
 
 #define BBINBUFSIZE 500
 
-/* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
-   "BBINBUFSIZE" but want to avoid trouble with preprocessors.  */
-
-#define BBINBUFSIZESTR "499"
-
 struct bb_edge
 {
   struct bb_edge *next;
@@ -1876,7 +1832,7 @@ gclose (FILE *f)
 /* Called once per program.  */
 
 static void
-__bb_exit_trace_func ()
+__bb_exit_trace_func (void)
 {
   FILE *file = fopen ("bb.out", "a");
   struct bb_func *f;
@@ -2014,8 +1970,8 @@ found:        ;
                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", 
+                   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);
@@ -2071,7 +2027,7 @@ found:        ;
 /* Called once per program.  */
 
 static void
-__bb_init_prg ()
+__bb_init_prg (void)
 {
   FILE *file;
   char buf[BBINBUFSIZE];
@@ -2086,8 +2042,12 @@ __bb_init_prg ()
   if (!(file = fopen ("bb.in", "r")))
     return;
 
-  while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
+  while(fgets (buf, BBINBUFSIZE, file) != 0)
     {
+      i = strlen (buf);
+      if (buf[i] == '\n')
+       buf[i--] = '\0';
+
       p = buf;
       if (*p == '-') 
         { 
@@ -2177,7 +2137,7 @@ __bb_init_prg ()
 /* Called upon entering a basic block.  */
 
 void
-__bb_trace_func ()
+__bb_trace_func (void)
 {
   struct bb_edge *bucket;
 
@@ -2250,7 +2210,7 @@ skip:
 /* Called when returning from a function and `__bb_showret__' is set.  */
 
 static void
-__bb_trace_func_ret ()
+__bb_trace_func_ret (void)
 {
   struct bb_edge *bucket;
 
@@ -2348,7 +2308,7 @@ __bb_init_file (struct bb *blocks)
 /* Called when exiting from a function.  */
 
 void
-__bb_trace_ret ()
+__bb_trace_ret (void)
 {
 
   MACHINE_STATE_SAVE("2")
@@ -2458,7 +2418,8 @@ unsigned int __shtab[] = {
 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
 
 void
-__clear_cache (char *beg, char *end)
+__clear_cache (char *beg __attribute__((__unused__)),
+              char *end __attribute__((__unused__)))
 {
 #ifdef CLEAR_INSN_CACHE 
   CLEAR_INSN_CACHE (beg, end);
@@ -2469,7 +2430,7 @@ __clear_cache (char *beg, char *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.
@@ -2572,7 +2533,8 @@ __clear_cache (char *beg, char *end)
 
 #if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
 
-long getpagesize()
+long
+getpagesize (void)
 {
 #ifdef _ALPHA_
   return 8192;
@@ -2581,7 +2543,7 @@ long getpagesize()
 #endif
 }
 
-#ifdef i386
+#ifdef __i386__
 extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
 #endif
 
@@ -2661,7 +2623,7 @@ __enable_execute_stack (char *addr)
 #include <machine/machparam.h>
 
 void
-__enable_execute_stack ()
+__enable_execute_stack (void)
 {
   int fp;
   static unsigned lowest = USRSTACK;
@@ -2688,7 +2650,7 @@ __enable_execute_stack ()
 #include <sys/m88kbcs.h>
 
 void
-__enable_execute_stack ()
+__enable_execute_stack (void)
 {
   int save_errno;
   static unsigned long lowest = USRSTACK;
@@ -2738,7 +2700,7 @@ noerror:\n\
    This is called from FINALIZE_TRAMPOLINE in mot3300.h.  */
 
 void
-__clear_insn_cache ()
+__clear_insn_cache (void)
 {
 #ifdef MCT_TEXT
   int save_errno;
@@ -2769,7 +2731,7 @@ __clear_insn_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,
@@ -2839,7 +2801,7 @@ extern unsigned char __EH_FRAME_BEGIN__[];
 /* 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;
@@ -2851,8 +2813,15 @@ __do_global_dtors ()
       (*(p-1)) ();
     }
 #endif
-#ifdef EH_FRAME_SECTION
-  __deregister_frame_info (__EH_FRAME_BEGIN__);
+#if defined (EH_FRAME_SECTION) && !defined (HAS_INIT_SECTION)
+  {
+    static int completed = 0;
+    if (! completed)
+      {
+       completed = 1;
+       __deregister_frame_info (__EH_FRAME_BEGIN__);
+      }
+  }
 #endif
 }
 #endif
@@ -2861,7 +2830,7 @@ __do_global_dtors ()
 /* Run all the global constructors on entry to the program.  */
 
 void
-__do_global_ctors ()
+__do_global_ctors (void)
 {
 #ifdef EH_FRAME_SECTION
   {
@@ -2965,8 +2934,8 @@ atexit (func_ptr func)
   return (0);
 }
 
-extern void _cleanup ();
-extern void _exit () __attribute__ ((noreturn));
+extern void _cleanup (void);
+extern void _exit (int) __attribute__ ((__noreturn__));
 
 void 
 exit (int status)
@@ -3009,18 +2978,17 @@ atexit (func_ptr func)
 
 /* Shared exception handling support routines.  */
 
-extern void __default_terminate (void) __attribute__ ((__noreturn__));
-
 void
-__default_terminate ()
+__default_terminate (void)
 {
   abort ();
 }
 
-void (*__terminate_func)() = __default_terminate;
+void (*__terminate_func)(void) __attribute__ ((__noreturn__)) =
+  __default_terminate;
 
 void
-__terminate ()
+__terminate (void)
 {
   (*__terminate_func)();
 }
@@ -3038,7 +3006,7 @@ __throw_type_match (void *catch_type, void *throw_type, void *obj)
 }
 
 void
-__empty ()
+__empty (void)
 {
 }
 \f
@@ -3052,10 +3020,9 @@ __empty ()
 
 /* Allocate and return a new EH context structure. */
 
-extern void __throw ();
-
+#if __GTHREADS
 static void *
-new_eh_context ()
+new_eh_context (void)
 {
   struct eh_full_context {
     struct eh_context c;
@@ -3079,7 +3046,6 @@ new_eh_context ()
   return &ehfc->c;
 }
 
-#if __GTHREADS
 static __gthread_key_t eh_context_key;
 
 /* Destructor for struct eh_context. */
@@ -3094,19 +3060,19 @@ eh_context_free (void *ptr)
 
 /* Pointer to function to return EH context. */
 
-static struct eh_context *eh_context_initialize ();
-static struct eh_context *eh_context_static ();
+static struct eh_context *eh_context_initialize (void);
+static struct eh_context *eh_context_static (void);
 #if __GTHREADS
-static struct eh_context *eh_context_specific ();
+static struct eh_context *eh_context_specific (void);
 #endif
 
-static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
+static struct eh_context *(*get_eh_context) (void) = &eh_context_initialize;
 
 /* Routine to get EH context.
    This one will simply call the function pointer. */
 
 void *
-__get_eh_context ()
+__get_eh_context (void)
 {
   return (void *) (*get_eh_context) ();
 }
@@ -3114,15 +3080,27 @@ __get_eh_context ()
 /* Get and set the language specific info pointer. */
 
 void **
-__get_eh_info ()
+__get_eh_info (void)
 {
   struct eh_context *eh = (*get_eh_context) ();
   return &eh->info;
 }
 \f
+#ifdef DWARF2_UNWIND_INFO
+static int dwarf_reg_size_table_initialized = 0;
+static char dwarf_reg_size_table[DWARF_FRAME_REGISTERS];
+
+static void
+init_reg_size_table (void)
+{
+  __builtin_init_dwarf_reg_size_table (dwarf_reg_size_table);
+  dwarf_reg_size_table_initialized = 1;
+}
+#endif
+
 #if __GTHREADS
 static void
-eh_threads_initialize ()
+eh_threads_initialize (void)
 {
   /* Try to create the key.  If it fails, revert to static method,
      otherwise start using thread specific EH contexts. */
@@ -3138,7 +3116,7 @@ eh_threads_initialize ()
    pointer to another routine. */
 
 static struct eh_context *
-eh_context_initialize ()
+eh_context_initialize (void)
 {
 #if __GTHREADS
 
@@ -3152,12 +3130,24 @@ eh_context_initialize ()
       /* Use static version of EH context. */
       get_eh_context = &eh_context_static;
     }
+#ifdef DWARF2_UNWIND_INFO
+  {
+    static __gthread_once_t once_regsizes = __GTHREAD_ONCE_INIT;
+    if (__gthread_once (&once_regsizes, init_reg_size_table) != 0
+       || ! dwarf_reg_size_table_initialized)
+      init_reg_size_table ();
+  }
+#endif
 
 #else /* no __GTHREADS */
 
   /* Use static version of EH context. */
   get_eh_context = &eh_context_static;
 
+#ifdef DWARF2_UNWIND_INFO
+  init_reg_size_table ();
+#endif
+
 #endif /* no __GTHREADS */
 
   return (*get_eh_context) ();
@@ -3166,7 +3156,7 @@ eh_context_initialize ()
 /* Return a static EH context. */
 
 static struct eh_context *
-eh_context_static ()
+eh_context_static (void)
 {
   static struct eh_context eh;
   static int initialized;
@@ -3185,7 +3175,7 @@ eh_context_static ()
 /* Return a thread specific EH context. */
 
 static struct eh_context *
-eh_context_specific ()
+eh_context_specific (void)
 {
   struct eh_context *eh;
   eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
@@ -3198,7 +3188,76 @@ eh_context_specific ()
 
   return eh;
 }
-#endif __GTHREADS
+#endif /* __GTHREADS */
+\f
+/* Support routines for alloc/free during exception handling */
+
+/* __eh_alloc and __eh_free attempt allocation using malloc, but fall back to
+   the small arena in the eh_context. This is needed because throwing an
+   out-of-memory exception would fail otherwise. The emergency space is
+   allocated in blocks of size EH_ALLOC_ALIGN, the
+   minimum allocation being two blocks. A bitmask indicates which blocks
+   have been allocated. To indicate the size of an allocation, the bit for
+   the final block is not set. Hence each allocation is a run of 1s followed
+   by a zero. */
+void *
+__eh_alloc (size_t size)
+{
+  void *p;
+  
+  if (!size)
+    abort();
+  p = malloc (size);
+  if (p == 0)
+    {
+      struct eh_context *eh = __get_eh_context ();
+      unsigned blocks = (size + EH_ALLOC_ALIGN - 1) / EH_ALLOC_ALIGN;
+      unsigned real_mask = eh->alloc_mask | (eh->alloc_mask << 1);
+      unsigned our_mask;
+      unsigned ix;
+      
+      if (blocks > EH_ALLOC_SIZE / EH_ALLOC_ALIGN)
+        __terminate ();
+      blocks += blocks == 1;
+      our_mask = (1 << blocks) - 1;
+      
+      for (ix = EH_ALLOC_SIZE / EH_ALLOC_ALIGN - blocks; ix; ix--)
+       if (! ((real_mask >> ix) & our_mask))
+         {
+           /* found some space */
+           p = &eh->alloc_buffer[ix * EH_ALLOC_ALIGN];
+           eh->alloc_mask |= (our_mask >> 1) << ix;
+           return p;
+         }
+      __terminate ();
+    }
+  return p;
+}
+
+/* Free the memory for an cp_eh_info and associated exception, given
+   a pointer to the cp_eh_info.  */
+void
+__eh_free (void *p)
+{
+  struct eh_context *eh = __get_eh_context ();
+
+  ptrdiff_t  diff = (char *)p - &eh->alloc_buffer[0];
+  if (diff >= 0 && diff < EH_ALLOC_SIZE)
+    {
+      unsigned mask = eh->alloc_mask;
+      unsigned bit = 1 << (diff / EH_ALLOC_ALIGN);
+      
+      do
+       {
+         mask ^= bit;
+         bit <<= 1;
+       }
+      while (mask & bit);
+      eh->alloc_mask = mask;
+    }
+  else
+    free (p);
+}
 \f
 /* Support routines for setjmp/longjmp exception handling.  */
 
@@ -3214,7 +3273,7 @@ extern void longjmp (void *, int);
    use for exception handling. */
 
 void ***
-__get_dynamic_handler_chain ()
+__get_dynamic_handler_chain (void)
 {
   struct eh_context *eh = (*get_eh_context) ();
   return &eh->dynamic_handler_chain;
@@ -3228,21 +3287,16 @@ __get_dynamic_handler_chain ()
    dynamic handler chain, and use longjmp to transfer back to the associated
    handler.  */
 
-extern void __sjthrow (void) __attribute__ ((__noreturn__));
-
 void
-__sjthrow ()
+__sjthrow (void)
 {
   struct eh_context *eh = (*get_eh_context) ();
   void ***dhc = &eh->dynamic_handler_chain;
   void *jmpbuf;
   void (*func)(void *, int);
   void *arg;
-  void ***cleanup;
-
-  /* The cleanup chain is one word into the buffer.  Get the cleanup
-     chain.  */
-  cleanup = (void***)&(*dhc)[1];
+  /* The cleanup chain is one word into the buffer.  Get the cleanup chain. */
+  void ***cleanup = (void***)&(*dhc)[1];
 
   /* If there are any cleanups in the chain, run them now.  */
   if (cleanup[0])
@@ -3306,20 +3360,15 @@ __sjthrow ()
    then throw.  This is used to skip the first handler, and transfer
    control to the next handler in the dynamic handler stack.  */
 
-extern void __sjpopnthrow (void) __attribute__ ((__noreturn__));
-
 void
-__sjpopnthrow ()
+__sjpopnthrow (void)
 {
   struct eh_context *eh = (*get_eh_context) ();
   void ***dhc = &eh->dynamic_handler_chain;
   void (*func)(void *, int);
   void *arg;
-  void ***cleanup;
-
-  /* The cleanup chain is one word into the buffer.  Get the cleanup
-     chain.  */
-  cleanup = (void***)&(*dhc)[1];
+  /* The cleanup chain is one word into the buffer.  Get the cleanup chain. */
+  void ***cleanup = (void***)&(*dhc)[1];
 
   /* If there are any cleanups in the chain, run them now.  */
   if (cleanup[0])
@@ -3395,7 +3444,6 @@ EH_TABLE_LOOKUP
 
 #ifdef DWARF2_UNWIND_INFO
 
-
 /* Return the table version of an exception descriptor */
 
 short 
@@ -3569,7 +3617,12 @@ in_reg_window (int reg, frame_state *udata)
 #endif
 }
 #else
-static inline int in_reg_window (int reg, frame_state *udata) { return 0; }
+static inline int
+in_reg_window (int reg __attribute__ ((__unused__)),
+              frame_state *udata __attribute__ ((__unused__)))
+{
+  return 0;
+}
 #endif /* INCOMING_REGNO */
 
 /* Get the address of register REG as saved in UDATA, where SUB_UDATA is a
@@ -3620,7 +3673,7 @@ copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
   word_type *preg = get_reg_addr (reg, udata, NULL);
   word_type *ptreg = get_reg_addr (reg, target_udata, NULL);
 
-  memcpy (ptreg, preg, __builtin_dwarf_reg_size (reg));
+  memcpy (ptreg, preg, dwarf_reg_size_table [reg]);
 }
 
 /* Retrieve the return address for frame UDATA.  */
@@ -3665,7 +3718,7 @@ next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
 
 /* Hook to call before __terminate if only cleanup handlers remain. */
 void 
-__unwinding_cleanup ()
+__unwinding_cleanup (void)
 {
 }
 
@@ -3683,19 +3736,16 @@ __unwinding_cleanup ()
    OFFSET_P is where we return the SP adjustment offset.  */
 
 static void *
-throw_helper (eh, pc, my_udata, offset_p)
-     struct eh_context *eh;
-     void *pc;
-     frame_state *my_udata;
-     long *offset_p;
+throw_helper (struct eh_context *eh, void *pc, frame_state *my_udata,
+             long *offset_p)
 {
   frame_state ustruct2, *udata = &ustruct2;
   frame_state ustruct;
   frame_state *sub_udata = &ustruct;
   void *saved_pc = pc;
   void *handler;
-  void *handler_p;
-  void *pc_p;
+  void *handler_p = 0;
+  void *pc_p = 0;
   frame_state saved_ustruct;
   int new_eh_model;
   int cleanup = 0;
@@ -3811,7 +3861,7 @@ throw_helper (eh, pc, my_udata, offset_p)
          udata = next_stack_level (pc, udata, sub_udata);
          sub_udata = p;
 
-         for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+         for (i = 0; i < DWARF_FRAME_REGISTERS; ++i)
            if (i != udata->retaddr_column && udata->saved[i])
              {
                /* If you modify the saved value of the return address
@@ -3866,7 +3916,7 @@ throw_helper (eh, pc, my_udata, offset_p)
 /*extern void __throw(void) __attribute__ ((__noreturn__));*/
 
 void
-__throw ()
+__throw (void)
 {
   struct eh_context *eh = (*get_eh_context) ();
   void *pc, *handler;
@@ -3911,8 +3961,7 @@ label:
 /*extern void __rethrow(void *) __attribute__ ((__noreturn__));*/
 
 void
-__rethrow (index)
-     void *index;
+__rethrow (void *index)
 {
   struct eh_context *eh = (*get_eh_context) ();
   void *pc, *handler;
@@ -3960,6 +4009,173 @@ label:
 }
 #endif /* DWARF2_UNWIND_INFO */
 
+#ifdef IA64_UNWIND_INFO
+#include "frame.h"
+
+/* Return handler to which we want to transfer control, NULL if we don't
+   intend to handle this exception here.  */
+void *
+__ia64_personality_v1 (void *pc, old_exception_table *table)
+{
+  if (table)
+    {
+      int pos;
+      int best = -1;
+
+      for (pos = 0; table[pos].start_region != (void *) -1; ++pos)
+        {
+          if (table[pos].start_region <= pc && table[pos].end_region > pc)
+            {
+              /* This can apply.  Make sure it is at least as small as
+                 the previous best.  */
+              if (best == -1 || (table[pos].end_region <= table[best].end_region
+                        && table[pos].start_region >= table[best].start_region))
+                best = pos;
+            }
+          /* It is sorted by starting PC within a function.  */
+          else if (best >= 0 && table[pos].start_region > pc)
+            break;
+        }
+      if (best != -1)
+        return table[best].exception_handler;
+    }
+  return (void *) 0;
+}
+
+static void
+ia64_throw_helper (throw_pc, throw_frame, caller, throw_bsp)
+     void *throw_pc;
+     ia64_frame_state *throw_frame;
+     ia64_frame_state *caller;
+     void *throw_bsp;
+{
+  unwind_info_ptr *info;
+  void *pc, *handler = NULL;
+  void *pc_base;
+  int frame_count;
+  void *bsp;
+
+  __builtin_ia64_flushrs ();      /*  Make the local register stacks available.  */
+
+  /* Start at our stack frame, get our state.  */
+  __build_ia64_frame_state (throw_pc, throw_frame, throw_bsp, &pc_base);
+
+  /* Now we have to find the proper frame for pc, and see if there
+     is a handler for it. if not, we keep going back frames until
+     we do find one. Otherwise we call uncaught ().  */
+
+  frame_count = 0;
+  memcpy (caller, throw_frame, sizeof (*caller));
+  while (!handler)
+    {
+      void *(*personality) ();
+      void *eh_table;
+
+      frame_count++;
+      /* We only care about the RP right now, so we dont need to keep
+         any other information about a call frame right now.  */
+      pc = __get_real_reg_value (&caller->rp) - 1;
+      bsp = __calc_caller_bsp ((long)__get_real_reg_value (&caller->pfs), caller->my_bsp);
+      info = __build_ia64_frame_state (pc, caller, bsp, &pc_base);
+
+      /* If we couldn't find the next frame, we lose.  */
+      if (! info)
+       break;
+
+      personality = __get_personality (info); 
+      /* TODO Haven't figured out how to actually load the personality address
+         yet, so just always default to the one we expect for now.  */
+      if (personality != 0)
+       personality = __ia64_personality_v1;
+      eh_table = __get_except_table (info);
+      /* If there is no personality routine, we'll keep unwinding.  */
+      if (personality)
+       /* Pass a segment relative PC address to the personality routine,
+          because the unwind_info section uses segrel relocs.  */
+       handler = personality (pc - pc_base, eh_table);
+    }
+  
+  if (!handler)
+   __terminate ();
+
+  /* Handler is a segment relative address, so we must adjust it here.  */
+  handler += (long) pc_base;
+
+  /* If we found a handler, we need to unwind the stack to that point.
+     We do this by copying saved values from previous frames into the
+     save slot for the throw_frame saved slots.  when __throw returns,
+     it'll pickup the correct values.  */
+  
+  /* Start with where __throw saved things, and copy each saved register
+     of each previous frame until we get to the one before we're 
+     throwing back to.  */
+  memcpy (caller, throw_frame, sizeof (*caller));
+  for ( ; frame_count > 0; frame_count--)
+    {
+      pc = __get_real_reg_value (&caller->rp) - 1;
+      bsp = __calc_caller_bsp ((long)__get_real_reg_value (&caller->pfs), caller->my_bsp);
+      __build_ia64_frame_state (pc, caller, bsp, &pc_base);
+      /* Any regs that were saved can be put in the throw frame now.  */
+      /* We don't want to copy any saved register from the 
+         target destination, but we do want to load up it's frame.  */
+      if (frame_count > 1)
+       __copy_saved_reg_state (throw_frame, caller);
+    }
+
+  /* Set return address of the throw frame to the handler. */
+  __set_real_reg_value (&throw_frame->rp, handler);
+
+  /* TODO, do we need to do anything to make the values we wrote 'stick'? */
+  /* DO we need to go through the whole loadrs seqeunce?  */
+
+}
+
+void
+__throw ()
+{
+  struct eh_context *eh = (*get_eh_context) ();
+  ia64_frame_state my_frame;
+  ia64_frame_state originator; /* For the context handler is in.  */
+  void *bsp, *tmp_bsp;
+  long offset;
+
+  /* This is required for C++ semantics.  We must call terminate if we
+     try and rethrow an exception, when there is no exception currently
+     active.  */
+  if (! eh->info)
+    __terminate ();
+
+  __builtin_unwind_init ();
+label_ia64:
+  /* We have to call another routine to actually process the frame 
+     information, which will force all of __throw's local registers into
+     backing store.  */
+
+  /* Get the value of ar.bsp while we're here.  */
+
+  bsp = __builtin_ia64_bsp ();
+  ia64_throw_helper (&&label_ia64, &my_frame, &originator, bsp);
+
+  /* Now we have to fudge the bsp by the amount in our (__throw)
+     frame marker, since the return is going to adjust it by that much. */
+
+  tmp_bsp = __calc_caller_bsp ((long)__get_real_reg_value (&my_frame.pfs), 
+                            my_frame.my_bsp);
+  offset = (char *)my_frame.my_bsp - (char *)tmp_bsp;
+  tmp_bsp = (char *)originator.my_bsp + offset;
+
+  /* A throw handler is trated like a  non-local goto, which is architeched
+     to set the FP (or PSP) in r7 before branching.  gr[0-3] map to 
+     r4-r7, so we want gr[3].  */
+  __set_real_reg_value (&my_frame.gr[3], __get_real_reg_value (&originator.psp));
+
+  __builtin_eh_return (tmp_bsp, offset, originator.my_sp);
+
+  /* The return address was already set by throw_helper.  */
+}
+
+#endif /* IA64_UNWIND_INFO  */
+
 #endif /* L_eh */
 \f
 #ifdef L_pure
@@ -3977,10 +4193,8 @@ label:
 
 #define MESSAGE "pure virtual method called\n"
 
-extern void __terminate (void) __attribute__ ((__noreturn__));
-
 void
-__pure_virtual ()
+__pure_virtual (void)
 {
 #ifndef inhibit_libc
   write (2, MESSAGE, sizeof (MESSAGE) - 1);