OSDN Git Service

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