* pa.md (alternate dbra pattern): Remove incorrect pattern.
[official-gcc.git] / gcc / libgcc2.c
blobc32a7e03fa26d1ea45a784e10e0cb695555598a4
1 /* More subroutines needed by GCC output code on some machines. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989, 92, 93, 94, 95, 96, 1997 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)
10 any later version.
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, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 /* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License. */
29 /* It is incorrect to include config.h here, because this file is being
30 compiled for the target, and hence definitions concerning only the host
31 do not apply. */
33 #include "tconfig.h"
34 #include "machmode.h"
35 #include "defaults.h"
36 #ifndef L_trampoline
37 #include <stddef.h>
38 #endif
40 /* Don't use `fancy_abort' here even if config.h says to use it. */
41 #ifdef abort
42 #undef abort
43 #endif
45 #if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS))
46 #define WEAK_ALIAS
47 #endif
49 /* Permit the tm.h file to select the endianness to use just for this
50 file. This is used when the endianness is determined when the
51 compiler is run. */
53 #ifndef LIBGCC2_WORDS_BIG_ENDIAN
54 #define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
55 #endif
57 /* In the first part of this file, we are interfacing to calls generated
58 by the compiler itself. These calls pass values into these routines
59 which have very specific modes (rather than very specific types), and
60 these compiler-generated calls also expect any return values to have
61 very specific modes (rather than very specific types). Thus, we need
62 to avoid using regular C language type names in this part of the file
63 because the sizes for those types can be configured to be anything.
64 Instead we use the following special type names. */
66 typedef unsigned int UQItype __attribute__ ((mode (QI)));
67 typedef int SItype __attribute__ ((mode (SI)));
68 typedef unsigned int USItype __attribute__ ((mode (SI)));
69 typedef int DItype __attribute__ ((mode (DI)));
70 typedef unsigned int UDItype __attribute__ ((mode (DI)));
72 typedef float SFtype __attribute__ ((mode (SF)));
73 typedef float DFtype __attribute__ ((mode (DF)));
75 #if LONG_DOUBLE_TYPE_SIZE == 96
76 typedef float XFtype __attribute__ ((mode (XF)));
77 #endif
78 #if LONG_DOUBLE_TYPE_SIZE == 128
79 typedef float TFtype __attribute__ ((mode (TF)));
80 #endif
82 typedef int word_type __attribute__ ((mode (__word__)));
84 /* Make sure that we don't accidentally use any normal C language built-in
85 type names in the first part of this file. Instead we want to use *only*
86 the type names defined above. The following macro definitions insure
87 that if we *do* accidentally use some normal C language built-in type name,
88 we will get a syntax error. */
90 #define char bogus_type
91 #define short bogus_type
92 #define int bogus_type
93 #define long bogus_type
94 #define unsigned bogus_type
95 #define float bogus_type
96 #define double bogus_type
98 #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
100 /* DIstructs are pairs of SItype values in the order determined by
101 LIBGCC2_WORDS_BIG_ENDIAN. */
103 #if LIBGCC2_WORDS_BIG_ENDIAN
104 struct DIstruct {SItype high, low;};
105 #else
106 struct DIstruct {SItype low, high;};
107 #endif
109 /* We need this union to unpack/pack DImode values, since we don't have
110 any arithmetic yet. Incoming DImode parameters are stored into the
111 `ll' field, and the unpacked result is read from the struct `s'. */
113 typedef union
115 struct DIstruct s;
116 DItype ll;
117 } DIunion;
119 #if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\
120 || defined (L_divdi3) || defined (L_udivdi3) \
121 || defined (L_moddi3) || defined (L_umoddi3))
123 #include "longlong.h"
125 #endif /* udiv or mul */
127 extern DItype __fixunssfdi (SFtype a);
128 extern DItype __fixunsdfdi (DFtype a);
129 #if LONG_DOUBLE_TYPE_SIZE == 96
130 extern DItype __fixunsxfdi (XFtype a);
131 #endif
132 #if LONG_DOUBLE_TYPE_SIZE == 128
133 extern DItype __fixunstfdi (TFtype a);
134 #endif
136 #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
137 #if defined (L_divdi3) || defined (L_moddi3)
138 static inline
139 #endif
140 DItype
141 __negdi2 (DItype u)
143 DIunion w;
144 DIunion uu;
146 uu.ll = u;
148 w.s.low = -uu.s.low;
149 w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
151 return w.ll;
153 #endif
155 /* Unless shift functions are defined whith full ANSI prototypes,
156 parameter b will be promoted to int if word_type is smaller than an int. */
157 #ifdef L_lshrdi3
158 DItype
159 __lshrdi3 (DItype u, word_type b)
161 DIunion w;
162 word_type bm;
163 DIunion uu;
165 if (b == 0)
166 return u;
168 uu.ll = u;
170 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
171 if (bm <= 0)
173 w.s.high = 0;
174 w.s.low = (USItype)uu.s.high >> -bm;
176 else
178 USItype carries = (USItype)uu.s.high << bm;
179 w.s.high = (USItype)uu.s.high >> b;
180 w.s.low = ((USItype)uu.s.low >> b) | carries;
183 return w.ll;
185 #endif
187 #ifdef L_ashldi3
188 DItype
189 __ashldi3 (DItype u, word_type b)
191 DIunion w;
192 word_type bm;
193 DIunion uu;
195 if (b == 0)
196 return u;
198 uu.ll = u;
200 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
201 if (bm <= 0)
203 w.s.low = 0;
204 w.s.high = (USItype)uu.s.low << -bm;
206 else
208 USItype carries = (USItype)uu.s.low >> bm;
209 w.s.low = (USItype)uu.s.low << b;
210 w.s.high = ((USItype)uu.s.high << b) | carries;
213 return w.ll;
215 #endif
217 #ifdef L_ashrdi3
218 DItype
219 __ashrdi3 (DItype u, word_type b)
221 DIunion w;
222 word_type bm;
223 DIunion uu;
225 if (b == 0)
226 return u;
228 uu.ll = u;
230 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
231 if (bm <= 0)
233 /* w.s.high = 1..1 or 0..0 */
234 w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
235 w.s.low = uu.s.high >> -bm;
237 else
239 USItype carries = (USItype)uu.s.high << bm;
240 w.s.high = uu.s.high >> b;
241 w.s.low = ((USItype)uu.s.low >> b) | carries;
244 return w.ll;
246 #endif
248 #ifdef L_ffsdi2
249 DItype
250 __ffsdi2 (DItype u)
252 DIunion uu, w;
253 uu.ll = u;
254 w.s.high = 0;
255 w.s.low = ffs (uu.s.low);
256 if (w.s.low != 0)
257 return w.ll;
258 w.s.low = ffs (uu.s.high);
259 if (w.s.low != 0)
261 w.s.low += BITS_PER_UNIT * sizeof (SItype);
262 return w.ll;
264 return w.ll;
266 #endif
268 #ifdef L_muldi3
269 DItype
270 __muldi3 (DItype u, DItype v)
272 DIunion w;
273 DIunion uu, vv;
275 uu.ll = u,
276 vv.ll = v;
278 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
279 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
280 + (USItype) uu.s.high * (USItype) vv.s.low);
282 return w.ll;
284 #endif
286 #ifdef L_udiv_w_sdiv
287 #if defined (sdiv_qrnnd)
288 USItype
289 __udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
291 USItype q, r;
292 USItype c0, c1, b1;
294 if ((SItype) d >= 0)
296 if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
298 /* dividend, divisor, and quotient are nonnegative */
299 sdiv_qrnnd (q, r, a1, a0, d);
301 else
303 /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
304 sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
305 /* Divide (c1*2^32 + c0) by d */
306 sdiv_qrnnd (q, r, c1, c0, d);
307 /* Add 2^31 to quotient */
308 q += (USItype) 1 << (SI_TYPE_SIZE - 1);
311 else
313 b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
314 c1 = a1 >> 1; /* A/2 */
315 c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
317 if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
319 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
321 r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
322 if ((d & 1) != 0)
324 if (r >= q)
325 r = r - q;
326 else if (q - r <= d)
328 r = r - q + d;
329 q--;
331 else
333 r = r - q + 2*d;
334 q -= 2;
338 else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
340 c1 = (b1 - 1) - c1;
341 c0 = ~c0; /* logical NOT */
343 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
345 q = ~q; /* (A/2)/b1 */
346 r = (b1 - 1) - r;
348 r = 2*r + (a0 & 1); /* A/(2*b1) */
350 if ((d & 1) != 0)
352 if (r >= q)
353 r = r - q;
354 else if (q - r <= d)
356 r = r - q + d;
357 q--;
359 else
361 r = r - q + 2*d;
362 q -= 2;
366 else /* Implies c1 = b1 */
367 { /* Hence a1 = d - 1 = 2*b1 - 1 */
368 if (a0 >= -d)
370 q = -1;
371 r = a0 + d;
373 else
375 q = -2;
376 r = a0 + 2*d;
381 *rp = r;
382 return q;
384 #else
385 /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
386 USItype
387 __udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
389 #endif
390 #endif
392 #if (defined (L_udivdi3) || defined (L_divdi3) || \
393 defined (L_umoddi3) || defined (L_moddi3))
394 #define L_udivmoddi4
395 #endif
397 #ifdef L_udivmoddi4
398 static const UQItype __clz_tab[] =
400 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,
401 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,
402 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,
403 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,
404 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,
405 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,
406 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,
407 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,
410 #if (defined (L_udivdi3) || defined (L_divdi3) || \
411 defined (L_umoddi3) || defined (L_moddi3))
412 static inline
413 #endif
414 UDItype
415 __udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
417 DIunion ww;
418 DIunion nn, dd;
419 DIunion rr;
420 USItype d0, d1, n0, n1, n2;
421 USItype q0, q1;
422 USItype b, bm;
424 nn.ll = n;
425 dd.ll = d;
427 d0 = dd.s.low;
428 d1 = dd.s.high;
429 n0 = nn.s.low;
430 n1 = nn.s.high;
432 #if !UDIV_NEEDS_NORMALIZATION
433 if (d1 == 0)
435 if (d0 > n1)
437 /* 0q = nn / 0D */
439 udiv_qrnnd (q0, n0, n1, n0, d0);
440 q1 = 0;
442 /* Remainder in n0. */
444 else
446 /* qq = NN / 0d */
448 if (d0 == 0)
449 d0 = 1 / d0; /* Divide intentionally by zero. */
451 udiv_qrnnd (q1, n1, 0, n1, d0);
452 udiv_qrnnd (q0, n0, n1, n0, d0);
454 /* Remainder in n0. */
457 if (rp != 0)
459 rr.s.low = n0;
460 rr.s.high = 0;
461 *rp = rr.ll;
465 #else /* UDIV_NEEDS_NORMALIZATION */
467 if (d1 == 0)
469 if (d0 > n1)
471 /* 0q = nn / 0D */
473 count_leading_zeros (bm, d0);
475 if (bm != 0)
477 /* Normalize, i.e. make the most significant bit of the
478 denominator set. */
480 d0 = d0 << bm;
481 n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
482 n0 = n0 << bm;
485 udiv_qrnnd (q0, n0, n1, n0, d0);
486 q1 = 0;
488 /* Remainder in n0 >> bm. */
490 else
492 /* qq = NN / 0d */
494 if (d0 == 0)
495 d0 = 1 / d0; /* Divide intentionally by zero. */
497 count_leading_zeros (bm, d0);
499 if (bm == 0)
501 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
502 conclude (the most significant bit of n1 is set) /\ (the
503 leading quotient digit q1 = 1).
505 This special case is necessary, not an optimization.
506 (Shifts counts of SI_TYPE_SIZE are undefined.) */
508 n1 -= d0;
509 q1 = 1;
511 else
513 /* Normalize. */
515 b = SI_TYPE_SIZE - bm;
517 d0 = d0 << bm;
518 n2 = n1 >> b;
519 n1 = (n1 << bm) | (n0 >> b);
520 n0 = n0 << bm;
522 udiv_qrnnd (q1, n1, n2, n1, d0);
525 /* n1 != d0... */
527 udiv_qrnnd (q0, n0, n1, n0, d0);
529 /* Remainder in n0 >> bm. */
532 if (rp != 0)
534 rr.s.low = n0 >> bm;
535 rr.s.high = 0;
536 *rp = rr.ll;
539 #endif /* UDIV_NEEDS_NORMALIZATION */
541 else
543 if (d1 > n1)
545 /* 00 = nn / DD */
547 q0 = 0;
548 q1 = 0;
550 /* Remainder in n1n0. */
551 if (rp != 0)
553 rr.s.low = n0;
554 rr.s.high = n1;
555 *rp = rr.ll;
558 else
560 /* 0q = NN / dd */
562 count_leading_zeros (bm, d1);
563 if (bm == 0)
565 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
566 conclude (the most significant bit of n1 is set) /\ (the
567 quotient digit q0 = 0 or 1).
569 This special case is necessary, not an optimization. */
571 /* The condition on the next line takes advantage of that
572 n1 >= d1 (true due to program flow). */
573 if (n1 > d1 || n0 >= d0)
575 q0 = 1;
576 sub_ddmmss (n1, n0, n1, n0, d1, d0);
578 else
579 q0 = 0;
581 q1 = 0;
583 if (rp != 0)
585 rr.s.low = n0;
586 rr.s.high = n1;
587 *rp = rr.ll;
590 else
592 USItype m1, m0;
593 /* Normalize. */
595 b = SI_TYPE_SIZE - bm;
597 d1 = (d1 << bm) | (d0 >> b);
598 d0 = d0 << bm;
599 n2 = n1 >> b;
600 n1 = (n1 << bm) | (n0 >> b);
601 n0 = n0 << bm;
603 udiv_qrnnd (q0, n1, n2, n1, d1);
604 umul_ppmm (m1, m0, q0, d0);
606 if (m1 > n1 || (m1 == n1 && m0 > n0))
608 q0--;
609 sub_ddmmss (m1, m0, m1, m0, d1, d0);
612 q1 = 0;
614 /* Remainder in (n1n0 - m1m0) >> bm. */
615 if (rp != 0)
617 sub_ddmmss (n1, n0, n1, n0, m1, m0);
618 rr.s.low = (n1 << b) | (n0 >> bm);
619 rr.s.high = n1 >> bm;
620 *rp = rr.ll;
626 ww.s.low = q0;
627 ww.s.high = q1;
628 return ww.ll;
630 #endif
632 #ifdef L_divdi3
633 UDItype __udivmoddi4 ();
635 DItype
636 __divdi3 (DItype u, DItype v)
638 word_type c = 0;
639 DIunion uu, vv;
640 DItype w;
642 uu.ll = u;
643 vv.ll = v;
645 if (uu.s.high < 0)
646 c = ~c,
647 uu.ll = __negdi2 (uu.ll);
648 if (vv.s.high < 0)
649 c = ~c,
650 vv.ll = __negdi2 (vv.ll);
652 w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
653 if (c)
654 w = __negdi2 (w);
656 return w;
658 #endif
660 #ifdef L_moddi3
661 UDItype __udivmoddi4 ();
662 DItype
663 __moddi3 (DItype u, DItype v)
665 word_type c = 0;
666 DIunion uu, vv;
667 DItype w;
669 uu.ll = u;
670 vv.ll = v;
672 if (uu.s.high < 0)
673 c = ~c,
674 uu.ll = __negdi2 (uu.ll);
675 if (vv.s.high < 0)
676 vv.ll = __negdi2 (vv.ll);
678 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
679 if (c)
680 w = __negdi2 (w);
682 return w;
684 #endif
686 #ifdef L_umoddi3
687 UDItype __udivmoddi4 ();
688 UDItype
689 __umoddi3 (UDItype u, UDItype v)
691 UDItype w;
693 (void) __udivmoddi4 (u, v, &w);
695 return w;
697 #endif
699 #ifdef L_udivdi3
700 UDItype __udivmoddi4 ();
701 UDItype
702 __udivdi3 (UDItype n, UDItype d)
704 return __udivmoddi4 (n, d, (UDItype *) 0);
706 #endif
708 #ifdef L_cmpdi2
709 word_type
710 __cmpdi2 (DItype a, DItype b)
712 DIunion au, bu;
714 au.ll = a, bu.ll = b;
716 if (au.s.high < bu.s.high)
717 return 0;
718 else if (au.s.high > bu.s.high)
719 return 2;
720 if ((USItype) au.s.low < (USItype) bu.s.low)
721 return 0;
722 else if ((USItype) au.s.low > (USItype) bu.s.low)
723 return 2;
724 return 1;
726 #endif
728 #ifdef L_ucmpdi2
729 word_type
730 __ucmpdi2 (DItype a, DItype b)
732 DIunion au, bu;
734 au.ll = a, bu.ll = b;
736 if ((USItype) au.s.high < (USItype) bu.s.high)
737 return 0;
738 else if ((USItype) au.s.high > (USItype) bu.s.high)
739 return 2;
740 if ((USItype) au.s.low < (USItype) bu.s.low)
741 return 0;
742 else if ((USItype) au.s.low > (USItype) bu.s.low)
743 return 2;
744 return 1;
746 #endif
748 #if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
749 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
750 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
752 DItype
753 __fixunstfdi (TFtype a)
755 TFtype b;
756 UDItype v;
758 if (a < 0)
759 return 0;
761 /* Compute high word of result, as a flonum. */
762 b = (a / HIGH_WORD_COEFF);
763 /* Convert that to fixed (but not to DItype!),
764 and shift it into the high word. */
765 v = (USItype) b;
766 v <<= WORD_SIZE;
767 /* Remove high part from the TFtype, leaving the low part as flonum. */
768 a -= (TFtype)v;
769 /* Convert that to fixed (but not to DItype!) and add it in.
770 Sometimes A comes out negative. This is significant, since
771 A has more bits than a long int does. */
772 if (a < 0)
773 v -= (USItype) (- a);
774 else
775 v += (USItype) a;
776 return v;
778 #endif
780 #if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
781 DItype
782 __fixtfdi (TFtype a)
784 if (a < 0)
785 return - __fixunstfdi (-a);
786 return __fixunstfdi (a);
788 #endif
790 #if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
791 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
792 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
794 DItype
795 __fixunsxfdi (XFtype a)
797 XFtype b;
798 UDItype v;
800 if (a < 0)
801 return 0;
803 /* Compute high word of result, as a flonum. */
804 b = (a / HIGH_WORD_COEFF);
805 /* Convert that to fixed (but not to DItype!),
806 and shift it into the high word. */
807 v = (USItype) b;
808 v <<= WORD_SIZE;
809 /* Remove high part from the XFtype, leaving the low part as flonum. */
810 a -= (XFtype)v;
811 /* Convert that to fixed (but not to DItype!) and add it in.
812 Sometimes A comes out negative. This is significant, since
813 A has more bits than a long int does. */
814 if (a < 0)
815 v -= (USItype) (- a);
816 else
817 v += (USItype) a;
818 return v;
820 #endif
822 #if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
823 DItype
824 __fixxfdi (XFtype a)
826 if (a < 0)
827 return - __fixunsxfdi (-a);
828 return __fixunsxfdi (a);
830 #endif
832 #ifdef L_fixunsdfdi
833 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
834 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
836 DItype
837 __fixunsdfdi (DFtype a)
839 DFtype b;
840 UDItype v;
842 if (a < 0)
843 return 0;
845 /* Compute high word of result, as a flonum. */
846 b = (a / HIGH_WORD_COEFF);
847 /* Convert that to fixed (but not to DItype!),
848 and shift it into the high word. */
849 v = (USItype) b;
850 v <<= WORD_SIZE;
851 /* Remove high part from the DFtype, leaving the low part as flonum. */
852 a -= (DFtype)v;
853 /* Convert that to fixed (but not to DItype!) and add it in.
854 Sometimes A comes out negative. This is significant, since
855 A has more bits than a long int does. */
856 if (a < 0)
857 v -= (USItype) (- a);
858 else
859 v += (USItype) a;
860 return v;
862 #endif
864 #ifdef L_fixdfdi
865 DItype
866 __fixdfdi (DFtype a)
868 if (a < 0)
869 return - __fixunsdfdi (-a);
870 return __fixunsdfdi (a);
872 #endif
874 #ifdef L_fixunssfdi
875 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
876 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
878 DItype
879 __fixunssfdi (SFtype original_a)
881 /* Convert the SFtype to a DFtype, because that is surely not going
882 to lose any bits. Some day someone else can write a faster version
883 that avoids converting to DFtype, and verify it really works right. */
884 DFtype a = original_a;
885 DFtype b;
886 UDItype v;
888 if (a < 0)
889 return 0;
891 /* Compute high word of result, as a flonum. */
892 b = (a / HIGH_WORD_COEFF);
893 /* Convert that to fixed (but not to DItype!),
894 and shift it into the high word. */
895 v = (USItype) b;
896 v <<= WORD_SIZE;
897 /* Remove high part from the DFtype, leaving the low part as flonum. */
898 a -= (DFtype)v;
899 /* Convert that to fixed (but not to DItype!) and add it in.
900 Sometimes A comes out negative. This is significant, since
901 A has more bits than a long int does. */
902 if (a < 0)
903 v -= (USItype) (- a);
904 else
905 v += (USItype) a;
906 return v;
908 #endif
910 #ifdef L_fixsfdi
911 DItype
912 __fixsfdi (SFtype a)
914 if (a < 0)
915 return - __fixunssfdi (-a);
916 return __fixunssfdi (a);
918 #endif
920 #if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
921 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
922 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
923 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
925 XFtype
926 __floatdixf (DItype u)
928 XFtype d;
929 SItype negate = 0;
931 if (u < 0)
932 u = -u, negate = 1;
934 d = (USItype) (u >> WORD_SIZE);
935 d *= HIGH_HALFWORD_COEFF;
936 d *= HIGH_HALFWORD_COEFF;
937 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
939 return (negate ? -d : d);
941 #endif
943 #if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
944 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
945 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
946 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
948 TFtype
949 __floatditf (DItype u)
951 TFtype d;
952 SItype negate = 0;
954 if (u < 0)
955 u = -u, negate = 1;
957 d = (USItype) (u >> WORD_SIZE);
958 d *= HIGH_HALFWORD_COEFF;
959 d *= HIGH_HALFWORD_COEFF;
960 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
962 return (negate ? -d : d);
964 #endif
966 #ifdef L_floatdidf
967 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
968 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
969 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
971 DFtype
972 __floatdidf (DItype u)
974 DFtype d;
975 SItype negate = 0;
977 if (u < 0)
978 u = -u, negate = 1;
980 d = (USItype) (u >> WORD_SIZE);
981 d *= HIGH_HALFWORD_COEFF;
982 d *= HIGH_HALFWORD_COEFF;
983 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
985 return (negate ? -d : d);
987 #endif
989 #ifdef L_floatdisf
990 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
991 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
992 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
993 #define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
995 /* Define codes for all the float formats that we know of. Note
996 that this is copied from real.h. */
998 #define UNKNOWN_FLOAT_FORMAT 0
999 #define IEEE_FLOAT_FORMAT 1
1000 #define VAX_FLOAT_FORMAT 2
1001 #define IBM_FLOAT_FORMAT 3
1003 /* Default to IEEE float if not specified. Nearly all machines use it. */
1004 #ifndef HOST_FLOAT_FORMAT
1005 #define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
1006 #endif
1008 #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
1009 #define DF_SIZE 53
1010 #define SF_SIZE 24
1011 #endif
1013 #if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
1014 #define DF_SIZE 56
1015 #define SF_SIZE 24
1016 #endif
1018 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
1019 #define DF_SIZE 56
1020 #define SF_SIZE 24
1021 #endif
1023 SFtype
1024 __floatdisf (DItype u)
1026 /* Do the calculation in DFmode
1027 so that we don't lose any of the precision of the high word
1028 while multiplying it. */
1029 DFtype f;
1030 SItype negate = 0;
1032 if (u < 0)
1033 u = -u, negate = 1;
1035 /* Protect against double-rounding error.
1036 Represent any low-order bits, that might be truncated in DFmode,
1037 by a bit that won't be lost. The bit can go in anywhere below the
1038 rounding position of the SFmode. A fixed mask and bit position
1039 handles all usual configurations. It doesn't handle the case
1040 of 128-bit DImode, however. */
1041 if (DF_SIZE < DI_SIZE
1042 && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1044 #define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
1045 if (u >= ((UDItype) 1 << DF_SIZE))
1047 if ((USItype) u & (REP_BIT - 1))
1048 u |= REP_BIT;
1051 f = (USItype) (u >> WORD_SIZE);
1052 f *= HIGH_HALFWORD_COEFF;
1053 f *= HIGH_HALFWORD_COEFF;
1054 f += (USItype) (u & (HIGH_WORD_COEFF - 1));
1056 return (SFtype) (negate ? -f : f);
1058 #endif
1060 #if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
1061 /* Reenable the normal types, in case limits.h needs them. */
1062 #undef char
1063 #undef short
1064 #undef int
1065 #undef long
1066 #undef unsigned
1067 #undef float
1068 #undef double
1069 #undef MIN
1070 #undef MAX
1071 #include <limits.h>
1073 USItype
1074 __fixunsxfsi (XFtype a)
1076 if (a >= - (DFtype) LONG_MIN)
1077 return (SItype) (a + LONG_MIN) - LONG_MIN;
1078 return (SItype) a;
1080 #endif
1082 #ifdef L_fixunsdfsi
1083 /* Reenable the normal types, in case limits.h needs them. */
1084 #undef char
1085 #undef short
1086 #undef int
1087 #undef long
1088 #undef unsigned
1089 #undef float
1090 #undef double
1091 #undef MIN
1092 #undef MAX
1093 #include <limits.h>
1095 USItype
1096 __fixunsdfsi (DFtype a)
1098 if (a >= - (DFtype) LONG_MIN)
1099 return (SItype) (a + LONG_MIN) - LONG_MIN;
1100 return (SItype) a;
1102 #endif
1104 #ifdef L_fixunssfsi
1105 /* Reenable the normal types, in case limits.h needs them. */
1106 #undef char
1107 #undef short
1108 #undef int
1109 #undef long
1110 #undef unsigned
1111 #undef float
1112 #undef double
1113 #undef MIN
1114 #undef MAX
1115 #include <limits.h>
1117 USItype
1118 __fixunssfsi (SFtype a)
1120 if (a >= - (SFtype) LONG_MIN)
1121 return (SItype) (a + LONG_MIN) - LONG_MIN;
1122 return (SItype) a;
1124 #endif
1126 /* From here on down, the routines use normal data types. */
1128 #define SItype bogus_type
1129 #define USItype bogus_type
1130 #define DItype bogus_type
1131 #define UDItype bogus_type
1132 #define SFtype bogus_type
1133 #define DFtype bogus_type
1135 #undef char
1136 #undef short
1137 #undef int
1138 #undef long
1139 #undef unsigned
1140 #undef float
1141 #undef double
1143 #ifdef L__gcc_bcmp
1145 /* Like bcmp except the sign is meaningful.
1146 Result is negative if S1 is less than S2,
1147 positive if S1 is greater, 0 if S1 and S2 are equal. */
1150 __gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size)
1152 while (size > 0)
1154 unsigned char c1 = *s1++, c2 = *s2++;
1155 if (c1 != c2)
1156 return c1 - c2;
1157 size--;
1159 return 0;
1162 #endif
1163 \f\f
1164 #ifdef L__dummy
1165 void
1166 __dummy () {}
1167 #endif
1169 #ifdef L_varargs
1170 #ifdef __i860__
1171 #if defined(__svr4__) || defined(__alliant__)
1172 asm (" .text");
1173 asm (" .align 4");
1175 /* The Alliant needs the added underscore. */
1176 asm (".globl __builtin_saveregs");
1177 asm ("__builtin_saveregs:");
1178 asm (".globl ___builtin_saveregs");
1179 asm ("___builtin_saveregs:");
1181 asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
1182 asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
1183 area and also for a new va_list
1184 structure */
1185 /* Save all argument registers in the arg reg save area. The
1186 arg reg save area must have the following layout (according
1187 to the svr4 ABI):
1189 struct {
1190 union {
1191 float freg[8];
1192 double dreg[4];
1193 } float_regs;
1194 long ireg[12];
1198 asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
1199 asm (" fst.q %f12,16(%sp)");
1201 asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
1202 asm (" st.l %r17,36(%sp)");
1203 asm (" st.l %r18,40(%sp)");
1204 asm (" st.l %r19,44(%sp)");
1205 asm (" st.l %r20,48(%sp)");
1206 asm (" st.l %r21,52(%sp)");
1207 asm (" st.l %r22,56(%sp)");
1208 asm (" st.l %r23,60(%sp)");
1209 asm (" st.l %r24,64(%sp)");
1210 asm (" st.l %r25,68(%sp)");
1211 asm (" st.l %r26,72(%sp)");
1212 asm (" st.l %r27,76(%sp)");
1214 asm (" adds 80,%sp,%r16"); /* compute the address of the new
1215 va_list structure. Put in into
1216 r16 so that it will be returned
1217 to the caller. */
1219 /* Initialize all fields of the new va_list structure. This
1220 structure looks like:
1222 typedef struct {
1223 unsigned long ireg_used;
1224 unsigned long freg_used;
1225 long *reg_base;
1226 long *mem_ptr;
1227 } va_list;
1230 asm (" st.l %r0, 0(%r16)"); /* nfixed */
1231 asm (" st.l %r0, 4(%r16)"); /* nfloating */
1232 asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
1233 asm (" bri %r1"); /* delayed return */
1234 asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
1236 #else /* not __svr4__ */
1237 #if defined(__PARAGON__)
1239 * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1240 * and we stand a better chance of hooking into libraries
1241 * compiled by PGI. [andyp@ssd.intel.com]
1243 asm (" .text");
1244 asm (" .align 4");
1245 asm (".globl __builtin_saveregs");
1246 asm ("__builtin_saveregs:");
1247 asm (".globl ___builtin_saveregs");
1248 asm ("___builtin_saveregs:");
1250 asm (" andnot 0x0f,sp,sp"); /* round down to 16-byte boundary */
1251 asm (" adds -96,sp,sp"); /* allocate stack space for reg save
1252 area and also for a new va_list
1253 structure */
1254 /* Save all argument registers in the arg reg save area. The
1255 arg reg save area must have the following layout (according
1256 to the svr4 ABI):
1258 struct {
1259 union {
1260 float freg[8];
1261 double dreg[4];
1262 } float_regs;
1263 long ireg[12];
1267 asm (" fst.q f8, 0(sp)");
1268 asm (" fst.q f12,16(sp)");
1269 asm (" st.l r16,32(sp)");
1270 asm (" st.l r17,36(sp)");
1271 asm (" st.l r18,40(sp)");
1272 asm (" st.l r19,44(sp)");
1273 asm (" st.l r20,48(sp)");
1274 asm (" st.l r21,52(sp)");
1275 asm (" st.l r22,56(sp)");
1276 asm (" st.l r23,60(sp)");
1277 asm (" st.l r24,64(sp)");
1278 asm (" st.l r25,68(sp)");
1279 asm (" st.l r26,72(sp)");
1280 asm (" st.l r27,76(sp)");
1282 asm (" adds 80,sp,r16"); /* compute the address of the new
1283 va_list structure. Put in into
1284 r16 so that it will be returned
1285 to the caller. */
1287 /* Initialize all fields of the new va_list structure. This
1288 structure looks like:
1290 typedef struct {
1291 unsigned long ireg_used;
1292 unsigned long freg_used;
1293 long *reg_base;
1294 long *mem_ptr;
1295 } va_list;
1298 asm (" st.l r0, 0(r16)"); /* nfixed */
1299 asm (" st.l r0, 4(r16)"); /* nfloating */
1300 asm (" st.l sp, 8(r16)"); /* __va_ctl points to __va_struct. */
1301 asm (" bri r1"); /* delayed return */
1302 asm (" st.l r28,12(r16)"); /* pointer to overflow args */
1303 #else /* not __PARAGON__ */
1304 asm (" .text");
1305 asm (" .align 4");
1307 asm (".globl ___builtin_saveregs");
1308 asm ("___builtin_saveregs:");
1309 asm (" mov sp,r30");
1310 asm (" andnot 0x0f,sp,sp");
1311 asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
1313 /* Fill in the __va_struct. */
1314 asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
1315 asm (" st.l r17, 4(sp)"); /* int fixed[12] */
1316 asm (" st.l r18, 8(sp)");
1317 asm (" st.l r19,12(sp)");
1318 asm (" st.l r20,16(sp)");
1319 asm (" st.l r21,20(sp)");
1320 asm (" st.l r22,24(sp)");
1321 asm (" st.l r23,28(sp)");
1322 asm (" st.l r24,32(sp)");
1323 asm (" st.l r25,36(sp)");
1324 asm (" st.l r26,40(sp)");
1325 asm (" st.l r27,44(sp)");
1327 asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
1328 asm (" fst.q f12,64(sp)"); /* int floating[8] */
1330 /* Fill in the __va_ctl. */
1331 asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
1332 asm (" st.l r28,84(sp)"); /* pointer to more args */
1333 asm (" st.l r0, 88(sp)"); /* nfixed */
1334 asm (" st.l r0, 92(sp)"); /* nfloating */
1336 asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
1337 asm (" bri r1");
1338 asm (" mov r30,sp");
1339 /* recover stack and pass address to start
1340 of data. */
1341 #endif /* not __PARAGON__ */
1342 #endif /* not __svr4__ */
1343 #else /* not __i860__ */
1344 #ifdef __sparc__
1345 asm (".global __builtin_saveregs");
1346 asm ("__builtin_saveregs:");
1347 asm (".global ___builtin_saveregs");
1348 asm ("___builtin_saveregs:");
1349 #ifdef NEED_PROC_COMMAND
1350 asm (".proc 020");
1351 #endif
1352 asm ("st %i0,[%fp+68]");
1353 asm ("st %i1,[%fp+72]");
1354 asm ("st %i2,[%fp+76]");
1355 asm ("st %i3,[%fp+80]");
1356 asm ("st %i4,[%fp+84]");
1357 asm ("retl");
1358 asm ("st %i5,[%fp+88]");
1359 #ifdef NEED_TYPE_COMMAND
1360 asm (".type __builtin_saveregs,#function");
1361 asm (".size __builtin_saveregs,.-__builtin_saveregs");
1362 #endif
1363 #else /* not __sparc__ */
1364 #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1366 asm (" .text");
1367 asm (" .ent __builtin_saveregs");
1368 asm (" .globl __builtin_saveregs");
1369 asm ("__builtin_saveregs:");
1370 asm (" sw $4,0($30)");
1371 asm (" sw $5,4($30)");
1372 asm (" sw $6,8($30)");
1373 asm (" sw $7,12($30)");
1374 asm (" j $31");
1375 asm (" .end __builtin_saveregs");
1376 #else /* not __mips__, etc. */
1378 void *
1379 __builtin_saveregs ()
1381 abort ();
1384 #endif /* not __mips__ */
1385 #endif /* not __sparc__ */
1386 #endif /* not __i860__ */
1387 #endif
1389 #ifdef L_eprintf
1390 #ifndef inhibit_libc
1392 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1393 #include <stdio.h>
1394 /* This is used by the `assert' macro. */
1395 void
1396 __eprintf (const char *string, const char *expression,
1397 int line, const char *filename)
1399 fprintf (stderr, string, expression, line, filename);
1400 fflush (stderr);
1401 abort ();
1404 #endif
1405 #endif
1407 #ifdef L_bb
1409 /* Structure emitted by -a */
1410 struct bb
1412 long zero_word;
1413 const char *filename;
1414 long *counts;
1415 long ncounts;
1416 struct bb *next;
1417 const unsigned long *addresses;
1419 /* Older GCC's did not emit these fields. */
1420 long nwords;
1421 const char **functions;
1422 const long *line_nums;
1423 const char **filenames;
1424 char *flags;
1427 #ifdef BLOCK_PROFILER_CODE
1428 BLOCK_PROFILER_CODE
1429 #else
1430 #ifndef inhibit_libc
1432 /* Simple minded basic block profiling output dumper for
1433 systems that don't provide tcov support. At present,
1434 it requires atexit and stdio. */
1436 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1437 #include <stdio.h>
1438 char *ctime ();
1440 #include "gbl-ctors.h"
1441 #include "gcov-io.h"
1443 static struct bb *bb_head;
1445 /* Return the number of digits needed to print a value */
1446 /* __inline__ */ static int num_digits (long value, int base)
1448 int minus = (value < 0 && base != 16);
1449 unsigned long v = (minus) ? -value : value;
1450 int ret = minus;
1454 v /= base;
1455 ret++;
1457 while (v);
1459 return ret;
1462 void
1463 __bb_exit_func (void)
1465 FILE *da_file, *file;
1466 long time_value;
1467 int i;
1469 if (bb_head == 0)
1470 return;
1472 i = strlen (bb_head->filename) - 3;
1474 if (!strcmp (bb_head->filename+i, ".da"))
1476 /* Must be -fprofile-arcs not -a.
1477 Dump data in a form that gcov expects. */
1479 struct bb *ptr;
1481 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1483 /* If the file exists, and the number of counts in it is the same,
1484 then merge them in. */
1486 if ((da_file = fopen (ptr->filename, "r")) != 0)
1488 long n_counts = 0;
1489 unsigned char tmp;
1490 int i;
1491 int ret = 0;
1494 if (__read_long (&n_counts, da_file, 8) != 0)
1496 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1497 ptr->filename);
1498 continue;
1501 if (n_counts == ptr->ncounts)
1503 int i;
1505 for (i = 0; i < n_counts; i++)
1507 long v = 0;
1508 unsigned char tmp;
1509 int j;
1510 int ret = 0;
1512 if (__read_long (&v, da_file, 8) != 0)
1514 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1515 ptr->filename);
1516 break;
1518 ptr->counts[i] += v;
1522 if (fclose (da_file) == EOF)
1523 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1524 ptr->filename);
1526 if ((da_file = fopen (ptr->filename, "w")) < 0)
1528 fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1529 ptr->filename);
1530 continue;
1533 /* ??? Should first write a header to the file. Perferably, a 4 byte
1534 magic number, 4 bytes containing the time the program was
1535 compiled, 4 bytes containing the last modification time of the
1536 source file, and 4 bytes indicating the compiler options used.
1538 That way we can easily verify that the proper source/executable/
1539 data file combination is being used from gcov. */
1541 if (__write_long (ptr->ncounts, da_file, 8) != 0)
1544 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1545 ptr->filename);
1547 else
1549 int j;
1550 long *count_ptr = ptr->counts;
1551 int ret = 0;
1552 for (j = ptr->ncounts; j > 0; j--)
1554 if (__write_long (*count_ptr, da_file, 8) != 0)
1556 ret=1;
1557 break;
1559 count_ptr++;
1561 if (ret)
1562 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1563 ptr->filename);
1566 if (fclose (da_file) == EOF)
1567 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1568 ptr->filename);
1571 return;
1574 /* Must be basic block profiling. Emit a human readable output file. */
1576 file = fopen ("bb.out", "a");
1578 if (!file)
1579 perror ("bb.out");
1581 else
1583 struct bb *ptr;
1585 /* This is somewhat type incorrect, but it avoids worrying about
1586 exactly where time.h is included from. It should be ok unless
1587 a void * differs from other pointer formats, or if sizeof (long)
1588 is < sizeof (time_t). It would be nice if we could assume the
1589 use of rationale standards here. */
1591 time ((void *) &time_value);
1592 fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1594 /* We check the length field explicitly in order to allow compatibility
1595 with older GCC's which did not provide it. */
1597 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1599 int i;
1600 int func_p = (ptr->nwords >= sizeof (struct bb)
1601 && ptr->nwords <= 1000
1602 && ptr->functions);
1603 int line_p = (func_p && ptr->line_nums);
1604 int file_p = (func_p && ptr->filenames);
1605 int addr_p = (ptr->addresses != 0);
1606 long ncounts = ptr->ncounts;
1607 long cnt_max = 0;
1608 long line_max = 0;
1609 long addr_max = 0;
1610 int file_len = 0;
1611 int func_len = 0;
1612 int blk_len = num_digits (ncounts, 10);
1613 int cnt_len;
1614 int line_len;
1615 int addr_len;
1617 fprintf (file, "File %s, %ld basic blocks \n\n",
1618 ptr->filename, ncounts);
1620 /* Get max values for each field. */
1621 for (i = 0; i < ncounts; i++)
1623 const char *p;
1624 int len;
1626 if (cnt_max < ptr->counts[i])
1627 cnt_max = ptr->counts[i];
1629 if (addr_p && addr_max < ptr->addresses[i])
1630 addr_max = ptr->addresses[i];
1632 if (line_p && line_max < ptr->line_nums[i])
1633 line_max = ptr->line_nums[i];
1635 if (func_p)
1637 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1638 len = strlen (p);
1639 if (func_len < len)
1640 func_len = len;
1643 if (file_p)
1645 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1646 len = strlen (p);
1647 if (file_len < len)
1648 file_len = len;
1652 addr_len = num_digits (addr_max, 16);
1653 cnt_len = num_digits (cnt_max, 10);
1654 line_len = num_digits (line_max, 10);
1656 /* Now print out the basic block information. */
1657 for (i = 0; i < ncounts; i++)
1659 fprintf (file,
1660 " Block #%*d: executed %*ld time(s)",
1661 blk_len, i+1,
1662 cnt_len, ptr->counts[i]);
1664 if (addr_p)
1665 fprintf (file, " address= 0x%.*lx", addr_len,
1666 ptr->addresses[i]);
1668 if (func_p)
1669 fprintf (file, " function= %-*s", func_len,
1670 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1672 if (line_p)
1673 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1675 if (file_p)
1676 fprintf (file, " file= %s",
1677 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1679 fprintf (file, "\n");
1682 fprintf (file, "\n");
1683 fflush (file);
1686 fprintf (file, "\n\n");
1687 fclose (file);
1691 void
1692 __bb_init_func (struct bb *blocks)
1694 /* User is supposed to check whether the first word is non-0,
1695 but just in case.... */
1697 if (blocks->zero_word)
1698 return;
1700 #ifdef ON_EXIT
1701 /* Initialize destructor. */
1702 if (!bb_head)
1703 ON_EXIT (__bb_exit_func, 0);
1704 #endif
1706 /* Set up linked list. */
1707 blocks->zero_word = 1;
1708 blocks->next = bb_head;
1709 bb_head = blocks;
1712 #ifndef MACHINE_STATE_SAVE
1713 #define MACHINE_STATE_SAVE(ID)
1714 #endif
1715 #ifndef MACHINE_STATE_RESTORE
1716 #define MACHINE_STATE_RESTORE(ID)
1717 #endif
1719 #include <string.h>
1721 /* Number of buckets in hashtable of basic block addresses. */
1723 #define BB_BUCKETS 311
1725 /* Maximum length of string in file bb.in. */
1727 #define BBINBUFSIZE 500
1729 /* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
1730 "BBINBUFSIZE" but want to avoid trouble with preprocessors. */
1732 #define BBINBUFSIZESTR "499"
1734 struct bb_edge
1736 struct bb_edge *next;
1737 unsigned long src_addr;
1738 unsigned long dst_addr;
1739 unsigned long count;
1742 enum bb_func_mode
1744 TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1747 struct bb_func
1749 struct bb_func *next;
1750 char *funcname;
1751 char *filename;
1752 enum bb_func_mode mode;
1755 /* This is the connection to the outside world.
1756 The BLOCK_PROFILER macro must set __bb.blocks
1757 and __bb.blockno. */
1759 struct {
1760 unsigned long blockno;
1761 struct bb *blocks;
1762 } __bb;
1764 /* Vars to store addrs of source and destination basic blocks
1765 of a jump. */
1767 static unsigned long bb_src = 0;
1768 static unsigned long bb_dst = 0;
1770 static FILE *bb_tracefile = (FILE *) 0;
1771 static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1772 static struct bb_func *bb_func_head = (struct bb_func *) 0;
1773 static unsigned long bb_callcount = 0;
1774 static int bb_mode = 0;
1776 static unsigned long *bb_stack = (unsigned long *) 0;
1777 static size_t bb_stacksize = 0;
1779 static int reported = 0;
1781 /* Trace modes:
1782 Always : Print execution frequencies of basic blocks
1783 to file bb.out.
1784 bb_mode & 1 != 0 : Dump trace of basic blocks to file bbtrace[.gz]
1785 bb_mode & 2 != 0 : Print jump frequencies to file bb.out.
1786 bb_mode & 4 != 0 : Cut call instructions from basic block flow.
1787 bb_mode & 8 != 0 : Insert return instructions in basic block flow.
1790 #ifdef HAVE_POPEN
1792 /*#include <sys/types.h>*/
1793 #include <sys/stat.h>
1794 /*#include <malloc.h>*/
1796 /* Commands executed by gopen. */
1798 #define GOPENDECOMPRESS "gzip -cd "
1799 #define GOPENCOMPRESS "gzip -c >"
1801 /* Like fopen but pipes through gzip. mode may only be "r" or "w".
1802 If it does not compile, simply replace gopen by fopen and delete
1803 '.gz' from any first parameter to gopen. */
1805 static FILE *
1806 gopen (char *fn, char *mode)
1808 int use_gzip;
1809 char *p;
1811 if (mode[1])
1812 return (FILE *) 0;
1814 if (mode[0] != 'r' && mode[0] != 'w')
1815 return (FILE *) 0;
1817 p = fn + strlen (fn)-1;
1818 use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
1819 || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1821 if (use_gzip)
1823 if (mode[0]=='r')
1825 FILE *f;
1826 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1827 + sizeof (GOPENDECOMPRESS));
1828 strcpy (s, GOPENDECOMPRESS);
1829 strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1830 f = popen (s, mode);
1831 free (s);
1832 return f;
1835 else
1837 FILE *f;
1838 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1839 + sizeof (GOPENCOMPRESS));
1840 strcpy (s, GOPENCOMPRESS);
1841 strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1842 if (!(f = popen (s, mode)))
1843 f = fopen (s, mode);
1844 free (s);
1845 return f;
1849 else
1850 return fopen (fn, mode);
1853 static int
1854 gclose (FILE *f)
1856 struct stat buf;
1858 if (f != 0)
1860 if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1861 return pclose (f);
1863 return fclose (f);
1865 return 0;
1868 #endif /* HAVE_POPEN */
1870 /* Called once per program. */
1872 static void
1873 __bb_exit_trace_func ()
1875 FILE *file = fopen ("bb.out", "a");
1876 struct bb_func *f;
1877 struct bb_edge *e;
1878 struct bb *b;
1880 if (!file)
1881 perror ("bb.out");
1883 if (bb_mode & 1)
1885 if (!bb_tracefile)
1886 perror ("bbtrace");
1887 else
1888 #ifdef HAVE_POPEN
1889 gclose (bb_tracefile);
1890 #else
1891 fclose (bb_tracefile);
1892 #endif /* HAVE_POPEN */
1895 /* Check functions in `bb.in'. */
1897 if (file)
1899 long time_value;
1900 const struct bb_func *p;
1901 int printed_something = 0;
1902 struct bb *ptr;
1903 long blk;
1905 /* This is somewhat type incorrect. */
1906 time ((void *) &time_value);
1908 for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
1910 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1912 if (!ptr->filename || p->filename != (char *) 0 && strcmp (p->filename, ptr->filename))
1913 continue;
1914 for (blk = 0; blk < ptr->ncounts; blk++)
1916 if (!strcmp (p->funcname, ptr->functions[blk]))
1917 goto found;
1921 if (!printed_something)
1923 fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1924 printed_something = 1;
1927 fprintf (file, "\tFunction %s", p->funcname);
1928 if (p->filename)
1929 fprintf (file, " of file %s", p->filename);
1930 fprintf (file, "\n" );
1932 found: ;
1935 if (printed_something)
1936 fprintf (file, "\n");
1940 if (bb_mode & 2)
1942 if (!bb_hashbuckets)
1944 if (!reported)
1946 fprintf (stderr, "Profiler: out of memory\n");
1947 reported = 1;
1949 return;
1952 else if (file)
1954 long time_value;
1955 int i;
1956 unsigned long addr_max = 0;
1957 unsigned long cnt_max = 0;
1958 int cnt_len;
1959 int addr_len;
1961 /* This is somewhat type incorrect, but it avoids worrying about
1962 exactly where time.h is included from. It should be ok unless
1963 a void * differs from other pointer formats, or if sizeof (long)
1964 is < sizeof (time_t). It would be nice if we could assume the
1965 use of rationale standards here. */
1967 time ((void *) &time_value);
1968 fprintf (file, "Basic block jump tracing");
1970 switch (bb_mode & 12)
1972 case 0:
1973 fprintf (file, " (with call)");
1974 break;
1976 case 4:
1977 /* Print nothing. */
1978 break;
1980 case 8:
1981 fprintf (file, " (with call & ret)");
1982 break;
1984 case 12:
1985 fprintf (file, " (with ret)");
1986 break;
1989 fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1991 for (i = 0; i < BB_BUCKETS; i++)
1993 struct bb_edge *bucket = bb_hashbuckets[i];
1994 for ( ; bucket; bucket = bucket->next )
1996 if (addr_max < bucket->src_addr)
1997 addr_max = bucket->src_addr;
1998 if (addr_max < bucket->dst_addr)
1999 addr_max = bucket->dst_addr;
2000 if (cnt_max < bucket->count)
2001 cnt_max = bucket->count;
2004 addr_len = num_digits (addr_max, 16);
2005 cnt_len = num_digits (cnt_max, 10);
2007 for ( i = 0; i < BB_BUCKETS; i++)
2009 struct bb_edge *bucket = bb_hashbuckets[i];
2010 for ( ; bucket; bucket = bucket->next )
2012 fprintf (file, "Jump from block 0x%.*lx to "
2013 "block 0x%.*lx executed %*d time(s)\n",
2014 addr_len, bucket->src_addr,
2015 addr_len, bucket->dst_addr,
2016 cnt_len, bucket->count);
2020 fprintf (file, "\n");
2025 if (file)
2026 fclose (file);
2028 /* Free allocated memory. */
2030 f = bb_func_head;
2031 while (f)
2033 struct bb_func *old = f;
2035 f = f->next;
2036 if (old->funcname) free (old->funcname);
2037 if (old->filename) free (old->filename);
2038 free (old);
2041 if (bb_stack)
2042 free (bb_stack);
2044 if (bb_hashbuckets)
2046 int i;
2048 for (i = 0; i < BB_BUCKETS; i++)
2050 struct bb_edge *old, *bucket = bb_hashbuckets[i];
2052 while (bucket)
2054 old = bucket;
2055 bucket = bucket->next;
2056 free (old);
2059 free (bb_hashbuckets);
2062 for (b = bb_head; b; b = b->next)
2063 if (b->flags) free (b->flags);
2066 /* Called once per program. */
2068 static void
2069 __bb_init_prg ()
2072 FILE *file;
2073 char buf[BBINBUFSIZE];
2074 const char *p;
2075 const char *pos;
2076 enum bb_func_mode m;
2078 #ifdef ON_EXIT
2079 /* Initialize destructor. */
2080 ON_EXIT (__bb_exit_func, 0);
2081 #endif
2083 if (!(file = fopen ("bb.in", "r")))
2084 return;
2086 while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
2088 p = buf;
2089 if (*p == '-')
2091 m = TRACE_OFF;
2092 p++;
2094 else
2096 m = TRACE_ON;
2098 if (!strcmp (p, "__bb_trace__"))
2099 bb_mode |= 1;
2100 else if (!strcmp (p, "__bb_jumps__"))
2101 bb_mode |= 2;
2102 else if (!strcmp (p, "__bb_hidecall__"))
2103 bb_mode |= 4;
2104 else if (!strcmp (p, "__bb_showret__"))
2105 bb_mode |= 8;
2106 else
2108 struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
2109 if (f)
2111 unsigned long l;
2112 f->next = bb_func_head;
2113 if (pos = strchr (p, ':'))
2115 if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
2116 continue;
2117 strcpy (f->funcname, pos+1);
2118 l = pos-p;
2119 if ((f->filename = (char *) malloc (l+1)))
2121 strncpy (f->filename, p, l);
2122 f->filename[l] = '\0';
2124 else
2125 f->filename = (char *) 0;
2127 else
2129 if (!(f->funcname = (char *) malloc (strlen (p)+1)))
2130 continue;
2131 strcpy (f->funcname, p);
2132 f->filename = (char *) 0;
2134 f->mode = m;
2135 bb_func_head = f;
2139 fclose (file);
2141 #ifdef HAVE_POPEN
2143 if (bb_mode & 1)
2144 bb_tracefile = gopen ("bbtrace.gz", "w");
2146 #else
2148 if (bb_mode & 1)
2149 bb_tracefile = fopen ("bbtrace", "w");
2151 #endif /* HAVE_POPEN */
2153 if (bb_mode & 2)
2155 bb_hashbuckets = (struct bb_edge **)
2156 malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2157 if (bb_hashbuckets)
2158 bzero ((char *) bb_hashbuckets, BB_BUCKETS);
2161 if (bb_mode & 12)
2163 bb_stacksize = 10;
2164 bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2167 #ifdef ON_EXIT
2168 /* Initialize destructor. */
2169 ON_EXIT (__bb_exit_trace_func, 0);
2170 #endif
2174 /* Called upon entering a basic block. */
2176 void
2177 __bb_trace_func ()
2179 struct bb_edge *bucket;
2181 MACHINE_STATE_SAVE("1")
2183 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2184 goto skip;
2186 bb_dst = __bb.blocks->addresses[__bb.blockno];
2187 __bb.blocks->counts[__bb.blockno]++;
2189 if (bb_tracefile)
2191 fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2194 if (bb_hashbuckets)
2196 struct bb_edge **startbucket, **oldnext;
2198 oldnext = startbucket
2199 = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
2200 bucket = *startbucket;
2202 for (bucket = *startbucket; bucket;
2203 oldnext = &(bucket->next), bucket = *oldnext)
2205 if (bucket->src_addr == bb_src
2206 && bucket->dst_addr == bb_dst)
2208 bucket->count++;
2209 *oldnext = bucket->next;
2210 bucket->next = *startbucket;
2211 *startbucket = bucket;
2212 goto ret;
2216 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2218 if (!bucket)
2220 if (!reported)
2222 fprintf (stderr, "Profiler: out of memory\n");
2223 reported = 1;
2227 else
2229 bucket->src_addr = bb_src;
2230 bucket->dst_addr = bb_dst;
2231 bucket->next = *startbucket;
2232 *startbucket = bucket;
2233 bucket->count = 1;
2237 ret:
2238 bb_src = bb_dst;
2240 skip:
2243 MACHINE_STATE_RESTORE("1")
2247 /* Called when returning from a function and `__bb_showret__' is set. */
2249 static void
2250 __bb_trace_func_ret ()
2252 struct bb_edge *bucket;
2254 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2255 goto skip;
2257 if (bb_hashbuckets)
2259 struct bb_edge **startbucket, **oldnext;
2261 oldnext = startbucket
2262 = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
2263 bucket = *startbucket;
2265 for (bucket = *startbucket; bucket;
2266 oldnext = &(bucket->next), bucket = *oldnext)
2268 if (bucket->src_addr == bb_dst
2269 && bucket->dst_addr == bb_src)
2271 bucket->count++;
2272 *oldnext = bucket->next;
2273 bucket->next = *startbucket;
2274 *startbucket = bucket;
2275 goto ret;
2279 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2281 if (!bucket)
2283 if (!reported)
2285 fprintf (stderr, "Profiler: out of memory\n");
2286 reported = 1;
2290 else
2292 bucket->src_addr = bb_dst;
2293 bucket->dst_addr = bb_src;
2294 bucket->next = *startbucket;
2295 *startbucket = bucket;
2296 bucket->count = 1;
2300 ret:
2301 bb_dst = bb_src;
2303 skip:
2308 /* Called upon entering the first function of a file. */
2310 static void
2311 __bb_init_file (struct bb *blocks)
2314 const struct bb_func *p;
2315 long blk, ncounts = blocks->ncounts;
2316 const char **functions = blocks->functions;
2318 /* Set up linked list. */
2319 blocks->zero_word = 1;
2320 blocks->next = bb_head;
2321 bb_head = blocks;
2323 blocks->flags = 0;
2324 if (!bb_func_head
2325 || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
2326 return;
2328 for (blk = 0; blk < ncounts; blk++)
2329 blocks->flags[blk] = 0;
2331 for (blk = 0; blk < ncounts; blk++)
2333 for (p = bb_func_head; p; p = p->next)
2335 if (!strcmp (p->funcname, functions[blk])
2336 && (!p->filename || !strcmp (p->filename, blocks->filename)))
2338 blocks->flags[blk] |= p->mode;
2345 /* Called when exiting from a function. */
2347 void
2348 __bb_trace_ret ()
2351 MACHINE_STATE_SAVE("2")
2353 if (bb_callcount)
2355 if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2357 bb_src = bb_stack[bb_callcount];
2358 if (bb_mode & 8)
2359 __bb_trace_func_ret ();
2362 bb_callcount -= 1;
2365 MACHINE_STATE_RESTORE("2")
2369 /* Called when entering a function. */
2371 void
2372 __bb_init_trace_func (struct bb *blocks, unsigned long blockno)
2374 static int trace_init = 0;
2376 MACHINE_STATE_SAVE("3")
2378 if (!blocks->zero_word)
2380 if (!trace_init)
2382 trace_init = 1;
2383 __bb_init_prg ();
2385 __bb_init_file (blocks);
2388 if (bb_callcount)
2391 bb_callcount += 1;
2393 if (bb_mode & 12)
2395 if (bb_callcount >= bb_stacksize)
2397 size_t newsize = bb_callcount + 100;
2399 bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2400 if (! bb_stack)
2402 if (!reported)
2404 fprintf (stderr, "Profiler: out of memory\n");
2405 reported = 1;
2407 bb_stacksize = 0;
2408 goto stack_overflow;
2410 bb_stacksize = newsize;
2412 bb_stack[bb_callcount] = bb_src;
2414 if (bb_mode & 4)
2415 bb_src = 0;
2419 stack_overflow:;
2423 else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2425 bb_callcount = 1;
2426 bb_src = 0;
2428 if (bb_stack)
2429 bb_stack[bb_callcount] = bb_src;
2432 MACHINE_STATE_RESTORE("3")
2435 #endif /* not inhibit_libc */
2436 #endif /* not BLOCK_PROFILER_CODE */
2437 #endif /* L_bb */
2439 /* Default free-store management functions for C++, per sections 12.5 and
2440 17.3.3 of the Working Paper. */
2442 #ifdef L_op_new
2443 /* operator new (size_t), described in 17.3.3.5. This function is used by
2444 C++ programs to allocate a block of memory to hold a single object. */
2446 typedef void (*vfp)(void);
2447 extern vfp __new_handler;
2448 extern void __default_new_handler (void);
2450 #ifdef WEAK_ALIAS
2451 void * __builtin_new (size_t sz)
2452 __attribute__ ((weak, alias ("___builtin_new")));
2453 void *
2454 ___builtin_new (size_t sz)
2455 #else
2456 void *
2457 __builtin_new (size_t sz)
2458 #endif
2460 void *p;
2461 vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
2463 /* malloc (0) is unpredictable; avoid it. */
2464 if (sz == 0)
2465 sz = 1;
2466 p = (void *) malloc (sz);
2467 while (p == 0)
2469 (*handler) ();
2470 p = (void *) malloc (sz);
2473 return p;
2475 #endif /* L_op_new */
2477 #ifdef L_op_vnew
2478 /* void * operator new [] (size_t), described in 17.3.3.6. This function
2479 is used by C++ programs to allocate a block of memory for an array. */
2481 extern void * __builtin_new (size_t);
2483 #ifdef WEAK_ALIAS
2484 void * __builtin_vec_new (size_t sz)
2485 __attribute__ ((weak, alias ("___builtin_vec_new")));
2486 void *
2487 ___builtin_vec_new (size_t sz)
2488 #else
2489 void *
2490 __builtin_vec_new (size_t sz)
2491 #endif
2493 return __builtin_new (sz);
2495 #endif /* L_op_vnew */
2497 #ifdef L_new_handler
2498 /* set_new_handler (fvoid_t *) and the default new handler, described in
2499 17.3.3.2 and 17.3.3.5. These functions define the result of a failure
2500 to allocate the amount of memory requested from operator new or new []. */
2502 #ifndef inhibit_libc
2503 /* This gets us __GNU_LIBRARY__. */
2504 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
2505 #include <stdio.h>
2507 #ifdef __GNU_LIBRARY__
2508 /* Avoid forcing the library's meaning of `write' on the user program
2509 by using the "internal" name (for use within the library) */
2510 #define write(fd, buf, n) __write((fd), (buf), (n))
2511 #endif
2512 #endif /* inhibit_libc */
2514 typedef void (*vfp)(void);
2515 void __default_new_handler (void);
2517 vfp __new_handler = (vfp) 0;
2520 set_new_handler (vfp handler)
2522 vfp prev_handler;
2524 prev_handler = __new_handler;
2525 if (handler == 0) handler = __default_new_handler;
2526 __new_handler = handler;
2527 return prev_handler;
2530 #define MESSAGE "Virtual memory exceeded in `new'\n"
2532 void
2533 __default_new_handler ()
2535 #ifndef inhibit_libc
2536 /* don't use fprintf (stderr, ...) because it may need to call malloc. */
2537 /* This should really print the name of the program, but that is hard to
2538 do. We need a standard, clean way to get at the name. */
2539 write (2, MESSAGE, sizeof (MESSAGE));
2540 #endif
2541 /* don't call exit () because that may call global destructors which
2542 may cause a loop. */
2543 _exit (-1);
2545 #endif
2547 #ifdef L_op_delete
2548 /* operator delete (void *), described in 17.3.3.3. This function is used
2549 by C++ programs to return to the free store a block of memory allocated
2550 as a single object. */
2552 #ifdef WEAK_ALIAS
2553 void __builtin_delete (void *ptr)
2554 __attribute__ ((weak, alias ("___builtin_delete")));
2555 void
2556 ___builtin_delete (void *ptr)
2557 #else
2558 void
2559 __builtin_delete (void *ptr)
2560 #endif
2562 if (ptr)
2563 free (ptr);
2565 #endif
2567 #ifdef L_op_vdel
2568 /* operator delete [] (void *), described in 17.3.3.4. This function is
2569 used by C++ programs to return to the free store a block of memory
2570 allocated as an array. */
2572 extern void __builtin_delete (void *);
2574 #ifdef WEAK_ALIAS
2575 void __builtin_vec_delete (void *ptr)
2576 __attribute__ ((weak, alias ("___builtin_vec_delete")));
2577 void
2578 ___builtin_vec_delete (void *ptr)
2579 #else
2580 void
2581 __builtin_vec_delete (void *ptr)
2582 #endif
2584 __builtin_delete (ptr);
2586 #endif
2588 /* End of C++ free-store management functions */
2590 #ifdef L_shtab
2591 unsigned int __shtab[] = {
2592 0x00000001, 0x00000002, 0x00000004, 0x00000008,
2593 0x00000010, 0x00000020, 0x00000040, 0x00000080,
2594 0x00000100, 0x00000200, 0x00000400, 0x00000800,
2595 0x00001000, 0x00002000, 0x00004000, 0x00008000,
2596 0x00010000, 0x00020000, 0x00040000, 0x00080000,
2597 0x00100000, 0x00200000, 0x00400000, 0x00800000,
2598 0x01000000, 0x02000000, 0x04000000, 0x08000000,
2599 0x10000000, 0x20000000, 0x40000000, 0x80000000
2601 #endif
2603 #ifdef L_clear_cache
2604 /* Clear part of an instruction cache. */
2606 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2608 void
2609 __clear_cache (char *beg, char *end)
2611 #ifdef CLEAR_INSN_CACHE
2612 CLEAR_INSN_CACHE (beg, end);
2613 #else
2614 #ifdef INSN_CACHE_SIZE
2615 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
2616 static int initialized;
2617 int offset;
2618 void *start_addr
2619 void *end_addr;
2620 typedef (*function_ptr) ();
2622 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2623 /* It's cheaper to clear the whole cache.
2624 Put in a series of jump instructions so that calling the beginning
2625 of the cache will clear the whole thing. */
2627 if (! initialized)
2629 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2630 & -INSN_CACHE_LINE_WIDTH);
2631 int end_ptr = ptr + INSN_CACHE_SIZE;
2633 while (ptr < end_ptr)
2635 *(INSTRUCTION_TYPE *)ptr
2636 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2637 ptr += INSN_CACHE_LINE_WIDTH;
2639 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
2641 initialized = 1;
2644 /* Call the beginning of the sequence. */
2645 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2646 & -INSN_CACHE_LINE_WIDTH))
2647 ());
2649 #else /* Cache is large. */
2651 if (! initialized)
2653 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2654 & -INSN_CACHE_LINE_WIDTH);
2656 while (ptr < (int) array + sizeof array)
2658 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2659 ptr += INSN_CACHE_LINE_WIDTH;
2662 initialized = 1;
2665 /* Find the location in array that occupies the same cache line as BEG. */
2667 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2668 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2669 & -INSN_CACHE_PLANE_SIZE)
2670 + offset);
2672 /* Compute the cache alignment of the place to stop clearing. */
2673 #if 0 /* This is not needed for gcc's purposes. */
2674 /* If the block to clear is bigger than a cache plane,
2675 we clear the entire cache, and OFFSET is already correct. */
2676 if (end < beg + INSN_CACHE_PLANE_SIZE)
2677 #endif
2678 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2679 & -INSN_CACHE_LINE_WIDTH)
2680 & (INSN_CACHE_PLANE_SIZE - 1));
2682 #if INSN_CACHE_DEPTH > 1
2683 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2684 if (end_addr <= start_addr)
2685 end_addr += INSN_CACHE_PLANE_SIZE;
2687 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2689 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2690 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2692 while (addr != stop)
2694 /* Call the return instruction at ADDR. */
2695 ((function_ptr) addr) ();
2697 addr += INSN_CACHE_LINE_WIDTH;
2700 #else /* just one plane */
2703 /* Call the return instruction at START_ADDR. */
2704 ((function_ptr) start_addr) ();
2706 start_addr += INSN_CACHE_LINE_WIDTH;
2708 while ((start_addr % INSN_CACHE_SIZE) != offset);
2709 #endif /* just one plane */
2710 #endif /* Cache is large */
2711 #endif /* Cache exists */
2712 #endif /* CLEAR_INSN_CACHE */
2715 #endif /* L_clear_cache */
2717 #ifdef L_trampoline
2719 /* Jump to a trampoline, loading the static chain address. */
2721 #ifdef WINNT
2723 long getpagesize()
2725 #ifdef _ALPHA_
2726 return 8192;
2727 #else
2728 return 4096;
2729 #endif
2732 int mprotect(char *addr, int len, int prot)
2734 int np, op;
2736 if (prot == 7) np = 0x40;
2737 else if (prot == 5) np = 0x20;
2738 else if (prot == 4) np = 0x10;
2739 else if (prot == 3) np = 0x04;
2740 else if (prot == 1) np = 0x02;
2741 else if (prot == 0) np = 0x01;
2743 if (VirtualProtect (addr, len, np, &op))
2744 return 0;
2745 else
2746 return -1;
2750 #endif
2752 #ifdef TRANSFER_FROM_TRAMPOLINE
2753 TRANSFER_FROM_TRAMPOLINE
2754 #endif
2756 #if defined (NeXT) && defined (__MACH__)
2758 /* Make stack executable so we can call trampolines on stack.
2759 This is called from INITIALIZE_TRAMPOLINE in next.h. */
2760 #ifdef NeXTStep21
2761 #include <mach.h>
2762 #else
2763 #include <mach/mach.h>
2764 #endif
2766 void
2767 __enable_execute_stack (char *addr)
2769 kern_return_t r;
2770 char *eaddr = addr + TRAMPOLINE_SIZE;
2771 vm_address_t a = (vm_address_t) addr;
2773 /* turn on execute access on stack */
2774 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2775 if (r != KERN_SUCCESS)
2777 mach_error("vm_protect VM_PROT_ALL", r);
2778 exit(1);
2781 /* We inline the i-cache invalidation for speed */
2783 #ifdef CLEAR_INSN_CACHE
2784 CLEAR_INSN_CACHE (addr, eaddr);
2785 #else
2786 __clear_cache ((int) addr, (int) eaddr);
2787 #endif
2790 #endif /* defined (NeXT) && defined (__MACH__) */
2792 #ifdef __convex__
2794 /* Make stack executable so we can call trampolines on stack.
2795 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
2797 #include <sys/mman.h>
2798 #include <sys/vmparam.h>
2799 #include <machine/machparam.h>
2801 void
2802 __enable_execute_stack ()
2804 int fp;
2805 static unsigned lowest = USRSTACK;
2806 unsigned current = (unsigned) &fp & -NBPG;
2808 if (lowest > current)
2810 unsigned len = lowest - current;
2811 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2812 lowest = current;
2815 /* Clear instruction cache in case an old trampoline is in it. */
2816 asm ("pich");
2818 #endif /* __convex__ */
2820 #ifdef __DOLPHIN__
2822 /* Modified from the convex -code above. */
2824 #include <sys/param.h>
2825 #include <errno.h>
2826 #include <sys/m88kbcs.h>
2828 void
2829 __enable_execute_stack ()
2831 int save_errno;
2832 static unsigned long lowest = USRSTACK;
2833 unsigned long current = (unsigned long) &save_errno & -NBPC;
2835 /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2836 address is seen as 'negative'. That is the case with the stack. */
2838 save_errno=errno;
2839 if (lowest > current)
2841 unsigned len=lowest-current;
2842 memctl(current,len,MCT_TEXT);
2843 lowest = current;
2845 else
2846 memctl(current,NBPC,MCT_TEXT);
2847 errno=save_errno;
2850 #endif /* __DOLPHIN__ */
2852 #ifdef __pyr__
2854 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
2855 #include <stdio.h>
2856 #include <sys/mman.h>
2857 #include <sys/types.h>
2858 #include <sys/param.h>
2859 #include <sys/vmmac.h>
2861 /* Modified from the convex -code above.
2862 mremap promises to clear the i-cache. */
2864 void
2865 __enable_execute_stack ()
2867 int fp;
2868 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2869 PROT_READ|PROT_WRITE|PROT_EXEC))
2871 perror ("mprotect in __enable_execute_stack");
2872 fflush (stderr);
2873 abort ();
2876 #endif /* __pyr__ */
2878 #if defined (sony_news) && defined (SYSTYPE_BSD)
2880 #include <stdio.h>
2881 #include <sys/types.h>
2882 #include <sys/param.h>
2883 #include <syscall.h>
2884 #include <machine/sysnews.h>
2886 /* cacheflush function for NEWS-OS 4.2.
2887 This function is called from trampoline-initialize code
2888 defined in config/mips/mips.h. */
2890 void
2891 cacheflush (char *beg, int size, int flag)
2893 if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
2895 perror ("cache_flush");
2896 fflush (stderr);
2897 abort ();
2901 #endif /* sony_news */
2902 #endif /* L_trampoline */
2904 #ifdef L__main
2906 #include "gbl-ctors.h"
2907 /* Some systems use __main in a way incompatible with its use in gcc, in these
2908 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2909 give the same symbol without quotes for an alternative entry point. You
2910 must define both, or neither. */
2911 #ifndef NAME__MAIN
2912 #define NAME__MAIN "__main"
2913 #define SYMBOL__MAIN __main
2914 #endif
2916 #ifdef INIT_SECTION_ASM_OP
2917 #undef HAS_INIT_SECTION
2918 #define HAS_INIT_SECTION
2919 #endif
2921 #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
2922 /* Run all the global destructors on exit from the program. */
2924 void
2925 __do_global_dtors ()
2927 #ifdef DO_GLOBAL_DTORS_BODY
2928 DO_GLOBAL_DTORS_BODY;
2929 #else
2930 static func_ptr *p = __DTOR_LIST__ + 1;
2931 while (*p)
2933 p++;
2934 (*(p-1)) ();
2936 #endif
2938 #endif
2940 #ifndef HAS_INIT_SECTION
2941 /* Run all the global constructors on entry to the program. */
2943 #ifndef ON_EXIT
2944 #define ON_EXIT(a, b)
2945 #else
2946 /* Make sure the exit routine is pulled in to define the globals as
2947 bss symbols, just in case the linker does not automatically pull
2948 bss definitions from the library. */
2950 extern int _exit_dummy_decl;
2951 int *_exit_dummy_ref = &_exit_dummy_decl;
2952 #endif /* ON_EXIT */
2954 void
2955 __do_global_ctors ()
2957 DO_GLOBAL_CTORS_BODY;
2958 ON_EXIT (__do_global_dtors, 0);
2960 #endif /* no HAS_INIT_SECTION */
2962 #if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
2963 /* Subroutine called automatically by `main'.
2964 Compiling a global function named `main'
2965 produces an automatic call to this function at the beginning.
2967 For many systems, this routine calls __do_global_ctors.
2968 For systems which support a .init section we use the .init section
2969 to run __do_global_ctors, so we need not do anything here. */
2971 void
2972 SYMBOL__MAIN ()
2974 /* Support recursive calls to `main': run initializers just once. */
2975 static int initialized;
2976 if (! initialized)
2978 initialized = 1;
2979 __do_global_ctors ();
2982 #endif /* no HAS_INIT_SECTION or INVOKE__main */
2984 #endif /* L__main */
2986 #ifdef L_ctors
2988 #include "gbl-ctors.h"
2990 /* Provide default definitions for the lists of constructors and
2991 destructors, so that we don't get linker errors. These symbols are
2992 intentionally bss symbols, so that gld and/or collect will provide
2993 the right values. */
2995 /* We declare the lists here with two elements each,
2996 so that they are valid empty lists if no other definition is loaded. */
2997 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2998 #if defined(__NeXT__) || defined(_AIX)
2999 /* After 2.3, try this definition on all systems. */
3000 func_ptr __CTOR_LIST__[2] = {0, 0};
3001 func_ptr __DTOR_LIST__[2] = {0, 0};
3002 #else
3003 func_ptr __CTOR_LIST__[2];
3004 func_ptr __DTOR_LIST__[2];
3005 #endif
3006 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
3007 #endif /* L_ctors */
3009 #ifdef L_exit
3011 #include "gbl-ctors.h"
3013 #ifdef NEED_ATEXIT
3014 # ifdef ON_EXIT
3015 # undef ON_EXIT
3016 # endif
3017 int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
3018 #endif
3020 #ifndef ON_EXIT
3022 #ifdef NEED_ATEXIT
3023 # include <errno.h>
3025 static func_ptr *atexit_chain = 0;
3026 static long atexit_chain_length = 0;
3027 static volatile long last_atexit_chain_slot = -1;
3029 int atexit (func_ptr func)
3031 if (++last_atexit_chain_slot == atexit_chain_length)
3033 atexit_chain_length += 32;
3034 if (atexit_chain)
3035 atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
3036 * sizeof (func_ptr));
3037 else
3038 atexit_chain = (func_ptr *) malloc (atexit_chain_length
3039 * sizeof (func_ptr));
3040 if (! atexit_chain)
3042 atexit_chain_length = 0;
3043 last_atexit_chain_slot = -1;
3044 errno = ENOMEM;
3045 return (-1);
3048 atexit_chain[last_atexit_chain_slot] = func;
3049 return (0);
3051 #endif /* NEED_ATEXIT */
3053 /* If we have no known way of registering our own __do_global_dtors
3054 routine so that it will be invoked at program exit time, then we
3055 have to define our own exit routine which will get this to happen. */
3057 extern void __do_global_dtors ();
3058 extern void __bb_exit_func ();
3059 extern void _cleanup ();
3060 extern void _exit () __attribute__ ((noreturn));
3062 void
3063 exit (int status)
3065 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
3066 #ifdef NEED_ATEXIT
3067 if (atexit_chain)
3069 for ( ; last_atexit_chain_slot-- >= 0; )
3071 (*atexit_chain[last_atexit_chain_slot + 1]) ();
3072 atexit_chain[last_atexit_chain_slot + 1] = 0;
3074 free (atexit_chain);
3075 atexit_chain = 0;
3077 #else /* No NEED_ATEXIT */
3078 __do_global_dtors ();
3079 #endif /* No NEED_ATEXIT */
3080 #endif
3081 #ifndef inhibit_libc
3082 __bb_exit_func ();
3083 #endif
3084 #ifdef EXIT_BODY
3085 EXIT_BODY;
3086 #else
3087 _cleanup ();
3088 #endif
3089 _exit (status);
3092 #else
3093 int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
3094 #endif
3096 #endif /* L_exit */
3098 #ifdef L_eh
3100 #ifdef EH_TABLE_LOOKUP
3102 EH_TABLE_LOOKUP
3104 #else
3106 void
3107 __default_terminate ()
3109 abort ();
3112 void (*__terminate_func)() = __default_terminate;
3114 void
3115 __terminate ()
3117 (*__terminate_func)();
3120 /* Calls to __sjthrow are generated by the compiler when an exception
3121 is raised when using the setjmp/longjmp exception handling codegen
3122 method. */
3124 extern void longjmp (void *, int);
3126 extern void *__eh_type;
3128 static void *top_elt[2];
3129 void **__dynamic_handler_chain = top_elt;
3131 /* Routine to get the head of the current thread's dynamic handler chain
3132 use for exception handling.
3134 TODO: make thread safe. */
3136 void ***
3137 __get_dynamic_handler_chain ()
3139 return &__dynamic_handler_chain;
3142 /* This is used to throw an exception when the setjmp/longjmp codegen
3143 method is used for exception handling.
3145 We call __terminate if there are no handlers left (we know this
3146 when the dynamic handler chain is top_elt). Otherwise we run the
3147 cleanup actions off the dynamic cleanup stack, and pop the top of
3148 the dynamic handler chain, and use longjmp to transfer back to the
3149 associated handler. */
3151 void
3152 __sjthrow ()
3154 void ***dhc = __get_dynamic_handler_chain ();
3155 void *jmpbuf;
3156 void (*func)(void *, int);
3157 void *arg;
3158 void ***cleanup;
3160 /* The cleanup chain is one word into the buffer. Get the cleanup
3161 chain. */
3162 cleanup = (void***)&(*dhc)[1];
3164 /* If there are any cleanups in the chain, run them now. */
3165 if (cleanup[0])
3167 double store[200];
3168 void **buf = (void**)store;
3169 buf[1] = 0;
3170 buf[0] = (*dhc);
3172 /* try { */
3173 #ifdef DONT_USE_BUILTIN_SETJMP
3174 if (! setjmp (&buf[2]))
3175 #else
3176 if (! __builtin_setjmp (&buf[2]))
3177 #endif
3179 *dhc = buf;
3180 while (cleanup[0])
3182 func = (void(*)(void*, int))cleanup[0][1];
3183 arg = (void*)cleanup[0][2];
3185 /* Update this before running the cleanup. */
3186 cleanup[0] = (void **)cleanup[0][0];
3188 (*func)(arg, 2);
3190 *dhc = buf[0];
3192 /* catch (...) */
3193 else
3195 __terminate ();
3199 /* We must call terminate if we try and rethrow an exception, when
3200 there is no exception currently active and when there are no
3201 handlers left. */
3202 if (! __eh_type || (*dhc) == top_elt)
3203 __terminate ();
3205 /* Find the jmpbuf associated with the top element of the dynamic
3206 handler chain. The jumpbuf starts two words into the buffer. */
3207 jmpbuf = &(*dhc)[2];
3209 /* Then we pop the top element off the dynamic handler chain. */
3210 *dhc = (void**)(*dhc)[0];
3212 /* And then we jump to the handler. */
3214 #ifdef DONT_USE_BUILTIN_SETJMP
3215 longjmp (jmpbuf, 1);
3216 #else
3217 __builtin_longjmp (jmpbuf, 1);
3218 #endif
3221 /* Run cleanups on the dynamic cleanup stack for the current dynamic
3222 handler, then pop the handler off the dynamic handler stack, and
3223 then throw. This is used to skip the first handler, and transfer
3224 control to the next handler in the dynamic handler stack. */
3226 void
3227 __sjpopnthrow ()
3229 void ***dhc = __get_dynamic_handler_chain ();
3230 void *jmpbuf;
3231 void (*func)(void *, int);
3232 void *arg;
3233 void ***cleanup;
3235 /* The cleanup chain is one word into the buffer. Get the cleanup
3236 chain. */
3237 cleanup = (void***)&(*dhc)[1];
3239 /* If there are any cleanups in the chain, run them now. */
3240 if (cleanup[0])
3242 double store[200];
3243 void **buf = (void**)store;
3244 buf[1] = 0;
3245 buf[0] = (*dhc);
3247 /* try { */
3248 #ifdef DONT_USE_BUILTIN_SETJMP
3249 if (! setjmp (&buf[2]))
3250 #else
3251 if (! __builtin_setjmp (&buf[2]))
3252 #endif
3254 *dhc = buf;
3255 while (cleanup[0])
3257 func = (void(*)(void*, int))cleanup[0][1];
3258 arg = (void*)cleanup[0][2];
3260 /* Update this before running the cleanup. */
3261 cleanup[0] = (void **)cleanup[0][0];
3263 (*func)(arg, 2);
3265 *dhc = buf[0];
3267 /* catch (...) */
3268 else
3270 __terminate ();
3274 /* Then we pop the top element off the dynamic handler chain. */
3275 *dhc = (void**)(*dhc)[0];
3277 __sjthrow ();
3280 typedef struct {
3281 void *start;
3282 void *end;
3283 void *exception_handler;
3284 } exception_table;
3286 struct exception_table_node {
3287 exception_table *table;
3288 void *start;
3289 void *end;
3290 struct exception_table_node *next;
3293 static struct exception_table_node *exception_table_list;
3295 /* this routine takes a pc, and the address of the exception handler associated
3296 with the closest exception table handler entry associated with that PC,
3297 or 0 if there are no table entries the PC fits in. The algorithm works
3298 something like this:
3300 while(current_entry exists) {
3301 if(current_entry.start < pc )
3302 current_entry = next_entry;
3303 else {
3304 if(prev_entry.start <= pc && prev_entry.end > pc) {
3305 save pointer to prev_entry;
3306 return prev_entry.exception_handler;
3308 else return 0;
3311 return 0;
3313 Assuming a correctly sorted table (ascending order) this routine should
3314 return the tightest match...
3316 In the advent of a tie, we have to give the last entry, as it represents
3317 an inner block. */
3319 void *
3320 __find_first_exception_table_match (void *pc)
3322 register struct exception_table_node *tnp;
3323 register exception_table *table;
3324 int pos;
3325 int best;
3327 #if 0
3328 printf ("find_first_exception_table_match (): pc = %x!\n", pc);
3329 #endif
3331 for (tnp = exception_table_list; tnp != 0; tnp = tnp->next)
3333 if (tnp->start > pc || tnp->end <= pc)
3334 continue;
3336 table = tnp->table;
3338 pos = 0;
3339 best = 0;
3340 #if 0
3341 /* We can't do this yet, as we don't know that the table is sorted. */
3342 do {
3343 ++pos;
3344 if (table[pos].start > pc)
3345 /* found the first table[pos].start > pc, so the previous
3346 entry better be the one we want! */
3347 break;
3348 } while (table[pos].exception_handler != (void *) -1);
3350 --pos;
3351 if (table[pos].start <= pc && table[pos].end > pc)
3353 #if 0
3354 printf ("find_first_eh_table_match (): found match: %x\n", table[pos].exception_handler);
3355 #endif
3356 return table[pos].exception_handler;
3358 #else
3359 while (table[++pos].exception_handler != (void *) -1) {
3360 if (table[pos].start <= pc && table[pos].end > pc)
3362 /* This can apply. Make sure it is better or as good as
3363 the previous best. */
3364 /* The best one ends first. */
3365 if (best == 0 || (table[pos].end <= table[best].end
3366 /* The best one starts last. */
3367 && table[pos].start >= table[best].start))
3368 best = pos;
3371 if (best != 0)
3372 return table[best].exception_handler;
3373 #endif
3376 #if 0
3377 printf ("find_first_eh_table_match (): else: returning NULL!\n");
3378 #endif
3379 return (void *) 0;
3382 void
3383 __register_exceptions (exception_table *table)
3385 struct exception_table_node *node;
3386 exception_table *range = table + 1;
3388 if (range->start == (void *) -1)
3389 return;
3391 node = (struct exception_table_node *)
3392 malloc (sizeof (struct exception_table_node));
3393 node->table = table;
3395 /* This look can be optimized away either if the table
3396 is sorted, or if we pass in extra parameters. */
3397 node->start = range->start;
3398 node->end = range->end;
3399 for (range++ ; range->start != (void *) (-1); range++)
3401 if (range->start < node->start)
3402 node->start = range->start;
3403 if (range->end > node->end)
3404 node->end = range->end;
3407 node->next = exception_table_list;
3408 exception_table_list = node;
3410 #endif
3412 void *
3413 __throw_type_match (void *catch_type, void *throw_type, void *obj)
3415 #if 0
3416 printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3417 catch_type, throw_type);
3418 #endif
3419 if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3420 return obj;
3421 return 0;
3424 /* Throw stub routine.
3426 This is work in progress, but not completed yet. */
3428 void
3429 __throw ()
3431 abort ();
3434 /* This value identifies the place from which an exception is being
3435 thrown. */
3437 void *__eh_pc;
3439 /* See expand_builtin_throw for details. */
3441 void **__eh_ffetmnpc () {
3442 static void *buf[2] = {
3443 &__find_first_exception_table_match,
3444 &__eh_pc
3446 return buf;
3449 void
3450 __empty ()
3454 #if #machine(i386)
3455 void
3456 __unwind_function(void *ptr)
3458 asm("movl 8(%esp),%ecx");
3459 /* Undo current frame */
3460 asm("movl %ebp,%esp");
3461 asm("popl %ebp");
3462 /* like ret, but stay here */
3463 asm("addl $4,%esp");
3465 /* Now, undo previous frame. */
3466 /* This is a test routine, as we have to dynamically probe to find out
3467 what to pop for certain, this is just a guess. */
3468 asm("leal -16(%ebp),%esp");
3469 asm("pop %ebx");
3470 asm("pop %esi");
3471 asm("pop %edi");
3472 asm("movl %ebp,%esp");
3473 asm("popl %ebp");
3475 asm("movl %ecx,0(%esp)");
3476 asm("ret");
3478 #elif #machine(rs6000) && !defined _ARCH_PPC
3479 __unwind_function(void *ptr)
3481 asm("mr 31,1");
3482 asm("l 1,0(1)");
3483 asm("l 31,-4(1)");
3484 asm("# br");
3486 asm("mr 31,1");
3487 asm("l 1,0(1)");
3488 /* use 31 as a scratch register to restore the link register. */
3489 asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
3490 asm("l 31,-4(1)");
3491 asm("# br");
3492 asm("mtctr 3;bctr # b 3");
3494 #elif (#machine(rs6000) || #machine(powerpc)) && defined _ARCH_PPC
3495 __unwind_function(void *ptr)
3497 asm("mr 31,1");
3498 asm("lwz 1,0(1)");
3499 asm("lwz 31,-4(1)");
3500 asm("# br");
3502 asm("mr 31,1");
3503 asm("lwz 1,0(1)");
3504 /* use 31 as a scratch register to restore the link register. */
3505 asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
3506 asm("lwz 31,-4(1)");
3507 asm("# br");
3508 asm("mtctr 3;bctr # b 3");
3510 #elif #machine(vax)
3511 __unwind_function(void *ptr)
3513 __label__ return_again;
3515 /* Replace our frame's return address with the label below.
3516 During execution, we will first return here instead of to
3517 caller, then second return takes caller's frame off the stack.
3518 Two returns matches two actual calls, so is less likely to
3519 confuse debuggers. `16' corresponds to RETURN_ADDRESS_OFFSET. */
3520 __asm ("movl %0,16(fp)" : : "p" (&& return_again));
3521 return;
3523 return_again:
3524 return;
3526 #else
3527 __unwind_function(void *ptr)
3529 abort ();
3531 #endif /* powerpc */
3532 #endif /* L_eh */
3534 #ifdef L_pure
3535 #ifndef inhibit_libc
3536 /* This gets us __GNU_LIBRARY__. */
3537 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
3538 #include <stdio.h>
3540 #ifdef __GNU_LIBRARY__
3541 /* Avoid forcing the library's meaning of `write' on the user program
3542 by using the "internal" name (for use within the library) */
3543 #define write(fd, buf, n) __write((fd), (buf), (n))
3544 #endif
3545 #endif /* inhibit_libc */
3547 #define MESSAGE "pure virtual method called\n"
3549 void
3550 __pure_virtual ()
3552 #ifndef inhibit_libc
3553 write (2, MESSAGE, sizeof (MESSAGE) - 1);
3554 #endif
3555 _exit (-1);
3557 #endif