* doc/gcc.texi, doc/install.texi, doc/invoke.texi: Remove trailing
[official-gcc.git] / gcc / libgcc2.c
blob0c42ac6e2db2563254dd778f3cdc2232958b6c47
1 /* More subroutines needed by GCC output code on some machines. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4 2000, 2001 Free Software Foundation, Inc.
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 In addition to the permissions in the GNU General Public License, the
14 Free Software Foundation gives you unlimited permission to link the
15 compiled version of this file into combinations with other programs,
16 and to distribute those combinations without any restriction coming
17 from the use of this file. (The General Public License restrictions
18 do apply in other respects; for example, they cover modification of
19 the file, and distribution when not linked into a combine
20 executable.)
22 GNU CC is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with GNU CC; see the file COPYING. If not, write to
29 the Free Software Foundation, 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA. */
32 /* It is incorrect to include config.h here, because this file is being
33 compiled for the target, and hence definitions concerning only the host
34 do not apply. */
36 #include "tconfig.h"
37 #include "tsystem.h"
39 #include "machmode.h"
41 /* Don't use `fancy_abort' here even if config.h says to use it. */
42 #ifdef abort
43 #undef abort
44 #endif
46 #include "libgcc2.h"
48 #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
49 #if defined (L_divdi3) || defined (L_moddi3)
50 static inline
51 #endif
52 DWtype
53 __negdi2 (DWtype u)
55 DWunion w;
56 DWunion uu;
58 uu.ll = u;
60 w.s.low = -uu.s.low;
61 w.s.high = -uu.s.high - ((UWtype) w.s.low > 0);
63 return w.ll;
65 #endif
67 #ifdef L_addvsi3
68 Wtype
69 __addvsi3 (Wtype a, Wtype b)
71 Wtype w;
73 w = a + b;
75 if (b >= 0 ? w < a : w > a)
76 abort ();
78 return w;
80 #endif
82 #ifdef L_addvdi3
83 DWtype
84 __addvdi3 (DWtype a, DWtype b)
86 DWtype w;
88 w = a + b;
90 if (b >= 0 ? w < a : w > a)
91 abort ();
93 return w;
95 #endif
97 #ifdef L_subvsi3
98 Wtype
99 __subvsi3 (Wtype a, Wtype b)
101 #ifdef L_addvsi3
102 return __addvsi3 (a, (-b));
103 #else
104 DWtype w;
106 w = a - b;
108 if (b >= 0 ? w > a : w < a)
109 abort ();
111 return w;
112 #endif
114 #endif
116 #ifdef L_subvdi3
117 DWtype
118 __subvdi3 (DWtype a, DWtype b)
120 #ifdef L_addvdi3
121 return (a, (-b));
122 #else
123 DWtype w;
125 w = a - b;
127 if (b >= 0 ? w > a : w < a)
128 abort ();
130 return w;
131 #endif
133 #endif
135 #ifdef L_mulvsi3
136 Wtype
137 __mulvsi3 (Wtype a, Wtype b)
139 DWtype w;
141 w = a * b;
143 if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0)
144 abort ();
146 return w;
148 #endif
150 #ifdef L_negvsi2
151 Wtype
152 __negvsi2 (Wtype a)
154 Wtype w;
156 w = -a;
158 if (a >= 0 ? w > 0 : w < 0)
159 abort ();
161 return w;
163 #endif
165 #ifdef L_negvdi2
166 DWtype
167 __negvdi2 (DWtype a)
169 DWtype w;
171 w = -a;
173 if (a >= 0 ? w > 0 : w < 0)
174 abort ();
176 return w;
178 #endif
180 #ifdef L_absvsi2
181 Wtype
182 __absvsi2 (Wtype a)
184 Wtype w = a;
186 if (a < 0)
187 #ifdef L_negvsi2
188 w = __negvsi2 (a);
189 #else
190 w = -a;
192 if (w < 0)
193 abort ();
194 #endif
196 return w;
198 #endif
200 #ifdef L_absvdi2
201 DWtype
202 __absvdi2 (DWtype a)
204 DWtype w = a;
206 if (a < 0)
207 #ifdef L_negvsi2
208 w = __negvsi2 (a);
209 #else
210 w = -a;
212 if (w < 0)
213 abort ();
214 #endif
216 return w;
218 #endif
220 #ifdef L_mulvdi3
221 DWtype
222 __mulvdi3 (DWtype u, DWtype v)
224 DWtype w;
226 w = u * v;
228 if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0)
229 abort ();
231 return w;
233 #endif
236 /* Unless shift functions are defined whith full ANSI prototypes,
237 parameter b will be promoted to int if word_type is smaller than an int. */
238 #ifdef L_lshrdi3
239 DWtype
240 __lshrdi3 (DWtype u, word_type b)
242 DWunion w;
243 word_type bm;
244 DWunion uu;
246 if (b == 0)
247 return u;
249 uu.ll = u;
251 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
252 if (bm <= 0)
254 w.s.high = 0;
255 w.s.low = (UWtype) uu.s.high >> -bm;
257 else
259 UWtype carries = (UWtype) uu.s.high << bm;
261 w.s.high = (UWtype) uu.s.high >> b;
262 w.s.low = ((UWtype) uu.s.low >> b) | carries;
265 return w.ll;
267 #endif
269 #ifdef L_ashldi3
270 DWtype
271 __ashldi3 (DWtype u, word_type b)
273 DWunion w;
274 word_type bm;
275 DWunion uu;
277 if (b == 0)
278 return u;
280 uu.ll = u;
282 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
283 if (bm <= 0)
285 w.s.low = 0;
286 w.s.high = (UWtype) uu.s.low << -bm;
288 else
290 UWtype carries = (UWtype) uu.s.low >> bm;
292 w.s.low = (UWtype) uu.s.low << b;
293 w.s.high = ((UWtype) uu.s.high << b) | carries;
296 return w.ll;
298 #endif
300 #ifdef L_ashrdi3
301 DWtype
302 __ashrdi3 (DWtype u, word_type b)
304 DWunion w;
305 word_type bm;
306 DWunion uu;
308 if (b == 0)
309 return u;
311 uu.ll = u;
313 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
314 if (bm <= 0)
316 /* w.s.high = 1..1 or 0..0 */
317 w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1);
318 w.s.low = uu.s.high >> -bm;
320 else
322 UWtype carries = (UWtype) uu.s.high << bm;
324 w.s.high = uu.s.high >> b;
325 w.s.low = ((UWtype) uu.s.low >> b) | carries;
328 return w.ll;
330 #endif
332 #ifdef L_ffsdi2
333 DWtype
334 __ffsdi2 (DWtype u)
336 DWunion uu;
337 UWtype word, count, add;
339 uu.ll = u;
340 if (uu.s.low != 0)
341 word = uu.s.low, add = 0;
342 else if (uu.s.high != 0)
343 word = uu.s.high, add = BITS_PER_UNIT * sizeof (Wtype);
344 else
345 return 0;
347 count_trailing_zeros (count, word);
348 return count + add + 1;
350 #endif
352 #ifdef L_muldi3
353 DWtype
354 __muldi3 (DWtype u, DWtype v)
356 DWunion w;
357 DWunion uu, vv;
359 uu.ll = u,
360 vv.ll = v;
362 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
363 w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
364 + (UWtype) uu.s.high * (UWtype) vv.s.low);
366 return w.ll;
368 #endif
370 #ifdef L_udiv_w_sdiv
371 #if defined (sdiv_qrnnd)
372 UWtype
373 __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
375 UWtype q, r;
376 UWtype c0, c1, b1;
378 if ((Wtype) d >= 0)
380 if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
382 /* dividend, divisor, and quotient are nonnegative */
383 sdiv_qrnnd (q, r, a1, a0, d);
385 else
387 /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
388 sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
389 /* Divide (c1*2^32 + c0) by d */
390 sdiv_qrnnd (q, r, c1, c0, d);
391 /* Add 2^31 to quotient */
392 q += (UWtype) 1 << (W_TYPE_SIZE - 1);
395 else
397 b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
398 c1 = a1 >> 1; /* A/2 */
399 c0 = (a1 << (W_TYPE_SIZE - 1)) + (a0 >> 1);
401 if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
403 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
405 r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
406 if ((d & 1) != 0)
408 if (r >= q)
409 r = r - q;
410 else if (q - r <= d)
412 r = r - q + d;
413 q--;
415 else
417 r = r - q + 2*d;
418 q -= 2;
422 else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
424 c1 = (b1 - 1) - c1;
425 c0 = ~c0; /* logical NOT */
427 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
429 q = ~q; /* (A/2)/b1 */
430 r = (b1 - 1) - r;
432 r = 2*r + (a0 & 1); /* A/(2*b1) */
434 if ((d & 1) != 0)
436 if (r >= q)
437 r = r - q;
438 else if (q - r <= d)
440 r = r - q + d;
441 q--;
443 else
445 r = r - q + 2*d;
446 q -= 2;
450 else /* Implies c1 = b1 */
451 { /* Hence a1 = d - 1 = 2*b1 - 1 */
452 if (a0 >= -d)
454 q = -1;
455 r = a0 + d;
457 else
459 q = -2;
460 r = a0 + 2*d;
465 *rp = r;
466 return q;
468 #else
469 /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
470 UWtype
471 __udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
472 UWtype a1 __attribute__ ((__unused__)),
473 UWtype a0 __attribute__ ((__unused__)),
474 UWtype d __attribute__ ((__unused__)))
476 return 0;
478 #endif
479 #endif
481 #if (defined (L_udivdi3) || defined (L_divdi3) || \
482 defined (L_umoddi3) || defined (L_moddi3))
483 #define L_udivmoddi4
484 #endif
486 #ifdef L_clz
487 const UQItype __clz_tab[] =
489 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,
490 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,
491 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,
492 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,
493 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,
494 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,
495 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,
496 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,
498 #endif
500 #ifdef L_udivmoddi4
502 #if (defined (L_udivdi3) || defined (L_divdi3) || \
503 defined (L_umoddi3) || defined (L_moddi3))
504 static inline
505 #endif
506 UDWtype
507 __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
509 DWunion ww;
510 DWunion nn, dd;
511 DWunion rr;
512 UWtype d0, d1, n0, n1, n2;
513 UWtype q0, q1;
514 UWtype b, bm;
516 nn.ll = n;
517 dd.ll = d;
519 d0 = dd.s.low;
520 d1 = dd.s.high;
521 n0 = nn.s.low;
522 n1 = nn.s.high;
524 #if !UDIV_NEEDS_NORMALIZATION
525 if (d1 == 0)
527 if (d0 > n1)
529 /* 0q = nn / 0D */
531 udiv_qrnnd (q0, n0, n1, n0, d0);
532 q1 = 0;
534 /* Remainder in n0. */
536 else
538 /* qq = NN / 0d */
540 if (d0 == 0)
541 d0 = 1 / d0; /* Divide intentionally by zero. */
543 udiv_qrnnd (q1, n1, 0, n1, d0);
544 udiv_qrnnd (q0, n0, n1, n0, d0);
546 /* Remainder in n0. */
549 if (rp != 0)
551 rr.s.low = n0;
552 rr.s.high = 0;
553 *rp = rr.ll;
557 #else /* UDIV_NEEDS_NORMALIZATION */
559 if (d1 == 0)
561 if (d0 > n1)
563 /* 0q = nn / 0D */
565 count_leading_zeros (bm, d0);
567 if (bm != 0)
569 /* Normalize, i.e. make the most significant bit of the
570 denominator set. */
572 d0 = d0 << bm;
573 n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
574 n0 = n0 << bm;
577 udiv_qrnnd (q0, n0, n1, n0, d0);
578 q1 = 0;
580 /* Remainder in n0 >> bm. */
582 else
584 /* qq = NN / 0d */
586 if (d0 == 0)
587 d0 = 1 / d0; /* Divide intentionally by zero. */
589 count_leading_zeros (bm, d0);
591 if (bm == 0)
593 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
594 conclude (the most significant bit of n1 is set) /\ (the
595 leading quotient digit q1 = 1).
597 This special case is necessary, not an optimization.
598 (Shifts counts of W_TYPE_SIZE are undefined.) */
600 n1 -= d0;
601 q1 = 1;
603 else
605 /* Normalize. */
607 b = W_TYPE_SIZE - bm;
609 d0 = d0 << bm;
610 n2 = n1 >> b;
611 n1 = (n1 << bm) | (n0 >> b);
612 n0 = n0 << bm;
614 udiv_qrnnd (q1, n1, n2, n1, d0);
617 /* n1 != d0... */
619 udiv_qrnnd (q0, n0, n1, n0, d0);
621 /* Remainder in n0 >> bm. */
624 if (rp != 0)
626 rr.s.low = n0 >> bm;
627 rr.s.high = 0;
628 *rp = rr.ll;
631 #endif /* UDIV_NEEDS_NORMALIZATION */
633 else
635 if (d1 > n1)
637 /* 00 = nn / DD */
639 q0 = 0;
640 q1 = 0;
642 /* Remainder in n1n0. */
643 if (rp != 0)
645 rr.s.low = n0;
646 rr.s.high = n1;
647 *rp = rr.ll;
650 else
652 /* 0q = NN / dd */
654 count_leading_zeros (bm, d1);
655 if (bm == 0)
657 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
658 conclude (the most significant bit of n1 is set) /\ (the
659 quotient digit q0 = 0 or 1).
661 This special case is necessary, not an optimization. */
663 /* The condition on the next line takes advantage of that
664 n1 >= d1 (true due to program flow). */
665 if (n1 > d1 || n0 >= d0)
667 q0 = 1;
668 sub_ddmmss (n1, n0, n1, n0, d1, d0);
670 else
671 q0 = 0;
673 q1 = 0;
675 if (rp != 0)
677 rr.s.low = n0;
678 rr.s.high = n1;
679 *rp = rr.ll;
682 else
684 UWtype m1, m0;
685 /* Normalize. */
687 b = W_TYPE_SIZE - bm;
689 d1 = (d1 << bm) | (d0 >> b);
690 d0 = d0 << bm;
691 n2 = n1 >> b;
692 n1 = (n1 << bm) | (n0 >> b);
693 n0 = n0 << bm;
695 udiv_qrnnd (q0, n1, n2, n1, d1);
696 umul_ppmm (m1, m0, q0, d0);
698 if (m1 > n1 || (m1 == n1 && m0 > n0))
700 q0--;
701 sub_ddmmss (m1, m0, m1, m0, d1, d0);
704 q1 = 0;
706 /* Remainder in (n1n0 - m1m0) >> bm. */
707 if (rp != 0)
709 sub_ddmmss (n1, n0, n1, n0, m1, m0);
710 rr.s.low = (n1 << b) | (n0 >> bm);
711 rr.s.high = n1 >> bm;
712 *rp = rr.ll;
718 ww.s.low = q0;
719 ww.s.high = q1;
720 return ww.ll;
722 #endif
724 #ifdef L_divdi3
725 DWtype
726 __divdi3 (DWtype u, DWtype v)
728 word_type c = 0;
729 DWunion uu, vv;
730 DWtype w;
732 uu.ll = u;
733 vv.ll = v;
735 if (uu.s.high < 0)
736 c = ~c,
737 uu.ll = __negdi2 (uu.ll);
738 if (vv.s.high < 0)
739 c = ~c,
740 vv.ll = __negdi2 (vv.ll);
742 w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
743 if (c)
744 w = __negdi2 (w);
746 return w;
748 #endif
750 #ifdef L_moddi3
751 DWtype
752 __moddi3 (DWtype u, DWtype v)
754 word_type c = 0;
755 DWunion uu, vv;
756 DWtype w;
758 uu.ll = u;
759 vv.ll = v;
761 if (uu.s.high < 0)
762 c = ~c,
763 uu.ll = __negdi2 (uu.ll);
764 if (vv.s.high < 0)
765 vv.ll = __negdi2 (vv.ll);
767 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
768 if (c)
769 w = __negdi2 (w);
771 return w;
773 #endif
775 #ifdef L_umoddi3
776 UDWtype
777 __umoddi3 (UDWtype u, UDWtype v)
779 UDWtype w;
781 (void) __udivmoddi4 (u, v, &w);
783 return w;
785 #endif
787 #ifdef L_udivdi3
788 UDWtype
789 __udivdi3 (UDWtype n, UDWtype d)
791 return __udivmoddi4 (n, d, (UDWtype *) 0);
793 #endif
795 #ifdef L_cmpdi2
796 word_type
797 __cmpdi2 (DWtype a, DWtype b)
799 DWunion au, bu;
801 au.ll = a, bu.ll = b;
803 if (au.s.high < bu.s.high)
804 return 0;
805 else if (au.s.high > bu.s.high)
806 return 2;
807 if ((UWtype) au.s.low < (UWtype) bu.s.low)
808 return 0;
809 else if ((UWtype) au.s.low > (UWtype) bu.s.low)
810 return 2;
811 return 1;
813 #endif
815 #ifdef L_ucmpdi2
816 word_type
817 __ucmpdi2 (DWtype a, DWtype b)
819 DWunion au, bu;
821 au.ll = a, bu.ll = b;
823 if ((UWtype) au.s.high < (UWtype) bu.s.high)
824 return 0;
825 else if ((UWtype) au.s.high > (UWtype) bu.s.high)
826 return 2;
827 if ((UWtype) au.s.low < (UWtype) bu.s.low)
828 return 0;
829 else if ((UWtype) au.s.low > (UWtype) bu.s.low)
830 return 2;
831 return 1;
833 #endif
835 #if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
836 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
837 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
839 DWtype
840 __fixunstfDI (TFtype a)
842 TFtype b;
843 UDWtype v;
845 if (a < 0)
846 return 0;
848 /* Compute high word of result, as a flonum. */
849 b = (a / HIGH_WORD_COEFF);
850 /* Convert that to fixed (but not to DWtype!),
851 and shift it into the high word. */
852 v = (UWtype) b;
853 v <<= WORD_SIZE;
854 /* Remove high part from the TFtype, leaving the low part as flonum. */
855 a -= (TFtype)v;
856 /* Convert that to fixed (but not to DWtype!) and add it in.
857 Sometimes A comes out negative. This is significant, since
858 A has more bits than a long int does. */
859 if (a < 0)
860 v -= (UWtype) (- a);
861 else
862 v += (UWtype) a;
863 return v;
865 #endif
867 #if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
868 DWtype
869 __fixtfdi (TFtype a)
871 if (a < 0)
872 return - __fixunstfDI (-a);
873 return __fixunstfDI (a);
875 #endif
877 #if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
878 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
879 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
881 DWtype
882 __fixunsxfDI (XFtype a)
884 XFtype b;
885 UDWtype v;
887 if (a < 0)
888 return 0;
890 /* Compute high word of result, as a flonum. */
891 b = (a / HIGH_WORD_COEFF);
892 /* Convert that to fixed (but not to DWtype!),
893 and shift it into the high word. */
894 v = (UWtype) b;
895 v <<= WORD_SIZE;
896 /* Remove high part from the XFtype, leaving the low part as flonum. */
897 a -= (XFtype)v;
898 /* Convert that to fixed (but not to DWtype!) and add it in.
899 Sometimes A comes out negative. This is significant, since
900 A has more bits than a long int does. */
901 if (a < 0)
902 v -= (UWtype) (- a);
903 else
904 v += (UWtype) a;
905 return v;
907 #endif
909 #if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
910 DWtype
911 __fixxfdi (XFtype a)
913 if (a < 0)
914 return - __fixunsxfDI (-a);
915 return __fixunsxfDI (a);
917 #endif
919 #ifdef L_fixunsdfdi
920 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
921 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
923 DWtype
924 __fixunsdfDI (DFtype a)
926 DFtype b;
927 UDWtype v;
929 if (a < 0)
930 return 0;
932 /* Compute high word of result, as a flonum. */
933 b = (a / HIGH_WORD_COEFF);
934 /* Convert that to fixed (but not to DWtype!),
935 and shift it into the high word. */
936 v = (UWtype) b;
937 v <<= WORD_SIZE;
938 /* Remove high part from the DFtype, leaving the low part as flonum. */
939 a -= (DFtype)v;
940 /* Convert that to fixed (but not to DWtype!) and add it in.
941 Sometimes A comes out negative. This is significant, since
942 A has more bits than a long int does. */
943 if (a < 0)
944 v -= (UWtype) (- a);
945 else
946 v += (UWtype) a;
947 return v;
949 #endif
951 #ifdef L_fixdfdi
952 DWtype
953 __fixdfdi (DFtype a)
955 if (a < 0)
956 return - __fixunsdfDI (-a);
957 return __fixunsdfDI (a);
959 #endif
961 #ifdef L_fixunssfdi
962 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
963 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
965 DWtype
966 __fixunssfDI (SFtype original_a)
968 /* Convert the SFtype to a DFtype, because that is surely not going
969 to lose any bits. Some day someone else can write a faster version
970 that avoids converting to DFtype, and verify it really works right. */
971 DFtype a = original_a;
972 DFtype b;
973 UDWtype v;
975 if (a < 0)
976 return 0;
978 /* Compute high word of result, as a flonum. */
979 b = (a / HIGH_WORD_COEFF);
980 /* Convert that to fixed (but not to DWtype!),
981 and shift it into the high word. */
982 v = (UWtype) b;
983 v <<= WORD_SIZE;
984 /* Remove high part from the DFtype, leaving the low part as flonum. */
985 a -= (DFtype) v;
986 /* Convert that to fixed (but not to DWtype!) and add it in.
987 Sometimes A comes out negative. This is significant, since
988 A has more bits than a long int does. */
989 if (a < 0)
990 v -= (UWtype) (- a);
991 else
992 v += (UWtype) a;
993 return v;
995 #endif
997 #ifdef L_fixsfdi
998 DWtype
999 __fixsfdi (SFtype a)
1001 if (a < 0)
1002 return - __fixunssfDI (-a);
1003 return __fixunssfDI (a);
1005 #endif
1007 #if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
1008 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1009 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1010 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1012 XFtype
1013 __floatdixf (DWtype u)
1015 XFtype d;
1017 d = (Wtype) (u >> WORD_SIZE);
1018 d *= HIGH_HALFWORD_COEFF;
1019 d *= HIGH_HALFWORD_COEFF;
1020 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1022 return d;
1024 #endif
1026 #if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
1027 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1028 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1029 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1031 TFtype
1032 __floatditf (DWtype u)
1034 TFtype d;
1036 d = (Wtype) (u >> WORD_SIZE);
1037 d *= HIGH_HALFWORD_COEFF;
1038 d *= HIGH_HALFWORD_COEFF;
1039 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1041 return d;
1043 #endif
1045 #ifdef L_floatdidf
1046 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1047 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1048 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1050 DFtype
1051 __floatdidf (DWtype u)
1053 DFtype d;
1055 d = (Wtype) (u >> WORD_SIZE);
1056 d *= HIGH_HALFWORD_COEFF;
1057 d *= HIGH_HALFWORD_COEFF;
1058 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1060 return d;
1062 #endif
1064 #ifdef L_floatdisf
1065 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1066 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1067 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1068 #define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
1070 /* Define codes for all the float formats that we know of. Note
1071 that this is copied from real.h. */
1073 #define UNKNOWN_FLOAT_FORMAT 0
1074 #define IEEE_FLOAT_FORMAT 1
1075 #define VAX_FLOAT_FORMAT 2
1076 #define IBM_FLOAT_FORMAT 3
1078 /* Default to IEEE float if not specified. Nearly all machines use it. */
1079 #ifndef HOST_FLOAT_FORMAT
1080 #define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
1081 #endif
1083 #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
1084 #define DF_SIZE 53
1085 #define SF_SIZE 24
1086 #endif
1088 #if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
1089 #define DF_SIZE 56
1090 #define SF_SIZE 24
1091 #endif
1093 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
1094 #define DF_SIZE 56
1095 #define SF_SIZE 24
1096 #endif
1098 SFtype
1099 __floatdisf (DWtype u)
1101 /* Do the calculation in DFmode
1102 so that we don't lose any of the precision of the high word
1103 while multiplying it. */
1104 DFtype f;
1106 /* Protect against double-rounding error.
1107 Represent any low-order bits, that might be truncated in DFmode,
1108 by a bit that won't be lost. The bit can go in anywhere below the
1109 rounding position of the SFmode. A fixed mask and bit position
1110 handles all usual configurations. It doesn't handle the case
1111 of 128-bit DImode, however. */
1112 if (DF_SIZE < DI_SIZE
1113 && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1115 #define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
1116 if (! (- ((DWtype) 1 << DF_SIZE) < u
1117 && u < ((DWtype) 1 << DF_SIZE)))
1119 if ((UDWtype) u & (REP_BIT - 1))
1120 u |= REP_BIT;
1123 f = (Wtype) (u >> WORD_SIZE);
1124 f *= HIGH_HALFWORD_COEFF;
1125 f *= HIGH_HALFWORD_COEFF;
1126 f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1128 return (SFtype) f;
1130 #endif
1132 #if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
1133 /* Reenable the normal types, in case limits.h needs them. */
1134 #undef char
1135 #undef short
1136 #undef int
1137 #undef long
1138 #undef unsigned
1139 #undef float
1140 #undef double
1141 #undef MIN
1142 #undef MAX
1143 #include <limits.h>
1145 UWtype
1146 __fixunsxfSI (XFtype a)
1148 if (a >= - (DFtype) Wtype_MIN)
1149 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1150 return (Wtype) a;
1152 #endif
1154 #ifdef L_fixunsdfsi
1155 /* Reenable the normal types, in case limits.h needs them. */
1156 #undef char
1157 #undef short
1158 #undef int
1159 #undef long
1160 #undef unsigned
1161 #undef float
1162 #undef double
1163 #undef MIN
1164 #undef MAX
1165 #include <limits.h>
1167 UWtype
1168 __fixunsdfSI (DFtype a)
1170 if (a >= - (DFtype) Wtype_MIN)
1171 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1172 return (Wtype) a;
1174 #endif
1176 #ifdef L_fixunssfsi
1177 /* Reenable the normal types, in case limits.h needs them. */
1178 #undef char
1179 #undef short
1180 #undef int
1181 #undef long
1182 #undef unsigned
1183 #undef float
1184 #undef double
1185 #undef MIN
1186 #undef MAX
1187 #include <limits.h>
1189 UWtype
1190 __fixunssfSI (SFtype a)
1192 if (a >= - (SFtype) Wtype_MIN)
1193 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1194 return (Wtype) a;
1196 #endif
1198 /* From here on down, the routines use normal data types. */
1200 #define SItype bogus_type
1201 #define USItype bogus_type
1202 #define DItype bogus_type
1203 #define UDItype bogus_type
1204 #define SFtype bogus_type
1205 #define DFtype bogus_type
1206 #undef Wtype
1207 #undef UWtype
1208 #undef HWtype
1209 #undef UHWtype
1210 #undef DWtype
1211 #undef UDWtype
1213 #undef char
1214 #undef short
1215 #undef int
1216 #undef long
1217 #undef unsigned
1218 #undef float
1219 #undef double
1221 #ifdef L__gcc_bcmp
1223 /* Like bcmp except the sign is meaningful.
1224 Result is negative if S1 is less than S2,
1225 positive if S1 is greater, 0 if S1 and S2 are equal. */
1228 __gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
1230 while (size > 0)
1232 unsigned char c1 = *s1++, c2 = *s2++;
1233 if (c1 != c2)
1234 return c1 - c2;
1235 size--;
1237 return 0;
1240 #endif
1242 /* __eprintf used to be used by GCC's private version of <assert.h>.
1243 We no longer provide that header, but this routine remains in libgcc.a
1244 for binary backward compatibility. Note that it is not included in
1245 the shared version of libgcc. */
1246 #ifdef L_eprintf
1247 #ifndef inhibit_libc
1249 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1250 #include <stdio.h>
1252 void
1253 __eprintf (const char *string, const char *expression,
1254 unsigned int line, const char *filename)
1256 fprintf (stderr, string, expression, line, filename);
1257 fflush (stderr);
1258 abort ();
1261 #endif
1262 #endif
1264 #ifdef L_bb
1266 #if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
1267 typedef long gcov_type;
1268 #else
1269 typedef long long gcov_type;
1270 #endif
1273 /* Structure emitted by -a */
1274 struct bb
1276 long zero_word;
1277 const char *filename;
1278 gcov_type *counts;
1279 long ncounts;
1280 struct bb *next;
1281 const unsigned long *addresses;
1283 /* Older GCC's did not emit these fields. */
1284 long nwords;
1285 const char **functions;
1286 const long *line_nums;
1287 const char **filenames;
1288 char *flags;
1291 #ifdef BLOCK_PROFILER_CODE
1292 BLOCK_PROFILER_CODE
1293 #else
1294 #ifndef inhibit_libc
1296 /* Simple minded basic block profiling output dumper for
1297 systems that don't provide tcov support. At present,
1298 it requires atexit and stdio. */
1300 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1301 #include <stdio.h>
1302 char *ctime PARAMS ((const time_t *));
1304 #include "gbl-ctors.h"
1305 #include "gcov-io.h"
1306 #include <string.h>
1307 #ifdef TARGET_HAS_F_SETLKW
1308 #include <fcntl.h>
1309 #include <errno.h>
1310 #endif
1312 static struct bb *bb_head;
1314 static int num_digits (long value, int base) __attribute__ ((const));
1316 /* Return the number of digits needed to print a value */
1317 /* __inline__ */ static int num_digits (long value, int base)
1319 int minus = (value < 0 && base != 16);
1320 unsigned long v = (minus) ? -value : value;
1321 int ret = minus;
1325 v /= base;
1326 ret++;
1328 while (v);
1330 return ret;
1333 void
1334 __bb_exit_func (void)
1336 FILE *da_file, *file;
1337 long time_value;
1338 int i;
1340 if (bb_head == 0)
1341 return;
1343 i = strlen (bb_head->filename) - 3;
1345 if (!strcmp (bb_head->filename+i, ".da"))
1347 /* Must be -fprofile-arcs not -a.
1348 Dump data in a form that gcov expects. */
1350 struct bb *ptr;
1352 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1354 int firstchar;
1356 /* Make sure the output file exists -
1357 but don't clobber exiting data. */
1358 if ((da_file = fopen (ptr->filename, "a")) != 0)
1359 fclose (da_file);
1361 /* Need to re-open in order to be able to write from the start. */
1362 da_file = fopen (ptr->filename, "r+b");
1363 /* Some old systems might not allow the 'b' mode modifier.
1364 Therefore, try to open without it. This can lead to a race
1365 condition so that when you delete and re-create the file, the
1366 file might be opened in text mode, but then, you shouldn't
1367 delete the file in the first place. */
1368 if (da_file == 0)
1369 da_file = fopen (ptr->filename, "r+");
1370 if (da_file == 0)
1372 fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1373 ptr->filename);
1374 continue;
1377 /* After a fork, another process might try to read and/or write
1378 the same file simultanously. So if we can, lock the file to
1379 avoid race conditions. */
1380 #if defined (TARGET_HAS_F_SETLKW)
1382 struct flock s_flock;
1384 s_flock.l_type = F_WRLCK;
1385 s_flock.l_whence = SEEK_SET;
1386 s_flock.l_start = 0;
1387 s_flock.l_len = 1;
1388 s_flock.l_pid = getpid ();
1390 while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
1391 && errno == EINTR);
1393 #endif
1395 /* If the file is not empty, and the number of counts in it is the
1396 same, then merge them in. */
1397 firstchar = fgetc (da_file);
1398 if (firstchar == EOF)
1400 if (ferror (da_file))
1402 fprintf (stderr, "arc profiling: Can't read output file ");
1403 perror (ptr->filename);
1406 else
1408 long n_counts = 0;
1410 if (ungetc (firstchar, da_file) == EOF)
1411 rewind (da_file);
1412 if (__read_long (&n_counts, da_file, 8) != 0)
1414 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1415 ptr->filename);
1416 continue;
1419 if (n_counts == ptr->ncounts)
1421 int i;
1423 for (i = 0; i < n_counts; i++)
1425 gcov_type v = 0;
1427 if (__read_gcov_type (&v, da_file, 8) != 0)
1429 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1430 ptr->filename);
1431 break;
1433 ptr->counts[i] += v;
1439 rewind (da_file);
1441 /* ??? Should first write a header to the file. Preferably, a 4 byte
1442 magic number, 4 bytes containing the time the program was
1443 compiled, 4 bytes containing the last modification time of the
1444 source file, and 4 bytes indicating the compiler options used.
1446 That way we can easily verify that the proper source/executable/
1447 data file combination is being used from gcov. */
1449 if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0)
1452 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1453 ptr->filename);
1455 else
1457 int j;
1458 gcov_type *count_ptr = ptr->counts;
1459 int ret = 0;
1460 for (j = ptr->ncounts; j > 0; j--)
1462 if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
1464 ret=1;
1465 break;
1467 count_ptr++;
1469 if (ret)
1470 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1471 ptr->filename);
1474 if (fclose (da_file) == EOF)
1475 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1476 ptr->filename);
1479 return;
1482 /* Must be basic block profiling. Emit a human readable output file. */
1484 file = fopen ("bb.out", "a");
1486 if (!file)
1487 perror ("bb.out");
1489 else
1491 struct bb *ptr;
1493 /* This is somewhat type incorrect, but it avoids worrying about
1494 exactly where time.h is included from. It should be ok unless
1495 a void * differs from other pointer formats, or if sizeof (long)
1496 is < sizeof (time_t). It would be nice if we could assume the
1497 use of rationale standards here. */
1499 time ((void *) &time_value);
1500 fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1502 /* We check the length field explicitly in order to allow compatibility
1503 with older GCC's which did not provide it. */
1505 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1507 int i;
1508 int func_p = (ptr->nwords >= (long) sizeof (struct bb)
1509 && ptr->nwords <= 1000
1510 && ptr->functions);
1511 int line_p = (func_p && ptr->line_nums);
1512 int file_p = (func_p && ptr->filenames);
1513 int addr_p = (ptr->addresses != 0);
1514 long ncounts = ptr->ncounts;
1515 long cnt_max = 0;
1516 long line_max = 0;
1517 long addr_max = 0;
1518 int file_len = 0;
1519 int func_len = 0;
1520 int blk_len = num_digits (ncounts, 10);
1521 int cnt_len;
1522 int line_len;
1523 int addr_len;
1525 fprintf (file, "File %s, %ld basic blocks \n\n",
1526 ptr->filename, ncounts);
1528 /* Get max values for each field. */
1529 for (i = 0; i < ncounts; i++)
1531 const char *p;
1532 int len;
1534 if (cnt_max < ptr->counts[i])
1535 cnt_max = ptr->counts[i];
1537 if (addr_p && (unsigned long) addr_max < ptr->addresses[i])
1538 addr_max = ptr->addresses[i];
1540 if (line_p && line_max < ptr->line_nums[i])
1541 line_max = ptr->line_nums[i];
1543 if (func_p)
1545 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1546 len = strlen (p);
1547 if (func_len < len)
1548 func_len = len;
1551 if (file_p)
1553 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1554 len = strlen (p);
1555 if (file_len < len)
1556 file_len = len;
1560 addr_len = num_digits (addr_max, 16);
1561 cnt_len = num_digits (cnt_max, 10);
1562 line_len = num_digits (line_max, 10);
1564 /* Now print out the basic block information. */
1565 for (i = 0; i < ncounts; i++)
1567 fprintf (file,
1568 " Block #%*d: executed %*ld time(s)",
1569 blk_len, i+1,
1570 cnt_len, ptr->counts[i]);
1572 if (addr_p)
1573 fprintf (file, " address= 0x%.*lx", addr_len,
1574 ptr->addresses[i]);
1576 if (func_p)
1577 fprintf (file, " function= %-*s", func_len,
1578 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1580 if (line_p)
1581 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1583 if (file_p)
1584 fprintf (file, " file= %s",
1585 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1587 fprintf (file, "\n");
1590 fprintf (file, "\n");
1591 fflush (file);
1594 fprintf (file, "\n\n");
1595 fclose (file);
1599 void
1600 __bb_init_func (struct bb *blocks)
1602 /* User is supposed to check whether the first word is non-0,
1603 but just in case.... */
1605 if (blocks->zero_word)
1606 return;
1608 /* Initialize destructor. */
1609 if (!bb_head)
1610 atexit (__bb_exit_func);
1612 /* Set up linked list. */
1613 blocks->zero_word = 1;
1614 blocks->next = bb_head;
1615 bb_head = blocks;
1618 /* Called before fork or exec - write out profile information gathered so
1619 far and reset it to zero. This avoids duplication or loss of the
1620 profile information gathered so far. */
1621 void
1622 __bb_fork_func (void)
1624 struct bb *ptr;
1626 __bb_exit_func ();
1627 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1629 long i;
1630 for (i = ptr->ncounts - 1; i >= 0; i--)
1631 ptr->counts[i] = 0;
1635 #ifndef MACHINE_STATE_SAVE
1636 #define MACHINE_STATE_SAVE(ID)
1637 #endif
1638 #ifndef MACHINE_STATE_RESTORE
1639 #define MACHINE_STATE_RESTORE(ID)
1640 #endif
1642 /* Number of buckets in hashtable of basic block addresses. */
1644 #define BB_BUCKETS 311
1646 /* Maximum length of string in file bb.in. */
1648 #define BBINBUFSIZE 500
1650 struct bb_edge
1652 struct bb_edge *next;
1653 unsigned long src_addr;
1654 unsigned long dst_addr;
1655 unsigned long count;
1658 enum bb_func_mode
1660 TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1663 struct bb_func
1665 struct bb_func *next;
1666 char *funcname;
1667 char *filename;
1668 enum bb_func_mode mode;
1671 /* This is the connection to the outside world.
1672 The BLOCK_PROFILER macro must set __bb.blocks
1673 and __bb.blockno. */
1675 struct {
1676 unsigned long blockno;
1677 struct bb *blocks;
1678 } __bb;
1680 /* Vars to store addrs of source and destination basic blocks
1681 of a jump. */
1683 static unsigned long bb_src = 0;
1684 static unsigned long bb_dst = 0;
1686 static FILE *bb_tracefile = (FILE *) 0;
1687 static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1688 static struct bb_func *bb_func_head = (struct bb_func *) 0;
1689 static unsigned long bb_callcount = 0;
1690 static int bb_mode = 0;
1692 static unsigned long *bb_stack = (unsigned long *) 0;
1693 static size_t bb_stacksize = 0;
1695 static int reported = 0;
1697 /* Trace modes:
1698 Always : Print execution frequencies of basic blocks
1699 to file bb.out.
1700 bb_mode & 1 != 0 : Dump trace of basic blocks to file bbtrace[.gz]
1701 bb_mode & 2 != 0 : Print jump frequencies to file bb.out.
1702 bb_mode & 4 != 0 : Cut call instructions from basic block flow.
1703 bb_mode & 8 != 0 : Insert return instructions in basic block flow.
1706 #ifdef HAVE_POPEN
1708 /*#include <sys/types.h>*/
1709 #include <sys/stat.h>
1710 /*#include <malloc.h>*/
1712 /* Commands executed by gopen. */
1714 #define GOPENDECOMPRESS "gzip -cd "
1715 #define GOPENCOMPRESS "gzip -c >"
1717 /* Like fopen but pipes through gzip. mode may only be "r" or "w".
1718 If it does not compile, simply replace gopen by fopen and delete
1719 '.gz' from any first parameter to gopen. */
1721 static FILE *
1722 gopen (char *fn, char *mode)
1724 int use_gzip;
1725 char *p;
1727 if (mode[1])
1728 return (FILE *) 0;
1730 if (mode[0] != 'r' && mode[0] != 'w')
1731 return (FILE *) 0;
1733 p = fn + strlen (fn)-1;
1734 use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
1735 || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1737 if (use_gzip)
1739 if (mode[0]=='r')
1741 FILE *f;
1742 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1743 + sizeof (GOPENDECOMPRESS));
1744 strcpy (s, GOPENDECOMPRESS);
1745 strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1746 f = popen (s, mode);
1747 free (s);
1748 return f;
1751 else
1753 FILE *f;
1754 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1755 + sizeof (GOPENCOMPRESS));
1756 strcpy (s, GOPENCOMPRESS);
1757 strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1758 if (!(f = popen (s, mode)))
1759 f = fopen (s, mode);
1760 free (s);
1761 return f;
1765 else
1766 return fopen (fn, mode);
1769 static int
1770 gclose (FILE *f)
1772 struct stat buf;
1774 if (f != 0)
1776 if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1777 return pclose (f);
1779 return fclose (f);
1781 return 0;
1784 #endif /* HAVE_POPEN */
1786 /* Called once per program. */
1788 static void
1789 __bb_exit_trace_func (void)
1791 FILE *file = fopen ("bb.out", "a");
1792 struct bb_func *f;
1793 struct bb *b;
1795 if (!file)
1796 perror ("bb.out");
1798 if (bb_mode & 1)
1800 if (!bb_tracefile)
1801 perror ("bbtrace");
1802 else
1803 #ifdef HAVE_POPEN
1804 gclose (bb_tracefile);
1805 #else
1806 fclose (bb_tracefile);
1807 #endif /* HAVE_POPEN */
1810 /* Check functions in `bb.in'. */
1812 if (file)
1814 long time_value;
1815 const struct bb_func *p;
1816 int printed_something = 0;
1817 struct bb *ptr;
1818 long blk;
1820 /* This is somewhat type incorrect. */
1821 time ((void *) &time_value);
1823 for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
1825 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1827 if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
1828 continue;
1829 for (blk = 0; blk < ptr->ncounts; blk++)
1831 if (!strcmp (p->funcname, ptr->functions[blk]))
1832 goto found;
1836 if (!printed_something)
1838 fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1839 printed_something = 1;
1842 fprintf (file, "\tFunction %s", p->funcname);
1843 if (p->filename)
1844 fprintf (file, " of file %s", p->filename);
1845 fprintf (file, "\n" );
1847 found: ;
1850 if (printed_something)
1851 fprintf (file, "\n");
1855 if (bb_mode & 2)
1857 if (!bb_hashbuckets)
1859 if (!reported)
1861 fprintf (stderr, "Profiler: out of memory\n");
1862 reported = 1;
1864 return;
1867 else if (file)
1869 long time_value;
1870 int i;
1871 unsigned long addr_max = 0;
1872 unsigned long cnt_max = 0;
1873 int cnt_len;
1874 int addr_len;
1876 /* This is somewhat type incorrect, but it avoids worrying about
1877 exactly where time.h is included from. It should be ok unless
1878 a void * differs from other pointer formats, or if sizeof (long)
1879 is < sizeof (time_t). It would be nice if we could assume the
1880 use of rationale standards here. */
1882 time ((void *) &time_value);
1883 fprintf (file, "Basic block jump tracing");
1885 switch (bb_mode & 12)
1887 case 0:
1888 fprintf (file, " (with call)");
1889 break;
1891 case 4:
1892 /* Print nothing. */
1893 break;
1895 case 8:
1896 fprintf (file, " (with call & ret)");
1897 break;
1899 case 12:
1900 fprintf (file, " (with ret)");
1901 break;
1904 fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1906 for (i = 0; i < BB_BUCKETS; i++)
1908 struct bb_edge *bucket = bb_hashbuckets[i];
1909 for ( ; bucket; bucket = bucket->next )
1911 if (addr_max < bucket->src_addr)
1912 addr_max = bucket->src_addr;
1913 if (addr_max < bucket->dst_addr)
1914 addr_max = bucket->dst_addr;
1915 if (cnt_max < bucket->count)
1916 cnt_max = bucket->count;
1919 addr_len = num_digits (addr_max, 16);
1920 cnt_len = num_digits (cnt_max, 10);
1922 for ( i = 0; i < BB_BUCKETS; i++)
1924 struct bb_edge *bucket = bb_hashbuckets[i];
1925 for ( ; bucket; bucket = bucket->next )
1927 fprintf (file,
1928 "Jump from block 0x%.*lx to block 0x%.*lx executed %*lu time(s)\n",
1929 addr_len, bucket->src_addr,
1930 addr_len, bucket->dst_addr,
1931 cnt_len, bucket->count);
1935 fprintf (file, "\n");
1940 if (file)
1941 fclose (file);
1943 /* Free allocated memory. */
1945 f = bb_func_head;
1946 while (f)
1948 struct bb_func *old = f;
1950 f = f->next;
1951 if (old->funcname) free (old->funcname);
1952 if (old->filename) free (old->filename);
1953 free (old);
1956 if (bb_stack)
1957 free (bb_stack);
1959 if (bb_hashbuckets)
1961 int i;
1963 for (i = 0; i < BB_BUCKETS; i++)
1965 struct bb_edge *old, *bucket = bb_hashbuckets[i];
1967 while (bucket)
1969 old = bucket;
1970 bucket = bucket->next;
1971 free (old);
1974 free (bb_hashbuckets);
1977 for (b = bb_head; b; b = b->next)
1978 if (b->flags) free (b->flags);
1981 /* Called once per program. */
1983 static void
1984 __bb_init_prg (void)
1986 FILE *file;
1987 char buf[BBINBUFSIZE];
1988 const char *p;
1989 const char *pos;
1990 enum bb_func_mode m;
1991 int i;
1993 /* Initialize destructor. */
1994 atexit (__bb_exit_func);
1996 if (!(file = fopen ("bb.in", "r")))
1997 return;
1999 while(fgets (buf, BBINBUFSIZE, file) != 0)
2001 i = strlen (buf);
2002 if (buf[i] == '\n')
2003 buf[i--] = '\0';
2005 p = buf;
2006 if (*p == '-')
2008 m = TRACE_OFF;
2009 p++;
2011 else
2013 m = TRACE_ON;
2015 if (!strcmp (p, "__bb_trace__"))
2016 bb_mode |= 1;
2017 else if (!strcmp (p, "__bb_jumps__"))
2018 bb_mode |= 2;
2019 else if (!strcmp (p, "__bb_hidecall__"))
2020 bb_mode |= 4;
2021 else if (!strcmp (p, "__bb_showret__"))
2022 bb_mode |= 8;
2023 else
2025 struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
2026 if (f)
2028 unsigned long l;
2029 f->next = bb_func_head;
2030 if ((pos = strchr (p, ':')))
2032 if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
2033 continue;
2034 strcpy (f->funcname, pos+1);
2035 l = pos-p;
2036 if ((f->filename = (char *) malloc (l+1)))
2038 strncpy (f->filename, p, l);
2039 f->filename[l] = '\0';
2041 else
2042 f->filename = (char *) 0;
2044 else
2046 if (!(f->funcname = (char *) malloc (strlen (p)+1)))
2047 continue;
2048 strcpy (f->funcname, p);
2049 f->filename = (char *) 0;
2051 f->mode = m;
2052 bb_func_head = f;
2056 fclose (file);
2058 #ifdef HAVE_POPEN
2060 if (bb_mode & 1)
2061 bb_tracefile = gopen ("bbtrace.gz", "w");
2063 #else
2065 if (bb_mode & 1)
2066 bb_tracefile = fopen ("bbtrace", "w");
2068 #endif /* HAVE_POPEN */
2070 if (bb_mode & 2)
2072 bb_hashbuckets = (struct bb_edge **)
2073 malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2074 if (bb_hashbuckets)
2075 /* Use a loop here rather than calling bzero to avoid having to
2076 conditionalize its existance. */
2077 for (i = 0; i < BB_BUCKETS; i++)
2078 bb_hashbuckets[i] = 0;
2081 if (bb_mode & 12)
2083 bb_stacksize = 10;
2084 bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2087 /* Initialize destructor. */
2088 atexit (__bb_exit_trace_func);
2091 /* Called upon entering a basic block. */
2093 void
2094 __bb_trace_func (void)
2096 struct bb_edge *bucket;
2098 MACHINE_STATE_SAVE("1")
2100 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2101 goto skip;
2103 bb_dst = __bb.blocks->addresses[__bb.blockno];
2104 __bb.blocks->counts[__bb.blockno]++;
2106 if (bb_tracefile)
2108 fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2111 if (bb_hashbuckets)
2113 struct bb_edge **startbucket, **oldnext;
2115 oldnext = startbucket
2116 = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
2117 bucket = *startbucket;
2119 for (bucket = *startbucket; bucket;
2120 oldnext = &(bucket->next), bucket = *oldnext)
2122 if (bucket->src_addr == bb_src
2123 && bucket->dst_addr == bb_dst)
2125 bucket->count++;
2126 *oldnext = bucket->next;
2127 bucket->next = *startbucket;
2128 *startbucket = bucket;
2129 goto ret;
2133 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2135 if (!bucket)
2137 if (!reported)
2139 fprintf (stderr, "Profiler: out of memory\n");
2140 reported = 1;
2144 else
2146 bucket->src_addr = bb_src;
2147 bucket->dst_addr = bb_dst;
2148 bucket->next = *startbucket;
2149 *startbucket = bucket;
2150 bucket->count = 1;
2154 ret:
2155 bb_src = bb_dst;
2157 skip:
2160 MACHINE_STATE_RESTORE("1")
2164 /* Called when returning from a function and `__bb_showret__' is set. */
2166 static void
2167 __bb_trace_func_ret (void)
2169 struct bb_edge *bucket;
2171 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2172 goto skip;
2174 if (bb_hashbuckets)
2176 struct bb_edge **startbucket, **oldnext;
2178 oldnext = startbucket
2179 = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
2180 bucket = *startbucket;
2182 for (bucket = *startbucket; bucket;
2183 oldnext = &(bucket->next), bucket = *oldnext)
2185 if (bucket->src_addr == bb_dst
2186 && bucket->dst_addr == bb_src)
2188 bucket->count++;
2189 *oldnext = bucket->next;
2190 bucket->next = *startbucket;
2191 *startbucket = bucket;
2192 goto ret;
2196 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2198 if (!bucket)
2200 if (!reported)
2202 fprintf (stderr, "Profiler: out of memory\n");
2203 reported = 1;
2207 else
2209 bucket->src_addr = bb_dst;
2210 bucket->dst_addr = bb_src;
2211 bucket->next = *startbucket;
2212 *startbucket = bucket;
2213 bucket->count = 1;
2217 ret:
2218 bb_dst = bb_src;
2220 skip:
2225 /* Called upon entering the first function of a file. */
2227 static void
2228 __bb_init_file (struct bb *blocks)
2231 const struct bb_func *p;
2232 long blk, ncounts = blocks->ncounts;
2233 const char **functions = blocks->functions;
2235 /* Set up linked list. */
2236 blocks->zero_word = 1;
2237 blocks->next = bb_head;
2238 bb_head = blocks;
2240 blocks->flags = 0;
2241 if (!bb_func_head
2242 || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
2243 return;
2245 for (blk = 0; blk < ncounts; blk++)
2246 blocks->flags[blk] = 0;
2248 for (blk = 0; blk < ncounts; blk++)
2250 for (p = bb_func_head; p; p = p->next)
2252 if (!strcmp (p->funcname, functions[blk])
2253 && (!p->filename || !strcmp (p->filename, blocks->filename)))
2255 blocks->flags[blk] |= p->mode;
2262 /* Called when exiting from a function. */
2264 void
2265 __bb_trace_ret (void)
2268 MACHINE_STATE_SAVE("2")
2270 if (bb_callcount)
2272 if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2274 bb_src = bb_stack[bb_callcount];
2275 if (bb_mode & 8)
2276 __bb_trace_func_ret ();
2279 bb_callcount -= 1;
2282 MACHINE_STATE_RESTORE("2")
2286 /* Called when entering a function. */
2288 void
2289 __bb_init_trace_func (struct bb *blocks, unsigned long blockno)
2291 static int trace_init = 0;
2293 MACHINE_STATE_SAVE("3")
2295 if (!blocks->zero_word)
2297 if (!trace_init)
2299 trace_init = 1;
2300 __bb_init_prg ();
2302 __bb_init_file (blocks);
2305 if (bb_callcount)
2308 bb_callcount += 1;
2310 if (bb_mode & 12)
2312 if (bb_callcount >= bb_stacksize)
2314 size_t newsize = bb_callcount + 100;
2316 bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2317 if (! bb_stack)
2319 if (!reported)
2321 fprintf (stderr, "Profiler: out of memory\n");
2322 reported = 1;
2324 bb_stacksize = 0;
2325 goto stack_overflow;
2327 bb_stacksize = newsize;
2329 bb_stack[bb_callcount] = bb_src;
2331 if (bb_mode & 4)
2332 bb_src = 0;
2336 stack_overflow:;
2340 else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2342 bb_callcount = 1;
2343 bb_src = 0;
2345 if (bb_stack)
2346 bb_stack[bb_callcount] = bb_src;
2349 MACHINE_STATE_RESTORE("3")
2352 #endif /* not inhibit_libc */
2353 #endif /* not BLOCK_PROFILER_CODE */
2354 #endif /* L_bb */
2356 #ifdef L_clear_cache
2357 /* Clear part of an instruction cache. */
2359 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2361 void
2362 __clear_cache (char *beg __attribute__((__unused__)),
2363 char *end __attribute__((__unused__)))
2365 #ifdef CLEAR_INSN_CACHE
2366 CLEAR_INSN_CACHE (beg, end);
2367 #else
2368 #ifdef INSN_CACHE_SIZE
2369 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
2370 static int initialized;
2371 int offset;
2372 void *start_addr
2373 void *end_addr;
2374 typedef (*function_ptr) (void);
2376 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2377 /* It's cheaper to clear the whole cache.
2378 Put in a series of jump instructions so that calling the beginning
2379 of the cache will clear the whole thing. */
2381 if (! initialized)
2383 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2384 & -INSN_CACHE_LINE_WIDTH);
2385 int end_ptr = ptr + INSN_CACHE_SIZE;
2387 while (ptr < end_ptr)
2389 *(INSTRUCTION_TYPE *)ptr
2390 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2391 ptr += INSN_CACHE_LINE_WIDTH;
2393 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
2395 initialized = 1;
2398 /* Call the beginning of the sequence. */
2399 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2400 & -INSN_CACHE_LINE_WIDTH))
2401 ());
2403 #else /* Cache is large. */
2405 if (! initialized)
2407 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2408 & -INSN_CACHE_LINE_WIDTH);
2410 while (ptr < (int) array + sizeof array)
2412 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2413 ptr += INSN_CACHE_LINE_WIDTH;
2416 initialized = 1;
2419 /* Find the location in array that occupies the same cache line as BEG. */
2421 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2422 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2423 & -INSN_CACHE_PLANE_SIZE)
2424 + offset);
2426 /* Compute the cache alignment of the place to stop clearing. */
2427 #if 0 /* This is not needed for gcc's purposes. */
2428 /* If the block to clear is bigger than a cache plane,
2429 we clear the entire cache, and OFFSET is already correct. */
2430 if (end < beg + INSN_CACHE_PLANE_SIZE)
2431 #endif
2432 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2433 & -INSN_CACHE_LINE_WIDTH)
2434 & (INSN_CACHE_PLANE_SIZE - 1));
2436 #if INSN_CACHE_DEPTH > 1
2437 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2438 if (end_addr <= start_addr)
2439 end_addr += INSN_CACHE_PLANE_SIZE;
2441 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2443 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2444 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2446 while (addr != stop)
2448 /* Call the return instruction at ADDR. */
2449 ((function_ptr) addr) ();
2451 addr += INSN_CACHE_LINE_WIDTH;
2454 #else /* just one plane */
2457 /* Call the return instruction at START_ADDR. */
2458 ((function_ptr) start_addr) ();
2460 start_addr += INSN_CACHE_LINE_WIDTH;
2462 while ((start_addr % INSN_CACHE_SIZE) != offset);
2463 #endif /* just one plane */
2464 #endif /* Cache is large */
2465 #endif /* Cache exists */
2466 #endif /* CLEAR_INSN_CACHE */
2469 #endif /* L_clear_cache */
2471 #ifdef L_trampoline
2473 /* Jump to a trampoline, loading the static chain address. */
2475 #if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
2477 long
2478 getpagesize (void)
2480 #ifdef _ALPHA_
2481 return 8192;
2482 #else
2483 return 4096;
2484 #endif
2487 #ifdef __i386__
2488 extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
2489 #endif
2492 mprotect (char *addr, int len, int prot)
2494 int np, op;
2496 if (prot == 7)
2497 np = 0x40;
2498 else if (prot == 5)
2499 np = 0x20;
2500 else if (prot == 4)
2501 np = 0x10;
2502 else if (prot == 3)
2503 np = 0x04;
2504 else if (prot == 1)
2505 np = 0x02;
2506 else if (prot == 0)
2507 np = 0x01;
2509 if (VirtualProtect (addr, len, np, &op))
2510 return 0;
2511 else
2512 return -1;
2515 #endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
2517 #ifdef TRANSFER_FROM_TRAMPOLINE
2518 TRANSFER_FROM_TRAMPOLINE
2519 #endif
2521 #if defined (NeXT) && defined (__MACH__)
2523 /* Make stack executable so we can call trampolines on stack.
2524 This is called from INITIALIZE_TRAMPOLINE in next.h. */
2525 #ifdef NeXTStep21
2526 #include <mach.h>
2527 #else
2528 #include <mach/mach.h>
2529 #endif
2531 void
2532 __enable_execute_stack (char *addr)
2534 kern_return_t r;
2535 char *eaddr = addr + TRAMPOLINE_SIZE;
2536 vm_address_t a = (vm_address_t) addr;
2538 /* turn on execute access on stack */
2539 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2540 if (r != KERN_SUCCESS)
2542 mach_error("vm_protect VM_PROT_ALL", r);
2543 exit(1);
2546 /* We inline the i-cache invalidation for speed */
2548 #ifdef CLEAR_INSN_CACHE
2549 CLEAR_INSN_CACHE (addr, eaddr);
2550 #else
2551 __clear_cache ((int) addr, (int) eaddr);
2552 #endif
2555 #endif /* defined (NeXT) && defined (__MACH__) */
2557 #ifdef __convex__
2559 /* Make stack executable so we can call trampolines on stack.
2560 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
2562 #include <sys/mman.h>
2563 #include <sys/vmparam.h>
2564 #include <machine/machparam.h>
2566 void
2567 __enable_execute_stack (void)
2569 int fp;
2570 static unsigned lowest = USRSTACK;
2571 unsigned current = (unsigned) &fp & -NBPG;
2573 if (lowest > current)
2575 unsigned len = lowest - current;
2576 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2577 lowest = current;
2580 /* Clear instruction cache in case an old trampoline is in it. */
2581 asm ("pich");
2583 #endif /* __convex__ */
2585 #ifdef __sysV88__
2587 /* Modified from the convex -code above. */
2589 #include <sys/param.h>
2590 #include <errno.h>
2591 #include <sys/m88kbcs.h>
2593 void
2594 __enable_execute_stack (void)
2596 int save_errno;
2597 static unsigned long lowest = USRSTACK;
2598 unsigned long current = (unsigned long) &save_errno & -NBPC;
2600 /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2601 address is seen as 'negative'. That is the case with the stack. */
2603 save_errno=errno;
2604 if (lowest > current)
2606 unsigned len=lowest-current;
2607 memctl(current,len,MCT_TEXT);
2608 lowest = current;
2610 else
2611 memctl(current,NBPC,MCT_TEXT);
2612 errno=save_errno;
2615 #endif /* __sysV88__ */
2617 #ifdef __sysV68__
2619 #include <sys/signal.h>
2620 #include <errno.h>
2622 /* Motorola forgot to put memctl.o in the libp version of libc881.a,
2623 so define it here, because we need it in __clear_insn_cache below */
2624 /* On older versions of this OS, no memctl or MCT_TEXT are defined;
2625 hence we enable this stuff only if MCT_TEXT is #define'd. */
2627 #ifdef MCT_TEXT
2628 asm("\n\
2629 global memctl\n\
2630 memctl:\n\
2631 movq &75,%d0\n\
2632 trap &0\n\
2633 bcc.b noerror\n\
2634 jmp cerror%\n\
2635 noerror:\n\
2636 movq &0,%d0\n\
2637 rts");
2638 #endif
2640 /* Clear instruction cache so we can call trampolines on stack.
2641 This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
2643 void
2644 __clear_insn_cache (void)
2646 #ifdef MCT_TEXT
2647 int save_errno;
2649 /* Preserve errno, because users would be surprised to have
2650 errno changing without explicitly calling any system-call. */
2651 save_errno = errno;
2653 /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
2654 No need to use an address derived from _start or %sp, as 0 works also. */
2655 memctl(0, 4096, MCT_TEXT);
2656 errno = save_errno;
2657 #endif
2660 #endif /* __sysV68__ */
2662 #ifdef __pyr__
2664 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
2665 #include <stdio.h>
2666 #include <sys/mman.h>
2667 #include <sys/types.h>
2668 #include <sys/param.h>
2669 #include <sys/vmmac.h>
2671 /* Modified from the convex -code above.
2672 mremap promises to clear the i-cache. */
2674 void
2675 __enable_execute_stack (void)
2677 int fp;
2678 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2679 PROT_READ|PROT_WRITE|PROT_EXEC))
2681 perror ("mprotect in __enable_execute_stack");
2682 fflush (stderr);
2683 abort ();
2686 #endif /* __pyr__ */
2688 #if defined (sony_news) && defined (SYSTYPE_BSD)
2690 #include <stdio.h>
2691 #include <sys/types.h>
2692 #include <sys/param.h>
2693 #include <syscall.h>
2694 #include <machine/sysnews.h>
2696 /* cacheflush function for NEWS-OS 4.2.
2697 This function is called from trampoline-initialize code
2698 defined in config/mips/mips.h. */
2700 void
2701 cacheflush (char *beg, int size, int flag)
2703 if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
2705 perror ("cache_flush");
2706 fflush (stderr);
2707 abort ();
2711 #endif /* sony_news */
2712 #endif /* L_trampoline */
2714 #ifndef __CYGWIN__
2715 #ifdef L__main
2717 #include "gbl-ctors.h"
2718 /* Some systems use __main in a way incompatible with its use in gcc, in these
2719 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2720 give the same symbol without quotes for an alternative entry point. You
2721 must define both, or neither. */
2722 #ifndef NAME__MAIN
2723 #define NAME__MAIN "__main"
2724 #define SYMBOL__MAIN __main
2725 #endif
2727 #ifdef INIT_SECTION_ASM_OP
2728 #undef HAS_INIT_SECTION
2729 #define HAS_INIT_SECTION
2730 #endif
2732 #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
2734 /* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
2735 code to run constructors. In that case, we need to handle EH here, too. */
2737 #ifdef EH_FRAME_SECTION
2738 #include "unwind-dw2-fde.h"
2739 extern unsigned char __EH_FRAME_BEGIN__[];
2740 #endif
2742 /* Run all the global destructors on exit from the program. */
2744 void
2745 __do_global_dtors (void)
2747 #ifdef DO_GLOBAL_DTORS_BODY
2748 DO_GLOBAL_DTORS_BODY;
2749 #else
2750 static func_ptr *p = __DTOR_LIST__ + 1;
2751 while (*p)
2753 p++;
2754 (*(p-1)) ();
2756 #endif
2757 #if defined (EH_FRAME_SECTION) && !defined (HAS_INIT_SECTION)
2759 static int completed = 0;
2760 if (! completed)
2762 completed = 1;
2763 __deregister_frame_info (__EH_FRAME_BEGIN__);
2766 #endif
2768 #endif
2770 #ifndef HAS_INIT_SECTION
2771 /* Run all the global constructors on entry to the program. */
2773 void
2774 __do_global_ctors (void)
2776 #ifdef EH_FRAME_SECTION
2778 static struct object object;
2779 __register_frame_info (__EH_FRAME_BEGIN__, &object);
2781 #endif
2782 DO_GLOBAL_CTORS_BODY;
2783 atexit (__do_global_dtors);
2785 #endif /* no HAS_INIT_SECTION */
2787 #if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
2788 /* Subroutine called automatically by `main'.
2789 Compiling a global function named `main'
2790 produces an automatic call to this function at the beginning.
2792 For many systems, this routine calls __do_global_ctors.
2793 For systems which support a .init section we use the .init section
2794 to run __do_global_ctors, so we need not do anything here. */
2796 void
2797 SYMBOL__MAIN ()
2799 /* Support recursive calls to `main': run initializers just once. */
2800 static int initialized;
2801 if (! initialized)
2803 initialized = 1;
2804 __do_global_ctors ();
2807 #endif /* no HAS_INIT_SECTION or INVOKE__main */
2809 #endif /* L__main */
2810 #endif /* __CYGWIN__ */
2812 #ifdef L_ctors
2814 #include "gbl-ctors.h"
2816 /* Provide default definitions for the lists of constructors and
2817 destructors, so that we don't get linker errors. These symbols are
2818 intentionally bss symbols, so that gld and/or collect will provide
2819 the right values. */
2821 /* We declare the lists here with two elements each,
2822 so that they are valid empty lists if no other definition is loaded.
2824 If we are using the old "set" extensions to have the gnu linker
2825 collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
2826 must be in the bss/common section.
2828 Long term no port should use those extensions. But many still do. */
2829 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2830 #if defined (ASM_OUTPUT_CONSTRUCTOR) || defined (USE_COLLECT2)
2831 func_ptr __CTOR_LIST__[2] = {0, 0};
2832 func_ptr __DTOR_LIST__[2] = {0, 0};
2833 #else
2834 func_ptr __CTOR_LIST__[2];
2835 func_ptr __DTOR_LIST__[2];
2836 #endif
2837 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2838 #endif /* L_ctors */
2840 #ifdef L_exit
2842 #include "gbl-ctors.h"
2844 #ifdef NEED_ATEXIT
2846 #ifndef ON_EXIT
2848 # include <errno.h>
2850 static func_ptr *atexit_chain = 0;
2851 static long atexit_chain_length = 0;
2852 static volatile long last_atexit_chain_slot = -1;
2855 atexit (func_ptr func)
2857 if (++last_atexit_chain_slot == atexit_chain_length)
2859 atexit_chain_length += 32;
2860 if (atexit_chain)
2861 atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2862 * sizeof (func_ptr));
2863 else
2864 atexit_chain = (func_ptr *) malloc (atexit_chain_length
2865 * sizeof (func_ptr));
2866 if (! atexit_chain)
2868 atexit_chain_length = 0;
2869 last_atexit_chain_slot = -1;
2870 errno = ENOMEM;
2871 return (-1);
2874 atexit_chain[last_atexit_chain_slot] = func;
2875 return (0);
2878 extern void _cleanup (void);
2879 extern void _exit (int) __attribute__ ((__noreturn__));
2881 void
2882 exit (int status)
2884 if (atexit_chain)
2886 for ( ; last_atexit_chain_slot-- >= 0; )
2888 (*atexit_chain[last_atexit_chain_slot + 1]) ();
2889 atexit_chain[last_atexit_chain_slot + 1] = 0;
2891 free (atexit_chain);
2892 atexit_chain = 0;
2894 #ifdef EXIT_BODY
2895 EXIT_BODY;
2896 #else
2897 _cleanup ();
2898 #endif
2899 _exit (status);
2902 #else /* ON_EXIT */
2904 /* Simple; we just need a wrapper for ON_EXIT. */
2906 atexit (func_ptr func)
2908 return ON_EXIT (func);
2911 #endif /* ON_EXIT */
2912 #endif /* NEED_ATEXIT */
2914 #endif /* L_exit */