X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Flibgcc2.c;h=0827d833f52171fd8190ff460d8f7f79c632abf7;hb=17ce2b542c426a551b24f6a6c4033b8b507fc1db;hp=46b2f9c8c27ee1828b5b3f34ef5f83283bb15824;hpb=856ba90edd7c9dce168d5ad40ec83b80b734fcc8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index 46b2f9c8c27..0827d833f52 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 Free Software Foundation, Inc. This file is part of GCC. @@ -29,18 +29,30 @@ 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 "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" #ifdef DECLARE_LIBRARY_RENAMES @@ -97,9 +109,6 @@ __addvdi3 (DWtype a, DWtype b) Wtype __subvsi3 (Wtype a, Wtype b) { -#ifdef L_addvsi3 - return __addvsi3 (a, (-b)); -#else DWtype w; w = a - b; @@ -108,7 +117,6 @@ __subvsi3 (Wtype a, Wtype b) abort (); return w; -#endif } #endif @@ -116,9 +124,6 @@ __subvsi3 (Wtype a, Wtype b) DWtype __subvdi3 (DWtype a, DWtype b) { -#ifdef L_addvdi3 - return (a, (-b)); -#else DWtype w; w = a - b; @@ -127,19 +132,21 @@ __subvdi3 (DWtype a, DWtype b) abort (); return w; -#endif } #endif #ifdef L_mulvsi3 +#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) Wtype __mulvsi3 (Wtype a, Wtype b) { DWtype w; - w = a * b; + w = (DWtype) a * (DWtype) b; - if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0) + if (((a >= 0) == (b >= 0)) + ? (UDWtype) w > (UDWtype) (((DWtype) 1 << (WORD_SIZE - 1)) - 1) + : (UDWtype) w < (UDWtype) ((DWtype) -1 << (WORD_SIZE - 1))) abort (); return w; @@ -203,8 +210,8 @@ __absvdi2 (DWtype a) DWtype w = a; if (a < 0) -#ifdef L_negvsi2 - w = __negvsi2 (a); +#ifdef L_negvdi2 + w = __negvdi2 (a); #else w = -a; @@ -217,22 +224,137 @@ __absvdi2 (DWtype a) #endif #ifdef L_mulvdi3 +#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT) DWtype __mulvdi3 (DWtype u, DWtype v) { - DWtype w; + /* The unchecked multiplication needs 3 Wtype x Wtype multiplications, + but the checked multiplication needs only two. */ + DWunion uu, vv; - w = u * v; + uu.ll = u; + vv.ll = 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, w1; + + w0.ll = (UDWtype) (UWtype) uu.s.low * (UDWtype) (UWtype) vv.s.low; + 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, w1; + + w0.ll = (UDWtype) (UWtype) uu.s.low * (UDWtype) (UWtype) vv.s.low; + 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) + { + DWtype w; + + 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; + + 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; + + 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; + + 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 -/* 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 @@ -328,9 +450,27 @@ __ashrdi3 (DWtype u, word_type b) } #endif +#ifdef L_ffssi2 +#undef int +extern int __ffsSI2 (UWtype u); +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 +extern int __ffsDI2 (DWtype u); +int +__ffsDI2 (DWtype u) { DWunion uu; UWtype word, count, add; @@ -366,8 +506,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) { @@ -495,12 +646,181 @@ 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 +extern int __clzSI2 (UWtype x); +int +__clzSI2 (UWtype x) +{ + Wtype ret; + + count_leading_zeros (ret, x); + + return ret; +} +#endif + +#ifdef L_clzdi2 +#undef int +extern int __clzDI2 (UDWtype x); +int +__clzDI2 (UDWtype x) +{ + DWunion uu; + UWtype word; + Wtype ret, add; + + uu.ll = x; + 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 +extern int __ctzSI2 (UWtype x); +int +__ctzSI2 (UWtype x) +{ + Wtype ret; + + count_trailing_zeros (ret, x); + + return ret; +} +#endif + +#ifdef L_ctzdi2 +#undef int +extern int __ctzDI2 (UDWtype x); +int +__ctzDI2 (UDWtype x) +{ + DWunion uu; + UWtype word; + Wtype ret, add; + + uu.ll = x; + 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 +extern int __popcountSI2 (UWtype x); +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 +extern int __popcountDI2 (UDWtype x); +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 +extern int __paritySI2 (UWtype x); +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 +extern int __parityDI2 (UDWtype x); +int +__parityDI2 (UDWtype x) +{ + DWunion uu; + UWtype nx; + + uu.ll = x; + 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) @@ -922,28 +1242,20 @@ __fixxfdi (XFtype a) DWtype __fixunsdfDI (DFtype a) { - DFtype b; - UDWtype v; + UWtype hi, lo; - 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. */ + 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. */ + lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF); + + /* Assemble result from the two parts. */ + return ((UDWtype) hi << WORD_SIZE) | lo; } #endif @@ -968,28 +1280,20 @@ __fixunssfDI (SFtype original_a) 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; + UWtype hi, lo; - 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. */ + 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. */ + lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF); + + /* Assemble result from the two parts. */ + return ((UDWtype) hi << WORD_SIZE) | lo; } #endif @@ -1091,7 +1395,10 @@ __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); @@ -1235,371 +1542,16 @@ __eprintf (const char *string, const char *expression, #endif #endif -#ifdef L_bb - -struct bb_function_info { - long checksum; - int arc_count; - const char *name; -}; - -/* Structure emitted by -a */ -struct bb -{ - long zero_word; - const char *filename; - gcov_type *counts; - long ncounts; - struct bb *next; - - /* Older GCC's did not emit these fields. */ - long sizeof_bb; - struct bb_function_info *function_infos; -}; - -#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 - -#include - -static struct bb *bb_head; - -int __global_counters = 0, __gthreads_active = 0; - -void -__bb_exit_func (void) -{ - FILE *da_file; - struct bb *ptr; - long n_counters_p = 0; - gcov_type max_counter_p = 0; - gcov_type sum_counters_p = 0; - - if (bb_head == 0) - return; - - /* Calculate overall "statistics". */ - - for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next) - { - int i; - - n_counters_p += ptr->ncounts; - - for (i = 0; i < ptr->ncounts; i++) - { - sum_counters_p += ptr->counts[i]; - - if (ptr->counts[i] > max_counter_p) - max_counter_p = ptr->counts[i]; - } - } - - for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next) - { - gcov_type max_counter_o = 0; - gcov_type sum_counters_o = 0; - int i; - - /* Calculate the per-object statistics. */ - - for (i = 0; i < ptr->ncounts; i++) - { - sum_counters_o += ptr->counts[i]; - - if (ptr->counts[i] > max_counter_o) - max_counter_o = ptr->counts[i]; - } - - /* open the file for appending, creating it if necessary. */ - da_file = fopen (ptr->filename, "ab"); - /* Some old systems might not allow the 'b' mode modifier. - Therefore, try to open without it. This can lead to a race - condition so that when you delete and re-create the file, the - file might be opened in text mode, but then, you shouldn't - delete the file in the first place. */ - if (da_file == 0) - da_file = fopen (ptr->filename, "a"); - if (da_file == 0) - { - 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 (__write_long (-123, da_file, 4) != 0) /* magic */ - { - fprintf (stderr, "arc profiling: Error writing output file %s.\n", - ptr->filename); - } - else - { - - struct bb_function_info *fn_info; - gcov_type *count_ptr = ptr->counts; - int i; - int count_functions = 0; - - for (fn_info = ptr->function_infos; fn_info->arc_count != -1; - fn_info++) - count_functions++; - - /* number of functions in this block. */ - __write_long (count_functions, da_file, 4); - - /* length of extra data in bytes. */ - __write_long ((4 + 8 + 8) + (4 + 8 + 8), da_file, 4); - - /* overall statistics. */ - /* number of counters. */ - __write_long (n_counters_p, da_file, 4); - /* sum of counters. */ - __write_gcov_type (sum_counters_p, da_file, 8); - /* maximal counter. */ - __write_gcov_type (max_counter_p, da_file, 8); - - /* per-object statistics. */ - /* number of counters. */ - __write_long (ptr->ncounts, da_file, 4); - /* sum of counters. */ - __write_gcov_type (sum_counters_o, da_file, 8); - /* maximal counter. */ - __write_gcov_type (max_counter_o, da_file, 8); - - /* write execution counts for each function. */ - - for (fn_info = ptr->function_infos; fn_info->arc_count != -1; - fn_info++) - { - /* new function. */ - if (__write_gcov_string - (fn_info->name, strlen (fn_info->name), da_file, -1) != 0) - { - fprintf (stderr, - "arc profiling: Error writing output file %s.\n", - ptr->filename); - break; - } - - if (__write_long (fn_info->checksum, da_file, 4) != 0) - { - fprintf (stderr, - "arc profiling: Error writing output file %s.\n", - ptr->filename); - break; - } - - if (__write_long (fn_info->arc_count, da_file, 4) != 0) - { - fprintf (stderr, - "arc profiling: Error writing output file %s.\n", - ptr->filename); - break; - } - - for (i = fn_info->arc_count; i > 0; i--, count_ptr++) - { - if (__write_gcov_type (*count_ptr, da_file, 8) != 0) - break; - } - - if (i) /* there was an error */ - { - fprintf (stderr, - "arc profiling: Error writing output file %s.\n", - ptr->filename); - break; - } - } - } - - if (fclose (da_file) != 0) - fprintf (stderr, "arc profiling: Error closing output file %s.\n", - ptr->filename); - } -} - -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 and per-thread data. */ - 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 /* 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 */ } @@ -1654,198 +1606,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__ @@ -1930,8 +1690,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; @@ -1973,79 +1734,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 */