1 /* More subroutines needed by GCC output code on some machines. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* As a special exception, if you link this library with files
22 compiled with GCC to produce an executable, this does not cause
23 the resulting executable to be covered by the GNU General Public License.
24 This exception does not however invalidate any other reasons why
25 the executable file might be covered by the GNU General Public License. */
27 /* It is incorrect to include config.h here, because this file is being
28 compiled for the target, and hence definitions concerning only the host
36 /* Don't use `fancy_abort' here even if config.h says to use it. */
41 /* Need to undef this because LONG_TYPE_SIZE may rely upon GCC's
42 internal `target_flags' variable. */
45 #define LONG_TYPE_SIZE (sizeof (long) * BITS_PER_UNIT)
48 #define SItype long int
51 /* long long ints are pairs of long ints in the order determined by
55 struct longlong {long high, low;};
57 struct longlong {long low, high;};
60 /* We need this union to unpack/pack longlongs, since we don't have
61 any arithmetic yet. Incoming long long parameters are stored
62 into the `ll' field, and the unpacked result is read from the struct
71 #if defined (L_udivmoddi4) || defined (L_muldi3)
75 #endif /* udiv or mul */
77 extern long long __fixunssfdi (float a);
78 extern long long __fixunsdfdi (double a);
80 #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
81 #if defined (L_divdi3) || defined (L_moddi3)
94 w.s.high = -uu.s.high - ((unsigned long) w.s.low > 0);
115 bm = (sizeof (long) * BITS_PER_UNIT) - b;
119 w.s.high = (unsigned long)uu.s.low << -bm;
123 unsigned long carries = (unsigned long)uu.s.low >> bm;
124 w.s.low = (unsigned long)uu.s.low << b;
125 w.s.high = ((unsigned long)uu.s.high << b) | carries;
147 bm = (sizeof (long) * BITS_PER_UNIT) - b;
151 w.s.low = (unsigned long)uu.s.high >> -bm;
155 unsigned long carries = (unsigned long)uu.s.high << bm;
156 w.s.high = (unsigned long)uu.s.high >> b;
157 w.s.low = ((unsigned long)uu.s.low >> b) | carries;
179 bm = (sizeof (long) * BITS_PER_UNIT) - b;
183 w.s.high = (unsigned long)uu.s.low << -bm;
187 unsigned long carries = (unsigned long)uu.s.low >> bm;
188 w.s.low = (unsigned long)uu.s.low << b;
189 w.s.high = ((unsigned long)uu.s.high << b) | carries;
211 bm = (sizeof (long) * BITS_PER_UNIT) - b;
214 /* w.s.high = 1..1 or 0..0 */
215 w.s.high = uu.s.high >> (sizeof (long) * BITS_PER_UNIT - 1);
216 w.s.low = uu.s.high >> -bm;
220 unsigned long carries = (unsigned long)uu.s.high << bm;
221 w.s.high = uu.s.high >> b;
222 w.s.low = ((unsigned long)uu.s.low >> b) | carries;
240 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
241 w.s.high += ((unsigned long) uu.s.low * (unsigned long) vv.s.high
242 + (unsigned long) uu.s.high * (unsigned long) vv.s.low);
249 static const unsigned char __clz_tab[] =
251 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
252 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
253 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
254 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
255 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,
256 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,
257 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,
258 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,
262 __udivmoddi4 (n, d, rp)
263 unsigned long long n, d;
264 unsigned long long int *rp;
269 unsigned long d0, d1, n0, n1, n2;
270 unsigned long q0, q1;
281 #if !UDIV_NEEDS_NORMALIZATION
288 udiv_qrnnd (q0, n0, n1, n0, d0);
291 /* Remainder in n0. */
298 d0 = 1 / d0; /* Divide intentionally by zero. */
300 udiv_qrnnd (q1, n1, 0, n1, d0);
301 udiv_qrnnd (q0, n0, n1, n0, d0);
303 /* Remainder in n0. */
314 #else /* UDIV_NEEDS_NORMALIZATION */
322 count_leading_zeros (bm, d0);
326 /* Normalize, i.e. make the most significant bit of the
330 n1 = (n1 << bm) | (n0 >> (LONG_TYPE_SIZE - bm));
334 udiv_qrnnd (q0, n0, n1, n0, d0);
337 /* Remainder in n0 >> bm. */
344 d0 = 1 / d0; /* Divide intentionally by zero. */
346 count_leading_zeros (bm, d0);
350 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
351 conclude (the most significant bit of n1 is set) /\ (the
352 leading quotient digit q1 = 1).
354 This special case is necessary, not an optimization.
355 (Shifts counts of LONG_TYPE_SIZE are undefined.) */
364 b = LONG_TYPE_SIZE - bm;
368 n1 = (n1 << bm) | (n0 >> b);
371 udiv_qrnnd (q1, n1, n2, n1, d0);
376 udiv_qrnnd (q0, n0, n1, n0, d0);
378 /* Remainder in n0 >> bm. */
388 #endif /* UDIV_NEEDS_NORMALIZATION */
399 /* Remainder in n1n0. */
411 count_leading_zeros (bm, d1);
414 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
415 conclude (the most significant bit of n1 is set) /\ (the
416 quotient digit q0 = 0 or 1).
418 This special case is necessary, not an optimization. */
420 /* The condition on the next line takes advantage of that
421 n1 >= d1 (true due to program flow). */
422 if (n1 > d1 || n0 >= d0)
425 sub_ddmmss (n1, n0, n1, n0, d1, d0);
441 unsigned long m1, m0;
444 b = LONG_TYPE_SIZE - bm;
446 d1 = (d1 << bm) | (d0 >> b);
449 n1 = (n1 << bm) | (n0 >> b);
452 udiv_qrnnd (q0, n1, n2, n1, d1);
453 umul_ppmm (m1, m0, q0, d0);
455 if (m1 > n1 || (m1 == n1 && m0 > n0))
458 sub_ddmmss (m1, m0, m1, m0, d1, d0);
463 /* Remainder in (n1n0 - m1m0) >> bm. */
466 sub_ddmmss (n1, n0, n1, n0, m1, m0);
467 rr.s.low = (n1 << b) | (n0 >> bm);
468 rr.s.high = n1 >> bm;
482 unsigned long long __udivmoddi4 ();
496 uu.ll = __negdi2 (uu.ll);
499 vv.ll = __negdi2 (vv.ll);
501 w = __udivmoddi4 (uu.ll, vv.ll, (unsigned long long *) 0);
510 unsigned long long __udivmoddi4 ();
524 uu.ll = __negdi2 (uu.ll);
526 vv.ll = __negdi2 (vv.ll);
528 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
537 unsigned long long __udivmoddi4 ();
540 unsigned long long u, v;
544 (void) __udivmoddi4 (u, v, &w);
551 unsigned long long __udivmoddi4 ();
554 unsigned long long n, d;
556 return __udivmoddi4 (n, d, (unsigned long long *) 0);
567 au.ll = a, bu.ll = b;
569 if (au.s.high < bu.s.high)
571 else if (au.s.high > bu.s.high)
573 if ((unsigned long) au.s.low < (unsigned long) bu.s.low)
575 else if ((unsigned long) au.s.low > (unsigned long) bu.s.low)
588 au.ll = a, bu.ll = b;
590 if ((unsigned long) au.s.high < (unsigned long) bu.s.high)
592 else if ((unsigned long) au.s.high > (unsigned long) bu.s.high)
594 if ((unsigned long) au.s.low < (unsigned long) bu.s.low)
596 else if ((unsigned long) au.s.low > (unsigned long) bu.s.low)
603 #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
604 #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
611 unsigned long long v;
616 /* Compute high word of result, as a flonum. */
617 b = (a / HIGH_WORD_COEFF);
618 /* Convert that to fixed (but not to long long!),
619 and shift it into the high word. */
620 v = (unsigned long int) b;
622 /* Remove high part from the double, leaving the low part as flonum. */
624 /* Convert that to fixed (but not to long long!) and add it in.
625 Sometimes A comes out negative. This is significant, since
626 A has more bits than a long int does. */
628 v -= (unsigned long int) (- a);
630 v += (unsigned long int) a;
641 return - __fixunsdfdi (-a);
642 return __fixunsdfdi (a);
647 #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
648 #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
651 __fixunssfdi (float original_a)
653 /* Convert the float to a double, because that is surely not going
654 to lose any bits. Some day someone else can write a faster version
655 that avoids converting to double, and verify it really works right. */
656 double a = original_a;
658 unsigned long long v;
663 /* Compute high word of result, as a flonum. */
664 b = (a / HIGH_WORD_COEFF);
665 /* Convert that to fixed (but not to long long!),
666 and shift it into the high word. */
667 v = (unsigned long int) b;
669 /* Remove high part from the double, leaving the low part as flonum. */
671 /* Convert that to fixed (but not to long long!) and add it in.
672 Sometimes A comes out negative. This is significant, since
673 A has more bits than a long int does. */
675 v -= (unsigned long int) (- a);
677 v += (unsigned long int) a;
687 return - __fixunssfdi (-a);
688 return __fixunssfdi (a);
693 #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
694 #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2))
695 #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
707 d = (unsigned int) (u >> WORD_SIZE);
708 d *= HIGH_HALFWORD_COEFF;
709 d *= HIGH_HALFWORD_COEFF;
710 d += (unsigned int) (u & (HIGH_WORD_COEFF - 1));
712 return (negate ? -d : d);
717 #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
718 #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2))
719 #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
731 f = (unsigned int) (u >> WORD_SIZE);
732 f *= HIGH_HALFWORD_COEFF;
733 f *= HIGH_HALFWORD_COEFF;
734 f += (unsigned int) (u & (HIGH_WORD_COEFF - 1));
736 return (negate ? -f : f);
747 if (a >= - (double) LONG_MIN)
748 return (SItype) (a + LONG_MIN) - LONG_MIN;
757 __fixunssfsi (float a)
759 if (a >= - (float) LONG_MIN)
760 return (SItype) (a + LONG_MIN) - LONG_MIN;
771 asm (".globl __builtin_saveregs");
772 asm ("__builtin_saveregs:");
773 asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
774 asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
775 area and also for a new va_list
777 /* Save all argument registers in the arg reg save area. The
778 arg reg save area must have the following layout (according
790 asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
791 asm (" fst.q %f12,16(%sp)");
793 asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
794 asm (" st.l %r17,36(%sp)");
795 asm (" st.l %r18,40(%sp)");
796 asm (" st.l %r19,44(%sp)");
797 asm (" st.l %r20,48(%sp)");
798 asm (" st.l %r21,52(%sp)");
799 asm (" st.l %r22,56(%sp)");
800 asm (" st.l %r23,60(%sp)");
801 asm (" st.l %r24,64(%sp)");
802 asm (" st.l %r25,68(%sp)");
803 asm (" st.l %r26,72(%sp)");
804 asm (" st.l %r27,76(%sp)");
806 asm (" adds 80,%sp,%r16"); /* compute the address of the new
807 va_list structure. Put in into
808 r16 so that it will be returned
811 /* Initialize all fields of the new va_list structure. This
812 structure looks like:
815 unsigned long ireg_used;
816 unsigned long freg_used;
822 asm (" st.l %r0, 0(%r16)"); /* nfixed */
823 asm (" st.l %r0, 4(%r16)"); /* nfloating */
824 asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
825 asm (" bri %r1"); /* delayed return */
826 asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
832 asm (".globl ___builtin_saveregs");
833 asm ("___builtin_saveregs:");
835 asm (" andnot 0x0f,sp,sp");
836 asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
838 /* Fill in the __va_struct. */
839 asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
840 asm (" st.l r17, 4(sp)"); /* int fixed[12] */
841 asm (" st.l r18, 8(sp)");
842 asm (" st.l r19,12(sp)");
843 asm (" st.l r20,16(sp)");
844 asm (" st.l r21,20(sp)");
845 asm (" st.l r22,24(sp)");
846 asm (" st.l r23,28(sp)");
847 asm (" st.l r24,32(sp)");
848 asm (" st.l r25,36(sp)");
849 asm (" st.l r26,40(sp)");
850 asm (" st.l r27,44(sp)");
852 asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
853 asm (" fst.q f12,64(sp)"); /* int floating[8] */
855 /* Fill in the __va_ctl. */
856 asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
857 asm (" st.l r28,84(sp)"); /* pointer to more args */
858 asm (" st.l r0, 88(sp)"); /* nfixed */
859 asm (" st.l r0, 92(sp)"); /* nfloating */
861 asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
864 /* recover stack and pass address to start
866 #endif /* not SVR4 */
867 #else /* not __i860__ */
869 #ifdef NO_UNDERSCORES
870 asm (".global __builtin_saveregs");
871 asm ("__builtin_saveregs:");
873 asm (".global ___builtin_saveregs");
874 asm ("___builtin_saveregs:");
876 asm ("st %i0,[%fp+68]");
877 asm ("st %i1,[%fp+72]");
878 asm ("st %i2,[%fp+76]");
879 asm ("st %i3,[%fp+80]");
880 asm ("st %i4,[%fp+84]");
882 asm ("st %i5,[%fp+88]");
883 #else /* not __sparc__ */
884 #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
887 asm (" .ent __builtin_saveregs");
888 asm (" .globl __builtin_saveregs");
889 asm ("__builtin_saveregs:");
890 asm (" sw $4,0($30)");
891 asm (" sw $5,4($30)");
892 asm (" sw $6,8($30)");
893 asm (" sw $7,12($30)");
895 asm (" .end __builtin_saveregs");
896 #else /* not __mips__, etc. */
897 __builtin_saveregs ()
901 #endif /* not __mips__ */
902 #endif /* not __sparc__ */
903 #endif /* not __i860__ */
907 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
909 /* This is used by the `assert' macro. */
911 __eprintf (string, expression, line, filename)
917 fprintf (stderr, string, expression, line, filename);
924 /* Avoid warning from ranlib about empty object file. */
926 __bb_avoid_warning ()
929 #if defined (__sun__) && defined (__mc68000__)
940 extern int ___tcov_init;
942 __bb_init_func (blocks)
946 ___tcov_init_func ();
948 ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);
957 typedef void (*vfp)(void);
959 extern vfp __new_handler;
967 p = (void *) malloc (sz);
975 typedef void (*vfp)(void);
977 static void default_new_handler ();
979 vfp __new_handler = default_new_handler;
982 __builtin_vec_new (p, maxindex, size, ctor)
985 void (*ctor)(void *);
987 int i, nelts = maxindex + 1;
991 p = (void *)__builtin_new (nelts * size);
995 for (i = 0; i < nelts; i++)
1005 __set_new_handler (handler)
1010 prev_handler = __new_handler;
1011 if (handler == 0) handler = default_new_handler;
1012 __new_handler = handler;
1013 return prev_handler;
1017 set_new_handler (handler)
1020 return __set_new_handler (handler);
1024 default_new_handler ()
1026 /* don't use fprintf (stderr, ...) because it may need to call malloc. */
1027 /* This should really print the name of the program, but that is hard to
1028 do. We need a standard, clean way to get at the name. */
1029 write (2, "Virtual memory exceeded in `new'\n", 33);
1030 /* don't call exit () because that may call global destructors which
1031 may cause a loop. */
1036 #ifdef L_builtin_del
1037 typedef void (*vfp)(void);
1040 __builtin_delete (ptr)
1048 __builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete)
1054 int i, nelts = maxindex + 1;
1057 ptr += nelts * size;
1059 for (i = 0; i < nelts; i++)
1062 (*dtor) (ptr, auto_delete);
1065 if (auto_delete_vec)
1066 __builtin_delete (p);
1072 unsigned int __shtab[] = {
1073 0x00000001, 0x00000002, 0x00000004, 0x00000008,
1074 0x00000010, 0x00000020, 0x00000040, 0x00000080,
1075 0x00000100, 0x00000200, 0x00000400, 0x00000800,
1076 0x00001000, 0x00002000, 0x00004000, 0x00008000,
1077 0x00010000, 0x00020000, 0x00040000, 0x00080000,
1078 0x00100000, 0x00200000, 0x00400000, 0x00800000,
1079 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1080 0x10000000, 0x20000000, 0x40000000, 0x80000000
1084 #ifdef L_clear_cache
1085 /* Clear part of an instruction cache. */
1087 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1090 __clear_cache (beg, end)
1093 #ifdef INSN_CACHE_SIZE
1094 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1095 static int initialized = 0;
1097 unsigned int start_addr, end_addr;
1098 typedef (*function_ptr) ();
1100 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1101 /* It's cheaper to clear the whole cache.
1102 Put in a series of jump instructions so that calling the beginning
1103 of the cache will clear the whole thing. */
1107 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1108 & -INSN_CACHE_LINE_WIDTH);
1109 int end_ptr = ptr + INSN_CACHE_SIZE;
1111 while (ptr < end_ptr)
1113 *(INSTRUCTION_TYPE *)ptr
1114 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1115 ptr += INSN_CACHE_LINE_WIDTH;
1117 *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1122 /* Call the beginning of the sequence. */
1123 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1124 & -INSN_CACHE_LINE_WIDTH))
1127 #else /* Cache is large. */
1131 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1132 & -INSN_CACHE_LINE_WIDTH);
1134 while (ptr < (int) array + sizeof array)
1136 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1137 ptr += INSN_CACHE_LINE_WIDTH;
1143 /* Find the location in array that occupies the same cache line as BEG. */
1145 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1146 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1147 & -INSN_CACHE_PLANE_SIZE)
1150 /* Compute the cache alignment of the place to stop clearing. */
1151 #if 0 /* This is not needed for gcc's purposes. */
1152 /* If the block to clear is bigger than a cache plane,
1153 we clear the entire cache, and OFFSET is already correct. */
1154 if (end < beg + INSN_CACHE_PLANE_SIZE)
1156 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1157 & -INSN_CACHE_LINE_WIDTH)
1158 & (INSN_CACHE_PLANE_SIZE - 1));
1160 #if INSN_CACHE_DEPTH > 1
1161 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1162 if (end_addr <= start_addr)
1163 end_addr += INSN_CACHE_PLANE_SIZE;
1165 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1167 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1168 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1170 while (addr != stop)
1172 /* Call the return instruction at ADDR. */
1173 ((function_ptr) addr) ();
1175 addr += INSN_CACHE_LINE_WIDTH;
1178 #else /* just one plane */
1181 /* Call the return instruction at START_ADDR. */
1182 ((function_ptr) start_addr) ();
1184 start_addr += INSN_CACHE_LINE_WIDTH;
1186 while ((start_addr % INSN_CACHE_SIZE) != offset);
1187 #endif /* just one plane */
1188 #endif /* Cache is large */
1189 #endif /* Cache exists */
1192 #endif /* L_clear_cache */
1196 /* Jump to a trampoline, loading the static chain address. */
1198 #ifdef TRANSFER_FROM_TRAMPOLINE
1199 TRANSFER_FROM_TRAMPOLINE
1204 /* Make stack executable so we can call trampolines on stack.
1205 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
1207 #include <sys/mman.h>
1208 #include <sys/vmparam.h>
1209 #include <machine/machparam.h>
1212 __enable_execute_stack ()
1215 static unsigned lowest = USRSTACK;
1216 unsigned current = (unsigned) &fp & -NBPG;
1218 if (lowest > current)
1220 unsigned len = lowest - current;
1221 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1225 /* Clear instruction cache in case an old trampoline is in it. */
1228 #endif /* __convex__ */
1233 #include <sys/mman.h>
1234 #include <sys/types.h>
1235 #include <sys/param.h>
1236 #include <sys/vmmac.h>
1238 /* Modified from the convex -code above.
1239 mremap promises to clear the i-cache. */
1242 __enable_execute_stack ()
1245 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
1246 PROT_READ|PROT_WRITE|PROT_EXEC))
1248 perror ("mprotect in __enable_execute_stack");
1253 #endif /* __pyr__ */
1254 #endif /* L_trampoline */
1258 #include "gbl-ctors.h"
1260 /* Run all the global destructors on exit from the program. */
1263 __do_global_dtors ()
1265 #ifdef DO_GLOBAL_DTORS_BODY
1266 DO_GLOBAL_DTORS_BODY;
1268 int nptrs = *(int *)__DTOR_LIST__;
1271 /* Some systems place the number of pointers
1272 in the first word of the table.
1273 On other systems, that word is -1.
1274 In all cases, the table is null-terminated. */
1276 /* If the length is not recorded, count up to the null. */
1278 for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
1280 /* GNU LD format. */
1281 for (i = nptrs; i >= 1; i--)
1282 __DTOR_LIST__[i] ();
1286 #ifndef INIT_SECTION_ASM_OP
1287 /* Run all the global constructors on entry to the program. */
1290 #define ON_EXIT(a, b)
1292 /* Make sure the exit routine is pulled in to define the globals as
1293 bss symbols, just in case the linker does not automatically pull
1294 bss definitions from the library. */
1296 extern int _exit_dummy_decl;
1297 int *_exit_dummy_ref = &_exit_dummy_decl;
1298 #endif /* ON_EXIT */
1301 __do_global_ctors ()
1303 DO_GLOBAL_CTORS_BODY;
1304 ON_EXIT (__do_global_dtors, 0);
1306 #endif /* no INIT_SECTION_ASM_OP */
1308 #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
1309 /* Subroutine called automatically by `main'.
1310 Compiling a global function named `main'
1311 produces an automatic call to this function at the beginning.
1313 For many systems, this routine calls __do_global_ctors.
1314 For systems which support a .init section we use the .init section
1315 to run __do_global_ctors, so we need not do anything here. */
1320 /* Support recursive calls to `main': run initializers just once. */
1321 static initialized = 0;
1325 __do_global_ctors ();
1328 #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
1330 #endif /* L__main */
1334 #include "gbl-ctors.h"
1336 /* Provide default definitions for the lists of constructors and
1337 destructors, so that we don't get linker errors. These symbols are
1338 intentionally bss symbols, so that gld and/or collect will provide
1339 the right values. */
1341 /* We declare the lists here with two elements each,
1342 so that they are valid empty lists if no other definition is loaded. */
1343 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
1344 func_ptr __CTOR_LIST__[2];
1345 func_ptr __DTOR_LIST__[2];
1346 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
1350 /* If we have no known way of registering our own __do_global_dtors
1351 routine so that it will be invoked at program exit time, then we
1352 have to define our own exit routine which will get this to happen. */
1354 extern void __do_global_dtors ();
1355 extern void _cleanup ();
1356 extern void _exit ();
1362 __do_global_dtors ();
1372 int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
1377 /* In a.out systems, we need to have these dummy constructor and destructor
1378 lists in the library.
1380 When using `collect', the first link will resolve __CTOR_LIST__
1381 and __DTOR_LIST__ to these symbols. We will then run "nm" on the
1382 result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink.
1383 Since we don't do the second link if no constructors existed, these
1384 dummies must be fully functional empty lists.
1386 When using `gnu ld', these symbols will be used if there are no
1387 constructors. If there are constructors, the N_SETV symbol defined
1388 by the linker from the N_SETT's in input files will define __CTOR_LIST__
1389 and __DTOR_LIST__ rather than its being allocated as common storage
1390 by the definitions below.
1392 When using a linker that supports constructor and destructor segments,
1393 these definitions will not be used, since crtbegin.o and crtend.o
1394 (from crtstuff.c) will have already defined __CTOR_LIST__ and
1395 __DTOR_LIST__. The crt*.o files are passed directly to the linker
1396 on its command line, by gcc. */
1398 /* The list needs two elements: one is ignored (the old count); the
1399 second is the terminating zero. Since both values are zero, this
1400 declaration is not initialized, and it becomes `common'. */
1403 #include "gbl-ctors.h"
1404 func_ptr __CTOR_LIST__[2];
1408 #include "gbl-ctors.h"
1409 func_ptr __DTOR_LIST__[2];