/* More subroutines needed by GCC output code on some machines. */
/* Compile this one with gcc. */
/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
+
+/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
+ supposedly valid even though this is a "target" file. */
+#include "auto-host.h"
+
/* It is incorrect to include config.h here, because this file is being
compiled for the target, and hence definitions concerning only the host
do not apply. */
-
#include "tconfig.h"
#include "tsystem.h"
#include "coretypes.h"
#undef abort
#endif
+#ifdef HAVE_GAS_HIDDEN
+#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
+#else
+#define ATTRIBUTE_HIDDEN
+#endif
+
#include "libgcc2.h"
\f
#ifdef DECLARE_LIBRARY_RENAMES
DWtype
__negdi2 (DWtype u)
{
- DWunion w;
- DWunion uu;
-
- uu.ll = u;
-
- w.s.low = -uu.s.low;
- w.s.high = -uu.s.high - ((UWtype) w.s.low > 0);
+ const DWunion uu = {.ll = u};
+ const DWunion w = { {.low = -uu.s.low,
+ .high = -uu.s.high - ((UWtype) -uu.s.low > 0) } };
return w.ll;
}
#ifdef L_addvsi3
Wtype
-__addvsi3 (Wtype a, Wtype b)
+__addvSI3 (Wtype a, Wtype b)
{
- Wtype w;
+ const Wtype w = a + b;
+
+ if (b >= 0 ? w < a : w > a)
+ abort ();
- w = a + b;
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__addvsi3 (SItype a, SItype b)
+{
+ const SItype w = a + b;
if (b >= 0 ? w < a : w > a)
abort ();
return w;
}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
\f
#ifdef L_addvdi3
DWtype
-__addvdi3 (DWtype a, DWtype b)
+__addvDI3 (DWtype a, DWtype b)
{
- DWtype w;
-
- w = a + b;
+ const DWtype w = a + b;
if (b >= 0 ? w < a : w > a)
abort ();
\f
#ifdef L_subvsi3
Wtype
-__subvsi3 (Wtype a, Wtype b)
+__subvSI3 (Wtype a, Wtype b)
{
-#ifdef L_addvsi3
- return __addvsi3 (a, (-b));
-#else
- DWtype w;
+ const Wtype w = a - b;
- w = a - b;
+ if (b >= 0 ? w > a : w < a)
+ abort ();
+
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__subvsi3 (SItype a, SItype b)
+{
+ const SItype w = a - b;
if (b >= 0 ? w > a : w < a)
abort ();
return w;
-#endif
}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
\f
#ifdef L_subvdi3
DWtype
-__subvdi3 (DWtype a, DWtype b)
+__subvDI3 (DWtype a, DWtype b)
{
-#ifdef L_addvdi3
- return (a, (-b));
-#else
- DWtype w;
-
- w = a - b;
+ const DWtype w = a - b;
if (b >= 0 ? w > a : w < a)
abort ();
return w;
-#endif
}
#endif
\f
#ifdef L_mulvsi3
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
Wtype
-__mulvsi3 (Wtype a, Wtype b)
+__mulvSI3 (Wtype a, Wtype b)
{
- DWtype w;
+ const DWtype w = (DWtype) a * (DWtype) b;
+
+ if ((Wtype) (w >> WORD_SIZE) != (Wtype) w >> (WORD_SIZE - 1))
+ abort ();
- w = a * b;
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+#undef WORD_SIZE
+#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
+SItype
+__mulvsi3 (SItype a, SItype b)
+{
+ const DItype w = (DItype) a * (DItype) b;
- if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0)
+ if ((SItype) (w >> WORD_SIZE) != (SItype) w >> (WORD_SIZE-1))
abort ();
return w;
}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
\f
#ifdef L_negvsi2
Wtype
-__negvsi2 (Wtype a)
+__negvSI2 (Wtype a)
{
- Wtype w;
+ const Wtype w = -a;
- w = -a;
+ if (a >= 0 ? w > 0 : w < 0)
+ abort ();
+
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__negvsi2 (SItype a)
+{
+ const SItype w = -a;
if (a >= 0 ? w > 0 : w < 0)
abort ();
return w;
}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
\f
#ifdef L_negvdi2
DWtype
-__negvdi2 (DWtype a)
+__negvDI2 (DWtype a)
{
- DWtype w;
-
- w = -a;
+ const DWtype w = -a;
if (a >= 0 ? w > 0 : w < 0)
abort ();
\f
#ifdef L_absvsi2
Wtype
-__absvsi2 (Wtype a)
+__absvSI2 (Wtype a)
{
Wtype w = a;
if (a < 0)
#ifdef L_negvsi2
+ w = __negvSI2 (a);
+#else
+ w = -a;
+
+ if (w < 0)
+ abort ();
+#endif
+
+ return w;
+}
+#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC
+SItype
+__absvsi2 (SItype a)
+{
+ SItype w = a;
+
+ if (a < 0)
+#ifdef L_negvsi2
w = __negvsi2 (a);
#else
w = -a;
return w;
}
+#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */
#endif
\f
#ifdef L_absvdi2
DWtype
-__absvdi2 (DWtype a)
+__absvDI2 (DWtype a)
{
DWtype w = a;
if (a < 0)
-#ifdef L_negvsi2
- w = __negvsi2 (a);
+#ifdef L_negvdi2
+ w = __negvDI2 (a);
#else
w = -a;
#endif
\f
#ifdef L_mulvdi3
+#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
DWtype
-__mulvdi3 (DWtype u, DWtype v)
+__mulvDI3 (DWtype u, DWtype v)
{
- DWtype w;
+ /* The unchecked multiplication needs 3 Wtype x Wtype multiplications,
+ but the checked multiplication needs only two. */
+ const DWunion uu = {.ll = u};
+ const DWunion vv = {.ll = v};
- w = u * v;
-
- if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0)
- abort ();
+ if (__builtin_expect (uu.s.high == uu.s.low >> (WORD_SIZE - 1), 1))
+ {
+ /* u fits in a single Wtype. */
+ if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1))
+ {
+ /* v fits in a single Wtype as well. */
+ /* A single multiplication. No overflow risk. */
+ return (DWtype) uu.s.low * (DWtype) vv.s.low;
+ }
+ else
+ {
+ /* Two multiplications. */
+ DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+ DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.high};
+
+ if (vv.s.high < 0)
+ w1.s.high -= uu.s.low;
+ if (uu.s.low < 0)
+ w1.ll -= vv.ll;
+ w1.ll += (UWtype) w0.s.high;
+ if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1))
+ {
+ w0.s.high = w1.s.low;
+ return w0.ll;
+ }
+ }
+ }
+ else
+ {
+ if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1))
+ {
+ /* v fits into a single Wtype. */
+ /* Two multiplications. */
+ DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+ DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.high
+ * (UDWtype) (UWtype) vv.s.low};
+
+ if (uu.s.high < 0)
+ w1.s.high -= vv.s.low;
+ if (vv.s.low < 0)
+ w1.ll -= uu.ll;
+ w1.ll += (UWtype) w0.s.high;
+ if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1))
+ {
+ w0.s.high = w1.s.low;
+ return w0.ll;
+ }
+ }
+ else
+ {
+ /* A few sign checks and a single multiplication. */
+ if (uu.s.high >= 0)
+ {
+ if (vv.s.high >= 0)
+ {
+ if (uu.s.high == 0 && vv.s.high == 0)
+ {
+ const DWtype w = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low;
+ if (__builtin_expect (w >= 0, 1))
+ return w;
+ }
+ }
+ else
+ {
+ if (uu.s.high == 0 && vv.s.high == (Wtype) -1)
+ {
+ DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+
+ ww.s.high -= uu.s.low;
+ if (__builtin_expect (ww.s.high < 0, 1))
+ return ww.ll;
+ }
+ }
+ }
+ else
+ {
+ if (vv.s.high >= 0)
+ {
+ if (uu.s.high == (Wtype) -1 && vv.s.high == 0)
+ {
+ DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+
+ ww.s.high -= vv.s.low;
+ if (__builtin_expect (ww.s.high < 0, 1))
+ return ww.ll;
+ }
+ }
+ else
+ {
+ if (uu.s.high == (Wtype) -1 && vv.s.high == (Wtype) - 1)
+ {
+ DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low
+ * (UDWtype) (UWtype) vv.s.low};
+
+ ww.s.high -= uu.s.low;
+ ww.s.high -= vv.s.low;
+ if (__builtin_expect (ww.s.high >= 0, 1))
+ return ww.ll;
+ }
+ }
+ }
+ }
+ }
- return w;
+ /* Overflow. */
+ abort ();
}
#endif
\f
-/* Unless shift functions are defined whith full ANSI prototypes,
+/* Unless shift functions are defined with full ANSI prototypes,
parameter b will be promoted to int if word_type is smaller than an int. */
#ifdef L_lshrdi3
DWtype
__lshrdi3 (DWtype u, word_type b)
{
- DWunion w;
- word_type bm;
- DWunion uu;
-
if (b == 0)
return u;
- uu.ll = u;
+ const DWunion uu = {.ll = u};
+ const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+ DWunion w;
- bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.high = 0;
}
else
{
- UWtype carries = (UWtype) uu.s.high << bm;
+ const UWtype carries = (UWtype) uu.s.high << bm;
w.s.high = (UWtype) uu.s.high >> b;
w.s.low = ((UWtype) uu.s.low >> b) | carries;
DWtype
__ashldi3 (DWtype u, word_type b)
{
- DWunion w;
- word_type bm;
- DWunion uu;
-
if (b == 0)
return u;
- uu.ll = u;
+ const DWunion uu = {.ll = u};
+ const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+ DWunion w;
- bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.low = 0;
}
else
{
- UWtype carries = (UWtype) uu.s.low >> bm;
+ const UWtype carries = (UWtype) uu.s.low >> bm;
w.s.low = (UWtype) uu.s.low << b;
w.s.high = ((UWtype) uu.s.high << b) | carries;
DWtype
__ashrdi3 (DWtype u, word_type b)
{
- DWunion w;
- word_type bm;
- DWunion uu;
-
if (b == 0)
return u;
- uu.ll = u;
+ const DWunion uu = {.ll = u};
+ const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
+ DWunion w;
- bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
/* w.s.high = 1..1 or 0..0 */
}
else
{
- UWtype carries = (UWtype) uu.s.high << bm;
+ const UWtype carries = (UWtype) uu.s.high << bm;
w.s.high = uu.s.high >> b;
w.s.low = ((UWtype) uu.s.low >> b) | carries;
}
#endif
\f
+#ifdef L_ffssi2
+#undef int
+int
+__ffsSI2 (UWtype u)
+{
+ UWtype count;
+
+ if (u == 0)
+ return 0;
+
+ count_trailing_zeros (count, u);
+ return count + 1;
+}
+#endif
+\f
#ifdef L_ffsdi2
-DWtype
-__ffsdi2 (DWtype u)
+#undef int
+int
+__ffsDI2 (DWtype u)
{
- DWunion uu;
+ const DWunion uu = {.ll = u};
UWtype word, count, add;
- uu.ll = u;
if (uu.s.low != 0)
word = uu.s.low, add = 0;
else if (uu.s.high != 0)
DWtype
__muldi3 (DWtype u, DWtype v)
{
- DWunion w;
- DWunion uu, vv;
-
- uu.ll = u,
- vv.ll = v;
+ const DWunion uu = {.ll = u};
+ const DWunion vv = {.ll = v};
+ DWunion w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)};
- w.ll = __umulsidi3 (uu.s.low, vv.s.low);
w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
+ (UWtype) uu.s.high * (UWtype) vv.s.low);
{
if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
{
- /* dividend, divisor, and quotient are nonnegative */
+ /* Dividend, divisor, and quotient are nonnegative. */
sdiv_qrnnd (q, r, a1, a0, d);
}
else
{
- /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
+ /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d. */
sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
- /* Divide (c1*2^32 + c0) by d */
+ /* Divide (c1*2^32 + c0) by d. */
sdiv_qrnnd (q, r, c1, c0, d);
- /* Add 2^31 to quotient */
+ /* Add 2^31 to quotient. */
q += (UWtype) 1 << (W_TYPE_SIZE - 1);
}
}
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
};
#endif
+\f
+#ifdef L_clzsi2
+#undef int
+int
+__clzSI2 (UWtype x)
+{
+ Wtype ret;
+
+ count_leading_zeros (ret, x);
+
+ return ret;
+}
+#endif
+\f
+#ifdef L_clzdi2
+#undef int
+int
+__clzDI2 (UDWtype x)
+{
+ const DWunion uu = {.ll = x};
+ UWtype word;
+ Wtype ret, add;
+
+ if (uu.s.high)
+ word = uu.s.high, add = 0;
+ else
+ word = uu.s.low, add = W_TYPE_SIZE;
+
+ count_leading_zeros (ret, word);
+ return ret + add;
+}
+#endif
+\f
+#ifdef L_ctzsi2
+#undef int
+int
+__ctzSI2 (UWtype x)
+{
+ Wtype ret;
+
+ count_trailing_zeros (ret, x);
+
+ return ret;
+}
+#endif
+\f
+#ifdef L_ctzdi2
+#undef int
+int
+__ctzDI2 (UDWtype x)
+{
+ const DWunion uu = {.ll = x};
+ UWtype word;
+ Wtype ret, add;
+
+ if (uu.s.low)
+ word = uu.s.low, add = 0;
+ else
+ word = uu.s.high, add = W_TYPE_SIZE;
+
+ count_trailing_zeros (ret, word);
+ return ret + add;
+}
+#endif
+
+#if (defined (L_popcountsi2) || defined (L_popcountdi2) \
+ || defined (L_popcount_tab))
+extern const UQItype __popcount_tab[] ATTRIBUTE_HIDDEN;
+#endif
+
+#ifdef L_popcount_tab
+const UQItype __popcount_tab[] =
+{
+ 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+ 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8,
+};
+#endif
+\f
+#ifdef L_popcountsi2
+#undef int
+int
+__popcountSI2 (UWtype x)
+{
+ UWtype i, ret = 0;
+
+ for (i = 0; i < W_TYPE_SIZE; i += 8)
+ ret += __popcount_tab[(x >> i) & 0xff];
+
+ return ret;
+}
+#endif
+\f
+#ifdef L_popcountdi2
+#undef int
+int
+__popcountDI2 (UDWtype x)
+{
+ UWtype i, ret = 0;
+
+ for (i = 0; i < 2*W_TYPE_SIZE; i += 8)
+ ret += __popcount_tab[(x >> i) & 0xff];
+
+ return ret;
+}
+#endif
+\f
+#ifdef L_paritysi2
+#undef int
+int
+__paritySI2 (UWtype x)
+{
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+ x ^= x >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+ x ^= x >> 16;
+#endif
+ x ^= x >> 8;
+ x ^= x >> 4;
+ x &= 0xf;
+ return (0x6996 >> x) & 1;
+}
+#endif
+\f
+#ifdef L_paritydi2
+#undef int
+int
+__parityDI2 (UDWtype x)
+{
+ const DWunion uu = {.ll = x};
+ UWtype nx = uu.s.low ^ uu.s.high;
+
+#if W_TYPE_SIZE > 64
+# error "fill out the table"
+#endif
+#if W_TYPE_SIZE > 32
+ nx ^= nx >> 32;
+#endif
+#if W_TYPE_SIZE > 16
+ nx ^= nx >> 16;
+#endif
+ nx ^= nx >> 8;
+ nx ^= nx >> 4;
+ nx &= 0xf;
+ return (0x6996 >> nx) & 1;
+}
+#endif
#ifdef L_udivmoddi4
UDWtype
__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
{
- DWunion ww;
- DWunion nn, dd;
+ const DWunion nn = {.ll = n};
+ const DWunion dd = {.ll = d};
DWunion rr;
UWtype d0, d1, n0, n1, n2;
UWtype q0, q1;
UWtype b, bm;
- nn.ll = n;
- dd.ll = d;
-
d0 = dd.s.low;
d1 = dd.s.high;
n0 = nn.s.low;
}
}
- ww.s.low = q0;
- ww.s.high = q1;
+ const DWunion ww = {{.low = q0, .high = q1}};
return ww.ll;
}
#endif
__divdi3 (DWtype u, DWtype v)
{
word_type c = 0;
- DWunion uu, vv;
+ DWunion uu = {.ll = u};
+ DWunion vv = {.ll = v};
DWtype w;
- uu.ll = u;
- vv.ll = v;
-
if (uu.s.high < 0)
c = ~c,
uu.ll = -uu.ll;
__moddi3 (DWtype u, DWtype v)
{
word_type c = 0;
- DWunion uu, vv;
+ DWunion uu = {.ll = u};
+ DWunion vv = {.ll = v};
DWtype w;
- uu.ll = u;
- vv.ll = v;
-
if (uu.s.high < 0)
c = ~c,
uu.ll = -uu.ll;
if (vv.s.high < 0)
vv.ll = -vv.ll;
- (void) __udivmoddi4 (uu.ll, vv.ll, &w);
+ (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
if (c)
w = -w;
word_type
__cmpdi2 (DWtype a, DWtype b)
{
- DWunion au, bu;
-
- au.ll = a, bu.ll = b;
+ const DWunion au = {.ll = a};
+ const DWunion bu = {.ll = b};
if (au.s.high < bu.s.high)
return 0;
word_type
__ucmpdi2 (DWtype a, DWtype b)
{
- DWunion au, bu;
-
- au.ll = a, bu.ll = b;
+ const DWunion au = {.ll = a};
+ const DWunion bu = {.ll = b};
if ((UWtype) au.s.high < (UWtype) bu.s.high)
return 0;
DWtype
__fixunstfDI (TFtype a)
{
- TFtype b;
- UDWtype v;
-
if (a < 0)
return 0;
/* Compute high word of result, as a flonum. */
- b = (a / HIGH_WORD_COEFF);
+ const TFtype b = (a / HIGH_WORD_COEFF);
/* Convert that to fixed (but not to DWtype!),
and shift it into the high word. */
- v = (UWtype) b;
+ UDWtype v = (UWtype) b;
v <<= WORD_SIZE;
/* Remove high part from the TFtype, leaving the low part as flonum. */
a -= (TFtype)v;
}
#endif
-#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
DWtype
__fixunsxfDI (XFtype a)
{
- XFtype b;
- UDWtype v;
-
if (a < 0)
return 0;
/* Compute high word of result, as a flonum. */
- b = (a / HIGH_WORD_COEFF);
+ const XFtype b = (a / HIGH_WORD_COEFF);
/* Convert that to fixed (but not to DWtype!),
and shift it into the high word. */
- v = (UWtype) b;
+ UDWtype v = (UWtype) b;
v <<= WORD_SIZE;
/* Remove high part from the XFtype, leaving the low part as flonum. */
a -= (XFtype)v;
}
#endif
-#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
DWtype
__fixxfdi (XFtype a)
{
DWtype
__fixunsdfDI (DFtype a)
{
- UWtype hi, lo;
-
/* Get high part of result. The division here will just moves the radix
point and will not cause any rounding. Then the conversion to integral
type chops result as desired. */
- hi = a / HIGH_WORD_COEFF;
+ const UWtype hi = a / HIGH_WORD_COEFF;
/* Get low part of result. Convert `hi' to floating type and scale it back,
then subtract this from the number being converted. This leaves the low
part. Convert that to integral type. */
- lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
+ const UWtype lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
/* Assemble result from the two parts. */
return ((UDWtype) hi << WORD_SIZE) | lo;
/* 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;
- UWtype hi, lo;
+ const DFtype a = original_a;
/* Get high part of result. The division here will just moves the radix
point and will not cause any rounding. Then the conversion to integral
type chops result as desired. */
- hi = a / HIGH_WORD_COEFF;
+ const UWtype hi = a / HIGH_WORD_COEFF;
/* Get low part of result. Convert `hi' to floating type and scale it back,
then subtract this from the number being converted. This leaves the low
part. Convert that to integral type. */
- lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
+ const UWtype lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
/* Assemble result from the two parts. */
return ((UDWtype) hi << WORD_SIZE) | lo;
}
#endif
-#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
XFtype
__floatdixf (DWtype u)
{
- XFtype d;
-
- d = (Wtype) (u >> WORD_SIZE);
+ XFtype d = (Wtype) (u >> WORD_SIZE);
d *= HIGH_HALFWORD_COEFF;
d *= HIGH_HALFWORD_COEFF;
d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
TFtype
__floatditf (DWtype u)
{
- TFtype d;
-
- d = (Wtype) (u >> WORD_SIZE);
+ TFtype d = (Wtype) (u >> WORD_SIZE);
d *= HIGH_HALFWORD_COEFF;
d *= HIGH_HALFWORD_COEFF;
d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
DFtype
__floatdidf (DWtype u)
{
- DFtype d;
-
- d = (Wtype) (u >> WORD_SIZE);
+ DFtype d = (Wtype) (u >> WORD_SIZE);
d *= HIGH_HALFWORD_COEFF;
d *= HIGH_HALFWORD_COEFF;
d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
SFtype
__floatdisf (DWtype u)
{
- /* Do the calculation in DFmode
- so that we don't lose any of the precision of the high word
- while multiplying it. */
- DFtype f;
-
/* Protect against double-rounding error.
Represent any low-order bits, that might be truncated in DFmode,
by a bit that won't be lost. The bit can go in anywhere below the
}
}
}
- f = (Wtype) (u >> WORD_SIZE);
+ /* Do the calculation in DFmode
+ so that we don't lose any of the precision of the high word
+ while multiplying it. */
+ DFtype f = (Wtype) (u >> WORD_SIZE);
f *= HIGH_HALFWORD_COEFF;
f *= HIGH_HALFWORD_COEFF;
f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
}
#endif
-#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
+#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80
/* Reenable the normal types, in case limits.h needs them. */
#undef char
#undef short
}
#endif
\f
+/* Integer power helper used from __builtin_powi for non-constant
+ exponents. */
+
+#if defined(L_powisf2) || defined(L_powidf2) \
+ || (defined(L_powixf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) \
+ || (defined(L_powitf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
+# if defined(L_powisf2)
+# define TYPE SFtype
+# define NAME __powisf2
+# elif defined(L_powidf2)
+# define TYPE DFtype
+# define NAME __powidf2
+# elif defined(L_powixf2)
+# define TYPE XFtype
+# define NAME __powixf2
+# elif defined(L_powitf2)
+# define TYPE TFtype
+# define NAME __powitf2
+# endif
+
+TYPE
+NAME (TYPE x, Wtype m)
+{
+ UWtype n = m < 0 ? -m : m;
+ TYPE y = n % 2 ? x : 1;
+ while (n >>= 1)
+ {
+ x = x * x;
+ if (n % 2)
+ y = y * x;
+ }
+ return m < 0 ? 1/y : y;
+}
+
+#endif
+\f
/* From here on down, the routines use normal data types. */
#define SItype bogus_type
{
while (size > 0)
{
- unsigned char c1 = *s1++, c2 = *s2++;
+ const unsigned char c1 = *s1++, c2 = *s2++;
if (c1 != c2)
return c1 - c2;
size--;
#endif
#endif
-#ifdef L_gcov
-
-/* Gcov profile dumper. Requires atexit and stdio. */
-
-#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
-#include <stdio.h>
-
-#include "gcov-io.h"
-#include <string.h>
-#if defined (TARGET_HAS_F_SETLKW)
-#include <fcntl.h>
-#include <errno.h>
-#endif
-
-/* Chain of per-object gcov structures. */
-static struct gcov_info *gcov_list;
-
-/* A program checksum allows us to distinguish program data for an
- object file included in multiple programs. */
-static unsigned gcov_crc32;
-
-static void
-gcov_version_mismatch (struct gcov_info *ptr, unsigned version)
-{
- unsigned expected = GCOV_VERSION;
- unsigned ix;
- char e[4], v[4];
-
- for (ix = 4; ix--; expected >>= 8, version >>= 8)
- {
- e[ix] = expected;
- v[ix] = version;
- }
-
- fprintf (stderr,
- "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
- ptr->filename, e, v);
-}
-
-/* Dump the coverage counts. We merge with existing counts when
- possible, to avoid growing the .da files ad infinitum. We use this
- program's checksum to make sure we only accumulate whole program
- statistics to the correct summary. An object file might be embedded
- in two separate programs, and we must keep the two program
- summaries separate. */
-
-static void
-gcov_exit (void)
-{
- struct gcov_info *ptr;
- unsigned ix, jx;
- struct gcov_summary program;
- gcov_type program_max_one = 0;
- gcov_type program_max_sum = 0;
- gcov_type program_sum = 0;
- unsigned program_arcs = 0;
-
-#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 = 0; /* Until EOF. */
- s_flock.l_pid = getpid ();
-#endif
-
- memset (&program, 0, sizeof (program));
- program.checksum = gcov_crc32;
-
- for (ptr = gcov_list; ptr; ptr = ptr->next)
- {
- FILE *da_file;
- struct gcov_summary object;
- struct gcov_summary local_prg;
- int merging = 0;
- long base;
- const struct function_info *fn_info;
- gcov_type *count_ptr;
- gcov_type object_max_one = 0;
-
- ptr->wkspc = 0;
- if (!ptr->filename)
- continue;
-
- for (ix = ptr->n_arc_counts, count_ptr = ptr->arc_counts; ix--;)
- {
- gcov_type count = *count_ptr++;
-
- if (count > object_max_one)
- object_max_one = count;
- }
- if (object_max_one > program_max_one)
- program_max_one = object_max_one;
-
- memset (&local_prg, 0, sizeof (local_prg));
- memset (&object, 0, sizeof (object));
-
- /* Open for modification */
- if ((da_file = fopen (ptr->filename, "r+b")))
- merging = 1;
- else if ((da_file = fopen (ptr->filename, "w+b")))
- ;
- else
- {
- fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
- ptr->filename = 0;
- continue;
- }
-
-#if defined (TARGET_HAS_F_SETLKW)
- /* 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. */
- while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
- && errno == EINTR)
- continue;
-#endif
- if (merging)
- {
- /* Merge data from file. */
- unsigned tag, length;
-
- if (gcov_read_unsigned (da_file, &tag) || tag != GCOV_DATA_MAGIC)
- {
- fprintf (stderr, "profiling:%s:Not a gcov data file\n",
- ptr->filename);
- read_fatal:;
- fclose (da_file);
- ptr->filename = 0;
- continue;
- }
- if (gcov_read_unsigned (da_file, &length) || length != GCOV_VERSION)
- {
- gcov_version_mismatch (ptr, length);
- goto read_fatal;
- }
-
- /* Merge execution counts for each function. */
- count_ptr = ptr->arc_counts;
- for (ix = ptr->n_functions, fn_info = ptr->functions;
- ix--; fn_info++)
- {
- if (gcov_read_unsigned (da_file, &tag)
- || gcov_read_unsigned (da_file, &length))
- {
- read_error:;
- fprintf (stderr, "profiling:%s:Error merging\n",
- ptr->filename);
- goto read_fatal;
- }
-
- /* Check function */
- if (tag != GCOV_TAG_FUNCTION)
- {
- read_mismatch:;
- fprintf (stderr, "profiling:%s:Merge mismatch at %s\n",
- ptr->filename, fn_info->name);
- goto read_fatal;
- }
- {
- unsigned flength, checksum;
-
- if (gcov_read_unsigned (da_file, &flength)
- || gcov_skip_string (da_file, flength)
- || gcov_read_unsigned (da_file, &checksum))
- goto read_error;
- if (flength != strlen (fn_info->name)
- || checksum != fn_info->checksum)
- goto read_mismatch;
- }
- /* Check arc counts */
- if (gcov_read_unsigned (da_file, &tag)
- || gcov_read_unsigned (da_file, &length))
- goto read_error;
- if (tag != GCOV_TAG_ARC_COUNTS
- || length / 8 != fn_info->n_arc_counts)
- goto read_mismatch;
- {
- gcov_type count;
-
- for (jx = fn_info->n_arc_counts; jx--; count_ptr++)
- if (gcov_read_counter (da_file, &count))
- goto read_error;
- else
- *count_ptr += count;
- }
- }
-
- /* Check object summary */
- if (gcov_read_unsigned (da_file, &tag)
- || gcov_read_unsigned (da_file, &length))
- goto read_error;
- if (tag != GCOV_TAG_OBJECT_SUMMARY)
- goto read_mismatch;
- if (gcov_read_summary (da_file, &object))
- goto read_error;
-
- /* Check program summary */
- while (1)
- {
- long base = ftell (da_file);
-
- if (gcov_read_unsigned (da_file, &tag)
- || gcov_read_unsigned (da_file, &length))
- {
- if (feof (da_file))
- break;
- goto read_error;
- }
- if (tag != GCOV_TAG_PROGRAM_SUMMARY
- && tag != GCOV_TAG_PLACEHOLDER_SUMMARY
- && tag != GCOV_TAG_INCORRECT_SUMMARY)
- goto read_mismatch;
- if (gcov_read_summary (da_file, &local_prg))
- goto read_error;
- if (local_prg.checksum != program.checksum)
- continue;
- if (tag == GCOV_TAG_PLACEHOLDER_SUMMARY)
- {
- fprintf (stderr,
- "profiling:%s:Concurrent race detected\n",
- ptr->filename);
- goto read_fatal;
- }
- merging = -1;
- if (tag != GCOV_TAG_PROGRAM_SUMMARY)
- break;
-
- if (program.runs
- && memcmp (&program, &local_prg, sizeof (program)))
- {
- fprintf (stderr, "profiling:%s:Invocation mismatch\n",
- ptr->filename);
- local_prg.runs = 0;
- }
- else
- memcpy (&program, &local_prg, sizeof (program));
- ptr->wkspc = base;
- break;
- }
- fseek (da_file, 0, SEEK_SET);
- }
-
- object.runs++;
- object.arcs = ptr->n_arc_counts;
- object.arc_sum = 0;
- if (object.arc_max_one < object_max_one)
- object.arc_max_one = object_max_one;
- object.arc_sum_max += object_max_one;
-
- /* Write out the data. */
- if (/* magic */
- gcov_write_unsigned (da_file, GCOV_DATA_MAGIC)
- /* version number */
- || gcov_write_unsigned (da_file, GCOV_VERSION))
- {
- write_error:;
- fclose (da_file);
- fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
- ptr->filename = 0;
- continue;
- }
-
- /* Write execution counts for each function. */
- count_ptr = ptr->arc_counts;
- for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
- {
- /* Announce function. */
- if (gcov_write_unsigned (da_file, GCOV_TAG_FUNCTION)
- || !(base = gcov_reserve_length (da_file))
- /* function name */
- || gcov_write_string (da_file, fn_info->name,
- strlen (fn_info->name))
- /* function checksum */
- || gcov_write_unsigned (da_file, fn_info->checksum)
- || gcov_write_length (da_file, base))
- goto write_error;
-
- /* arc counts. */
- if (gcov_write_unsigned (da_file, GCOV_TAG_ARC_COUNTS)
- || !(base = gcov_reserve_length (da_file)))
- goto write_error;
-
- for (jx = fn_info->n_arc_counts; jx--;)
- {
- gcov_type count = *count_ptr++;
-
- object.arc_sum += count;
- if (object.arc_max_sum < count)
- object.arc_max_sum = count;
- if (gcov_write_counter (da_file, count))
- goto write_error; /* RIP Edsger Dijkstra */
- }
- if (gcov_write_length (da_file, base))
- goto write_error;
- }
-
- /* Object file summary. */
- if (gcov_write_summary (da_file, GCOV_TAG_OBJECT_SUMMARY, &object))
- goto write_error;
-
- if (merging >= 0)
- {
- if (fseek (da_file, 0, SEEK_END))
- goto write_error;
- ptr->wkspc = ftell (da_file);
- if (gcov_write_summary (da_file, GCOV_TAG_PLACEHOLDER_SUMMARY,
- &program))
- goto write_error;
- }
- else if (ptr->wkspc)
- {
- /* Zap trailing program summary */
- if (fseek (da_file, ptr->wkspc, SEEK_SET))
- goto write_error;
- if (!local_prg.runs)
- ptr->wkspc = 0;
- if (gcov_write_unsigned (da_file,
- local_prg.runs ? GCOV_TAG_PLACEHOLDER_SUMMARY
- : GCOV_TAG_INCORRECT_SUMMARY))
- goto write_error;
- }
- if (fflush (da_file))
- goto write_error;
-
- if (fclose (da_file))
- {
- fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
- ptr->filename = 0;
- }
- else
- {
- program_arcs += ptr->n_arc_counts;
- program_sum += object.arc_sum;
- if (program_max_sum < object.arc_max_sum)
- program_max_sum = object.arc_max_sum;
- }
- }
-
- /* Generate whole program statistics. */
- program.runs++;
- program.arcs = program_arcs;
- program.arc_sum = program_sum;
- if (program.arc_max_one < program_max_one)
- program.arc_max_one = program_max_one;
- if (program.arc_max_sum < program_max_sum)
- program.arc_max_sum = program_max_sum;
- program.arc_sum_max += program_max_one;
-
- /* Upate whole program statistics. */
- for (ptr = gcov_list; ptr; ptr = ptr->next)
- if (ptr->filename && ptr->wkspc)
- {
- FILE *da_file;
-
- da_file = fopen (ptr->filename, "r+b");
- if (!da_file)
- {
- fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
- continue;
- }
-
-#if defined (TARGET_HAS_F_SETLKW)
- while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
- && errno == EINTR)
- continue;
-#endif
- if (fseek (da_file, ptr->wkspc, SEEK_SET)
- || gcov_write_summary (da_file, GCOV_TAG_PROGRAM_SUMMARY, &program)
- || fflush (da_file))
- fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
- if (fclose (da_file))
- fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
- }
-}
-
-/* Add a new object file onto the bb chain. Invoked automatically
- when running an object file's global ctors. */
-
-void
-__gcov_init (struct gcov_info *info)
-{
- if (!info->version)
- return;
- if (info->version != GCOV_VERSION)
- gcov_version_mismatch (info, info->version);
- else
- {
- const char *ptr = info->filename;
- unsigned crc32 = gcov_crc32;
-
- do
- {
- unsigned ix;
- unsigned value = *ptr << 24;
-
- for (ix = 8; ix--; value <<= 1)
- {
- unsigned feedback;
-
- feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
- crc32 <<= 1;
- crc32 ^= feedback;
- }
- }
- while (*ptr++);
-
- gcov_crc32 = crc32;
-
- if (!gcov_list)
- atexit (gcov_exit);
-
- info->next = gcov_list;
- gcov_list = info;
- }
- info->version = 0;
-}
-
-/* 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
-__gcov_flush (void)
-{
- struct gcov_info *ptr;
-
- gcov_exit ();
- for (ptr = gcov_list; ptr; ptr = ptr->next)
- {
- unsigned i;
-
- for (i = ptr->n_arc_counts; i--;)
- ptr->arc_counts[i] = 0;
- }
-}
-
-#endif /* L_gcov */
\f
#ifdef L_clear_cache
/* Clear part of an instruction cache. */
-#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
-
void
__clear_cache (char *beg __attribute__((__unused__)),
char *end __attribute__((__unused__)))
{
#ifdef CLEAR_INSN_CACHE
CLEAR_INSN_CACHE (beg, end);
-#else
-#ifdef INSN_CACHE_SIZE
- static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
- static int initialized;
- int offset;
- void *start_addr
- void *end_addr;
- typedef (*function_ptr) (void);
-
-#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
- /* It's cheaper to clear the whole cache.
- Put in a series of jump instructions so that calling the beginning
- of the cache will clear the whole thing. */
-
- if (! initialized)
- {
- int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH);
- int end_ptr = ptr + INSN_CACHE_SIZE;
-
- while (ptr < end_ptr)
- {
- *(INSTRUCTION_TYPE *)ptr
- = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
- ptr += INSN_CACHE_LINE_WIDTH;
- }
- *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
-
- initialized = 1;
- }
-
- /* Call the beginning of the sequence. */
- (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH))
- ());
-
-#else /* Cache is large. */
-
- if (! initialized)
- {
- int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH);
-
- while (ptr < (int) array + sizeof array)
- {
- *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
- ptr += INSN_CACHE_LINE_WIDTH;
- }
-
- initialized = 1;
- }
-
- /* Find the location in array that occupies the same cache line as BEG. */
-
- offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
- start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
- & -INSN_CACHE_PLANE_SIZE)
- + offset);
-
- /* Compute the cache alignment of the place to stop clearing. */
-#if 0 /* This is not needed for gcc's purposes. */
- /* If the block to clear is bigger than a cache plane,
- we clear the entire cache, and OFFSET is already correct. */
- if (end < beg + INSN_CACHE_PLANE_SIZE)
-#endif
- offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH)
- & (INSN_CACHE_PLANE_SIZE - 1));
-
-#if INSN_CACHE_DEPTH > 1
- end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
- if (end_addr <= start_addr)
- end_addr += INSN_CACHE_PLANE_SIZE;
-
- for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
- {
- int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
- int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
-
- while (addr != stop)
- {
- /* Call the return instruction at ADDR. */
- ((function_ptr) addr) ();
-
- addr += INSN_CACHE_LINE_WIDTH;
- }
- }
-#else /* just one plane */
- do
- {
- /* Call the return instruction at START_ADDR. */
- ((function_ptr) start_addr) ();
-
- start_addr += INSN_CACHE_LINE_WIDTH;
- }
- while ((start_addr % INSN_CACHE_SIZE) != offset);
-#endif /* just one plane */
-#endif /* Cache is large */
-#endif /* Cache exists */
#endif /* CLEAR_INSN_CACHE */
}
#endif /* L_clear_cache */
\f
+#ifdef L_enable_execute_stack
+/* Attempt to turn on execute permission for the stack. */
+
+#ifdef ENABLE_EXECUTE_STACK
+ ENABLE_EXECUTE_STACK
+#else
+void
+__enable_execute_stack (void *addr __attribute__((__unused__)))
+{}
+#endif /* ENABLE_EXECUTE_STACK */
+
+#endif /* L_enable_execute_stack */
+\f
#ifdef L_trampoline
/* Jump to a trampoline, loading the static chain address. */
#if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
-long
+int
getpagesize (void)
{
#ifdef _ALPHA_
#ifdef TRANSFER_FROM_TRAMPOLINE
TRANSFER_FROM_TRAMPOLINE
#endif
-
-#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__ */
#endif /* L_trampoline */
\f
#ifndef __CYGWIN__
For systems which support a .init section we use the .init section
to run __do_global_ctors, so we need not do anything here. */
+extern void SYMBOL__MAIN (void);
void
-SYMBOL__MAIN ()
+SYMBOL__MAIN (void)
{
/* Support recursive calls to `main': run initializers just once. */
static int initialized;
#endif
#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
#endif /* L_ctors */
-\f
-#ifdef L_exit
-
-#include "gbl-ctors.h"
-
-#ifdef NEED_ATEXIT
-
-#ifndef ON_EXIT
-
-# include <errno.h>
-
-static func_ptr *atexit_chain = 0;
-static long atexit_chain_length = 0;
-static volatile long last_atexit_chain_slot = -1;
-
-int
-atexit (func_ptr func)
-{
- if (++last_atexit_chain_slot == atexit_chain_length)
- {
- atexit_chain_length += 32;
- if (atexit_chain)
- atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
- * sizeof (func_ptr));
- else
- atexit_chain = (func_ptr *) malloc (atexit_chain_length
- * sizeof (func_ptr));
- if (! atexit_chain)
- {
- atexit_chain_length = 0;
- last_atexit_chain_slot = -1;
- errno = ENOMEM;
- return (-1);
- }
- }
- atexit_chain[last_atexit_chain_slot] = func;
- return (0);
-}
-
-extern void _cleanup (void);
-extern void _exit (int) __attribute__ ((__noreturn__));
-
-void
-exit (int status)
-{
- if (atexit_chain)
- {
- for ( ; last_atexit_chain_slot-- >= 0; )
- {
- (*atexit_chain[last_atexit_chain_slot + 1]) ();
- atexit_chain[last_atexit_chain_slot + 1] = 0;
- }
- free (atexit_chain);
- atexit_chain = 0;
- }
-#ifdef EXIT_BODY
- EXIT_BODY;
-#else
- _cleanup ();
-#endif
- _exit (status);
-}
-
-#else /* ON_EXIT */
-
-/* Simple; we just need a wrapper for ON_EXIT. */
-int
-atexit (func_ptr func)
-{
- return ON_EXIT (func);
-}
-
-#endif /* ON_EXIT */
-#endif /* NEED_ATEXIT */
-#endif /* L_exit */