OSDN Git Service

(struct bb): Add flags field.
[pf3gnuchains/gcc-fork.git] / gcc / libgcc2.c
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 Free Software Foundation, Inc.
4
5 This file is part of GNU CC.
6
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.
11
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.
16
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.  */
21
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.  */
28
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.  */
32
33 #include "tconfig.h"
34 #include "machmode.h"
35 #include "defaults.h" 
36 #ifndef L_trampoline
37 #include <stddef.h>
38 #endif
39
40 /* Don't use `fancy_abort' here even if config.h says to use it.  */
41 #ifdef abort
42 #undef abort
43 #endif
44
45 #if (SUPPORTS_WEAK == 1) && defined (ASM_OUTPUT_DEF)
46 #define WEAK_ALIAS
47 #endif
48
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.  */
52
53 #ifndef LIBGCC2_WORDS_BIG_ENDIAN
54 #define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
55 #endif
56
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.  */
65
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)));
71
72 typedef         float SFtype    __attribute__ ((mode (SF)));
73 typedef         float DFtype    __attribute__ ((mode (DF)));
74
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
81
82 typedef int word_type __attribute__ ((mode (__word__)));
83
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.  */
89
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
97
98 #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
99
100 /* DIstructs are pairs of SItype values in the order determined by
101    LIBGCC2_WORDS_BIG_ENDIAN.  */
102
103 #if LIBGCC2_WORDS_BIG_ENDIAN
104   struct DIstruct {SItype high, low;};
105 #else
106   struct DIstruct {SItype low, high;};
107 #endif
108
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'.  */
112
113 typedef union
114 {
115   struct DIstruct s;
116   DItype ll;
117 } DIunion;
118
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))
122
123 #include "longlong.h"
124
125 #endif /* udiv or mul */
126
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
135 \f
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 (u)
142      DItype u;
143 {
144   DIunion w;
145   DIunion uu;
146
147   uu.ll = u;
148
149   w.s.low = -uu.s.low;
150   w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
151
152   return w.ll;
153 }
154 #endif
155 \f
156 #ifdef L_lshrdi3
157 DItype
158 __lshrdi3 (u, b)
159      DItype u;
160      word_type b;
161 {
162   DIunion w;
163   word_type bm;
164   DIunion uu;
165
166   if (b == 0)
167     return u;
168
169   uu.ll = u;
170
171   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
172   if (bm <= 0)
173     {
174       w.s.high = 0;
175       w.s.low = (USItype)uu.s.high >> -bm;
176     }
177   else
178     {
179       USItype carries = (USItype)uu.s.high << bm;
180       w.s.high = (USItype)uu.s.high >> b;
181       w.s.low = ((USItype)uu.s.low >> b) | carries;
182     }
183
184   return w.ll;
185 }
186 #endif
187
188 #ifdef L_ashldi3
189 DItype
190 __ashldi3 (u, b)
191      DItype u;
192      word_type b;
193 {
194   DIunion w;
195   word_type bm;
196   DIunion uu;
197
198   if (b == 0)
199     return u;
200
201   uu.ll = u;
202
203   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
204   if (bm <= 0)
205     {
206       w.s.low = 0;
207       w.s.high = (USItype)uu.s.low << -bm;
208     }
209   else
210     {
211       USItype carries = (USItype)uu.s.low >> bm;
212       w.s.low = (USItype)uu.s.low << b;
213       w.s.high = ((USItype)uu.s.high << b) | carries;
214     }
215
216   return w.ll;
217 }
218 #endif
219
220 #ifdef L_ashrdi3
221 DItype
222 __ashrdi3 (u, b)
223      DItype u;
224      word_type b;
225 {
226   DIunion w;
227   word_type bm;
228   DIunion uu;
229
230   if (b == 0)
231     return u;
232
233   uu.ll = u;
234
235   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
236   if (bm <= 0)
237     {
238       /* w.s.high = 1..1 or 0..0 */
239       w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
240       w.s.low = uu.s.high >> -bm;
241     }
242   else
243     {
244       USItype carries = (USItype)uu.s.high << bm;
245       w.s.high = uu.s.high >> b;
246       w.s.low = ((USItype)uu.s.low >> b) | carries;
247     }
248
249   return w.ll;
250 }
251 #endif
252 \f
253 #ifdef L_ffsdi2
254 DItype
255 __ffsdi2 (u)
256      DItype u;
257 {
258   DIunion uu, w;
259   uu.ll = u;
260   w.s.high = 0;
261   w.s.low = ffs (uu.s.low);
262   if (w.s.low != 0)
263     return w.ll;
264   w.s.low = ffs (uu.s.high);
265   if (w.s.low != 0)
266     {
267       w.s.low += BITS_PER_UNIT * sizeof (SItype);
268       return w.ll;
269     }
270   return w.ll;
271 }
272 #endif
273 \f
274 #ifdef L_muldi3
275 DItype
276 __muldi3 (u, v)
277      DItype u, v;
278 {
279   DIunion w;
280   DIunion uu, vv;
281
282   uu.ll = u,
283   vv.ll = v;
284
285   w.ll = __umulsidi3 (uu.s.low, vv.s.low);
286   w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
287                + (USItype) uu.s.high * (USItype) vv.s.low);
288
289   return w.ll;
290 }
291 #endif
292 \f
293 #ifdef L_udiv_w_sdiv
294 #if defined (sdiv_qrnnd)
295 USItype
296 __udiv_w_sdiv (rp, a1, a0, d)
297      USItype *rp, a1, a0, d;
298 {
299   USItype q, r;
300   USItype c0, c1, b1;
301
302   if ((SItype) d >= 0)
303     {
304       if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
305         {
306           /* dividend, divisor, and quotient are nonnegative */
307           sdiv_qrnnd (q, r, a1, a0, d);
308         }
309       else
310         {
311           /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
312           sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
313           /* Divide (c1*2^32 + c0) by d */
314           sdiv_qrnnd (q, r, c1, c0, d);
315           /* Add 2^31 to quotient */
316           q += (USItype) 1 << (SI_TYPE_SIZE - 1);
317         }
318     }
319   else
320     {
321       b1 = d >> 1;                      /* d/2, between 2^30 and 2^31 - 1 */
322       c1 = a1 >> 1;                     /* A/2 */
323       c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
324
325       if (a1 < b1)                      /* A < 2^32*b1, so A/2 < 2^31*b1 */
326         {
327           sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
328
329           r = 2*r + (a0 & 1);           /* Remainder from A/(2*b1) */
330           if ((d & 1) != 0)
331             {
332               if (r >= q)
333                 r = r - q;
334               else if (q - r <= d)
335                 {
336                   r = r - q + d;
337                   q--;
338                 }
339               else
340                 {
341                   r = r - q + 2*d;
342                   q -= 2;
343                 }
344             }
345         }
346       else if (c1 < b1)                 /* So 2^31 <= (A/2)/b1 < 2^32 */
347         {
348           c1 = (b1 - 1) - c1;
349           c0 = ~c0;                     /* logical NOT */
350
351           sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
352
353           q = ~q;                       /* (A/2)/b1 */
354           r = (b1 - 1) - r;
355
356           r = 2*r + (a0 & 1);           /* A/(2*b1) */
357
358           if ((d & 1) != 0)
359             {
360               if (r >= q)
361                 r = r - q;
362               else if (q - r <= d)
363                 {
364                   r = r - q + d;
365                   q--;
366                 }
367               else
368                 {
369                   r = r - q + 2*d;
370                   q -= 2;
371                 }
372             }
373         }
374       else                              /* Implies c1 = b1 */
375         {                               /* Hence a1 = d - 1 = 2*b1 - 1 */
376           if (a0 >= -d)
377             {
378               q = -1;
379               r = a0 + d;
380             }
381           else
382             {
383               q = -2;
384               r = a0 + 2*d;
385             }
386         }
387     }
388
389   *rp = r;
390   return q;
391 }
392 #else
393 /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv.  */
394 USItype
395 __udiv_w_sdiv (rp, a1, a0, d)
396      USItype *rp, a1, a0, d;
397 {}
398 #endif
399 #endif
400 \f
401 #if (defined (L_udivdi3) || defined (L_divdi3) || \
402      defined (L_umoddi3) || defined (L_moddi3))
403 #define L_udivmoddi4
404 #endif
405
406 #ifdef L_udivmoddi4
407 static const UQItype __clz_tab[] =
408 {
409   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,
410   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,
411   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,
412   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,
413   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,
414   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,
415   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,
416   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,
417 };
418
419 #if (defined (L_udivdi3) || defined (L_divdi3) || \
420      defined (L_umoddi3) || defined (L_moddi3))
421 static inline
422 #endif
423 UDItype
424 __udivmoddi4 (n, d, rp)
425      UDItype n, d;
426      UDItype *rp;
427 {
428   DIunion ww;
429   DIunion nn, dd;
430   DIunion rr;
431   USItype d0, d1, n0, n1, n2;
432   USItype q0, q1;
433   USItype b, bm;
434
435   nn.ll = n;
436   dd.ll = d;
437
438   d0 = dd.s.low;
439   d1 = dd.s.high;
440   n0 = nn.s.low;
441   n1 = nn.s.high;
442
443 #if !UDIV_NEEDS_NORMALIZATION
444   if (d1 == 0)
445     {
446       if (d0 > n1)
447         {
448           /* 0q = nn / 0D */
449
450           udiv_qrnnd (q0, n0, n1, n0, d0);
451           q1 = 0;
452
453           /* Remainder in n0.  */
454         }
455       else
456         {
457           /* qq = NN / 0d */
458
459           if (d0 == 0)
460             d0 = 1 / d0;        /* Divide intentionally by zero.  */
461
462           udiv_qrnnd (q1, n1, 0, n1, d0);
463           udiv_qrnnd (q0, n0, n1, n0, d0);
464
465           /* Remainder in n0.  */
466         }
467
468       if (rp != 0)
469         {
470           rr.s.low = n0;
471           rr.s.high = 0;
472           *rp = rr.ll;
473         }
474     }
475
476 #else /* UDIV_NEEDS_NORMALIZATION */
477
478   if (d1 == 0)
479     {
480       if (d0 > n1)
481         {
482           /* 0q = nn / 0D */
483
484           count_leading_zeros (bm, d0);
485
486           if (bm != 0)
487             {
488               /* Normalize, i.e. make the most significant bit of the
489                  denominator set.  */
490
491               d0 = d0 << bm;
492               n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
493               n0 = n0 << bm;
494             }
495
496           udiv_qrnnd (q0, n0, n1, n0, d0);
497           q1 = 0;
498
499           /* Remainder in n0 >> bm.  */
500         }
501       else
502         {
503           /* qq = NN / 0d */
504
505           if (d0 == 0)
506             d0 = 1 / d0;        /* Divide intentionally by zero.  */
507
508           count_leading_zeros (bm, d0);
509
510           if (bm == 0)
511             {
512               /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
513                  conclude (the most significant bit of n1 is set) /\ (the
514                  leading quotient digit q1 = 1).
515
516                  This special case is necessary, not an optimization.
517                  (Shifts counts of SI_TYPE_SIZE are undefined.)  */
518
519               n1 -= d0;
520               q1 = 1;
521             }
522           else
523             {
524               /* Normalize.  */
525
526               b = SI_TYPE_SIZE - bm;
527
528               d0 = d0 << bm;
529               n2 = n1 >> b;
530               n1 = (n1 << bm) | (n0 >> b);
531               n0 = n0 << bm;
532
533               udiv_qrnnd (q1, n1, n2, n1, d0);
534             }
535
536           /* n1 != d0... */
537
538           udiv_qrnnd (q0, n0, n1, n0, d0);
539
540           /* Remainder in n0 >> bm.  */
541         }
542
543       if (rp != 0)
544         {
545           rr.s.low = n0 >> bm;
546           rr.s.high = 0;
547           *rp = rr.ll;
548         }
549     }
550 #endif /* UDIV_NEEDS_NORMALIZATION */
551
552   else
553     {
554       if (d1 > n1)
555         {
556           /* 00 = nn / DD */
557
558           q0 = 0;
559           q1 = 0;
560
561           /* Remainder in n1n0.  */
562           if (rp != 0)
563             {
564               rr.s.low = n0;
565               rr.s.high = n1;
566               *rp = rr.ll;
567             }
568         }
569       else
570         {
571           /* 0q = NN / dd */
572
573           count_leading_zeros (bm, d1);
574           if (bm == 0)
575             {
576               /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
577                  conclude (the most significant bit of n1 is set) /\ (the
578                  quotient digit q0 = 0 or 1).
579
580                  This special case is necessary, not an optimization.  */
581
582               /* The condition on the next line takes advantage of that
583                  n1 >= d1 (true due to program flow).  */
584               if (n1 > d1 || n0 >= d0)
585                 {
586                   q0 = 1;
587                   sub_ddmmss (n1, n0, n1, n0, d1, d0);
588                 }
589               else
590                 q0 = 0;
591
592               q1 = 0;
593
594               if (rp != 0)
595                 {
596                   rr.s.low = n0;
597                   rr.s.high = n1;
598                   *rp = rr.ll;
599                 }
600             }
601           else
602             {
603               USItype m1, m0;
604               /* Normalize.  */
605
606               b = SI_TYPE_SIZE - bm;
607
608               d1 = (d1 << bm) | (d0 >> b);
609               d0 = d0 << bm;
610               n2 = n1 >> b;
611               n1 = (n1 << bm) | (n0 >> b);
612               n0 = n0 << bm;
613
614               udiv_qrnnd (q0, n1, n2, n1, d1);
615               umul_ppmm (m1, m0, q0, d0);
616
617               if (m1 > n1 || (m1 == n1 && m0 > n0))
618                 {
619                   q0--;
620                   sub_ddmmss (m1, m0, m1, m0, d1, d0);
621                 }
622
623               q1 = 0;
624
625               /* Remainder in (n1n0 - m1m0) >> bm.  */
626               if (rp != 0)
627                 {
628                   sub_ddmmss (n1, n0, n1, n0, m1, m0);
629                   rr.s.low = (n1 << b) | (n0 >> bm);
630                   rr.s.high = n1 >> bm;
631                   *rp = rr.ll;
632                 }
633             }
634         }
635     }
636
637   ww.s.low = q0;
638   ww.s.high = q1;
639   return ww.ll;
640 }
641 #endif
642
643 #ifdef L_divdi3
644 UDItype __udivmoddi4 ();
645
646 DItype
647 __divdi3 (u, v)
648      DItype u, v;
649 {
650   word_type c = 0;
651   DIunion uu, vv;
652   DItype w;
653
654   uu.ll = u;
655   vv.ll = v;
656
657   if (uu.s.high < 0)
658     c = ~c,
659     uu.ll = __negdi2 (uu.ll);
660   if (vv.s.high < 0)
661     c = ~c,
662     vv.ll = __negdi2 (vv.ll);
663
664   w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
665   if (c)
666     w = __negdi2 (w);
667
668   return w;
669 }
670 #endif
671
672 #ifdef L_moddi3
673 UDItype __udivmoddi4 ();
674 DItype
675 __moddi3 (u, v)
676      DItype u, v;
677 {
678   word_type c = 0;
679   DIunion uu, vv;
680   DItype w;
681
682   uu.ll = u;
683   vv.ll = v;
684
685   if (uu.s.high < 0)
686     c = ~c,
687     uu.ll = __negdi2 (uu.ll);
688   if (vv.s.high < 0)
689     vv.ll = __negdi2 (vv.ll);
690
691   (void) __udivmoddi4 (uu.ll, vv.ll, &w);
692   if (c)
693     w = __negdi2 (w);
694
695   return w;
696 }
697 #endif
698
699 #ifdef L_umoddi3
700 UDItype __udivmoddi4 ();
701 UDItype
702 __umoddi3 (u, v)
703      UDItype u, v;
704 {
705   UDItype w;
706
707   (void) __udivmoddi4 (u, v, &w);
708
709   return w;
710 }
711 #endif
712
713 #ifdef L_udivdi3
714 UDItype __udivmoddi4 ();
715 UDItype
716 __udivdi3 (n, d)
717      UDItype n, d;
718 {
719   return __udivmoddi4 (n, d, (UDItype *) 0);
720 }
721 #endif
722 \f
723 #ifdef L_cmpdi2
724 word_type
725 __cmpdi2 (a, b)
726      DItype a, b;
727 {
728   DIunion au, bu;
729
730   au.ll = a, bu.ll = b;
731
732   if (au.s.high < bu.s.high)
733     return 0;
734   else if (au.s.high > bu.s.high)
735     return 2;
736   if ((USItype) au.s.low < (USItype) bu.s.low)
737     return 0;
738   else if ((USItype) au.s.low > (USItype) bu.s.low)
739     return 2;
740   return 1;
741 }
742 #endif
743
744 #ifdef L_ucmpdi2
745 word_type
746 __ucmpdi2 (a, b)
747      DItype a, b;
748 {
749   DIunion au, bu;
750
751   au.ll = a, bu.ll = b;
752
753   if ((USItype) au.s.high < (USItype) bu.s.high)
754     return 0;
755   else if ((USItype) au.s.high > (USItype) bu.s.high)
756     return 2;
757   if ((USItype) au.s.low < (USItype) bu.s.low)
758     return 0;
759   else if ((USItype) au.s.low > (USItype) bu.s.low)
760     return 2;
761   return 1;
762 }
763 #endif
764 \f
765 #if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
766 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
767 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
768
769 DItype
770 __fixunstfdi (a)
771      TFtype a;
772 {
773   TFtype b;
774   UDItype v;
775
776   if (a < 0)
777     return 0;
778
779   /* Compute high word of result, as a flonum.  */
780   b = (a / HIGH_WORD_COEFF);
781   /* Convert that to fixed (but not to DItype!),
782      and shift it into the high word.  */
783   v = (USItype) b;
784   v <<= WORD_SIZE;
785   /* Remove high part from the TFtype, leaving the low part as flonum.  */
786   a -= (TFtype)v;
787   /* Convert that to fixed (but not to DItype!) and add it in.
788      Sometimes A comes out negative.  This is significant, since
789      A has more bits than a long int does.  */
790   if (a < 0)
791     v -= (USItype) (- a);
792   else
793     v += (USItype) a;
794   return v;
795 }
796 #endif
797
798 #if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
799 DItype
800 __fixtfdi (a)
801      TFtype a;
802 {
803   if (a < 0)
804     return - __fixunstfdi (-a);
805   return __fixunstfdi (a);
806 }
807 #endif
808
809 #if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
810 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
811 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
812
813 DItype
814 __fixunsxfdi (a)
815      XFtype a;
816 {
817   XFtype b;
818   UDItype v;
819
820   if (a < 0)
821     return 0;
822
823   /* Compute high word of result, as a flonum.  */
824   b = (a / HIGH_WORD_COEFF);
825   /* Convert that to fixed (but not to DItype!),
826      and shift it into the high word.  */
827   v = (USItype) b;
828   v <<= WORD_SIZE;
829   /* Remove high part from the XFtype, leaving the low part as flonum.  */
830   a -= (XFtype)v;
831   /* Convert that to fixed (but not to DItype!) and add it in.
832      Sometimes A comes out negative.  This is significant, since
833      A has more bits than a long int does.  */
834   if (a < 0)
835     v -= (USItype) (- a);
836   else
837     v += (USItype) a;
838   return v;
839 }
840 #endif
841
842 #if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
843 DItype
844 __fixxfdi (a)
845      XFtype a;
846 {
847   if (a < 0)
848     return - __fixunsxfdi (-a);
849   return __fixunsxfdi (a);
850 }
851 #endif
852
853 #ifdef L_fixunsdfdi
854 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
855 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
856
857 DItype
858 __fixunsdfdi (a)
859      DFtype a;
860 {
861   DFtype b;
862   UDItype v;
863
864   if (a < 0)
865     return 0;
866
867   /* Compute high word of result, as a flonum.  */
868   b = (a / HIGH_WORD_COEFF);
869   /* Convert that to fixed (but not to DItype!),
870      and shift it into the high word.  */
871   v = (USItype) b;
872   v <<= WORD_SIZE;
873   /* Remove high part from the DFtype, leaving the low part as flonum.  */
874   a -= (DFtype)v;
875   /* Convert that to fixed (but not to DItype!) and add it in.
876      Sometimes A comes out negative.  This is significant, since
877      A has more bits than a long int does.  */
878   if (a < 0)
879     v -= (USItype) (- a);
880   else
881     v += (USItype) a;
882   return v;
883 }
884 #endif
885
886 #ifdef L_fixdfdi
887 DItype
888 __fixdfdi (a)
889      DFtype a;
890 {
891   if (a < 0)
892     return - __fixunsdfdi (-a);
893   return __fixunsdfdi (a);
894 }
895 #endif
896
897 #ifdef L_fixunssfdi
898 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
899 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
900
901 DItype
902 __fixunssfdi (SFtype original_a)
903 {
904   /* Convert the SFtype to a DFtype, because that is surely not going
905      to lose any bits.  Some day someone else can write a faster version
906      that avoids converting to DFtype, and verify it really works right.  */
907   DFtype a = original_a;
908   DFtype b;
909   UDItype v;
910
911   if (a < 0)
912     return 0;
913
914   /* Compute high word of result, as a flonum.  */
915   b = (a / HIGH_WORD_COEFF);
916   /* Convert that to fixed (but not to DItype!),
917      and shift it into the high word.  */
918   v = (USItype) b;
919   v <<= WORD_SIZE;
920   /* Remove high part from the DFtype, leaving the low part as flonum.  */
921   a -= (DFtype)v;
922   /* Convert that to fixed (but not to DItype!) and add it in.
923      Sometimes A comes out negative.  This is significant, since
924      A has more bits than a long int does.  */
925   if (a < 0)
926     v -= (USItype) (- a);
927   else
928     v += (USItype) a;
929   return v;
930 }
931 #endif
932
933 #ifdef L_fixsfdi
934 DItype
935 __fixsfdi (SFtype a)
936 {
937   if (a < 0)
938     return - __fixunssfdi (-a);
939   return __fixunssfdi (a);
940 }
941 #endif
942
943 #if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
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)
947
948 XFtype
949 __floatdixf (u)
950      DItype u;
951 {
952   XFtype d;
953   SItype negate = 0;
954
955   if (u < 0)
956     u = -u, negate = 1;
957
958   d = (USItype) (u >> WORD_SIZE);
959   d *= HIGH_HALFWORD_COEFF;
960   d *= HIGH_HALFWORD_COEFF;
961   d += (USItype) (u & (HIGH_WORD_COEFF - 1));
962
963   return (negate ? -d : d);
964 }
965 #endif
966
967 #if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
968 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
969 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
970 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
971
972 TFtype
973 __floatditf (u)
974      DItype u;
975 {
976   TFtype d;
977   SItype negate = 0;
978
979   if (u < 0)
980     u = -u, negate = 1;
981
982   d = (USItype) (u >> WORD_SIZE);
983   d *= HIGH_HALFWORD_COEFF;
984   d *= HIGH_HALFWORD_COEFF;
985   d += (USItype) (u & (HIGH_WORD_COEFF - 1));
986
987   return (negate ? -d : d);
988 }
989 #endif
990
991 #ifdef L_floatdidf
992 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
993 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
994 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
995
996 DFtype
997 __floatdidf (u)
998      DItype u;
999 {
1000   DFtype d;
1001   SItype negate = 0;
1002
1003   if (u < 0)
1004     u = -u, negate = 1;
1005
1006   d = (USItype) (u >> WORD_SIZE);
1007   d *= HIGH_HALFWORD_COEFF;
1008   d *= HIGH_HALFWORD_COEFF;
1009   d += (USItype) (u & (HIGH_WORD_COEFF - 1));
1010
1011   return (negate ? -d : d);
1012 }
1013 #endif
1014
1015 #ifdef L_floatdisf
1016 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
1017 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
1018 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
1019 #define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
1020
1021 /* Define codes for all the float formats that we know of.  Note
1022    that this is copied from real.h.  */
1023    
1024 #define UNKNOWN_FLOAT_FORMAT 0
1025 #define IEEE_FLOAT_FORMAT 1
1026 #define VAX_FLOAT_FORMAT 2
1027 #define IBM_FLOAT_FORMAT 3
1028
1029 /* Default to IEEE float if not specified.  Nearly all machines use it.  */
1030 #ifndef HOST_FLOAT_FORMAT
1031 #define HOST_FLOAT_FORMAT       IEEE_FLOAT_FORMAT
1032 #endif
1033
1034 #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
1035 #define DF_SIZE 53
1036 #define SF_SIZE 24
1037 #endif
1038
1039 #if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
1040 #define DF_SIZE 56
1041 #define SF_SIZE 24
1042 #endif
1043
1044 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
1045 #define DF_SIZE 56
1046 #define SF_SIZE 24
1047 #endif
1048
1049 SFtype
1050 __floatdisf (u)
1051      DItype u;
1052 {
1053   /* Do the calculation in DFmode
1054      so that we don't lose any of the precision of the high word
1055      while multiplying it.  */
1056   DFtype f;
1057   SItype negate = 0;
1058
1059   if (u < 0)
1060     u = -u, negate = 1;
1061
1062   /* Protect against double-rounding error.
1063      Represent any low-order bits, that might be truncated in DFmode,
1064      by a bit that won't be lost.  The bit can go in anywhere below the
1065      rounding position of the SFmode.  A fixed mask and bit position
1066      handles all usual configurations.  It doesn't handle the case
1067      of 128-bit DImode, however.  */
1068   if (DF_SIZE < DI_SIZE
1069       && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1070     {
1071 #define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
1072       if (u >= ((UDItype) 1 << DF_SIZE))
1073         {
1074           if ((USItype) u & (REP_BIT - 1))
1075             u |= REP_BIT;
1076         }
1077     }
1078   f = (USItype) (u >> WORD_SIZE);
1079   f *= HIGH_HALFWORD_COEFF;
1080   f *= HIGH_HALFWORD_COEFF;
1081   f += (USItype) (u & (HIGH_WORD_COEFF - 1));
1082
1083   return (SFtype) (negate ? -f : f);
1084 }
1085 #endif
1086
1087 #if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
1088 /* Reenable the normal types, in case limits.h needs them.  */
1089 #undef char
1090 #undef short
1091 #undef int
1092 #undef long
1093 #undef unsigned
1094 #undef float
1095 #undef double
1096 #undef MIN
1097 #undef MAX
1098 #include <limits.h>
1099
1100 USItype
1101 __fixunsxfsi (a)
1102      XFtype a;
1103 {
1104   if (a >= - (DFtype) LONG_MIN)
1105     return (SItype) (a + LONG_MIN) - LONG_MIN;
1106   return (SItype) a;
1107 }
1108 #endif
1109
1110 #ifdef L_fixunsdfsi
1111 /* Reenable the normal types, in case limits.h needs them.  */
1112 #undef char
1113 #undef short
1114 #undef int
1115 #undef long
1116 #undef unsigned
1117 #undef float
1118 #undef double
1119 #undef MIN
1120 #undef MAX
1121 #include <limits.h>
1122
1123 USItype
1124 __fixunsdfsi (a)
1125      DFtype a;
1126 {
1127   if (a >= - (DFtype) LONG_MIN)
1128     return (SItype) (a + LONG_MIN) - LONG_MIN;
1129   return (SItype) a;
1130 }
1131 #endif
1132
1133 #ifdef L_fixunssfsi
1134 /* Reenable the normal types, in case limits.h needs them.  */
1135 #undef char
1136 #undef short
1137 #undef int
1138 #undef long
1139 #undef unsigned
1140 #undef float
1141 #undef double
1142 #undef MIN
1143 #undef MAX
1144 #include <limits.h>
1145
1146 USItype
1147 __fixunssfsi (SFtype a)
1148 {
1149   if (a >= - (SFtype) LONG_MIN)
1150     return (SItype) (a + LONG_MIN) - LONG_MIN;
1151   return (SItype) a;
1152 }
1153 #endif
1154 \f
1155 /* From here on down, the routines use normal data types.  */
1156
1157 #define SItype bogus_type
1158 #define USItype bogus_type
1159 #define DItype bogus_type
1160 #define UDItype bogus_type
1161 #define SFtype bogus_type
1162 #define DFtype bogus_type
1163
1164 #undef char
1165 #undef short
1166 #undef int
1167 #undef long
1168 #undef unsigned
1169 #undef float
1170 #undef double
1171 \f
1172 #ifdef L__gcc_bcmp
1173
1174 /* Like bcmp except the sign is meaningful.
1175    Result is negative if S1 is less than S2,
1176    positive if S1 is greater, 0 if S1 and S2 are equal.  */
1177
1178 int
1179 __gcc_bcmp (s1, s2, size)
1180      unsigned char *s1, *s2;
1181      size_t size;
1182 {
1183   while (size > 0)
1184     {
1185       unsigned char c1 = *s1++, c2 = *s2++;
1186       if (c1 != c2)
1187         return c1 - c2;
1188       size--;
1189     }
1190   return 0;
1191 }
1192
1193 #endif
1194 \f\f
1195 #ifdef L_varargs
1196 #ifdef __i860__
1197 #if defined(__svr4__) || defined(__alliant__)
1198         asm ("  .text");
1199         asm ("  .align  4");
1200
1201 /* The Alliant needs the added underscore.  */
1202         asm (".globl    __builtin_saveregs");
1203 asm ("__builtin_saveregs:");
1204         asm (".globl    ___builtin_saveregs");
1205 asm ("___builtin_saveregs:");
1206
1207         asm ("  andnot  0x0f,%sp,%sp"); /* round down to 16-byte boundary */
1208         asm ("  adds    -96,%sp,%sp");  /* allocate stack space for reg save
1209                                            area and also for a new va_list
1210                                            structure */
1211         /* Save all argument registers in the arg reg save area.  The
1212            arg reg save area must have the following layout (according
1213            to the svr4 ABI):
1214
1215                 struct {
1216                   union  {
1217                     float freg[8];
1218                     double dreg[4];
1219                   } float_regs;
1220                   long  ireg[12];
1221                 };
1222         */
1223
1224         asm ("  fst.q   %f8,  0(%sp)"); /* save floating regs (f8-f15)  */
1225         asm ("  fst.q   %f12,16(%sp)"); 
1226
1227         asm ("  st.l    %r16,32(%sp)"); /* save integer regs (r16-r27) */
1228         asm ("  st.l    %r17,36(%sp)"); 
1229         asm ("  st.l    %r18,40(%sp)");
1230         asm ("  st.l    %r19,44(%sp)");
1231         asm ("  st.l    %r20,48(%sp)");
1232         asm ("  st.l    %r21,52(%sp)");
1233         asm ("  st.l    %r22,56(%sp)");
1234         asm ("  st.l    %r23,60(%sp)");
1235         asm ("  st.l    %r24,64(%sp)");
1236         asm ("  st.l    %r25,68(%sp)");
1237         asm ("  st.l    %r26,72(%sp)");
1238         asm ("  st.l    %r27,76(%sp)");
1239
1240         asm ("  adds    80,%sp,%r16");  /* compute the address of the new
1241                                            va_list structure.  Put in into
1242                                            r16 so that it will be returned
1243                                            to the caller.  */
1244
1245         /* Initialize all fields of the new va_list structure.  This
1246            structure looks like:
1247
1248                 typedef struct {
1249                     unsigned long       ireg_used;
1250                     unsigned long       freg_used;
1251                     long                *reg_base;
1252                     long                *mem_ptr;
1253                 } va_list;
1254         */
1255
1256         asm ("  st.l    %r0, 0(%r16)"); /* nfixed */
1257         asm ("  st.l    %r0, 4(%r16)"); /* nfloating */
1258         asm ("  st.l    %sp, 8(%r16)"); /* __va_ctl points to __va_struct.  */
1259         asm ("  bri     %r1");          /* delayed return */
1260         asm ("  st.l    %r28,12(%r16)"); /* pointer to overflow args */
1261
1262 #else /* not __svr4__ */
1263 #if defined(__PARAGON__)
1264         /*
1265          *      we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1266          *      and we stand a better chance of hooking into libraries
1267          *      compiled by PGI.  [andyp@ssd.intel.com]
1268          */
1269         asm ("  .text");
1270         asm ("  .align  4");
1271         asm (".globl    __builtin_saveregs");
1272 asm ("__builtin_saveregs:");
1273         asm (".globl    ___builtin_saveregs");
1274 asm ("___builtin_saveregs:");
1275
1276         asm ("  andnot  0x0f,sp,sp");   /* round down to 16-byte boundary */
1277         asm ("  adds    -96,sp,sp");    /* allocate stack space for reg save
1278                                            area and also for a new va_list
1279                                            structure */
1280         /* Save all argument registers in the arg reg save area.  The
1281            arg reg save area must have the following layout (according
1282            to the svr4 ABI):
1283
1284                 struct {
1285                   union  {
1286                     float freg[8];
1287                     double dreg[4];
1288                   } float_regs;
1289                   long  ireg[12];
1290                 };
1291         */
1292
1293         asm ("  fst.q   f8,  0(sp)");
1294         asm ("  fst.q   f12,16(sp)"); 
1295         asm ("  st.l    r16,32(sp)");
1296         asm ("  st.l    r17,36(sp)"); 
1297         asm ("  st.l    r18,40(sp)");
1298         asm ("  st.l    r19,44(sp)");
1299         asm ("  st.l    r20,48(sp)");
1300         asm ("  st.l    r21,52(sp)");
1301         asm ("  st.l    r22,56(sp)");
1302         asm ("  st.l    r23,60(sp)");
1303         asm ("  st.l    r24,64(sp)");
1304         asm ("  st.l    r25,68(sp)");
1305         asm ("  st.l    r26,72(sp)");
1306         asm ("  st.l    r27,76(sp)");
1307
1308         asm ("  adds    80,sp,r16");  /* compute the address of the new
1309                                            va_list structure.  Put in into
1310                                            r16 so that it will be returned
1311                                            to the caller.  */
1312
1313         /* Initialize all fields of the new va_list structure.  This
1314            structure looks like:
1315
1316                 typedef struct {
1317                     unsigned long       ireg_used;
1318                     unsigned long       freg_used;
1319                     long                *reg_base;
1320                     long                *mem_ptr;
1321                 } va_list;
1322         */
1323
1324         asm ("  st.l    r0, 0(r16)"); /* nfixed */
1325         asm ("  st.l    r0, 4(r16)"); /* nfloating */
1326         asm ("  st.l    sp, 8(r16)"); /* __va_ctl points to __va_struct.  */
1327         asm ("  bri     r1");           /* delayed return */
1328         asm ("   st.l   r28,12(r16)"); /* pointer to overflow args */
1329 #else /* not __PARAGON__ */
1330         asm ("  .text");
1331         asm ("  .align  4");
1332
1333         asm (".globl    ___builtin_saveregs");
1334         asm ("___builtin_saveregs:");
1335         asm ("  mov     sp,r30");
1336         asm ("  andnot  0x0f,sp,sp");
1337         asm ("  adds    -96,sp,sp");  /* allocate sufficient space on the stack */
1338
1339 /* Fill in the __va_struct.  */
1340         asm ("  st.l    r16, 0(sp)"); /* save integer regs (r16-r27) */
1341         asm ("  st.l    r17, 4(sp)"); /* int    fixed[12] */
1342         asm ("  st.l    r18, 8(sp)");
1343         asm ("  st.l    r19,12(sp)");
1344         asm ("  st.l    r20,16(sp)");
1345         asm ("  st.l    r21,20(sp)");
1346         asm ("  st.l    r22,24(sp)");
1347         asm ("  st.l    r23,28(sp)");
1348         asm ("  st.l    r24,32(sp)");
1349         asm ("  st.l    r25,36(sp)");
1350         asm ("  st.l    r26,40(sp)");
1351         asm ("  st.l    r27,44(sp)");
1352
1353         asm ("  fst.q   f8, 48(sp)"); /* save floating regs (f8-f15) */
1354         asm ("  fst.q   f12,64(sp)"); /* int floating[8] */
1355
1356 /* Fill in the __va_ctl.  */
1357         asm ("  st.l    sp, 80(sp)"); /* __va_ctl points to __va_struct.  */
1358         asm ("  st.l    r28,84(sp)"); /* pointer to more args */
1359         asm ("  st.l    r0, 88(sp)"); /* nfixed */
1360         asm ("  st.l    r0, 92(sp)"); /* nfloating */
1361
1362         asm ("  adds    80,sp,r16");  /* return address of the __va_ctl.  */
1363         asm ("  bri     r1");
1364         asm ("  mov     r30,sp");
1365                                 /* recover stack and pass address to start 
1366                                    of data.  */
1367 #endif /* not __PARAGON__ */
1368 #endif /* not __svr4__ */
1369 #else /* not __i860__ */
1370 #ifdef __sparc__
1371         asm (".global __builtin_saveregs");
1372         asm ("__builtin_saveregs:");
1373         asm (".global ___builtin_saveregs");
1374         asm ("___builtin_saveregs:");
1375 #ifdef NEED_PROC_COMMAND
1376         asm (".proc 020");
1377 #endif
1378         asm ("st %i0,[%fp+68]");
1379         asm ("st %i1,[%fp+72]");
1380         asm ("st %i2,[%fp+76]");
1381         asm ("st %i3,[%fp+80]");
1382         asm ("st %i4,[%fp+84]");
1383         asm ("retl");
1384         asm ("st %i5,[%fp+88]");
1385 #ifdef NEED_TYPE_COMMAND
1386         asm (".type __builtin_saveregs,#function");
1387         asm (".size __builtin_saveregs,.-__builtin_saveregs");
1388 #endif
1389 #else /* not __sparc__ */
1390 #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1391
1392   asm ("        .text");
1393   asm ("        .ent __builtin_saveregs");
1394   asm ("        .globl __builtin_saveregs");
1395   asm ("__builtin_saveregs:");
1396   asm ("        sw      $4,0($30)");
1397   asm ("        sw      $5,4($30)");
1398   asm ("        sw      $6,8($30)");
1399   asm ("        sw      $7,12($30)");
1400   asm ("        j       $31");
1401   asm ("        .end __builtin_saveregs");
1402 #else /* not __mips__, etc. */
1403
1404 void *
1405 __builtin_saveregs ()
1406 {
1407   abort ();
1408 }
1409
1410 #endif /* not __mips__ */
1411 #endif /* not __sparc__ */
1412 #endif /* not __i860__ */
1413 #endif
1414 \f
1415 #ifdef L_eprintf
1416 #ifndef inhibit_libc
1417
1418 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1419 #include <stdio.h>
1420 /* This is used by the `assert' macro.  */
1421 void
1422 __eprintf (string, expression, line, filename)
1423      const char *string;
1424      const char *expression;
1425      int line;
1426      const char *filename;
1427 {
1428   fprintf (stderr, string, expression, line, filename);
1429   fflush (stderr);
1430   abort ();
1431 }
1432
1433 #endif
1434 #endif
1435
1436 #ifdef L_bb
1437
1438 /* Structure emitted by -a  */
1439 struct bb
1440 {
1441   long zero_word;
1442   const char *filename;
1443   long *counts;
1444   long ncounts;
1445   struct bb *next;
1446   const unsigned long *addresses;
1447
1448   /* Older GCC's did not emit these fields.  */
1449   long nwords;
1450   const char **functions;
1451   const long *line_nums;
1452   const char **filenames;
1453   char *flags;
1454 };
1455
1456 #ifdef BLOCK_PROFILER_CODE
1457 BLOCK_PROFILER_CODE
1458 #else
1459 #ifndef inhibit_libc
1460
1461 /* Simple minded basic block profiling output dumper for
1462    systems that don't provide tcov support.  At present,
1463    it requires atexit and stdio.  */
1464
1465 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1466 #include <stdio.h>
1467 char *ctime ();
1468
1469 #ifdef HAVE_ATEXIT
1470 #ifdef WINNT
1471 extern int atexit (void (*) (void));
1472 #else
1473 extern void atexit (void (*) (void));
1474 #endif
1475 #define ON_EXIT(FUNC,ARG) atexit ((FUNC))
1476 #else
1477 #ifdef sun
1478 extern void on_exit (void*, void*);
1479 #define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
1480 #endif
1481 #endif
1482
1483 static struct bb *bb_head;
1484
1485 /* Return the number of digits needed to print a value */
1486 /* __inline__ */ static int num_digits (long value, int base)
1487 {
1488   int minus = (value < 0 && base != 16);
1489   unsigned long v = (minus) ? -value : value;
1490   int ret = minus;
1491
1492   do
1493     {
1494       v /= base;
1495       ret++;
1496     }
1497   while (v);
1498
1499   return ret;
1500 }
1501
1502 void
1503 __bb_exit_func (void)
1504 {
1505   FILE *file = fopen ("bb.out", "a");
1506   long time_value;
1507
1508   if (!file)
1509     perror ("bb.out");
1510
1511   else
1512     {
1513       struct bb *ptr;
1514
1515       /* This is somewhat type incorrect, but it avoids worrying about
1516          exactly where time.h is included from.  It should be ok unless
1517          a void * differs from other pointer formats, or if sizeof (long)
1518          is < sizeof (time_t).  It would be nice if we could assume the
1519          use of rationale standards here.  */
1520
1521       time ((void *) &time_value);
1522       fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1523
1524       /* We check the length field explicitly in order to allow compatibility
1525          with older GCC's which did not provide it.  */
1526
1527       for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
1528         {
1529           int i;
1530           int func_p    = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
1531           int line_p    = (func_p && ptr->line_nums);
1532           int file_p    = (func_p && ptr->filenames);
1533           long ncounts  = ptr->ncounts;
1534           long cnt_max  = 0;
1535           long line_max = 0;
1536           long addr_max = 0;
1537           int file_len  = 0;
1538           int func_len  = 0;
1539           int blk_len   = num_digits (ncounts, 10);
1540           int cnt_len;
1541           int line_len;
1542           int addr_len;
1543
1544           fprintf (file, "File %s, %ld basic blocks \n\n",
1545                    ptr->filename, ncounts);
1546
1547           /* Get max values for each field.  */
1548           for (i = 0; i < ncounts; i++)
1549             {
1550               const char *p;
1551               int len;
1552
1553               if (cnt_max < ptr->counts[i])
1554                 cnt_max = ptr->counts[i];
1555
1556               if (addr_max < ptr->addresses[i])
1557                 addr_max = ptr->addresses[i];
1558
1559               if (line_p && line_max < ptr->line_nums[i])
1560                 line_max = ptr->line_nums[i];
1561
1562               if (func_p)
1563                 {
1564                   p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1565                   len = strlen (p);
1566                   if (func_len < len)
1567                     func_len = len;
1568                 }
1569
1570               if (file_p)
1571                 {
1572                   p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1573                   len = strlen (p);
1574                   if (file_len < len)
1575                     file_len = len;
1576                 }
1577             }
1578
1579           addr_len = num_digits (addr_max, 16);
1580           cnt_len  = num_digits (cnt_max, 10);
1581           line_len = num_digits (line_max, 10);
1582
1583           /* Now print out the basic block information.  */
1584           for (i = 0; i < ncounts; i++)
1585             {
1586               fprintf (file,
1587                        "    Block #%*d: executed %*ld time(s) address= 0x%.*lx",
1588                        blk_len, i+1,
1589                        cnt_len, ptr->counts[i],
1590                        addr_len, ptr->addresses[i]);
1591
1592               if (func_p)
1593                 fprintf (file, " function= %-*s", func_len,
1594                          (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1595
1596               if (line_p)
1597                 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1598
1599               if (file_p)
1600                 fprintf (file, " file= %s",
1601                          (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1602
1603               fprintf (file, "\n");
1604             }
1605
1606           fprintf (file, "\n");
1607           fflush (file);
1608         }
1609
1610       fprintf (file, "\n\n");
1611       fclose (file);
1612     }
1613 }
1614
1615 void
1616 __bb_init_func (struct bb *blocks)
1617 {
1618   /* User is supposed to check whether the first word is non-0,
1619      but just in case.... */
1620
1621   if (blocks->zero_word)
1622     return;
1623
1624 #ifdef ON_EXIT
1625   /* Initialize destructor.  */
1626   if (!bb_head)
1627     ON_EXIT (__bb_exit_func, 0);
1628 #endif
1629
1630   /* Set up linked list.  */
1631   blocks->zero_word = 1;
1632   blocks->next = bb_head;
1633   bb_head = blocks;
1634 }
1635
1636 #ifndef MACHINE_STATE_SAVE
1637 #define MACHINE_STATE_SAVE(ID)
1638 #endif
1639 #ifndef MACHINE_STATE_RESTORE
1640 #define MACHINE_STATE_RESTORE(ID)
1641 #endif
1642
1643 #include <string.h>
1644
1645 /* Number of buckets in hashtable of basic block addresses. */
1646
1647 #define BB_BUCKETS 311
1648
1649 /* Maximum length of string in file bb.in. */
1650
1651 #define BBINBUFSIZE 500
1652
1653 /* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
1654    "BBINBUFSIZE" but want to avoid trouble with preprocessors. */
1655
1656 #define BBINBUFSIZESTR "499"
1657
1658 struct bb_edge
1659 {
1660   struct bb_edge *next;
1661   unsigned long src_addr;
1662   unsigned long dst_addr;
1663   unsigned long count;
1664 };
1665
1666 enum bb_func_mode
1667 {
1668   TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1669 };
1670
1671 struct bb_func
1672 {
1673   struct bb_func *next;
1674   char *funcname;
1675   char *filename;
1676   enum bb_func_mode mode;
1677 };
1678
1679 /* This is the connection to the outside world.
1680    The BLOCK_PROFILER macro must set __bb.blocks
1681    and __bb.blockno. */
1682
1683 struct {
1684   unsigned long blockno;
1685   struct bb *blocks;
1686 } __bb;
1687
1688 /* Vars to store addrs of source and destination basic blocks 
1689    of a jump. */
1690
1691 static unsigned long bb_src = 0;
1692 static unsigned long bb_dst = 0;
1693
1694 static FILE *bb_tracefile = (FILE*)0;
1695 static struct bb_edge **bb_hashbuckets = (struct bb_edge**)0;
1696 static struct bb_func *bb_func_head = (struct bb_func*)0;
1697 static unsigned long bb_callcount = 0;
1698 static int bb_mode = 0;
1699
1700 static unsigned long *bb_stack = (unsigned long *)0;
1701 static size_t bb_stacksize = 0;
1702
1703 static int reported = 0;
1704
1705 /* Trace modes:
1706 Always             :   Print execution frequencies of basic blocks
1707                        to file bb.out.
1708 bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
1709 bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
1710 bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
1711 bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
1712 */
1713
1714 #ifdef HAVE_POPEN
1715
1716 /*#include <sys/types.h>*/
1717 #include <sys/stat.h>
1718 /*#include <malloc.h>*/
1719
1720 /* Commands executed by gopen. */
1721
1722 #define GOPENDECOMPRESS "gzip -cd "
1723 #define GOPENCOMPRESS "gzip -c >"
1724
1725 /* Like fopen but pipes through gzip.  mode may only be "r" or "w".
1726    If it does not compile, simply replace gopen by fopen and delete
1727    '.gz' from any first parameter to gopen. */
1728
1729 static FILE *
1730 gopen (fn, mode)
1731      char *fn;
1732      char *mode;
1733 {
1734   int use_gzip;
1735   char *p;
1736
1737   if (mode[1])
1738     return (FILE*)0;
1739
1740   if (mode[0] != 'r' && mode[0] != 'w') 
1741     return (FILE*)0;
1742
1743   p = fn + strlen (fn)-1;
1744   use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z')) ||
1745               (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1746
1747   if (use_gzip)
1748     {
1749       if (mode[0]=='r')
1750         {
1751           FILE *f;
1752           char *s = (char*) malloc (sizeof (char) * strlen (fn)
1753                                     + sizeof (GOPENDECOMPRESS));
1754           strcpy (s, GOPENDECOMPRESS);
1755           strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1756           f = popen (s, mode);
1757           free (s);
1758           return f;
1759         }
1760
1761       else
1762         {
1763           FILE *f;
1764           char *s = (char*) malloc (sizeof (char) * strlen (fn)
1765                                     + sizeof (GOPENCOMPRESS));
1766           strcpy (s, GOPENCOMPRESS);
1767           strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1768           if (!(f = popen (s, mode)))
1769             f = fopen (s, mode);
1770           free (s);
1771           return f;
1772         }
1773     }
1774
1775   else
1776     return fopen (fn, mode);
1777 }
1778
1779 static int
1780 gclose (f)
1781      FILE *f;
1782 {
1783   struct stat buf;
1784
1785   if (f != NULL)
1786     {
1787       if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1788         return pclose (f);
1789
1790       return fclose (f);
1791     }
1792   return 0;
1793 }
1794
1795 #endif /* HAVE_POPEN */
1796
1797 /* Called once per program. */
1798
1799 static void
1800 __bb_exit_trace_func ()
1801 {
1802   FILE *file = fopen ("bb.out", "a");
1803   struct bb_func *f;
1804   struct bb_edge *e;
1805   struct bb *b;
1806         
1807   if (!file)
1808     perror ("bb.out");
1809
1810   if (bb_mode & 1)
1811     {
1812       if (!bb_tracefile)
1813         perror ("bbtrace");
1814       else
1815 #ifdef HAVE_POPEN
1816         gclose (bb_tracefile);
1817 #else
1818         fclose (bb_tracefile);
1819 #endif /* HAVE_POPEN */
1820     }
1821
1822   /* Check functions in `bb.in'. */
1823
1824   if (file)
1825     {
1826       long time_value;
1827       const struct bb_func *p;
1828       int printed_something = 0;
1829       struct bb *ptr;
1830       long blk;
1831
1832       /* This is somewhat type incorrect. */
1833       time ((void *) &time_value);
1834
1835       for (p = bb_func_head; p != (struct bb_func *)0; p = p->next)
1836         {
1837           for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
1838             {
1839               if (!ptr->filename || p->filename != (char *)0 && strcmp (p->filename, ptr->filename))
1840                 continue;
1841               for (blk = 0; blk < ptr->ncounts; blk++)
1842                 {
1843                   if (!strcmp (p->funcname, ptr->functions[blk]))
1844                     goto found;
1845                 }
1846             }
1847   
1848           if (!printed_something)
1849             {
1850               fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1851               printed_something = 1;
1852             }
1853
1854           fprintf (file, "\tFunction %s", p->funcname);
1855           if (p->filename)
1856               fprintf (file, " of file %s", p->filename);
1857           fprintf (file, "\n" );
1858   
1859 found:        ;
1860         }
1861
1862       if (printed_something)
1863        fprintf (file, "\n");
1864
1865     }
1866
1867   if (bb_mode & 2)
1868     {
1869       if (!bb_hashbuckets)
1870         {
1871           if (!reported)
1872             {
1873               fprintf (stderr, "Profiler: out of memory\n");
1874               reported = 1;
1875             }
1876           return;
1877         }
1878     
1879       else if (file)
1880         {
1881           long time_value;
1882           int i;
1883           unsigned long addr_max = 0;
1884           unsigned long cnt_max  = 0;
1885           int cnt_len;
1886           int addr_len;
1887     
1888           /* This is somewhat type incorrect, but it avoids worrying about
1889              exactly where time.h is included from.  It should be ok unless
1890              a void * differs from other pointer formats, or if sizeof (long)
1891              is < sizeof (time_t).  It would be nice if we could assume the
1892              use of rationale standards here.  */
1893     
1894           time ((void *) &time_value);
1895           fprintf (file, "Basic block jump tracing");
1896
1897           switch (bb_mode & 12)
1898             {
1899               case 0:
1900                 fprintf (file, " (with call)");
1901               break;
1902
1903               case 4:
1904                 /* Print nothing. */
1905               break;
1906
1907               case 8:
1908                 fprintf (file, " (with call & ret)");
1909               break;
1910
1911               case 12:
1912                 fprintf (file, " (with ret)");
1913               break;
1914             }
1915
1916           fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1917     
1918           for (i = 0; i < BB_BUCKETS; i++)
1919             {
1920                struct bb_edge *bucket = bb_hashbuckets[i];
1921                for ( ; bucket; bucket = bucket->next )
1922                  {
1923                    if (addr_max < bucket->src_addr) 
1924                      addr_max = bucket->src_addr;
1925                    if (addr_max < bucket->dst_addr) 
1926                      addr_max = bucket->dst_addr;
1927                    if (cnt_max < bucket->count) 
1928                      cnt_max = bucket->count;
1929                  }
1930             }
1931           addr_len = num_digits (addr_max, 16);
1932           cnt_len  = num_digits (cnt_max, 10);
1933     
1934           for ( i = 0; i < BB_BUCKETS; i++)
1935             {
1936                struct bb_edge *bucket = bb_hashbuckets[i];
1937                for ( ; bucket; bucket = bucket->next )
1938                  {
1939                    fprintf (file, "Jump from block 0x%.*lx to "
1940                                   "block 0x%.*lx executed %*d time(s)\n", 
1941                             addr_len, bucket->src_addr, 
1942                             addr_len, bucket->dst_addr, 
1943                             cnt_len, bucket->count);
1944                  }
1945             }
1946   
1947           fprintf (file, "\n");
1948
1949         }
1950     }
1951
1952    if (file)
1953      fclose (file);
1954
1955    /* Free allocated memory. */
1956
1957    f = bb_func_head;
1958    while (f)
1959      {
1960        struct bb_func *old = f;
1961
1962        f = f->next;
1963        if (old->funcname) free (old->funcname);
1964        if (old->filename) free (old->filename);
1965        free (old);
1966      }
1967
1968    if (bb_stack)
1969      free (bb_stack);
1970
1971    if (bb_hashbuckets)
1972      {
1973        int i;
1974
1975        for (i = 0; i < BB_BUCKETS; i++)
1976          {
1977            struct bb_edge *old, *bucket = bb_hashbuckets[i];
1978
1979            while (bucket)
1980              {
1981                old = bucket;
1982                bucket = bucket->next;
1983                free (old);
1984              }
1985          }
1986        free (bb_hashbuckets);
1987      }
1988
1989    for (b = bb_head; b; b = b->next)
1990      if (b->flags) free (b->flags);
1991 }
1992
1993 /* Called once per program. */
1994
1995 static void
1996 __bb_init_prg ()
1997 {
1998
1999   FILE *file;
2000   char buf[BBINBUFSIZE];
2001   const char *p;
2002   const char *pos;
2003   enum bb_func_mode m;
2004
2005 #ifdef ON_EXIT
2006   /* Initialize destructor.  */
2007   ON_EXIT (__bb_exit_func, 0);
2008 #endif
2009
2010   if (!(file = fopen ("bb.in", "r")))
2011     return;
2012
2013   while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
2014     {
2015       p = buf;
2016       if (*p == '-') 
2017         { 
2018           m = TRACE_OFF; 
2019           p++; 
2020         }
2021       else 
2022         { 
2023           m = TRACE_ON; 
2024         }
2025       if (!strcmp (p, "__bb_trace__"))
2026         bb_mode |= 1;
2027       else if (!strcmp (p, "__bb_jumps__"))
2028         bb_mode |= 2;
2029       else if (!strcmp (p, "__bb_hidecall__"))
2030         bb_mode |= 4;
2031       else if (!strcmp (p, "__bb_showret__"))
2032         bb_mode |= 8;
2033       else 
2034         {
2035           struct bb_func *f = (struct bb_func*) malloc (sizeof (struct bb_func));
2036           if (f)
2037             {
2038               unsigned long l;
2039               f->next = bb_func_head;
2040               if (pos = strchr (p, ':'))
2041                 {
2042                   if (!(f->funcname = (char*) malloc (strlen (pos+1)+1)))
2043                     continue;
2044                   strcpy (f->funcname, pos+1);
2045                   l = pos-p;
2046                   if ((f->filename = (char*) malloc (l+1)))
2047                     {
2048                       strncpy (f->filename, p, l);
2049                       f->filename[l] = '\0';
2050                     }
2051                   else
2052                     f->filename = (char*)0;
2053                 }
2054               else
2055                 {
2056                   if (!(f->funcname = (char*) malloc (strlen (p)+1)))
2057                     continue;
2058                   strcpy (f->funcname, p);
2059                   f->filename = (char*)0;
2060                 }
2061               f->mode = m;
2062               bb_func_head = f;
2063             }
2064          }
2065     }
2066   fclose (file);
2067
2068 #ifdef HAVE_POPEN 
2069
2070   if (bb_mode & 1)
2071       bb_tracefile = gopen ("bbtrace.gz", "w");
2072
2073 #else
2074
2075   if (bb_mode & 1)
2076       bb_tracefile = fopen ("bbtrace", "w");
2077
2078 #endif /* HAVE_POPEN */
2079
2080   if (bb_mode & 2)
2081     {
2082       bb_hashbuckets = (struct bb_edge **) 
2083                    malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2084       if (bb_hashbuckets)
2085         bzero (bb_hashbuckets, BB_BUCKETS);
2086     }
2087
2088   if (bb_mode & 12)
2089     {
2090       bb_stacksize = 10;
2091       bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2092     }
2093
2094 #ifdef ON_EXIT
2095       /* Initialize destructor.  */
2096       ON_EXIT (__bb_exit_trace_func, 0);
2097 #endif
2098
2099 }
2100
2101 /* Called upon entering a basic block. */
2102
2103 void
2104 __bb_trace_func ()
2105 {
2106   struct bb_edge *bucket;
2107
2108   MACHINE_STATE_SAVE("1")
2109
2110   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2111     goto skip;
2112
2113   bb_dst = __bb.blocks->addresses[__bb.blockno];
2114   __bb.blocks->counts[__bb.blockno]++;
2115
2116   if (bb_tracefile)
2117     {
2118       fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2119     }
2120
2121   if (bb_hashbuckets)
2122     {
2123       struct bb_edge **startbucket, **oldnext;
2124
2125       oldnext = startbucket =
2126           & bb_hashbuckets[ (((int)bb_src*8)^(int)bb_dst) % BB_BUCKETS ];
2127       bucket = *startbucket;
2128
2129       for (bucket = *startbucket; bucket; 
2130            oldnext = &(bucket->next), bucket = *oldnext)
2131         {
2132           if ( bucket->src_addr == bb_src &&
2133                bucket->dst_addr == bb_dst )
2134             {
2135               bucket->count++;
2136               *oldnext = bucket->next;
2137               bucket->next = *startbucket;
2138               *startbucket = bucket;
2139               goto ret;
2140             }
2141         }
2142
2143       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2144
2145       if (!bucket)
2146         {
2147           if (!reported)
2148             {
2149               fprintf (stderr, "Profiler: out of memory\n");
2150               reported = 1;
2151             }
2152         }
2153
2154       else
2155         {
2156           bucket->src_addr = bb_src;
2157           bucket->dst_addr = bb_dst;
2158           bucket->next = *startbucket;
2159           *startbucket = bucket;
2160           bucket->count = 1;
2161         }
2162     }
2163
2164 ret:
2165   bb_src = bb_dst;
2166
2167 skip:
2168   ;
2169
2170   MACHINE_STATE_RESTORE("1")
2171
2172 }
2173
2174 /* Called when returning from a function and `__bb_showret__' is set. */
2175
2176 static void
2177 __bb_trace_func_ret ()
2178 {
2179   struct bb_edge *bucket;
2180
2181   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2182     goto skip;
2183
2184   if (bb_hashbuckets)
2185     {
2186       struct bb_edge **startbucket, **oldnext;
2187
2188       oldnext = startbucket =
2189           & bb_hashbuckets[ (((int)bb_dst*8)^(int)bb_src) % BB_BUCKETS ];
2190       bucket = *startbucket;
2191
2192       for (bucket = *startbucket; bucket; 
2193            oldnext = &(bucket->next), bucket = *oldnext)
2194         {
2195           if ( bucket->src_addr == bb_dst &&
2196                bucket->dst_addr == bb_src )
2197             {
2198               bucket->count++;
2199               *oldnext = bucket->next;
2200               bucket->next = *startbucket;
2201               *startbucket = bucket;
2202               goto ret;
2203             }
2204         }
2205
2206       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2207
2208       if (!bucket)
2209         {
2210           if (!reported)
2211             {
2212               fprintf (stderr, "Profiler: out of memory\n");
2213               reported = 1;
2214             }
2215         }
2216
2217       else
2218         {
2219           bucket->src_addr = bb_dst;
2220           bucket->dst_addr = bb_src;
2221           bucket->next = *startbucket;
2222           *startbucket = bucket;
2223           bucket->count = 1;
2224         }
2225     }
2226
2227 ret:
2228   bb_dst = bb_src;
2229
2230 skip:
2231   ;
2232
2233 }
2234
2235 /* Called upon entering the first function of a file. */
2236
2237 static void
2238 __bb_init_file (blocks)
2239      struct bb *blocks;
2240 {
2241
2242   const struct bb_func *p;
2243   long blk, ncounts = blocks->ncounts;
2244   const char **functions = blocks->functions;
2245
2246   /* Set up linked list.  */
2247   blocks->zero_word = 1;
2248   blocks->next = bb_head;
2249   bb_head = blocks;
2250
2251   blocks->flags = 0;
2252   if (!bb_func_head ||
2253       !(blocks->flags = (char*) malloc (sizeof (char) * blocks->ncounts)))
2254     return;
2255
2256   for (blk = 0; blk < ncounts; blk++)
2257     blocks->flags[blk] = 0;
2258
2259   for (blk = 0; blk < ncounts; blk++)
2260     {
2261       for (p = bb_func_head; p; p = p->next)
2262         {
2263           if (!strcmp (p->funcname, functions[blk]) &&
2264               (!p->filename || !strcmp (p->filename, blocks->filename)))
2265             {
2266               blocks->flags[blk] |= p->mode;
2267             }
2268         }
2269     }
2270
2271 }
2272
2273 /* Called when exiting from a function. */
2274
2275 void
2276 __bb_trace_ret ()
2277 {
2278
2279   MACHINE_STATE_SAVE("2")
2280
2281   if (bb_callcount)
2282     {
2283       if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2284         {
2285           bb_src = bb_stack[bb_callcount];
2286           if (bb_mode & 8)
2287             __bb_trace_func_ret ();
2288         }
2289
2290       bb_callcount -= 1;
2291     }
2292
2293   MACHINE_STATE_RESTORE("2")
2294
2295 }
2296
2297 /* Called when entering a function. */
2298
2299 void
2300 __bb_init_trace_func (blocks, blockno)
2301      struct bb *blocks;
2302      unsigned long blockno;
2303 {
2304   static int trace_init = 0;
2305
2306   MACHINE_STATE_SAVE("3")
2307
2308   if (!blocks->zero_word)
2309     { 
2310       if (!trace_init)
2311         { 
2312           trace_init = 1;
2313           __bb_init_prg ();
2314         }
2315       __bb_init_file (blocks);
2316     }
2317
2318   if (bb_callcount)
2319     {
2320
2321       bb_callcount += 1;
2322
2323       if (bb_mode & 12)
2324         {
2325           if (bb_callcount >= bb_stacksize)
2326             {
2327               size_t newsize = bb_callcount + 100;
2328
2329               bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2330               if (! bb_stack)
2331                 {
2332                   if (!reported)
2333                     {
2334                       fprintf (stderr, "Profiler: out of memory\n");
2335                       reported = 1;
2336                     }
2337                   bb_stacksize = 0;
2338                   goto stack_overflow;
2339                 }
2340               bb_stacksize = newsize;
2341             }
2342           bb_stack[bb_callcount] = bb_src;
2343
2344           if (bb_mode & 4)
2345             bb_src = 0;
2346
2347         }
2348
2349 stack_overflow:;
2350
2351     }
2352
2353   else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2354     {
2355       bb_callcount = 1;
2356       bb_src = 0;
2357
2358       if (bb_stack)
2359           bb_stack[bb_callcount] = bb_src;
2360     }
2361
2362   MACHINE_STATE_RESTORE("3")
2363 }
2364
2365 #endif /* not inhibit_libc */
2366 #endif /* not BLOCK_PROFILER_CODE */
2367 #endif /* L_bb */
2368 \f
2369 /* Default free-store management functions for C++, per sections 12.5 and
2370    17.3.3 of the Working Paper. */
2371
2372 #ifdef L_op_new
2373 /* operator new (size_t), described in 17.3.3.5.  This function is used by
2374    C++ programs to allocate a block of memory to hold a single object. */
2375
2376 typedef void (*vfp)(void);
2377 extern vfp __new_handler;
2378 extern void __default_new_handler (void);
2379
2380 #ifdef WEAK_ALIAS
2381 void * __builtin_new (size_t sz)
2382      __attribute__ ((weak, alias ("___builtin_new")));
2383 void *
2384 ___builtin_new (size_t sz)
2385 #else
2386 void *
2387 __builtin_new (size_t sz)
2388 #endif
2389 {
2390   void *p;
2391   vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
2392
2393   /* malloc (0) is unpredictable; avoid it.  */
2394   if (sz == 0)
2395     sz = 1;
2396   p = (void *) malloc (sz);
2397   while (p == 0)
2398     {
2399       (*handler) ();
2400       p = (void *) malloc (sz);
2401     }
2402   
2403   return p;
2404 }
2405 #endif /* L_op_new */
2406
2407 #ifdef L_op_vnew
2408 /* void * operator new [] (size_t), described in 17.3.3.6.  This function
2409    is used by C++ programs to allocate a block of memory for an array.  */
2410
2411 extern void * __builtin_new (size_t);
2412
2413 #ifdef WEAK_ALIAS
2414 void * __builtin_vec_new (size_t sz)
2415      __attribute__ ((weak, alias ("___builtin_vec_new")));
2416 void *
2417 ___builtin_vec_new (size_t sz)
2418 #else
2419 void *
2420 __builtin_vec_new (size_t sz)
2421 #endif
2422 {
2423   return __builtin_new (sz);
2424 }
2425 #endif /* L_op_vnew */
2426
2427 #ifdef L_new_handler
2428 /* set_new_handler (fvoid_t *) and the default new handler, described in
2429    17.3.3.2 and 17.3.3.5.  These functions define the result of a failure
2430    to allocate the amount of memory requested from operator new or new []. */
2431
2432 #ifndef inhibit_libc
2433 /* This gets us __GNU_LIBRARY__.  */
2434 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2435 #include <stdio.h>
2436
2437 #ifdef __GNU_LIBRARY__
2438   /* Avoid forcing the library's meaning of `write' on the user program
2439      by using the "internal" name (for use within the library)  */
2440 #define write(fd, buf, n)       __write((fd), (buf), (n))
2441 #endif
2442 #endif /* inhibit_libc */
2443
2444 typedef void (*vfp)(void);
2445 void __default_new_handler (void);
2446
2447 vfp __new_handler = (vfp)0;
2448
2449 vfp
2450 set_new_handler (vfp handler)
2451 {
2452   vfp prev_handler;
2453
2454   prev_handler = __new_handler;
2455   if (handler == 0) handler = __default_new_handler;
2456   __new_handler = handler;
2457   return prev_handler;
2458 }
2459
2460 #define MESSAGE "Virtual memory exceeded in `new'\n"
2461
2462 void
2463 __default_new_handler ()
2464 {
2465 #ifndef inhibit_libc
2466   /* don't use fprintf (stderr, ...) because it may need to call malloc.  */
2467   /* This should really print the name of the program, but that is hard to
2468      do.  We need a standard, clean way to get at the name.  */
2469   write (2, MESSAGE, sizeof (MESSAGE));
2470 #endif
2471   /* don't call exit () because that may call global destructors which
2472      may cause a loop.  */
2473   _exit (-1);
2474 }
2475 #endif
2476
2477 #ifdef L_op_delete
2478 /* operator delete (void *), described in 17.3.3.3.  This function is used
2479    by C++ programs to return to the free store a block of memory allocated
2480    as a single object. */
2481
2482 #ifdef WEAK_ALIAS
2483 void __builtin_delete (void *ptr)
2484      __attribute__ ((weak, alias ("___builtin_delete")));
2485 void
2486 ___builtin_delete (void *ptr)
2487 #else
2488 void
2489 __builtin_delete (void *ptr)
2490 #endif
2491 {
2492   if (ptr)
2493     free (ptr);
2494 }
2495 #endif
2496
2497 #ifdef L_op_vdel
2498 /* operator delete [] (void *), described in 17.3.3.4.  This function is
2499    used by C++ programs to return to the free store a block of memory
2500    allocated as an array. */
2501
2502 extern void __builtin_delete (void *);
2503
2504 #ifdef WEAK_ALIAS
2505 void __builtin_vec_delete (void *ptr)
2506      __attribute__ ((weak, alias ("___builtin_vec_delete")));
2507 void
2508 ___builtin_vec_delete (void *ptr)
2509 #else
2510 void
2511 __builtin_vec_delete (void *ptr)
2512 #endif
2513 {
2514   __builtin_delete (ptr);
2515 }
2516 #endif
2517
2518 /* End of C++ free-store management functions */
2519 \f
2520 #ifdef L_shtab
2521 unsigned int __shtab[] = {
2522     0x00000001, 0x00000002, 0x00000004, 0x00000008,
2523     0x00000010, 0x00000020, 0x00000040, 0x00000080,
2524     0x00000100, 0x00000200, 0x00000400, 0x00000800,
2525     0x00001000, 0x00002000, 0x00004000, 0x00008000,
2526     0x00010000, 0x00020000, 0x00040000, 0x00080000,
2527     0x00100000, 0x00200000, 0x00400000, 0x00800000,
2528     0x01000000, 0x02000000, 0x04000000, 0x08000000,
2529     0x10000000, 0x20000000, 0x40000000, 0x80000000
2530   };
2531 #endif
2532 \f
2533 #ifdef L_clear_cache
2534 /* Clear part of an instruction cache.  */
2535
2536 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2537
2538 void
2539 __clear_cache (beg, end)
2540      char *beg, *end;
2541 {
2542 #ifdef CLEAR_INSN_CACHE 
2543   CLEAR_INSN_CACHE (beg, end);
2544 #else
2545 #ifdef INSN_CACHE_SIZE
2546   static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
2547   static int initialized;
2548   int offset;
2549   void *start_addr
2550   void *end_addr;
2551   typedef (*function_ptr) ();
2552
2553 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2554   /* It's cheaper to clear the whole cache.
2555      Put in a series of jump instructions so that calling the beginning
2556      of the cache will clear the whole thing.  */
2557
2558   if (! initialized)
2559     {
2560       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2561                  & -INSN_CACHE_LINE_WIDTH);
2562       int end_ptr = ptr + INSN_CACHE_SIZE;
2563
2564       while (ptr < end_ptr)
2565         {
2566           *(INSTRUCTION_TYPE *)ptr
2567             = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2568           ptr += INSN_CACHE_LINE_WIDTH;
2569         }
2570       *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
2571
2572       initialized = 1;
2573     }
2574
2575   /* Call the beginning of the sequence.  */
2576   (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2577                     & -INSN_CACHE_LINE_WIDTH))
2578    ());
2579
2580 #else /* Cache is large.  */
2581
2582   if (! initialized)
2583     {
2584       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2585                  & -INSN_CACHE_LINE_WIDTH);
2586
2587       while (ptr < (int) array + sizeof array)
2588         {
2589           *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2590           ptr += INSN_CACHE_LINE_WIDTH;
2591         }
2592
2593       initialized = 1;
2594     }
2595
2596   /* Find the location in array that occupies the same cache line as BEG.  */
2597
2598   offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2599   start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2600                  & -INSN_CACHE_PLANE_SIZE)
2601                 + offset);
2602
2603   /* Compute the cache alignment of the place to stop clearing.  */
2604 #if 0  /* This is not needed for gcc's purposes.  */
2605   /* If the block to clear is bigger than a cache plane,
2606      we clear the entire cache, and OFFSET is already correct.  */ 
2607   if (end < beg + INSN_CACHE_PLANE_SIZE)
2608 #endif
2609     offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2610                & -INSN_CACHE_LINE_WIDTH)
2611               & (INSN_CACHE_PLANE_SIZE - 1));
2612
2613 #if INSN_CACHE_DEPTH > 1
2614   end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2615   if (end_addr <= start_addr)
2616     end_addr += INSN_CACHE_PLANE_SIZE;
2617
2618   for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2619     {
2620       int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2621       int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2622
2623       while (addr != stop)
2624         {
2625           /* Call the return instruction at ADDR.  */
2626           ((function_ptr) addr) ();
2627
2628           addr += INSN_CACHE_LINE_WIDTH;
2629         }
2630     }
2631 #else /* just one plane */
2632   do
2633     {
2634       /* Call the return instruction at START_ADDR.  */
2635       ((function_ptr) start_addr) ();
2636
2637       start_addr += INSN_CACHE_LINE_WIDTH;
2638     }
2639   while ((start_addr % INSN_CACHE_SIZE) != offset);
2640 #endif /* just one plane */
2641 #endif /* Cache is large */
2642 #endif /* Cache exists */
2643 #endif /* CLEAR_INSN_CACHE */
2644 }
2645
2646 #endif /* L_clear_cache */
2647 \f
2648 #ifdef L_trampoline
2649
2650 /* Jump to a trampoline, loading the static chain address.  */
2651
2652 #ifdef WINNT
2653
2654 long getpagesize()
2655 {
2656 #ifdef _ALPHA_
2657   return 8192;
2658 #else
2659   return 4096;
2660 #endif
2661 }
2662
2663 int mprotect(addr, len, prot)
2664   char *addr;
2665   int len, prot;
2666 {
2667   int np, op;
2668
2669   if (prot == 7) np = 0x40;
2670   else if (prot == 5) np = 0x20;
2671   else if (prot == 4) np = 0x10;
2672   else if (prot == 3) np = 0x04;
2673   else if (prot == 1) np = 0x02;
2674   else if (prot == 0) np = 0x01;
2675
2676   if (VirtualProtect (addr, len, np, &op))
2677     return 0;
2678   else
2679     return -1;
2680     
2681 }
2682
2683 #endif
2684
2685 #ifdef TRANSFER_FROM_TRAMPOLINE 
2686 TRANSFER_FROM_TRAMPOLINE 
2687 #endif
2688
2689 #if defined (NeXT) && defined (__MACH__)
2690
2691 /* Make stack executable so we can call trampolines on stack.
2692    This is called from INITIALIZE_TRAMPOLINE in next.h.  */
2693 #ifdef NeXTStep21
2694  #include <mach.h>
2695 #else
2696  #include <mach/mach.h>
2697 #endif
2698
2699 void
2700 __enable_execute_stack (addr)
2701      char *addr;
2702 {
2703   kern_return_t r;
2704   char *eaddr = addr + TRAMPOLINE_SIZE;
2705   vm_address_t a = (vm_address_t) addr;
2706
2707   /* turn on execute access on stack */
2708   r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2709   if (r != KERN_SUCCESS)
2710     {
2711       mach_error("vm_protect VM_PROT_ALL", r);
2712       exit(1);
2713     }
2714
2715   /* We inline the i-cache invalidation for speed */
2716
2717 #ifdef CLEAR_INSN_CACHE
2718   CLEAR_INSN_CACHE (addr, eaddr);
2719 #else
2720   __clear_cache ((int) addr, (int) eaddr);
2721 #endif
2722
2723
2724 #endif /* defined (NeXT) && defined (__MACH__) */
2725
2726 #ifdef __convex__
2727
2728 /* Make stack executable so we can call trampolines on stack.
2729    This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
2730
2731 #include <sys/mman.h>
2732 #include <sys/vmparam.h>
2733 #include <machine/machparam.h>
2734
2735 void
2736 __enable_execute_stack ()
2737 {
2738   int fp;
2739   static unsigned lowest = USRSTACK;
2740   unsigned current = (unsigned) &fp & -NBPG;
2741
2742   if (lowest > current)
2743     {
2744       unsigned len = lowest - current;
2745       mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2746       lowest = current;
2747     }
2748
2749   /* Clear instruction cache in case an old trampoline is in it. */
2750   asm ("pich");
2751 }
2752 #endif /* __convex__ */
2753
2754 #ifdef __DOLPHIN__
2755
2756 /* Modified from the convex -code above. */
2757
2758 #include <sys/param.h>
2759 #include <errno.h>
2760 #include <sys/m88kbcs.h>
2761
2762 void
2763 __enable_execute_stack ()
2764 {
2765   int save_errno;
2766   static unsigned long lowest = USRSTACK;
2767   unsigned long current = (unsigned long) &save_errno & -NBPC;
2768   
2769   /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2770      address is seen as 'negative'. That is the case with the stack.   */
2771
2772   save_errno=errno;
2773   if (lowest > current)
2774     {
2775       unsigned len=lowest-current;
2776       memctl(current,len,MCT_TEXT);
2777       lowest = current;
2778     }
2779   else
2780     memctl(current,NBPC,MCT_TEXT);
2781   errno=save_errno;
2782 }
2783
2784 #endif /* __DOLPHIN__ */
2785
2786 #ifdef __pyr__
2787
2788 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2789 #include <stdio.h>
2790 #include <sys/mman.h>
2791 #include <sys/types.h>
2792 #include <sys/param.h>
2793 #include <sys/vmmac.h>
2794
2795 /* Modified from the convex -code above.
2796    mremap promises to clear the i-cache. */
2797
2798 void
2799 __enable_execute_stack ()
2800 {
2801   int fp;
2802   if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2803                 PROT_READ|PROT_WRITE|PROT_EXEC))
2804     {
2805       perror ("mprotect in __enable_execute_stack");
2806       fflush (stderr);
2807       abort ();
2808     }
2809 }
2810 #endif /* __pyr__ */
2811 #endif /* L_trampoline */
2812 \f
2813 #ifdef L__main
2814
2815 #include "gbl-ctors.h"
2816 /* Some systems use __main in a way incompatible with its use in gcc, in these
2817    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2818    give the same symbol without quotes for an alternative entry point.  You
2819    must define both, or neither. */
2820 #ifndef NAME__MAIN
2821 #define NAME__MAIN "__main"
2822 #define SYMBOL__MAIN __main
2823 #endif
2824
2825 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
2826 /* Run all the global destructors on exit from the program.  */
2827
2828 void
2829 __do_global_dtors ()
2830 {
2831 #ifdef DO_GLOBAL_DTORS_BODY
2832   DO_GLOBAL_DTORS_BODY;
2833 #else
2834   func_ptr *p;
2835   for (p = __DTOR_LIST__ + 1; *p; )
2836     (*p++) ();
2837 #endif
2838 }
2839 #endif
2840
2841 #ifndef INIT_SECTION_ASM_OP
2842 /* Run all the global constructors on entry to the program.  */
2843
2844 #ifndef ON_EXIT
2845 #define ON_EXIT(a, b)
2846 #else
2847 /* Make sure the exit routine is pulled in to define the globals as
2848    bss symbols, just in case the linker does not automatically pull
2849    bss definitions from the library.  */
2850
2851 extern int _exit_dummy_decl;
2852 int *_exit_dummy_ref = &_exit_dummy_decl;
2853 #endif /* ON_EXIT */
2854
2855 void
2856 __do_global_ctors ()
2857 {
2858   DO_GLOBAL_CTORS_BODY;
2859   ON_EXIT (__do_global_dtors, 0);
2860 }
2861 #endif /* no INIT_SECTION_ASM_OP */
2862
2863 #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
2864 /* Subroutine called automatically by `main'.
2865    Compiling a global function named `main'
2866    produces an automatic call to this function at the beginning.
2867
2868    For many systems, this routine calls __do_global_ctors.
2869    For systems which support a .init section we use the .init section
2870    to run __do_global_ctors, so we need not do anything here.  */
2871
2872 void
2873 SYMBOL__MAIN ()
2874 {
2875   /* Support recursive calls to `main': run initializers just once.  */
2876   static int initialized;
2877   if (! initialized)
2878     {
2879       initialized = 1;
2880       __do_global_ctors ();
2881     }
2882 }
2883 #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
2884
2885 #endif /* L__main */
2886 \f
2887 #ifdef L_ctors
2888
2889 #include "gbl-ctors.h"
2890
2891 /* Provide default definitions for the lists of constructors and
2892    destructors, so that we don't get linker errors.  These symbols are
2893    intentionally bss symbols, so that gld and/or collect will provide
2894    the right values.  */
2895
2896 /* We declare the lists here with two elements each,
2897    so that they are valid empty lists if no other definition is loaded.  */
2898 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2899 #if defined(__NeXT__) || defined(_AIX)
2900 /* After 2.3, try this definition on all systems.  */
2901 func_ptr __CTOR_LIST__[2] = {0, 0};
2902 func_ptr __DTOR_LIST__[2] = {0, 0};
2903 #else
2904 func_ptr __CTOR_LIST__[2];
2905 func_ptr __DTOR_LIST__[2];
2906 #endif
2907 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2908 #endif /* L_ctors */
2909 \f
2910 #ifdef L_exit
2911
2912 #include "gbl-ctors.h"
2913
2914 #ifndef ON_EXIT
2915
2916 /* If we have no known way of registering our own __do_global_dtors
2917    routine so that it will be invoked at program exit time, then we
2918    have to define our own exit routine which will get this to happen.  */
2919
2920 extern void __do_global_dtors ();
2921 extern void _cleanup ();
2922 extern void _exit () __attribute__ ((noreturn));
2923
2924 void 
2925 exit (status)
2926      int status;
2927 {
2928 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
2929   __do_global_dtors ();
2930 #endif
2931 #ifdef EXIT_BODY
2932   EXIT_BODY;
2933 #else
2934   _cleanup ();
2935 #endif
2936   _exit (status);
2937 }
2938
2939 #else
2940 int _exit_dummy_decl = 0;       /* prevent compiler & linker warnings */
2941 #endif
2942
2943 #endif /* L_exit */
2944 \f
2945 #ifdef L_eh
2946 typedef struct {
2947   void *start;
2948   void *end;
2949   void *exception_handler;
2950 } exception_table;
2951
2952 struct exception_table_node {
2953   exception_table *table;
2954   void *start;
2955   void *end;
2956   struct exception_table_node *next;
2957 };
2958
2959 static int except_table_pos;
2960 static void *except_pc;
2961 static struct exception_table_node *exception_table_list;
2962
2963 static exception_table *
2964 find_exception_table (pc)
2965      void* pc;
2966 {
2967   register struct exception_table_node *table = exception_table_list;
2968   for ( ; table != 0; table = table->next)
2969     {
2970       if (table->start <= pc && table->end > pc)
2971         return table->table;
2972     }
2973   return 0;
2974 }
2975
2976 /* this routine takes a pc, and the address of the exception handler associated
2977    with the closest exception table handler entry associated with that PC,
2978    or 0 if there are no table entries the PC fits in.  The algorithm works
2979    something like this:
2980
2981     while(current_entry exists) {
2982         if(current_entry.start < pc )
2983             current_entry = next_entry;
2984         else {
2985             if(prev_entry.start <= pc && prev_entry.end > pc) {
2986                 save pointer to prev_entry;
2987                 return prev_entry.exception_handler;
2988              }
2989             else return 0;
2990          }
2991      }
2992     return 0;
2993
2994    Assuming a correctly sorted table (ascending order) this routine should
2995    return the tightest match...
2996
2997    In the advent of a tie, we have to give the last entry, as it represents
2998    an inner block.
2999  */
3000
3001
3002 void *
3003 __find_first_exception_table_match(pc)
3004 void *pc;
3005 {
3006   exception_table *table = find_exception_table (pc);
3007   int pos = 0;
3008   int best = 0;
3009   if (table == 0)
3010     return (void*)0;
3011 #if 0
3012   printf("find_first_exception_table_match(): pc = %x!\n",pc);
3013 #endif
3014
3015   except_pc = pc;
3016
3017 #if 0
3018   /* We can't do this yet, as we don't know that the table is sorted.  */
3019   do {
3020     ++pos;
3021     if (table[pos].start > except_pc)
3022       /* found the first table[pos].start > except_pc, so the previous
3023          entry better be the one we want! */
3024       break;
3025   } while(table[pos].exception_handler != (void*)-1);
3026
3027   --pos;
3028   if (table[pos].start <= except_pc && table[pos].end > except_pc)
3029     {
3030       except_table_pos = pos;
3031 #if 0
3032       printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
3033 #endif
3034       return table[pos].exception_handler;
3035     }
3036 #else
3037   while (table[++pos].exception_handler != (void*)-1) {
3038     if (table[pos].start <= except_pc && table[pos].end > except_pc)
3039       {
3040         /* This can apply.  Make sure it is better or as good as the previous
3041            best.  */
3042         /* The best one ends first. */
3043         if (best == 0 || (table[pos].end <= table[best].end
3044                           /* The best one starts last.  */
3045                           && table[pos].start >= table[best].start))
3046           best = pos;
3047       }
3048   }
3049   if (best != 0)
3050     return table[best].exception_handler;
3051 #endif
3052
3053 #if 0
3054   printf("find_first_eh_table_match(): else: returning NULL!\n");
3055 #endif
3056   return (void*)0;
3057 }
3058
3059 void *
3060 __throw_type_match (void *catch_type, void *throw_type, void* obj)
3061 {
3062 #if 0
3063  printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3064         catch_type, throw_type);
3065 #endif
3066  if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3067    return obj;
3068  return 0;
3069 }
3070
3071 void
3072 __register_exceptions (exception_table *table)
3073 {
3074   struct exception_table_node *node;
3075   exception_table *range = table + 1;
3076
3077   if (range->start == (void*)-1)
3078     return;
3079
3080   node = (struct exception_table_node*)
3081     malloc (sizeof (struct exception_table_node));
3082   node->table = table;
3083
3084   /* This look can be optimized away either if the table
3085      is sorted, or if we pass in extra parameters. */
3086   node->start = range->start;
3087   node->end = range->end;
3088   for (range++ ; range->start != (void*)(-1); range++)
3089     {
3090       if (range->start < node->start)
3091         node->start = range->start;
3092       if (range->end > node->end)
3093         node->end = range->end;
3094     }
3095
3096   node->next = exception_table_list;
3097   exception_table_list = node;
3098 }
3099
3100 void
3101 __empty ()
3102 {
3103 }
3104
3105 #if #machine(i386)
3106 void
3107 __unwind_function(void *ptr)
3108 {
3109   asm("movl 8(%esp),%ecx");
3110   /* Undo current frame */
3111   asm("movl %ebp,%esp");
3112   asm("popl %ebp");
3113   /* like ret, but stay here */
3114   asm("addl $4,%esp");
3115   
3116   /* Now, undo previous frame. */
3117   /* This is a test routine, as we have to dynamically probe to find out
3118      what to pop for certain, this is just a guess. */
3119   asm("leal -16(%ebp),%esp");
3120   asm("pop %ebx");
3121   asm("pop %esi");
3122   asm("pop %edi");
3123   asm("movl %ebp,%esp");
3124   asm("popl %ebp");
3125
3126   asm("movl %ecx,0(%esp)");
3127   asm("ret");
3128 }
3129 #elif #machine(rs6000)
3130 __unwind_function(void *ptr)
3131 {
3132   asm("mr 31,1");
3133   asm("l 1,0(1)");
3134   asm("l 31,-4(1)");
3135   asm("# br");
3136
3137   asm("mr 31,1");
3138   asm("l 1,0(1)");
3139   /* use 31 as a scratch register to restore the link register. */
3140   asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
3141   asm("l 31,-4(1)");
3142   asm("# br");
3143   asm("mtctr 3;bctr # b 3");
3144 }
3145 #elif #machine(powerpc)
3146 __unwind_function(void *ptr)
3147 {
3148   asm("mr 31,1");
3149   asm("lwz 1,0(1)");
3150   asm("lwz 31,-4(1)");
3151   asm("# br");
3152
3153   asm("mr 31,1");
3154   asm("lwz 1,0(1)");
3155   /* use 31 as a scratch register to restore the link register. */
3156   asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
3157   asm("lwz 31,-4(1)");
3158   asm("# br");
3159   asm("mtctr 3;bctr # b 3");
3160 }
3161 #elif #machine(vax)
3162 __unwind_function(void *ptr)
3163 {
3164   __label__ return_again;
3165
3166   /* Replace our frame's return address with the label below.
3167      During execution, we will first return here instead of to
3168      caller, then second return takes caller's frame off the stack.
3169      Two returns matches two actual calls, so is less likely to
3170      confuse debuggers.  `16' corresponds to RETURN_ADDRESS_OFFSET.  */
3171   __asm ("movl %0,16(fp)" : : "p" (&& return_again));
3172   return;
3173
3174  return_again:
3175   return;
3176 }
3177 #else
3178 __unwind_function(void *ptr)
3179 {
3180   abort ();
3181 }
3182 #endif /* powerpc */
3183 #endif /* L_eh */
3184 \f
3185 #ifdef L_pure
3186 #ifndef inhibit_libc
3187 /* This gets us __GNU_LIBRARY__.  */
3188 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
3189 #include <stdio.h>
3190
3191 #ifdef __GNU_LIBRARY__
3192   /* Avoid forcing the library's meaning of `write' on the user program
3193      by using the "internal" name (for use within the library)  */
3194 #define write(fd, buf, n)       __write((fd), (buf), (n))
3195 #endif
3196 #endif /* inhibit_libc */
3197
3198 #define MESSAGE "pure virtual method called\n"
3199
3200 void
3201 __pure_virtual ()
3202 {
3203 #ifndef inhibit_libc
3204   write (2, MESSAGE, sizeof (MESSAGE) - 1);
3205 #endif
3206   _exit (-1);
3207 }
3208 #endif