OSDN Git Service

install EH code
[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, 92, 93, 94, 95, 1996 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__dummy
1196 void
1197 __dummy () {}
1198 #endif
1199
1200 #ifdef L_varargs
1201 #ifdef __i860__
1202 #if defined(__svr4__) || defined(__alliant__)
1203         asm ("  .text");
1204         asm ("  .align  4");
1205
1206 /* The Alliant needs the added underscore.  */
1207         asm (".globl    __builtin_saveregs");
1208 asm ("__builtin_saveregs:");
1209         asm (".globl    ___builtin_saveregs");
1210 asm ("___builtin_saveregs:");
1211
1212         asm ("  andnot  0x0f,%sp,%sp"); /* round down to 16-byte boundary */
1213         asm ("  adds    -96,%sp,%sp");  /* allocate stack space for reg save
1214                                            area and also for a new va_list
1215                                            structure */
1216         /* Save all argument registers in the arg reg save area.  The
1217            arg reg save area must have the following layout (according
1218            to the svr4 ABI):
1219
1220                 struct {
1221                   union  {
1222                     float freg[8];
1223                     double dreg[4];
1224                   } float_regs;
1225                   long  ireg[12];
1226                 };
1227         */
1228
1229         asm ("  fst.q   %f8,  0(%sp)"); /* save floating regs (f8-f15)  */
1230         asm ("  fst.q   %f12,16(%sp)"); 
1231
1232         asm ("  st.l    %r16,32(%sp)"); /* save integer regs (r16-r27) */
1233         asm ("  st.l    %r17,36(%sp)"); 
1234         asm ("  st.l    %r18,40(%sp)");
1235         asm ("  st.l    %r19,44(%sp)");
1236         asm ("  st.l    %r20,48(%sp)");
1237         asm ("  st.l    %r21,52(%sp)");
1238         asm ("  st.l    %r22,56(%sp)");
1239         asm ("  st.l    %r23,60(%sp)");
1240         asm ("  st.l    %r24,64(%sp)");
1241         asm ("  st.l    %r25,68(%sp)");
1242         asm ("  st.l    %r26,72(%sp)");
1243         asm ("  st.l    %r27,76(%sp)");
1244
1245         asm ("  adds    80,%sp,%r16");  /* compute the address of the new
1246                                            va_list structure.  Put in into
1247                                            r16 so that it will be returned
1248                                            to the caller.  */
1249
1250         /* Initialize all fields of the new va_list structure.  This
1251            structure looks like:
1252
1253                 typedef struct {
1254                     unsigned long       ireg_used;
1255                     unsigned long       freg_used;
1256                     long                *reg_base;
1257                     long                *mem_ptr;
1258                 } va_list;
1259         */
1260
1261         asm ("  st.l    %r0, 0(%r16)"); /* nfixed */
1262         asm ("  st.l    %r0, 4(%r16)"); /* nfloating */
1263         asm ("  st.l    %sp, 8(%r16)"); /* __va_ctl points to __va_struct.  */
1264         asm ("  bri     %r1");          /* delayed return */
1265         asm ("  st.l    %r28,12(%r16)"); /* pointer to overflow args */
1266
1267 #else /* not __svr4__ */
1268 #if defined(__PARAGON__)
1269         /*
1270          *      we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1271          *      and we stand a better chance of hooking into libraries
1272          *      compiled by PGI.  [andyp@ssd.intel.com]
1273          */
1274         asm ("  .text");
1275         asm ("  .align  4");
1276         asm (".globl    __builtin_saveregs");
1277 asm ("__builtin_saveregs:");
1278         asm (".globl    ___builtin_saveregs");
1279 asm ("___builtin_saveregs:");
1280
1281         asm ("  andnot  0x0f,sp,sp");   /* round down to 16-byte boundary */
1282         asm ("  adds    -96,sp,sp");    /* allocate stack space for reg save
1283                                            area and also for a new va_list
1284                                            structure */
1285         /* Save all argument registers in the arg reg save area.  The
1286            arg reg save area must have the following layout (according
1287            to the svr4 ABI):
1288
1289                 struct {
1290                   union  {
1291                     float freg[8];
1292                     double dreg[4];
1293                   } float_regs;
1294                   long  ireg[12];
1295                 };
1296         */
1297
1298         asm ("  fst.q   f8,  0(sp)");
1299         asm ("  fst.q   f12,16(sp)"); 
1300         asm ("  st.l    r16,32(sp)");
1301         asm ("  st.l    r17,36(sp)"); 
1302         asm ("  st.l    r18,40(sp)");
1303         asm ("  st.l    r19,44(sp)");
1304         asm ("  st.l    r20,48(sp)");
1305         asm ("  st.l    r21,52(sp)");
1306         asm ("  st.l    r22,56(sp)");
1307         asm ("  st.l    r23,60(sp)");
1308         asm ("  st.l    r24,64(sp)");
1309         asm ("  st.l    r25,68(sp)");
1310         asm ("  st.l    r26,72(sp)");
1311         asm ("  st.l    r27,76(sp)");
1312
1313         asm ("  adds    80,sp,r16");  /* compute the address of the new
1314                                            va_list structure.  Put in into
1315                                            r16 so that it will be returned
1316                                            to the caller.  */
1317
1318         /* Initialize all fields of the new va_list structure.  This
1319            structure looks like:
1320
1321                 typedef struct {
1322                     unsigned long       ireg_used;
1323                     unsigned long       freg_used;
1324                     long                *reg_base;
1325                     long                *mem_ptr;
1326                 } va_list;
1327         */
1328
1329         asm ("  st.l    r0, 0(r16)"); /* nfixed */
1330         asm ("  st.l    r0, 4(r16)"); /* nfloating */
1331         asm ("  st.l    sp, 8(r16)"); /* __va_ctl points to __va_struct.  */
1332         asm ("  bri     r1");           /* delayed return */
1333         asm ("   st.l   r28,12(r16)"); /* pointer to overflow args */
1334 #else /* not __PARAGON__ */
1335         asm ("  .text");
1336         asm ("  .align  4");
1337
1338         asm (".globl    ___builtin_saveregs");
1339         asm ("___builtin_saveregs:");
1340         asm ("  mov     sp,r30");
1341         asm ("  andnot  0x0f,sp,sp");
1342         asm ("  adds    -96,sp,sp");  /* allocate sufficient space on the stack */
1343
1344 /* Fill in the __va_struct.  */
1345         asm ("  st.l    r16, 0(sp)"); /* save integer regs (r16-r27) */
1346         asm ("  st.l    r17, 4(sp)"); /* int    fixed[12] */
1347         asm ("  st.l    r18, 8(sp)");
1348         asm ("  st.l    r19,12(sp)");
1349         asm ("  st.l    r20,16(sp)");
1350         asm ("  st.l    r21,20(sp)");
1351         asm ("  st.l    r22,24(sp)");
1352         asm ("  st.l    r23,28(sp)");
1353         asm ("  st.l    r24,32(sp)");
1354         asm ("  st.l    r25,36(sp)");
1355         asm ("  st.l    r26,40(sp)");
1356         asm ("  st.l    r27,44(sp)");
1357
1358         asm ("  fst.q   f8, 48(sp)"); /* save floating regs (f8-f15) */
1359         asm ("  fst.q   f12,64(sp)"); /* int floating[8] */
1360
1361 /* Fill in the __va_ctl.  */
1362         asm ("  st.l    sp, 80(sp)"); /* __va_ctl points to __va_struct.  */
1363         asm ("  st.l    r28,84(sp)"); /* pointer to more args */
1364         asm ("  st.l    r0, 88(sp)"); /* nfixed */
1365         asm ("  st.l    r0, 92(sp)"); /* nfloating */
1366
1367         asm ("  adds    80,sp,r16");  /* return address of the __va_ctl.  */
1368         asm ("  bri     r1");
1369         asm ("  mov     r30,sp");
1370                                 /* recover stack and pass address to start 
1371                                    of data.  */
1372 #endif /* not __PARAGON__ */
1373 #endif /* not __svr4__ */
1374 #else /* not __i860__ */
1375 #ifdef __sparc__
1376         asm (".global __builtin_saveregs");
1377         asm ("__builtin_saveregs:");
1378         asm (".global ___builtin_saveregs");
1379         asm ("___builtin_saveregs:");
1380 #ifdef NEED_PROC_COMMAND
1381         asm (".proc 020");
1382 #endif
1383         asm ("st %i0,[%fp+68]");
1384         asm ("st %i1,[%fp+72]");
1385         asm ("st %i2,[%fp+76]");
1386         asm ("st %i3,[%fp+80]");
1387         asm ("st %i4,[%fp+84]");
1388         asm ("retl");
1389         asm ("st %i5,[%fp+88]");
1390 #ifdef NEED_TYPE_COMMAND
1391         asm (".type __builtin_saveregs,#function");
1392         asm (".size __builtin_saveregs,.-__builtin_saveregs");
1393 #endif
1394 #else /* not __sparc__ */
1395 #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1396
1397   asm ("        .text");
1398   asm ("        .ent __builtin_saveregs");
1399   asm ("        .globl __builtin_saveregs");
1400   asm ("__builtin_saveregs:");
1401   asm ("        sw      $4,0($30)");
1402   asm ("        sw      $5,4($30)");
1403   asm ("        sw      $6,8($30)");
1404   asm ("        sw      $7,12($30)");
1405   asm ("        j       $31");
1406   asm ("        .end __builtin_saveregs");
1407 #else /* not __mips__, etc.  */
1408
1409 void *
1410 __builtin_saveregs ()
1411 {
1412   abort ();
1413 }
1414
1415 #endif /* not __mips__ */
1416 #endif /* not __sparc__ */
1417 #endif /* not __i860__ */
1418 #endif
1419 \f
1420 #ifdef L_eprintf
1421 #ifndef inhibit_libc
1422
1423 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1424 #include <stdio.h>
1425 /* This is used by the `assert' macro.  */
1426 void
1427 __eprintf (string, expression, line, filename)
1428      const char *string;
1429      const char *expression;
1430      int line;
1431      const char *filename;
1432 {
1433   fprintf (stderr, string, expression, line, filename);
1434   fflush (stderr);
1435   abort ();
1436 }
1437
1438 #endif
1439 #endif
1440
1441 #ifdef L_bb
1442
1443 /* Structure emitted by -a  */
1444 struct bb
1445 {
1446   long zero_word;
1447   const char *filename;
1448   long *counts;
1449   long ncounts;
1450   struct bb *next;
1451   const unsigned long *addresses;
1452
1453   /* Older GCC's did not emit these fields.  */
1454   long nwords;
1455   const char **functions;
1456   const long *line_nums;
1457   const char **filenames;
1458   char *flags;
1459 };
1460
1461 #ifdef BLOCK_PROFILER_CODE
1462 BLOCK_PROFILER_CODE
1463 #else
1464 #ifndef inhibit_libc
1465
1466 /* Simple minded basic block profiling output dumper for
1467    systems that don't provide tcov support.  At present,
1468    it requires atexit and stdio.  */
1469
1470 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1471 #include <stdio.h>
1472 char *ctime ();
1473
1474 #include "gbl-ctors.h"
1475
1476 static struct bb *bb_head;
1477
1478 /* Return the number of digits needed to print a value */
1479 /* __inline__ */ static int num_digits (long value, int base)
1480 {
1481   int minus = (value < 0 && base != 16);
1482   unsigned long v = (minus) ? -value : value;
1483   int ret = minus;
1484
1485   do
1486     {
1487       v /= base;
1488       ret++;
1489     }
1490   while (v);
1491
1492   return ret;
1493 }
1494
1495 void
1496 __bb_exit_func (void)
1497 {
1498   FILE *file = fopen ("bb.out", "a");
1499   long time_value;
1500
1501   if (!file)
1502     perror ("bb.out");
1503
1504   else
1505     {
1506       struct bb *ptr;
1507
1508       /* This is somewhat type incorrect, but it avoids worrying about
1509          exactly where time.h is included from.  It should be ok unless
1510          a void * differs from other pointer formats, or if sizeof (long)
1511          is < sizeof (time_t).  It would be nice if we could assume the
1512          use of rationale standards here.  */
1513
1514       time ((void *) &time_value);
1515       fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1516
1517       /* We check the length field explicitly in order to allow compatibility
1518          with older GCC's which did not provide it.  */
1519
1520       for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1521         {
1522           int i;
1523           int func_p    = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
1524           int line_p    = (func_p && ptr->line_nums);
1525           int file_p    = (func_p && ptr->filenames);
1526           long ncounts  = ptr->ncounts;
1527           long cnt_max  = 0;
1528           long line_max = 0;
1529           long addr_max = 0;
1530           int file_len  = 0;
1531           int func_len  = 0;
1532           int blk_len   = num_digits (ncounts, 10);
1533           int cnt_len;
1534           int line_len;
1535           int addr_len;
1536
1537           fprintf (file, "File %s, %ld basic blocks \n\n",
1538                    ptr->filename, ncounts);
1539
1540           /* Get max values for each field.  */
1541           for (i = 0; i < ncounts; i++)
1542             {
1543               const char *p;
1544               int len;
1545
1546               if (cnt_max < ptr->counts[i])
1547                 cnt_max = ptr->counts[i];
1548
1549               if (addr_max < ptr->addresses[i])
1550                 addr_max = ptr->addresses[i];
1551
1552               if (line_p && line_max < ptr->line_nums[i])
1553                 line_max = ptr->line_nums[i];
1554
1555               if (func_p)
1556                 {
1557                   p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1558                   len = strlen (p);
1559                   if (func_len < len)
1560                     func_len = len;
1561                 }
1562
1563               if (file_p)
1564                 {
1565                   p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1566                   len = strlen (p);
1567                   if (file_len < len)
1568                     file_len = len;
1569                 }
1570             }
1571
1572           addr_len = num_digits (addr_max, 16);
1573           cnt_len  = num_digits (cnt_max, 10);
1574           line_len = num_digits (line_max, 10);
1575
1576           /* Now print out the basic block information.  */
1577           for (i = 0; i < ncounts; i++)
1578             {
1579               fprintf (file,
1580                        "    Block #%*d: executed %*ld time(s) address= 0x%.*lx",
1581                        blk_len, i+1,
1582                        cnt_len, ptr->counts[i],
1583                        addr_len, ptr->addresses[i]);
1584
1585               if (func_p)
1586                 fprintf (file, " function= %-*s", func_len,
1587                          (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1588
1589               if (line_p)
1590                 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1591
1592               if (file_p)
1593                 fprintf (file, " file= %s",
1594                          (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1595
1596               fprintf (file, "\n");
1597             }
1598
1599           fprintf (file, "\n");
1600           fflush (file);
1601         }
1602
1603       fprintf (file, "\n\n");
1604       fclose (file);
1605     }
1606 }
1607
1608 void
1609 __bb_init_func (struct bb *blocks)
1610 {
1611   /* User is supposed to check whether the first word is non-0,
1612      but just in case....  */
1613
1614   if (blocks->zero_word)
1615     return;
1616
1617 #ifdef ON_EXIT
1618   /* Initialize destructor.  */
1619   if (!bb_head)
1620     ON_EXIT (__bb_exit_func, 0);
1621 #endif
1622
1623   /* Set up linked list.  */
1624   blocks->zero_word = 1;
1625   blocks->next = bb_head;
1626   bb_head = blocks;
1627 }
1628
1629 #ifndef MACHINE_STATE_SAVE
1630 #define MACHINE_STATE_SAVE(ID)
1631 #endif
1632 #ifndef MACHINE_STATE_RESTORE
1633 #define MACHINE_STATE_RESTORE(ID)
1634 #endif
1635
1636 #include <string.h>
1637
1638 /* Number of buckets in hashtable of basic block addresses.  */
1639
1640 #define BB_BUCKETS 311
1641
1642 /* Maximum length of string in file bb.in.  */
1643
1644 #define BBINBUFSIZE 500
1645
1646 /* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
1647    "BBINBUFSIZE" but want to avoid trouble with preprocessors.  */
1648
1649 #define BBINBUFSIZESTR "499"
1650
1651 struct bb_edge
1652 {
1653   struct bb_edge *next;
1654   unsigned long src_addr;
1655   unsigned long dst_addr;
1656   unsigned long count;
1657 };
1658
1659 enum bb_func_mode
1660 {
1661   TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1662 };
1663
1664 struct bb_func
1665 {
1666   struct bb_func *next;
1667   char *funcname;
1668   char *filename;
1669   enum bb_func_mode mode;
1670 };
1671
1672 /* This is the connection to the outside world.
1673    The BLOCK_PROFILER macro must set __bb.blocks
1674    and __bb.blockno.  */
1675
1676 struct {
1677   unsigned long blockno;
1678   struct bb *blocks;
1679 } __bb;
1680
1681 /* Vars to store addrs of source and destination basic blocks 
1682    of a jump.  */
1683
1684 static unsigned long bb_src = 0;
1685 static unsigned long bb_dst = 0;
1686
1687 static FILE *bb_tracefile = (FILE *) 0;
1688 static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1689 static struct bb_func *bb_func_head = (struct bb_func *) 0;
1690 static unsigned long bb_callcount = 0;
1691 static int bb_mode = 0;
1692
1693 static unsigned long *bb_stack = (unsigned long *) 0;
1694 static size_t bb_stacksize = 0;
1695
1696 static int reported = 0;
1697
1698 /* Trace modes:
1699 Always             :   Print execution frequencies of basic blocks
1700                        to file bb.out.
1701 bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
1702 bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
1703 bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
1704 bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
1705 */
1706
1707 #ifdef HAVE_POPEN
1708
1709 /*#include <sys/types.h>*/
1710 #include <sys/stat.h>
1711 /*#include <malloc.h>*/
1712
1713 /* Commands executed by gopen.  */
1714
1715 #define GOPENDECOMPRESS "gzip -cd "
1716 #define GOPENCOMPRESS "gzip -c >"
1717
1718 /* Like fopen but pipes through gzip.  mode may only be "r" or "w".
1719    If it does not compile, simply replace gopen by fopen and delete
1720    '.gz' from any first parameter to gopen.  */
1721
1722 static FILE *
1723 gopen (fn, mode)
1724      char *fn;
1725      char *mode;
1726 {
1727   int use_gzip;
1728   char *p;
1729
1730   if (mode[1])
1731     return (FILE *) 0;
1732
1733   if (mode[0] != 'r' && mode[0] != 'w') 
1734     return (FILE *) 0;
1735
1736   p = fn + strlen (fn)-1;
1737   use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z')) ||
1738               (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1739
1740   if (use_gzip)
1741     {
1742       if (mode[0]=='r')
1743         {
1744           FILE *f;
1745           char *s = (char *) malloc (sizeof (char) * strlen (fn)
1746                                      + sizeof (GOPENDECOMPRESS));
1747           strcpy (s, GOPENDECOMPRESS);
1748           strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1749           f = popen (s, mode);
1750           free (s);
1751           return f;
1752         }
1753
1754       else
1755         {
1756           FILE *f;
1757           char *s = (char *) malloc (sizeof (char) * strlen (fn)
1758                                      + sizeof (GOPENCOMPRESS));
1759           strcpy (s, GOPENCOMPRESS);
1760           strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1761           if (!(f = popen (s, mode)))
1762             f = fopen (s, mode);
1763           free (s);
1764           return f;
1765         }
1766     }
1767
1768   else
1769     return fopen (fn, mode);
1770 }
1771
1772 static int
1773 gclose (f)
1774      FILE *f;
1775 {
1776   struct stat buf;
1777
1778   if (f != NULL)
1779     {
1780       if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1781         return pclose (f);
1782
1783       return fclose (f);
1784     }
1785   return 0;
1786 }
1787
1788 #endif /* HAVE_POPEN */
1789
1790 /* Called once per program.  */
1791
1792 static void
1793 __bb_exit_trace_func ()
1794 {
1795   FILE *file = fopen ("bb.out", "a");
1796   struct bb_func *f;
1797   struct bb_edge *e;
1798   struct bb *b;
1799         
1800   if (!file)
1801     perror ("bb.out");
1802
1803   if (bb_mode & 1)
1804     {
1805       if (!bb_tracefile)
1806         perror ("bbtrace");
1807       else
1808 #ifdef HAVE_POPEN
1809         gclose (bb_tracefile);
1810 #else
1811         fclose (bb_tracefile);
1812 #endif /* HAVE_POPEN */
1813     }
1814
1815   /* Check functions in `bb.in'.  */
1816
1817   if (file)
1818     {
1819       long time_value;
1820       const struct bb_func *p;
1821       int printed_something = 0;
1822       struct bb *ptr;
1823       long blk;
1824
1825       /* This is somewhat type incorrect.  */
1826       time ((void *) &time_value);
1827
1828       for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
1829         {
1830           for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1831             {
1832               if (!ptr->filename || p->filename != (char *) 0 && strcmp (p->filename, ptr->filename))
1833                 continue;
1834               for (blk = 0; blk < ptr->ncounts; blk++)
1835                 {
1836                   if (!strcmp (p->funcname, ptr->functions[blk]))
1837                     goto found;
1838                 }
1839             }
1840   
1841           if (!printed_something)
1842             {
1843               fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1844               printed_something = 1;
1845             }
1846
1847           fprintf (file, "\tFunction %s", p->funcname);
1848           if (p->filename)
1849               fprintf (file, " of file %s", p->filename);
1850           fprintf (file, "\n" );
1851   
1852 found:        ;
1853         }
1854
1855       if (printed_something)
1856        fprintf (file, "\n");
1857
1858     }
1859
1860   if (bb_mode & 2)
1861     {
1862       if (!bb_hashbuckets)
1863         {
1864           if (!reported)
1865             {
1866               fprintf (stderr, "Profiler: out of memory\n");
1867               reported = 1;
1868             }
1869           return;
1870         }
1871     
1872       else if (file)
1873         {
1874           long time_value;
1875           int i;
1876           unsigned long addr_max = 0;
1877           unsigned long cnt_max  = 0;
1878           int cnt_len;
1879           int addr_len;
1880     
1881           /* This is somewhat type incorrect, but it avoids worrying about
1882              exactly where time.h is included from.  It should be ok unless
1883              a void * differs from other pointer formats, or if sizeof (long)
1884              is < sizeof (time_t).  It would be nice if we could assume the
1885              use of rationale standards here.  */
1886     
1887           time ((void *) &time_value);
1888           fprintf (file, "Basic block jump tracing");
1889
1890           switch (bb_mode & 12)
1891             {
1892               case 0:
1893                 fprintf (file, " (with call)");
1894               break;
1895
1896               case 4:
1897                 /* Print nothing.  */
1898               break;
1899
1900               case 8:
1901                 fprintf (file, " (with call & ret)");
1902               break;
1903
1904               case 12:
1905                 fprintf (file, " (with ret)");
1906               break;
1907             }
1908
1909           fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1910     
1911           for (i = 0; i < BB_BUCKETS; i++)
1912             {
1913                struct bb_edge *bucket = bb_hashbuckets[i];
1914                for ( ; bucket; bucket = bucket->next )
1915                  {
1916                    if (addr_max < bucket->src_addr) 
1917                      addr_max = bucket->src_addr;
1918                    if (addr_max < bucket->dst_addr) 
1919                      addr_max = bucket->dst_addr;
1920                    if (cnt_max < bucket->count) 
1921                      cnt_max = bucket->count;
1922                  }
1923             }
1924           addr_len = num_digits (addr_max, 16);
1925           cnt_len  = num_digits (cnt_max, 10);
1926     
1927           for ( i = 0; i < BB_BUCKETS; i++)
1928             {
1929                struct bb_edge *bucket = bb_hashbuckets[i];
1930                for ( ; bucket; bucket = bucket->next )
1931                  {
1932                    fprintf (file, "Jump from block 0x%.*lx to "
1933                                   "block 0x%.*lx executed %*d time(s)\n", 
1934                             addr_len, bucket->src_addr, 
1935                             addr_len, bucket->dst_addr, 
1936                             cnt_len, bucket->count);
1937                  }
1938             }
1939   
1940           fprintf (file, "\n");
1941
1942         }
1943     }
1944
1945    if (file)
1946      fclose (file);
1947
1948    /* Free allocated memory.  */
1949
1950    f = bb_func_head;
1951    while (f)
1952      {
1953        struct bb_func *old = f;
1954
1955        f = f->next;
1956        if (old->funcname) free (old->funcname);
1957        if (old->filename) free (old->filename);
1958        free (old);
1959      }
1960
1961    if (bb_stack)
1962      free (bb_stack);
1963
1964    if (bb_hashbuckets)
1965      {
1966        int i;
1967
1968        for (i = 0; i < BB_BUCKETS; i++)
1969          {
1970            struct bb_edge *old, *bucket = bb_hashbuckets[i];
1971
1972            while (bucket)
1973              {
1974                old = bucket;
1975                bucket = bucket->next;
1976                free (old);
1977              }
1978          }
1979        free (bb_hashbuckets);
1980      }
1981
1982    for (b = bb_head; b; b = b->next)
1983      if (b->flags) free (b->flags);
1984 }
1985
1986 /* Called once per program.  */
1987
1988 static void
1989 __bb_init_prg ()
1990 {
1991
1992   FILE *file;
1993   char buf[BBINBUFSIZE];
1994   const char *p;
1995   const char *pos;
1996   enum bb_func_mode m;
1997
1998 #ifdef ON_EXIT
1999   /* Initialize destructor.  */
2000   ON_EXIT (__bb_exit_func, 0);
2001 #endif
2002
2003   if (!(file = fopen ("bb.in", "r")))
2004     return;
2005
2006   while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
2007     {
2008       p = buf;
2009       if (*p == '-') 
2010         { 
2011           m = TRACE_OFF; 
2012           p++; 
2013         }
2014       else 
2015         { 
2016           m = TRACE_ON; 
2017         }
2018       if (!strcmp (p, "__bb_trace__"))
2019         bb_mode |= 1;
2020       else if (!strcmp (p, "__bb_jumps__"))
2021         bb_mode |= 2;
2022       else if (!strcmp (p, "__bb_hidecall__"))
2023         bb_mode |= 4;
2024       else if (!strcmp (p, "__bb_showret__"))
2025         bb_mode |= 8;
2026       else 
2027         {
2028           struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
2029           if (f)
2030             {
2031               unsigned long l;
2032               f->next = bb_func_head;
2033               if (pos = strchr (p, ':'))
2034                 {
2035                   if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
2036                     continue;
2037                   strcpy (f->funcname, pos+1);
2038                   l = pos-p;
2039                   if ((f->filename = (char *) malloc (l+1)))
2040                     {
2041                       strncpy (f->filename, p, l);
2042                       f->filename[l] = '\0';
2043                     }
2044                   else
2045                     f->filename = (char *) 0;
2046                 }
2047               else
2048                 {
2049                   if (!(f->funcname = (char *) malloc (strlen (p)+1)))
2050                     continue;
2051                   strcpy (f->funcname, p);
2052                   f->filename = (char *) 0;
2053                 }
2054               f->mode = m;
2055               bb_func_head = f;
2056             }
2057          }
2058     }
2059   fclose (file);
2060
2061 #ifdef HAVE_POPEN 
2062
2063   if (bb_mode & 1)
2064       bb_tracefile = gopen ("bbtrace.gz", "w");
2065
2066 #else
2067
2068   if (bb_mode & 1)
2069       bb_tracefile = fopen ("bbtrace", "w");
2070
2071 #endif /* HAVE_POPEN */
2072
2073   if (bb_mode & 2)
2074     {
2075       bb_hashbuckets = (struct bb_edge **) 
2076                    malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2077       if (bb_hashbuckets)
2078         bzero ((char *) bb_hashbuckets, BB_BUCKETS);
2079     }
2080
2081   if (bb_mode & 12)
2082     {
2083       bb_stacksize = 10;
2084       bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2085     }
2086
2087 #ifdef ON_EXIT
2088       /* Initialize destructor.  */
2089       ON_EXIT (__bb_exit_trace_func, 0);
2090 #endif
2091
2092 }
2093
2094 /* Called upon entering a basic block.  */
2095
2096 void
2097 __bb_trace_func ()
2098 {
2099   struct bb_edge *bucket;
2100
2101   MACHINE_STATE_SAVE("1")
2102
2103   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2104     goto skip;
2105
2106   bb_dst = __bb.blocks->addresses[__bb.blockno];
2107   __bb.blocks->counts[__bb.blockno]++;
2108
2109   if (bb_tracefile)
2110     {
2111       fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2112     }
2113
2114   if (bb_hashbuckets)
2115     {
2116       struct bb_edge **startbucket, **oldnext;
2117
2118       oldnext = startbucket =
2119           & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
2120       bucket = *startbucket;
2121
2122       for (bucket = *startbucket; bucket; 
2123            oldnext = &(bucket->next), bucket = *oldnext)
2124         {
2125           if ( bucket->src_addr == bb_src &&
2126                bucket->dst_addr == bb_dst )
2127             {
2128               bucket->count++;
2129               *oldnext = bucket->next;
2130               bucket->next = *startbucket;
2131               *startbucket = bucket;
2132               goto ret;
2133             }
2134         }
2135
2136       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2137
2138       if (!bucket)
2139         {
2140           if (!reported)
2141             {
2142               fprintf (stderr, "Profiler: out of memory\n");
2143               reported = 1;
2144             }
2145         }
2146
2147       else
2148         {
2149           bucket->src_addr = bb_src;
2150           bucket->dst_addr = bb_dst;
2151           bucket->next = *startbucket;
2152           *startbucket = bucket;
2153           bucket->count = 1;
2154         }
2155     }
2156
2157 ret:
2158   bb_src = bb_dst;
2159
2160 skip:
2161   ;
2162
2163   MACHINE_STATE_RESTORE("1")
2164
2165 }
2166
2167 /* Called when returning from a function and `__bb_showret__' is set.  */
2168
2169 static void
2170 __bb_trace_func_ret ()
2171 {
2172   struct bb_edge *bucket;
2173
2174   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2175     goto skip;
2176
2177   if (bb_hashbuckets)
2178     {
2179       struct bb_edge **startbucket, **oldnext;
2180
2181       oldnext = startbucket =
2182           & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
2183       bucket = *startbucket;
2184
2185       for (bucket = *startbucket; bucket; 
2186            oldnext = &(bucket->next), bucket = *oldnext)
2187         {
2188           if ( bucket->src_addr == bb_dst &&
2189                bucket->dst_addr == bb_src )
2190             {
2191               bucket->count++;
2192               *oldnext = bucket->next;
2193               bucket->next = *startbucket;
2194               *startbucket = bucket;
2195               goto ret;
2196             }
2197         }
2198
2199       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2200
2201       if (!bucket)
2202         {
2203           if (!reported)
2204             {
2205               fprintf (stderr, "Profiler: out of memory\n");
2206               reported = 1;
2207             }
2208         }
2209
2210       else
2211         {
2212           bucket->src_addr = bb_dst;
2213           bucket->dst_addr = bb_src;
2214           bucket->next = *startbucket;
2215           *startbucket = bucket;
2216           bucket->count = 1;
2217         }
2218     }
2219
2220 ret:
2221   bb_dst = bb_src;
2222
2223 skip:
2224   ;
2225
2226 }
2227
2228 /* Called upon entering the first function of a file.  */
2229
2230 static void
2231 __bb_init_file (blocks)
2232      struct bb *blocks;
2233 {
2234
2235   const struct bb_func *p;
2236   long blk, ncounts = blocks->ncounts;
2237   const char **functions = blocks->functions;
2238
2239   /* Set up linked list.  */
2240   blocks->zero_word = 1;
2241   blocks->next = bb_head;
2242   bb_head = blocks;
2243
2244   blocks->flags = 0;
2245   if (!bb_func_head ||
2246       !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
2247     return;
2248
2249   for (blk = 0; blk < ncounts; blk++)
2250     blocks->flags[blk] = 0;
2251
2252   for (blk = 0; blk < ncounts; blk++)
2253     {
2254       for (p = bb_func_head; p; p = p->next)
2255         {
2256           if (!strcmp (p->funcname, functions[blk]) &&
2257               (!p->filename || !strcmp (p->filename, blocks->filename)))
2258             {
2259               blocks->flags[blk] |= p->mode;
2260             }
2261         }
2262     }
2263
2264 }
2265
2266 /* Called when exiting from a function.  */
2267
2268 void
2269 __bb_trace_ret ()
2270 {
2271
2272   MACHINE_STATE_SAVE("2")
2273
2274   if (bb_callcount)
2275     {
2276       if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2277         {
2278           bb_src = bb_stack[bb_callcount];
2279           if (bb_mode & 8)
2280             __bb_trace_func_ret ();
2281         }
2282
2283       bb_callcount -= 1;
2284     }
2285
2286   MACHINE_STATE_RESTORE("2")
2287
2288 }
2289
2290 /* Called when entering a function.  */
2291
2292 void
2293 __bb_init_trace_func (blocks, blockno)
2294      struct bb *blocks;
2295      unsigned long blockno;
2296 {
2297   static int trace_init = 0;
2298
2299   MACHINE_STATE_SAVE("3")
2300
2301   if (!blocks->zero_word)
2302     { 
2303       if (!trace_init)
2304         { 
2305           trace_init = 1;
2306           __bb_init_prg ();
2307         }
2308       __bb_init_file (blocks);
2309     }
2310
2311   if (bb_callcount)
2312     {
2313
2314       bb_callcount += 1;
2315
2316       if (bb_mode & 12)
2317         {
2318           if (bb_callcount >= bb_stacksize)
2319             {
2320               size_t newsize = bb_callcount + 100;
2321
2322               bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2323               if (! bb_stack)
2324                 {
2325                   if (!reported)
2326                     {
2327                       fprintf (stderr, "Profiler: out of memory\n");
2328                       reported = 1;
2329                     }
2330                   bb_stacksize = 0;
2331                   goto stack_overflow;
2332                 }
2333               bb_stacksize = newsize;
2334             }
2335           bb_stack[bb_callcount] = bb_src;
2336
2337           if (bb_mode & 4)
2338             bb_src = 0;
2339
2340         }
2341
2342 stack_overflow:;
2343
2344     }
2345
2346   else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2347     {
2348       bb_callcount = 1;
2349       bb_src = 0;
2350
2351       if (bb_stack)
2352           bb_stack[bb_callcount] = bb_src;
2353     }
2354
2355   MACHINE_STATE_RESTORE("3")
2356 }
2357
2358 #endif /* not inhibit_libc */
2359 #endif /* not BLOCK_PROFILER_CODE */
2360 #endif /* L_bb */
2361 \f
2362 /* Default free-store management functions for C++, per sections 12.5 and
2363    17.3.3 of the Working Paper.  */
2364
2365 #ifdef L_op_new
2366 /* operator new (size_t), described in 17.3.3.5.  This function is used by
2367    C++ programs to allocate a block of memory to hold a single object.  */
2368
2369 typedef void (*vfp)(void);
2370 extern vfp __new_handler;
2371 extern void __default_new_handler (void);
2372
2373 #ifdef WEAK_ALIAS
2374 void * __builtin_new (size_t sz)
2375      __attribute__ ((weak, alias ("___builtin_new")));
2376 void *
2377 ___builtin_new (size_t sz)
2378 #else
2379 void *
2380 __builtin_new (size_t sz)
2381 #endif
2382 {
2383   void *p;
2384   vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
2385
2386   /* malloc (0) is unpredictable; avoid it.  */
2387   if (sz == 0)
2388     sz = 1;
2389   p = (void *) malloc (sz);
2390   while (p == 0)
2391     {
2392       (*handler) ();
2393       p = (void *) malloc (sz);
2394     }
2395   
2396   return p;
2397 }
2398 #endif /* L_op_new */
2399
2400 #ifdef L_op_vnew
2401 /* void * operator new [] (size_t), described in 17.3.3.6.  This function
2402    is used by C++ programs to allocate a block of memory for an array.  */
2403
2404 extern void * __builtin_new (size_t);
2405
2406 #ifdef WEAK_ALIAS
2407 void * __builtin_vec_new (size_t sz)
2408      __attribute__ ((weak, alias ("___builtin_vec_new")));
2409 void *
2410 ___builtin_vec_new (size_t sz)
2411 #else
2412 void *
2413 __builtin_vec_new (size_t sz)
2414 #endif
2415 {
2416   return __builtin_new (sz);
2417 }
2418 #endif /* L_op_vnew */
2419
2420 #ifdef L_new_handler
2421 /* set_new_handler (fvoid_t *) and the default new handler, described in
2422    17.3.3.2 and 17.3.3.5.  These functions define the result of a failure
2423    to allocate the amount of memory requested from operator new or new [].  */
2424
2425 #ifndef inhibit_libc
2426 /* This gets us __GNU_LIBRARY__.  */
2427 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2428 #include <stdio.h>
2429
2430 #ifdef __GNU_LIBRARY__
2431   /* Avoid forcing the library's meaning of `write' on the user program
2432      by using the "internal" name (for use within the library)  */
2433 #define write(fd, buf, n)       __write((fd), (buf), (n))
2434 #endif
2435 #endif /* inhibit_libc */
2436
2437 typedef void (*vfp)(void);
2438 void __default_new_handler (void);
2439
2440 vfp __new_handler = (vfp) 0;
2441
2442 vfp
2443 set_new_handler (vfp handler)
2444 {
2445   vfp prev_handler;
2446
2447   prev_handler = __new_handler;
2448   if (handler == 0) handler = __default_new_handler;
2449   __new_handler = handler;
2450   return prev_handler;
2451 }
2452
2453 #define MESSAGE "Virtual memory exceeded in `new'\n"
2454
2455 void
2456 __default_new_handler ()
2457 {
2458 #ifndef inhibit_libc
2459   /* don't use fprintf (stderr, ...) because it may need to call malloc.  */
2460   /* This should really print the name of the program, but that is hard to
2461      do.  We need a standard, clean way to get at the name.  */
2462   write (2, MESSAGE, sizeof (MESSAGE));
2463 #endif
2464   /* don't call exit () because that may call global destructors which
2465      may cause a loop.  */
2466   _exit (-1);
2467 }
2468 #endif
2469
2470 #ifdef L_op_delete
2471 /* operator delete (void *), described in 17.3.3.3.  This function is used
2472    by C++ programs to return to the free store a block of memory allocated
2473    as a single object.  */
2474
2475 #ifdef WEAK_ALIAS
2476 void __builtin_delete (void *ptr)
2477      __attribute__ ((weak, alias ("___builtin_delete")));
2478 void
2479 ___builtin_delete (void *ptr)
2480 #else
2481 void
2482 __builtin_delete (void *ptr)
2483 #endif
2484 {
2485   if (ptr)
2486     free (ptr);
2487 }
2488 #endif
2489
2490 #ifdef L_op_vdel
2491 /* operator delete [] (void *), described in 17.3.3.4.  This function is
2492    used by C++ programs to return to the free store a block of memory
2493    allocated as an array.  */
2494
2495 extern void __builtin_delete (void *);
2496
2497 #ifdef WEAK_ALIAS
2498 void __builtin_vec_delete (void *ptr)
2499      __attribute__ ((weak, alias ("___builtin_vec_delete")));
2500 void
2501 ___builtin_vec_delete (void *ptr)
2502 #else
2503 void
2504 __builtin_vec_delete (void *ptr)
2505 #endif
2506 {
2507   __builtin_delete (ptr);
2508 }
2509 #endif
2510
2511 /* End of C++ free-store management functions */
2512 \f
2513 #ifdef L_shtab
2514 unsigned int __shtab[] = {
2515     0x00000001, 0x00000002, 0x00000004, 0x00000008,
2516     0x00000010, 0x00000020, 0x00000040, 0x00000080,
2517     0x00000100, 0x00000200, 0x00000400, 0x00000800,
2518     0x00001000, 0x00002000, 0x00004000, 0x00008000,
2519     0x00010000, 0x00020000, 0x00040000, 0x00080000,
2520     0x00100000, 0x00200000, 0x00400000, 0x00800000,
2521     0x01000000, 0x02000000, 0x04000000, 0x08000000,
2522     0x10000000, 0x20000000, 0x40000000, 0x80000000
2523   };
2524 #endif
2525 \f
2526 #ifdef L_clear_cache
2527 /* Clear part of an instruction cache.  */
2528
2529 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2530
2531 void
2532 __clear_cache (beg, end)
2533      char *beg, *end;
2534 {
2535 #ifdef CLEAR_INSN_CACHE 
2536   CLEAR_INSN_CACHE (beg, end);
2537 #else
2538 #ifdef INSN_CACHE_SIZE
2539   static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
2540   static int initialized;
2541   int offset;
2542   void *start_addr
2543   void *end_addr;
2544   typedef (*function_ptr) ();
2545
2546 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2547   /* It's cheaper to clear the whole cache.
2548      Put in a series of jump instructions so that calling the beginning
2549      of the cache will clear the whole thing.  */
2550
2551   if (! initialized)
2552     {
2553       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2554                  & -INSN_CACHE_LINE_WIDTH);
2555       int end_ptr = ptr + INSN_CACHE_SIZE;
2556
2557       while (ptr < end_ptr)
2558         {
2559           *(INSTRUCTION_TYPE *)ptr
2560             = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2561           ptr += INSN_CACHE_LINE_WIDTH;
2562         }
2563       *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
2564
2565       initialized = 1;
2566     }
2567
2568   /* Call the beginning of the sequence.  */
2569   (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2570                     & -INSN_CACHE_LINE_WIDTH))
2571    ());
2572
2573 #else /* Cache is large.  */
2574
2575   if (! initialized)
2576     {
2577       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2578                  & -INSN_CACHE_LINE_WIDTH);
2579
2580       while (ptr < (int) array + sizeof array)
2581         {
2582           *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2583           ptr += INSN_CACHE_LINE_WIDTH;
2584         }
2585
2586       initialized = 1;
2587     }
2588
2589   /* Find the location in array that occupies the same cache line as BEG.  */
2590
2591   offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2592   start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2593                  & -INSN_CACHE_PLANE_SIZE)
2594                 + offset);
2595
2596   /* Compute the cache alignment of the place to stop clearing.  */
2597 #if 0  /* This is not needed for gcc's purposes.  */
2598   /* If the block to clear is bigger than a cache plane,
2599      we clear the entire cache, and OFFSET is already correct.  */ 
2600   if (end < beg + INSN_CACHE_PLANE_SIZE)
2601 #endif
2602     offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2603                & -INSN_CACHE_LINE_WIDTH)
2604               & (INSN_CACHE_PLANE_SIZE - 1));
2605
2606 #if INSN_CACHE_DEPTH > 1
2607   end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2608   if (end_addr <= start_addr)
2609     end_addr += INSN_CACHE_PLANE_SIZE;
2610
2611   for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2612     {
2613       int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2614       int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2615
2616       while (addr != stop)
2617         {
2618           /* Call the return instruction at ADDR.  */
2619           ((function_ptr) addr) ();
2620
2621           addr += INSN_CACHE_LINE_WIDTH;
2622         }
2623     }
2624 #else /* just one plane */
2625   do
2626     {
2627       /* Call the return instruction at START_ADDR.  */
2628       ((function_ptr) start_addr) ();
2629
2630       start_addr += INSN_CACHE_LINE_WIDTH;
2631     }
2632   while ((start_addr % INSN_CACHE_SIZE) != offset);
2633 #endif /* just one plane */
2634 #endif /* Cache is large */
2635 #endif /* Cache exists */
2636 #endif /* CLEAR_INSN_CACHE */
2637 }
2638
2639 #endif /* L_clear_cache */
2640 \f
2641 #ifdef L_trampoline
2642
2643 /* Jump to a trampoline, loading the static chain address.  */
2644
2645 #ifdef WINNT
2646
2647 long getpagesize()
2648 {
2649 #ifdef _ALPHA_
2650   return 8192;
2651 #else
2652   return 4096;
2653 #endif
2654 }
2655
2656 int mprotect(addr, len, prot)
2657   char *addr;
2658   int len, prot;
2659 {
2660   int np, op;
2661
2662   if (prot == 7) np = 0x40;
2663   else if (prot == 5) np = 0x20;
2664   else if (prot == 4) np = 0x10;
2665   else if (prot == 3) np = 0x04;
2666   else if (prot == 1) np = 0x02;
2667   else if (prot == 0) np = 0x01;
2668
2669   if (VirtualProtect (addr, len, np, &op))
2670     return 0;
2671   else
2672     return -1;
2673     
2674 }
2675
2676 #endif
2677
2678 #ifdef TRANSFER_FROM_TRAMPOLINE 
2679 TRANSFER_FROM_TRAMPOLINE 
2680 #endif
2681
2682 #if defined (NeXT) && defined (__MACH__)
2683
2684 /* Make stack executable so we can call trampolines on stack.
2685    This is called from INITIALIZE_TRAMPOLINE in next.h.  */
2686 #ifdef NeXTStep21
2687  #include <mach.h>
2688 #else
2689  #include <mach/mach.h>
2690 #endif
2691
2692 void
2693 __enable_execute_stack (addr)
2694      char *addr;
2695 {
2696   kern_return_t r;
2697   char *eaddr = addr + TRAMPOLINE_SIZE;
2698   vm_address_t a = (vm_address_t) addr;
2699
2700   /* turn on execute access on stack */
2701   r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2702   if (r != KERN_SUCCESS)
2703     {
2704       mach_error("vm_protect VM_PROT_ALL", r);
2705       exit(1);
2706     }
2707
2708   /* We inline the i-cache invalidation for speed */
2709
2710 #ifdef CLEAR_INSN_CACHE
2711   CLEAR_INSN_CACHE (addr, eaddr);
2712 #else
2713   __clear_cache ((int) addr, (int) eaddr);
2714 #endif
2715
2716
2717 #endif /* defined (NeXT) && defined (__MACH__) */
2718
2719 #ifdef __convex__
2720
2721 /* Make stack executable so we can call trampolines on stack.
2722    This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
2723
2724 #include <sys/mman.h>
2725 #include <sys/vmparam.h>
2726 #include <machine/machparam.h>
2727
2728 void
2729 __enable_execute_stack ()
2730 {
2731   int fp;
2732   static unsigned lowest = USRSTACK;
2733   unsigned current = (unsigned) &fp & -NBPG;
2734
2735   if (lowest > current)
2736     {
2737       unsigned len = lowest - current;
2738       mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2739       lowest = current;
2740     }
2741
2742   /* Clear instruction cache in case an old trampoline is in it.  */
2743   asm ("pich");
2744 }
2745 #endif /* __convex__ */
2746
2747 #ifdef __DOLPHIN__
2748
2749 /* Modified from the convex -code above.  */
2750
2751 #include <sys/param.h>
2752 #include <errno.h>
2753 #include <sys/m88kbcs.h>
2754
2755 void
2756 __enable_execute_stack ()
2757 {
2758   int save_errno;
2759   static unsigned long lowest = USRSTACK;
2760   unsigned long current = (unsigned long) &save_errno & -NBPC;
2761   
2762   /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2763      address is seen as 'negative'. That is the case with the stack.   */
2764
2765   save_errno=errno;
2766   if (lowest > current)
2767     {
2768       unsigned len=lowest-current;
2769       memctl(current,len,MCT_TEXT);
2770       lowest = current;
2771     }
2772   else
2773     memctl(current,NBPC,MCT_TEXT);
2774   errno=save_errno;
2775 }
2776
2777 #endif /* __DOLPHIN__ */
2778
2779 #ifdef __pyr__
2780
2781 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2782 #include <stdio.h>
2783 #include <sys/mman.h>
2784 #include <sys/types.h>
2785 #include <sys/param.h>
2786 #include <sys/vmmac.h>
2787
2788 /* Modified from the convex -code above.
2789    mremap promises to clear the i-cache.  */
2790
2791 void
2792 __enable_execute_stack ()
2793 {
2794   int fp;
2795   if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2796                 PROT_READ|PROT_WRITE|PROT_EXEC))
2797     {
2798       perror ("mprotect in __enable_execute_stack");
2799       fflush (stderr);
2800       abort ();
2801     }
2802 }
2803 #endif /* __pyr__ */
2804 #endif /* L_trampoline */
2805 \f
2806 #ifdef L__main
2807
2808 #include "gbl-ctors.h"
2809 /* Some systems use __main in a way incompatible with its use in gcc, in these
2810    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2811    give the same symbol without quotes for an alternative entry point.  You
2812    must define both, or neither.  */
2813 #ifndef NAME__MAIN
2814 #define NAME__MAIN "__main"
2815 #define SYMBOL__MAIN __main
2816 #endif
2817
2818 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
2819 /* Run all the global destructors on exit from the program.  */
2820
2821 void
2822 __do_global_dtors ()
2823 {
2824 #ifdef DO_GLOBAL_DTORS_BODY
2825   DO_GLOBAL_DTORS_BODY;
2826 #else
2827   func_ptr *p;
2828   for (p = __DTOR_LIST__ + 1; *p; )
2829     (*p++) ();
2830 #endif
2831 }
2832 #endif
2833
2834 #ifndef INIT_SECTION_ASM_OP
2835 /* Run all the global constructors on entry to the program.  */
2836
2837 #ifndef ON_EXIT
2838 #define ON_EXIT(a, b)
2839 #else
2840 /* Make sure the exit routine is pulled in to define the globals as
2841    bss symbols, just in case the linker does not automatically pull
2842    bss definitions from the library.  */
2843
2844 extern int _exit_dummy_decl;
2845 int *_exit_dummy_ref = &_exit_dummy_decl;
2846 #endif /* ON_EXIT */
2847
2848 void
2849 __do_global_ctors ()
2850 {
2851   DO_GLOBAL_CTORS_BODY;
2852   ON_EXIT (__do_global_dtors, 0);
2853 }
2854 #endif /* no INIT_SECTION_ASM_OP */
2855
2856 #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
2857 /* Subroutine called automatically by `main'.
2858    Compiling a global function named `main'
2859    produces an automatic call to this function at the beginning.
2860
2861    For many systems, this routine calls __do_global_ctors.
2862    For systems which support a .init section we use the .init section
2863    to run __do_global_ctors, so we need not do anything here.  */
2864
2865 void
2866 SYMBOL__MAIN ()
2867 {
2868   /* Support recursive calls to `main': run initializers just once.  */
2869   static int initialized;
2870   if (! initialized)
2871     {
2872       initialized = 1;
2873       __do_global_ctors ();
2874     }
2875 }
2876 #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
2877
2878 #endif /* L__main */
2879 \f
2880 #ifdef L_ctors
2881
2882 #include "gbl-ctors.h"
2883
2884 /* Provide default definitions for the lists of constructors and
2885    destructors, so that we don't get linker errors.  These symbols are
2886    intentionally bss symbols, so that gld and/or collect will provide
2887    the right values.  */
2888
2889 /* We declare the lists here with two elements each,
2890    so that they are valid empty lists if no other definition is loaded.  */
2891 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2892 #if defined(__NeXT__) || defined(_AIX)
2893 /* After 2.3, try this definition on all systems.  */
2894 func_ptr __CTOR_LIST__[2] = {0, 0};
2895 func_ptr __DTOR_LIST__[2] = {0, 0};
2896 #else
2897 func_ptr __CTOR_LIST__[2];
2898 func_ptr __DTOR_LIST__[2];
2899 #endif
2900 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2901 #endif /* L_ctors */
2902 \f
2903 #ifdef L_exit
2904
2905 #include "gbl-ctors.h"
2906
2907 #ifdef NEED_ATEXIT
2908 # ifdef ON_EXIT
2909 #  undef ON_EXIT
2910 # endif
2911 int _exit_dummy_decl = 0;       /* prevent compiler & linker warnings */
2912 #endif
2913
2914 #ifndef ON_EXIT
2915
2916 #ifdef NEED_ATEXIT
2917 # include <errno.h>
2918
2919 extern void *malloc ();
2920 extern void *realloc ();
2921
2922 static func_ptr *atexit_chain = NULL;
2923 static long atexit_chain_length = 0;
2924 static volatile long last_atexit_chain_slot = -1;
2925
2926 int atexit (func_ptr func)
2927 {
2928   if (++last_atexit_chain_slot == atexit_chain_length)
2929     {
2930       atexit_chain_length += 32;
2931       if (atexit_chain)
2932         atexit_chain = realloc (atexit_chain,
2933                                 atexit_chain_length * sizeof (func_ptr));
2934       else
2935         atexit_chain = malloc (atexit_chain_length * sizeof (func_ptr));
2936       if (! atexit_chain)
2937         {
2938           atexit_chain_length = 0;
2939           last_atexit_chain_slot = -1;
2940           errno = ENOMEM;
2941           return (-1);
2942         }
2943     }
2944   atexit_chain[last_atexit_chain_slot] = func;
2945   return (0);
2946 }
2947 #endif /* NEED_ATEXIT */
2948
2949 /* If we have no known way of registering our own __do_global_dtors
2950    routine so that it will be invoked at program exit time, then we
2951    have to define our own exit routine which will get this to happen.  */
2952
2953 extern void __do_global_dtors ();
2954 extern void _cleanup ();
2955 extern void _exit () __attribute__ ((noreturn));
2956
2957 void 
2958 exit (status)
2959      int status;
2960 {
2961 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
2962 #ifdef NEED_ATEXIT
2963   if (atexit_chain)
2964     {
2965       for ( ; last_atexit_chain_slot-- >= 0; )
2966         {
2967           (*atexit_chain[last_atexit_chain_slot + 1]) ();
2968           atexit_chain[last_atexit_chain_slot + 1] = NULL;
2969         }
2970       free (atexit_chain);
2971       atexit_chain = NULL;
2972     }
2973 #else /* No NEED_ATEXIT */
2974   __do_global_dtors ();
2975 #endif /* No NEED_ATEXIT */
2976 #endif
2977 #ifdef EXIT_BODY
2978   EXIT_BODY;
2979 #else
2980   _cleanup ();
2981 #endif
2982   _exit (status);
2983 }
2984
2985 #else
2986 int _exit_dummy_decl = 0;       /* prevent compiler & linker warnings */
2987 #endif
2988
2989 #endif /* L_exit */
2990 \f
2991 #ifdef L_eh
2992
2993 #ifdef EH_TABLE_LOOKUP
2994
2995 EH_TABLE_LOOKUP
2996
2997 #else
2998
2999 typedef struct {
3000   void *start;
3001   void *end;
3002   void *exception_handler;
3003 } exception_table;
3004
3005 struct exception_table_node {
3006   exception_table *table;
3007   void *start;
3008   void *end;
3009   struct exception_table_node *next;
3010 };
3011
3012 static int except_table_pos;
3013 static void *except_pc;
3014 static struct exception_table_node *exception_table_list;
3015
3016 static exception_table *
3017 find_exception_table (pc)
3018      void *pc;
3019 {
3020   register struct exception_table_node *table = exception_table_list;
3021   for ( ; table != 0; table = table->next)
3022     {
3023       if (table->start <= pc && table->end > pc)
3024         return table->table;
3025     }
3026   return 0;
3027 }
3028
3029 /* this routine takes a pc, and the address of the exception handler associated
3030    with the closest exception table handler entry associated with that PC,
3031    or 0 if there are no table entries the PC fits in.  The algorithm works
3032    something like this:
3033
3034     while(current_entry exists) {
3035         if(current_entry.start < pc )
3036             current_entry = next_entry;
3037         else {
3038             if(prev_entry.start <= pc && prev_entry.end > pc) {
3039                 save pointer to prev_entry;
3040                 return prev_entry.exception_handler;
3041              }
3042             else return 0;
3043          }
3044      }
3045     return 0;
3046
3047    Assuming a correctly sorted table (ascending order) this routine should
3048    return the tightest match...
3049
3050    In the advent of a tie, we have to give the last entry, as it represents
3051    an inner block.  */
3052
3053 void *
3054 __find_first_exception_table_match(pc)
3055 void *pc;
3056 {
3057   exception_table *table = find_exception_table (pc);
3058   int pos = 0;
3059   int best = 0;
3060   if (table == 0)
3061     return (void *) 0;
3062 #if 0
3063   printf ("find_first_exception_table_match(): pc = %x!\n", pc);
3064 #endif
3065
3066   except_pc = pc;
3067
3068 #if 0
3069   /* We can't do this yet, as we don't know that the table is sorted.  */
3070   do {
3071     ++pos;
3072     if (table[pos].start > except_pc)
3073       /* found the first table[pos].start > except_pc, so the previous
3074          entry better be the one we want! */
3075       break;
3076   } while (table[pos].exception_handler != (void *) -1);
3077
3078   --pos;
3079   if (table[pos].start <= except_pc && table[pos].end > except_pc)
3080     {
3081       except_table_pos = pos;
3082 #if 0
3083       printf ("find_first_eh_table_match(): found match: %x\n", table[pos].exception_handler);
3084 #endif
3085       return table[pos].exception_handler;
3086     }
3087 #else
3088   while (table[++pos].exception_handler != (void *) -1) {
3089     if (table[pos].start <= except_pc && table[pos].end > except_pc)
3090       {
3091         /* This can apply.  Make sure it is better or as good as the previous
3092            best.  */
3093         /* The best one ends first.  */
3094         if (best == 0 || (table[pos].end <= table[best].end
3095                           /* The best one starts last.  */
3096                           && table[pos].start >= table[best].start))
3097           best = pos;
3098       }
3099   }
3100   if (best != 0)
3101     return table[best].exception_handler;
3102 #endif
3103
3104 #if 0
3105   printf ("find_first_eh_table_match(): else: returning NULL!\n");
3106 #endif
3107   return (void *) 0;
3108 }
3109
3110 void
3111 __register_exceptions (exception_table *table)
3112 {
3113   struct exception_table_node *node;
3114   exception_table *range = table + 1;
3115
3116   if (range->start == (void *) -1)
3117     return;
3118
3119   node = (struct exception_table_node *)
3120     malloc (sizeof (struct exception_table_node));
3121   node->table = table;
3122
3123   /* This look can be optimized away either if the table
3124      is sorted, or if we pass in extra parameters.  */
3125   node->start = range->start;
3126   node->end = range->end;
3127   for (range++ ; range->start != (void *) (-1); range++)
3128     {
3129       if (range->start < node->start)
3130         node->start = range->start;
3131       if (range->end > node->end)
3132         node->end = range->end;
3133     }
3134
3135   node->next = exception_table_list;
3136   exception_table_list = node;
3137 }
3138 #endif
3139
3140 void *
3141 __throw_type_match (void *catch_type, void *throw_type, void *obj)
3142 {
3143 #if 0
3144  printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3145          catch_type, throw_type);
3146 #endif
3147  if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3148    return obj;
3149  return 0;
3150 }
3151
3152 void
3153 __empty ()
3154 {
3155 }
3156
3157 #if #machine(i386)
3158 void
3159 __unwind_function(void *ptr)
3160 {
3161   asm("movl 8(%esp),%ecx");
3162   /* Undo current frame */
3163   asm("movl %ebp,%esp");
3164   asm("popl %ebp");
3165   /* like ret, but stay here */
3166   asm("addl $4,%esp");
3167   
3168   /* Now, undo previous frame.  */
3169   /* This is a test routine, as we have to dynamically probe to find out
3170      what to pop for certain, this is just a guess.  */
3171   asm("leal -16(%ebp),%esp");
3172   asm("pop %ebx");
3173   asm("pop %esi");
3174   asm("pop %edi");
3175   asm("movl %ebp,%esp");
3176   asm("popl %ebp");
3177
3178   asm("movl %ecx,0(%esp)");
3179   asm("ret");
3180 }
3181 #elif #machine(rs6000) && !defined _ARCH_PPC
3182 __unwind_function(void *ptr)
3183 {
3184   asm("mr 31,1");
3185   asm("l 1,0(1)");
3186   asm("l 31,-4(1)");
3187   asm("# br");
3188
3189   asm("mr 31,1");
3190   asm("l 1,0(1)");
3191   /* use 31 as a scratch register to restore the link register.  */
3192   asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
3193   asm("l 31,-4(1)");
3194   asm("# br");
3195   asm("mtctr 3;bctr # b 3");
3196 }
3197 #elif (#machine(rs6000) || #machine(powerpc)) && defined _ARCH_PPC
3198 __unwind_function(void *ptr)
3199 {
3200   asm("mr 31,1");
3201   asm("lwz 1,0(1)");
3202   asm("lwz 31,-4(1)");
3203   asm("# br");
3204
3205   asm("mr 31,1");
3206   asm("lwz 1,0(1)");
3207   /* use 31 as a scratch register to restore the link register.  */
3208   asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
3209   asm("lwz 31,-4(1)");
3210   asm("# br");
3211   asm("mtctr 3;bctr # b 3");
3212 }
3213 #elif #machine(vax)
3214 __unwind_function(void *ptr)
3215 {
3216   __label__ return_again;
3217
3218   /* Replace our frame's return address with the label below.
3219      During execution, we will first return here instead of to
3220      caller, then second return takes caller's frame off the stack.
3221      Two returns matches two actual calls, so is less likely to
3222      confuse debuggers.  `16' corresponds to RETURN_ADDRESS_OFFSET.  */
3223   __asm ("movl %0,16(fp)" : : "p" (&& return_again));
3224   return;
3225
3226  return_again:
3227   return;
3228 }
3229 #else
3230 __unwind_function(void *ptr)
3231 {
3232   abort ();
3233 }
3234 #endif /* powerpc */
3235 #endif /* L_eh */
3236 \f
3237 #ifdef L_pure
3238 #ifndef inhibit_libc
3239 /* This gets us __GNU_LIBRARY__.  */
3240 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
3241 #include <stdio.h>
3242
3243 #ifdef __GNU_LIBRARY__
3244   /* Avoid forcing the library's meaning of `write' on the user program
3245      by using the "internal" name (for use within the library)  */
3246 #define write(fd, buf, n)       __write((fd), (buf), (n))
3247 #endif
3248 #endif /* inhibit_libc */
3249
3250 #define MESSAGE "pure virtual method called\n"
3251
3252 void
3253 __pure_virtual ()
3254 {
3255 #ifndef inhibit_libc
3256   write (2, MESSAGE, sizeof (MESSAGE) - 1);
3257 #endif
3258   _exit (-1);
3259 }
3260 #endif