X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Flibgcc2.c;h=1b1455d5d8d785870a71c8ccd621dc9ff8d8cbef;hb=54daa60094d5125e41489c6f6fe28a6ec3302473;hp=a06b7951ab9268494be05c34c75d4f58d46dc9db;hpb=536f5fb115792c70f4e8e459454a9aaeb83cb8f4;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index a06b7951ab9..1b1455d5d8d 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -1,7 +1,7 @@ /* More subroutines needed by GCC output code on some machines. */ /* Compile this one with gcc. */ /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -29,36 +29,43 @@ along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is + supposedly valid even though this is a "target" file. */ +#include "auto-host.h" + /* It is incorrect to include config.h here, because this file is being compiled for the target, and hence definitions concerning only the host do not apply. */ - #include "tconfig.h" #include "tsystem.h" - -#include "machmode.h" +#include "coretypes.h" +#include "tm.h" /* Don't use `fancy_abort' here even if config.h says to use it. */ #ifdef abort #undef abort #endif +#ifdef HAVE_GAS_HIDDEN +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) +#else +#define ATTRIBUTE_HIDDEN +#endif + #include "libgcc2.h" -#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3) -#if defined (L_divdi3) || defined (L_moddi3) -static inline +#ifdef DECLARE_LIBRARY_RENAMES + DECLARE_LIBRARY_RENAMES #endif + +#if defined (L_negdi2) DWtype __negdi2 (DWtype u) { - DWunion w; - DWunion uu; - - uu.ll = u; - - w.s.low = -uu.s.low; - w.s.high = -uu.s.high - ((UWtype) w.s.low > 0); + const DWunion uu = {.ll = u}; + const DWunion w = { {.low = -uu.s.low, + .high = -uu.s.high - ((UWtype) -uu.s.low > 0) } }; return w.ll; } @@ -66,26 +73,34 @@ __negdi2 (DWtype u) #ifdef L_addvsi3 Wtype -__addvsi3 (Wtype a, Wtype b) +__addvSI3 (Wtype a, Wtype b) { - Wtype w; + const Wtype w = a + b; + + if (b >= 0 ? w < a : w > a) + abort (); - w = a + b; + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__addvsi3 (SItype a, SItype b) +{ + const SItype w = a + b; if (b >= 0 ? w < a : w > a) abort (); return w; } +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #endif #ifdef L_addvdi3 DWtype -__addvdi3 (DWtype a, DWtype b) +__addvDI3 (DWtype a, DWtype b) { - DWtype w; - - w = a + b; + const DWtype w = a + b; if (b >= 0 ? w < a : w > a) abort (); @@ -96,159 +111,306 @@ __addvdi3 (DWtype a, DWtype b) #ifdef L_subvsi3 Wtype -__subvsi3 (Wtype a, Wtype b) +__subvSI3 (Wtype a, Wtype b) { -#ifdef L_addvsi3 - return __addvsi3 (a, (-b)); -#else - DWtype w; + const Wtype w = a - b; + + if (b >= 0 ? w > a : w < a) + abort (); - w = a - b; + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__subvsi3 (SItype a, SItype b) +{ + const SItype w = a - b; if (b >= 0 ? w > a : w < a) abort (); return w; -#endif } +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #endif #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 #ifdef L_mulvsi3 +#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) Wtype -__mulvsi3 (Wtype a, Wtype b) +__mulvSI3 (Wtype a, Wtype b) { - DWtype w; + const DWtype w = (DWtype) a * (DWtype) b; - w = a * b; + if ((Wtype) (w >> WORD_SIZE) != (Wtype) w >> (WORD_SIZE - 1)) + abort (); + + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +#undef WORD_SIZE +#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) +SItype +__mulvsi3 (SItype a, SItype b) +{ + const DItype w = (DItype) a * (DItype) b; - if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0) + if ((SItype) (w >> WORD_SIZE) != (SItype) w >> (WORD_SIZE-1)) abort (); return w; } +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #endif #ifdef L_negvsi2 Wtype -__negvsi2 (Wtype a) +__negvSI2 (Wtype a) { - Wtype w; + const Wtype w = -a; + + if (a >= 0 ? w > 0 : w < 0) + abort (); - w = -a; + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__negvsi2 (SItype a) +{ + const SItype w = -a; if (a >= 0 ? w > 0 : w < 0) abort (); return w; } +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #endif #ifdef L_negvdi2 DWtype -__negvdi2 (DWtype a) +__negvDI2 (DWtype a) { - DWtype w; - - w = -a; + const DWtype w = -a; if (a >= 0 ? w > 0 : w < 0) abort (); - return w; + return w; } #endif #ifdef L_absvsi2 Wtype -__absvsi2 (Wtype a) +__absvSI2 (Wtype a) +{ + Wtype w = a; + + if (a < 0) +#ifdef L_negvsi2 + w = __negvSI2 (a); +#else + w = -a; + + if (w < 0) + abort (); +#endif + + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__absvsi2 (SItype a) { - Wtype w = a; + SItype w = a; - if (a < 0) + if (a < 0) #ifdef L_negvsi2 - w = __negvsi2 (a); + w = __negvsi2 (a); #else - w = -a; + w = -a; - if (w < 0) - abort (); + if (w < 0) + abort (); #endif return w; } +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ #endif #ifdef L_absvdi2 DWtype -__absvdi2 (DWtype a) +__absvDI2 (DWtype a) { - DWtype w = a; + DWtype w = a; - if (a < 0) -#ifdef L_negvsi2 - w = __negvsi2 (a); + if (a < 0) +#ifdef L_negvdi2 + w = __negvDI2 (a); #else - w = -a; + w = -a; - if (w < 0) - abort (); + if (w < 0) + abort (); #endif - return w; + return w; } #endif #ifdef L_mulvdi3 +#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) DWtype -__mulvdi3 (DWtype u, DWtype v) +__mulvDI3 (DWtype u, DWtype v) { - DWtype w; + /* The unchecked multiplication needs 3 Wtype x Wtype multiplications, + but the checked multiplication needs only two. */ + const DWunion uu = {.ll = u}; + const DWunion vv = {.ll = v}; - w = u * v; + if (__builtin_expect (uu.s.high == uu.s.low >> (WORD_SIZE - 1), 1)) + { + /* u fits in a single Wtype. */ + if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1)) + { + /* v fits in a single Wtype as well. */ + /* A single multiplication. No overflow risk. */ + return (DWtype) uu.s.low * (DWtype) vv.s.low; + } + else + { + /* Two multiplications. */ + DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low}; + DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.high}; + + if (vv.s.high < 0) + w1.s.high -= uu.s.low; + if (uu.s.low < 0) + w1.ll -= vv.ll; + w1.ll += (UWtype) w0.s.high; + if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1)) + { + w0.s.high = w1.s.low; + return w0.ll; + } + } + } + else + { + if (__builtin_expect (vv.s.high == vv.s.low >> (WORD_SIZE - 1), 1)) + { + /* v fits into a single Wtype. */ + /* Two multiplications. */ + DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low}; + DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.high + * (UDWtype) (UWtype) vv.s.low}; + + if (uu.s.high < 0) + w1.s.high -= vv.s.low; + if (vv.s.low < 0) + w1.ll -= uu.ll; + w1.ll += (UWtype) w0.s.high; + if (__builtin_expect (w1.s.high == w1.s.low >> (WORD_SIZE - 1), 1)) + { + w0.s.high = w1.s.low; + return w0.ll; + } + } + else + { + /* A few sign checks and a single multiplication. */ + if (uu.s.high >= 0) + { + if (vv.s.high >= 0) + { + if (uu.s.high == 0 && vv.s.high == 0) + { + const DWtype w = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low; + if (__builtin_expect (w >= 0, 1)) + return w; + } + } + else + { + if (uu.s.high == 0 && vv.s.high == (Wtype) -1) + { + DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low}; - if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0) - abort (); + ww.s.high -= uu.s.low; + if (__builtin_expect (ww.s.high < 0, 1)) + return ww.ll; + } + } + } + else + { + if (vv.s.high >= 0) + { + if (uu.s.high == (Wtype) -1 && vv.s.high == 0) + { + DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low}; - return w; + ww.s.high -= vv.s.low; + if (__builtin_expect (ww.s.high < 0, 1)) + return ww.ll; + } + } + else + { + if (uu.s.high == (Wtype) -1 && vv.s.high == (Wtype) - 1) + { + DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low}; + + ww.s.high -= uu.s.low; + ww.s.high -= vv.s.low; + if (__builtin_expect (ww.s.high >= 0, 1)) + return ww.ll; + } + } + } + } + } + + /* Overflow. */ + abort (); } #endif -/* Unless shift functions are defined whith full ANSI prototypes, +/* Unless shift functions are defined with full ANSI prototypes, parameter b will be promoted to int if word_type is smaller than an int. */ #ifdef L_lshrdi3 DWtype __lshrdi3 (DWtype u, word_type b) { - DWunion w; - word_type bm; - DWunion uu; - if (b == 0) return u; - uu.ll = u; + const DWunion uu = {.ll = u}; + const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; + DWunion w; - bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; if (bm <= 0) { w.s.high = 0; @@ -256,7 +418,7 @@ __lshrdi3 (DWtype u, word_type b) } else { - UWtype carries = (UWtype) uu.s.high << bm; + const UWtype carries = (UWtype) uu.s.high << bm; w.s.high = (UWtype) uu.s.high >> b; w.s.low = ((UWtype) uu.s.low >> b) | carries; @@ -270,16 +432,13 @@ __lshrdi3 (DWtype u, word_type b) DWtype __ashldi3 (DWtype u, word_type b) { - DWunion w; - word_type bm; - DWunion uu; - if (b == 0) return u; - uu.ll = u; + const DWunion uu = {.ll = u}; + const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; + DWunion w; - bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; if (bm <= 0) { w.s.low = 0; @@ -287,7 +446,7 @@ __ashldi3 (DWtype u, word_type b) } else { - UWtype carries = (UWtype) uu.s.low >> bm; + const UWtype carries = (UWtype) uu.s.low >> bm; w.s.low = (UWtype) uu.s.low << b; w.s.high = ((UWtype) uu.s.high << b) | carries; @@ -301,16 +460,13 @@ __ashldi3 (DWtype u, word_type b) DWtype __ashrdi3 (DWtype u, word_type b) { - DWunion w; - word_type bm; - DWunion uu; - if (b == 0) return u; - uu.ll = u; + const DWunion uu = {.ll = u}; + const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; + DWunion w; - bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; if (bm <= 0) { /* w.s.high = 1..1 or 0..0 */ @@ -319,7 +475,7 @@ __ashrdi3 (DWtype u, word_type b) } else { - UWtype carries = (UWtype) uu.s.high << bm; + const UWtype carries = (UWtype) uu.s.high << bm; w.s.high = uu.s.high >> b; w.s.low = ((UWtype) uu.s.low >> b) | carries; @@ -329,14 +485,29 @@ __ashrdi3 (DWtype u, word_type b) } #endif +#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 + #ifdef L_ffsdi2 -DWtype -__ffsdi2 (DWtype u) +#undef int +int +__ffsDI2 (DWtype u) { - DWunion uu; + const DWunion uu = {.ll = u}; UWtype word, count, add; - uu.ll = u; if (uu.s.low != 0) word = uu.s.low, add = 0; else if (uu.s.high != 0) @@ -353,13 +524,10 @@ __ffsdi2 (DWtype u) DWtype __muldi3 (DWtype u, DWtype v) { - DWunion w; - DWunion uu, vv; - - uu.ll = u, - vv.ll = v; + const DWunion uu = {.ll = u}; + const DWunion vv = {.ll = v}; + DWunion w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)}; - w.ll = __umulsidi3 (uu.s.low, vv.s.low); w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high + (UWtype) uu.s.high * (UWtype) vv.s.low); @@ -367,8 +535,19 @@ __muldi3 (DWtype u, DWtype v) } #endif +#if (defined (L_udivdi3) || defined (L_divdi3) || \ + defined (L_umoddi3) || defined (L_moddi3)) +#if defined (sdiv_qrnnd) +#define L_udiv_w_sdiv +#endif +#endif + #ifdef L_udiv_w_sdiv #if defined (sdiv_qrnnd) +#if (defined (L_udivdi3) || defined (L_divdi3) || \ + defined (L_umoddi3) || defined (L_moddi3)) +static inline __attribute__ ((__always_inline__)) +#endif UWtype __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d) { @@ -379,16 +558,16 @@ __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d) { if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1))) { - /* dividend, divisor, and quotient are nonnegative */ + /* Dividend, divisor, and quotient are nonnegative. */ sdiv_qrnnd (q, r, a1, a0, d); } else { - /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ + /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d. */ sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1)); - /* Divide (c1*2^32 + c0) by d */ + /* Divide (c1*2^32 + c0) by d. */ sdiv_qrnnd (q, r, c1, c0, d); - /* Add 2^31 to quotient */ + /* Add 2^31 to quotient. */ q += (UWtype) 1 << (W_TYPE_SIZE - 1); } } @@ -496,26 +675,179 @@ const UQItype __clz_tab[] = 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, }; #endif + +#ifdef L_clzsi2 +#undef int +int +__clzSI2 (UWtype x) +{ + Wtype ret; + + count_leading_zeros (ret, x); + + return ret; +} +#endif + +#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 + +#ifdef L_ctzsi2 +#undef int +int +__ctzSI2 (UWtype x) +{ + Wtype ret; + + count_trailing_zeros (ret, x); + + return ret; +} +#endif + +#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 + +#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 + +#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 + +#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 + +#ifdef L_paritydi2 +#undef int +int +__parityDI2 (UDWtype x) +{ + const DWunion uu = {.ll = x}; + UWtype nx = uu.s.low ^ uu.s.high; + +#if W_TYPE_SIZE > 64 +# error "fill out the table" +#endif +#if W_TYPE_SIZE > 32 + nx ^= nx >> 32; +#endif +#if W_TYPE_SIZE > 16 + nx ^= nx >> 16; +#endif + nx ^= nx >> 8; + nx ^= nx >> 4; + nx &= 0xf; + return (0x6996 >> nx) & 1; +} +#endif #ifdef L_udivmoddi4 #if (defined (L_udivdi3) || defined (L_divdi3) || \ defined (L_umoddi3) || defined (L_moddi3)) -static inline +static inline __attribute__ ((__always_inline__)) #endif UDWtype __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) { - DWunion ww; - DWunion nn, dd; + const DWunion nn = {.ll = n}; + const DWunion dd = {.ll = d}; DWunion rr; UWtype d0, d1, n0, n1, n2; UWtype q0, q1; UWtype b, bm; - nn.ll = n; - dd.ll = d; - d0 = dd.s.low; d1 = dd.s.high; n0 = nn.s.low; @@ -715,8 +1047,7 @@ __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) } } - ww.s.low = q0; - ww.s.high = q1; + const DWunion ww = {{.low = q0, .high = q1}}; return ww.ll; } #endif @@ -726,22 +1057,20 @@ DWtype __divdi3 (DWtype u, DWtype v) { word_type c = 0; - DWunion uu, vv; + DWunion uu = {.ll = u}; + DWunion vv = {.ll = v}; DWtype w; - uu.ll = u; - vv.ll = v; - if (uu.s.high < 0) c = ~c, - uu.ll = __negdi2 (uu.ll); + uu.ll = -uu.ll; if (vv.s.high < 0) c = ~c, - vv.ll = __negdi2 (vv.ll); + vv.ll = -vv.ll; w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0); if (c) - w = __negdi2 (w); + w = -w; return w; } @@ -752,21 +1081,19 @@ DWtype __moddi3 (DWtype u, DWtype v) { word_type c = 0; - DWunion uu, vv; + DWunion uu = {.ll = u}; + DWunion vv = {.ll = v}; DWtype w; - uu.ll = u; - vv.ll = v; - if (uu.s.high < 0) c = ~c, - uu.ll = __negdi2 (uu.ll); + uu.ll = -uu.ll; if (vv.s.high < 0) - vv.ll = __negdi2 (vv.ll); + vv.ll = -vv.ll; - (void) __udivmoddi4 (uu.ll, vv.ll, &w); + (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w); if (c) - w = __negdi2 (w); + w = -w; return w; } @@ -796,9 +1123,8 @@ __udivdi3 (UDWtype n, UDWtype d) word_type __cmpdi2 (DWtype a, DWtype b) { - DWunion au, bu; - - au.ll = a, bu.ll = b; + const DWunion au = {.ll = a}; + const DWunion bu = {.ll = b}; if (au.s.high < bu.s.high) return 0; @@ -816,9 +1142,8 @@ __cmpdi2 (DWtype a, DWtype b) word_type __ucmpdi2 (DWtype a, DWtype b) { - DWunion au, bu; - - au.ll = a, bu.ll = b; + const DWunion au = {.ll = a}; + const DWunion bu = {.ll = b}; if ((UWtype) au.s.high < (UWtype) bu.s.high) return 0; @@ -839,17 +1164,14 @@ __ucmpdi2 (DWtype a, DWtype b) DWtype __fixunstfDI (TFtype a) { - TFtype b; - UDWtype v; - if (a < 0) return 0; /* Compute high word of result, as a flonum. */ - b = (a / HIGH_WORD_COEFF); + const TFtype b = (a / HIGH_WORD_COEFF); /* Convert that to fixed (but not to DWtype!), and shift it into the high word. */ - v = (UWtype) b; + UDWtype v = (UWtype) b; v <<= WORD_SIZE; /* Remove high part from the TFtype, leaving the low part as flonum. */ a -= (TFtype)v; @@ -874,24 +1196,21 @@ __fixtfdi (TFtype a) } #endif -#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) +#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) DWtype __fixunsxfDI (XFtype a) { - XFtype b; - UDWtype v; - if (a < 0) return 0; /* Compute high word of result, as a flonum. */ - b = (a / HIGH_WORD_COEFF); + const XFtype b = (a / HIGH_WORD_COEFF); /* Convert that to fixed (but not to DWtype!), and shift it into the high word. */ - v = (UWtype) b; + UDWtype v = (UWtype) b; v <<= WORD_SIZE; /* Remove high part from the XFtype, leaving the low part as flonum. */ a -= (XFtype)v; @@ -906,7 +1225,7 @@ __fixunsxfDI (XFtype a) } #endif -#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) +#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) DWtype __fixxfdi (XFtype a) { @@ -923,28 +1242,18 @@ __fixxfdi (XFtype a) DWtype __fixunsdfDI (DFtype a) { - DFtype b; - UDWtype v; - - 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 DWtype!), - and shift it into the high word. */ - v = (UWtype) b; - v <<= WORD_SIZE; - /* Remove high part from the DFtype, leaving the low part as flonum. */ - a -= (DFtype)v; - /* Convert that to fixed (but not to DWtype!) and add it in. - Sometimes A comes out negative. This is significant, since - A has more bits than a long int does. */ - if (a < 0) - v -= (UWtype) (- a); - else - v += (UWtype) a; - return v; + /* Get high part of result. The division here will just moves the radix + point and will not cause any rounding. Then the conversion to integral + type chops result as desired. */ + const UWtype hi = a / HIGH_WORD_COEFF; + + /* Get low part of result. Convert `hi' to floating type and scale it back, + then subtract this from the number being converted. This leaves the low + part. Convert that to integral type. */ + const UWtype lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF); + + /* Assemble result from the two parts. */ + return ((UDWtype) hi << WORD_SIZE) | lo; } #endif @@ -968,29 +1277,20 @@ __fixunssfDI (SFtype original_a) /* Convert the SFtype to a DFtype, because that is surely not going to lose any bits. Some day someone else can write a faster version that avoids converting to DFtype, and verify it really works right. */ - DFtype a = original_a; - DFtype b; - UDWtype v; + const DFtype a = original_a; - if (a < 0) - return 0; + /* Get high part of result. The division here will just moves the radix + point and will not cause any rounding. Then the conversion to integral + type chops result as desired. */ + const UWtype hi = a / HIGH_WORD_COEFF; - /* Compute high word of result, as a flonum. */ - b = (a / HIGH_WORD_COEFF); - /* Convert that to fixed (but not to DWtype!), - and shift it into the high word. */ - v = (UWtype) b; - v <<= WORD_SIZE; - /* Remove high part from the DFtype, leaving the low part as flonum. */ - a -= (DFtype) v; - /* Convert that to fixed (but not to DWtype!) and add it in. - Sometimes A comes out negative. This is significant, since - A has more bits than a long int does. */ - if (a < 0) - v -= (UWtype) (- a); - else - v += (UWtype) a; - return v; + /* Get low part of result. Convert `hi' to floating type and scale it back, + then subtract this from the number being converted. This leaves the low + part. Convert that to integral type. */ + const UWtype lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF); + + /* Assemble result from the two parts. */ + return ((UDWtype) hi << WORD_SIZE) | lo; } #endif @@ -1004,7 +1304,7 @@ __fixsfdi (SFtype a) } #endif -#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96) +#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2)) #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE) @@ -1012,9 +1312,7 @@ __fixsfdi (SFtype a) XFtype __floatdixf (DWtype u) { - XFtype d; - - d = (Wtype) (u >> WORD_SIZE); + XFtype d = (Wtype) (u >> WORD_SIZE); d *= HIGH_HALFWORD_COEFF; d *= HIGH_HALFWORD_COEFF; d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); @@ -1031,9 +1329,7 @@ __floatdixf (DWtype u) TFtype __floatditf (DWtype u) { - TFtype d; - - d = (Wtype) (u >> WORD_SIZE); + TFtype d = (Wtype) (u >> WORD_SIZE); d *= HIGH_HALFWORD_COEFF; d *= HIGH_HALFWORD_COEFF; d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); @@ -1050,9 +1346,7 @@ __floatditf (DWtype u) DFtype __floatdidf (DWtype u) { - DFtype d; - - d = (Wtype) (u >> WORD_SIZE); + DFtype d = (Wtype) (u >> WORD_SIZE); d *= HIGH_HALFWORD_COEFF; d *= HIGH_HALFWORD_COEFF; d += (UWtype) (u & (HIGH_WORD_COEFF - 1)); @@ -1073,11 +1367,6 @@ __floatdidf (DWtype u) 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 @@ -1092,10 +1381,16 @@ __floatdisf (DWtype u) && u < ((DWtype) 1 << DF_SIZE))) { if ((UDWtype) u & (REP_BIT - 1)) - u |= REP_BIT; + { + u &= ~ (REP_BIT - 1); + u |= REP_BIT; + } } } - f = (Wtype) (u >> WORD_SIZE); + /* Do the calculation in DFmode + so that we don't lose any of the precision of the high word + while multiplying it. */ + DFtype f = (Wtype) (u >> WORD_SIZE); f *= HIGH_HALFWORD_COEFF; f *= HIGH_HALFWORD_COEFF; f += (UWtype) (u & (HIGH_WORD_COEFF - 1)); @@ -1104,7 +1399,7 @@ __floatdisf (DWtype u) } #endif -#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96 +#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80 /* Reenable the normal types, in case limits.h needs them. */ #undef char #undef short @@ -1204,7 +1499,7 @@ __gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size) { while (size > 0) { - unsigned char c1 = *s1++, c2 = *s2++; + const unsigned char c1 = *s1++, c2 = *s2++; if (c1 != c2) return c1 - c2; size--; @@ -1236,361 +1531,41 @@ __eprintf (const char *string, const char *expression, #endif #endif -#ifdef L_bb - -#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE -typedef long gcov_type; -#else -typedef long long gcov_type; -#endif - - -/* Structure emitted by -a */ -struct bb -{ - long zero_word; - const char *filename; - gcov_type *counts; - long ncounts; - struct bb *next; - const unsigned long *addresses; - - /* Older GCC's did not emit these fields. */ - long nwords; - const char **functions; - const long *line_nums; - const char **filenames; - char *flags; -}; - -#ifdef BLOCK_PROFILER_CODE -BLOCK_PROFILER_CODE -#else -#ifndef inhibit_libc - -/* Simple minded basic block profiling output dumper for - systems that don't provide tcov support. At present, - it requires atexit and stdio. */ - -#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ -#include - -#include "gbl-ctors.h" -#include "gcov-io.h" -#include -#ifdef TARGET_HAS_F_SETLKW -#include -#include -#endif - -static struct bb *bb_head; - -void -__bb_exit_func (void) -{ - FILE *da_file; - int i; - struct bb *ptr; - - if (bb_head == 0) - return; - - i = strlen (bb_head->filename) - 3; - - - for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next) - { - int firstchar; - - /* Make sure the output file exists - - but don't clobber exiting data. */ - if ((da_file = fopen (ptr->filename, "a")) != 0) - fclose (da_file); - - /* Need to re-open in order to be able to write from the start. */ - da_file = fopen (ptr->filename, "r+b"); - /* Some old systems might not allow the 'b' mode modifier. - Therefore, try to open without it. This can lead to a race - condition so that when you delete and re-create the file, the - file might be opened in text mode, but then, you shouldn't - delete the file in the first place. */ - if (da_file == 0) - da_file = fopen (ptr->filename, "r+"); - if (da_file == 0) - { - fprintf (stderr, "arc profiling: Can't open output file %s.\n", - ptr->filename); - continue; - } - - /* After a fork, another process might try to read and/or write - the same file simultanously. So if we can, lock the file to - avoid race conditions. */ -#if defined (TARGET_HAS_F_SETLKW) - { - struct flock s_flock; - - s_flock.l_type = F_WRLCK; - s_flock.l_whence = SEEK_SET; - s_flock.l_start = 0; - s_flock.l_len = 1; - s_flock.l_pid = getpid (); - - while (fcntl (fileno (da_file), F_SETLKW, &s_flock) - && errno == EINTR); - } -#endif - - /* If the file is not empty, and the number of counts in it is the - same, then merge them in. */ - firstchar = fgetc (da_file); - if (firstchar == EOF) - { - if (ferror (da_file)) - { - fprintf (stderr, "arc profiling: Can't read output file "); - perror (ptr->filename); - } - } - else - { - long n_counts = 0; - - if (ungetc (firstchar, da_file) == EOF) - rewind (da_file); - if (__read_long (&n_counts, da_file, 8) != 0) - { - fprintf (stderr, "arc profiling: Can't read output file %s.\n", - ptr->filename); - continue; - } - - if (n_counts == ptr->ncounts) - { - int i; - - for (i = 0; i < n_counts; i++) - { - gcov_type v = 0; - - if (__read_gcov_type (&v, da_file, 8) != 0) - { - fprintf (stderr, - "arc profiling: Can't read output file %s.\n", - ptr->filename); - break; - } - ptr->counts[i] += v; - } - } - - } - - rewind (da_file); - - /* ??? Should first write a header to the file. Preferably, a 4 byte - magic number, 4 bytes containing the time the program was - compiled, 4 bytes containing the last modification time of the - source file, and 4 bytes indicating the compiler options used. - - That way we can easily verify that the proper source/executable/ - data file combination is being used from gcov. */ - - if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0) - { - - fprintf (stderr, "arc profiling: Error writing output file %s.\n", - ptr->filename); - } - else - { - int j; - gcov_type *count_ptr = ptr->counts; - int ret = 0; - for (j = ptr->ncounts; j > 0; j--) - { - if (__write_gcov_type (*count_ptr, da_file, 8) != 0) - { - ret = 1; - break; - } - count_ptr++; - } - if (ret) - fprintf (stderr, "arc profiling: Error writing output file %s.\n", - ptr->filename); - } - - if (fclose (da_file) == EOF) - fprintf (stderr, "arc profiling: Error closing output file %s.\n", - ptr->filename); - } - - return; -} - -void -__bb_init_func (struct bb *blocks) -{ - /* User is supposed to check whether the first word is non-0, - but just in case.... */ - - if (blocks->zero_word) - return; - - /* Initialize destructor. */ - if (!bb_head) - atexit (__bb_exit_func); - - /* Set up linked list. */ - blocks->zero_word = 1; - blocks->next = bb_head; - bb_head = blocks; -} - -/* Called before fork or exec - write out profile information gathered so - far and reset it to zero. This avoids duplication or loss of the - profile information gathered so far. */ -void -__bb_fork_func (void) -{ - struct bb *ptr; - - __bb_exit_func (); - for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next) - { - long i; - for (i = ptr->ncounts - 1; i >= 0; i--) - ptr->counts[i] = 0; - } -} - -#endif /* not inhibit_libc */ -#endif /* not BLOCK_PROFILER_CODE */ -#endif /* L_bb */ #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 */ +#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 */ + #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_ @@ -1633,198 +1608,6 @@ mprotect (char *addr, int len, int prot) #ifdef TRANSFER_FROM_TRAMPOLINE TRANSFER_FROM_TRAMPOLINE #endif - -#if defined (NeXT) && defined (__MACH__) - -/* Make stack executable so we can call trampolines on stack. - This is called from INITIALIZE_TRAMPOLINE in next.h. */ -#ifdef NeXTStep21 - #include -#else - #include -#endif - -void -__enable_execute_stack (char *addr) -{ - kern_return_t r; - char *eaddr = addr + TRAMPOLINE_SIZE; - vm_address_t a = (vm_address_t) addr; - - /* turn on execute access on stack */ - r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL); - if (r != KERN_SUCCESS) - { - mach_error("vm_protect VM_PROT_ALL", r); - exit(1); - } - - /* We inline the i-cache invalidation for speed */ - -#ifdef CLEAR_INSN_CACHE - CLEAR_INSN_CACHE (addr, eaddr); -#else - __clear_cache ((int) addr, (int) eaddr); -#endif -} - -#endif /* defined (NeXT) && defined (__MACH__) */ - -#ifdef __convex__ - -/* Make stack executable so we can call trampolines on stack. - This is called from INITIALIZE_TRAMPOLINE in convex.h. */ - -#include -#include -#include - -void -__enable_execute_stack (void) -{ - int fp; - static unsigned lowest = USRSTACK; - unsigned current = (unsigned) &fp & -NBPG; - - if (lowest > current) - { - unsigned len = lowest - current; - mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE); - lowest = current; - } - - /* Clear instruction cache in case an old trampoline is in it. */ - asm ("pich"); -} -#endif /* __convex__ */ - -#ifdef __sysV88__ - -/* Modified from the convex -code above. */ - -#include -#include -#include - -void -__enable_execute_stack (void) -{ - int save_errno; - static unsigned long lowest = USRSTACK; - unsigned long current = (unsigned long) &save_errno & -NBPC; - - /* Ignore errno being set. memctl sets errno to EINVAL whenever the - address is seen as 'negative'. That is the case with the stack. */ - - save_errno=errno; - if (lowest > current) - { - unsigned len=lowest-current; - memctl(current,len,MCT_TEXT); - lowest = current; - } - else - memctl(current,NBPC,MCT_TEXT); - errno=save_errno; -} - -#endif /* __sysV88__ */ - -#ifdef __sysV68__ - -#include -#include - -/* Motorola forgot to put memctl.o in the libp version of libc881.a, - so define it here, because we need it in __clear_insn_cache below */ -/* On older versions of this OS, no memctl or MCT_TEXT are defined; - hence we enable this stuff only if MCT_TEXT is #define'd. */ - -#ifdef MCT_TEXT -asm("\n\ - global memctl\n\ -memctl:\n\ - movq &75,%d0\n\ - trap &0\n\ - bcc.b noerror\n\ - jmp cerror%\n\ -noerror:\n\ - movq &0,%d0\n\ - rts"); -#endif - -/* Clear instruction cache so we can call trampolines on stack. - This is called from FINALIZE_TRAMPOLINE in mot3300.h. */ - -void -__clear_insn_cache (void) -{ -#ifdef MCT_TEXT - int save_errno; - - /* Preserve errno, because users would be surprised to have - errno changing without explicitly calling any system-call. */ - save_errno = errno; - - /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache. - No need to use an address derived from _start or %sp, as 0 works also. */ - memctl(0, 4096, MCT_TEXT); - errno = save_errno; -#endif -} - -#endif /* __sysV68__ */ - -#ifdef __pyr__ - -#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ -#include -#include -#include -#include -#include - -/* Modified from the convex -code above. - mremap promises to clear the i-cache. */ - -void -__enable_execute_stack (void) -{ - int fp; - if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ, - PROT_READ|PROT_WRITE|PROT_EXEC)) - { - perror ("mprotect in __enable_execute_stack"); - fflush (stderr); - abort (); - } -} -#endif /* __pyr__ */ - -#if defined (sony_news) && defined (SYSTYPE_BSD) - -#include -#include -#include -#include -#include - -/* cacheflush function for NEWS-OS 4.2. - This function is called from trampoline-initialize code - defined in config/mips/mips.h. */ - -void -cacheflush (char *beg, int size, int flag) -{ - if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE)) - { - perror ("cache_flush"); - fflush (stderr); - abort (); - } -} - -#endif /* sony_news */ #endif /* L_trampoline */ #ifndef __CYGWIN__ @@ -1909,8 +1692,9 @@ __do_global_ctors (void) For systems which support a .init section we use the .init section to run __do_global_ctors, so we need not do anything here. */ +extern void SYMBOL__MAIN (void); void -SYMBOL__MAIN () +SYMBOL__MAIN (void) { /* Support recursive calls to `main': run initializers just once. */ static int initialized; @@ -1952,79 +1736,4 @@ func_ptr __DTOR_LIST__[2]; #endif #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */ #endif /* L_ctors */ - -#ifdef L_exit - -#include "gbl-ctors.h" - -#ifdef NEED_ATEXIT - -#ifndef ON_EXIT - -# include - -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 */