OSDN Git Service

* libgcc2.c (__register_exceptions): Handle empty tables.
[pf3gnuchains/gcc-fork.git] / gcc / libgcc2.c
1 /* More subroutines needed by GCC output code on some machines.  */
2 /* Compile this one with gcc.  */
3 /* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /* As a special exception, if you link this library with other files,
22    some of which are compiled with GCC, to produce an executable,
23    this library does not by itself cause the resulting executable
24    to be covered by the GNU General Public License.
25    This exception does not however invalidate any other reasons why
26    the executable file might be covered by the GNU General Public License.  */
27
28 /* It is incorrect to include config.h here, because this file is being
29    compiled for the target, and hence definitions concerning only the host
30    do not apply.  */
31
32 #include "tconfig.h"
33 #include "machmode.h"
34 #ifndef L_trampoline
35 #include <stddef.h>
36 #endif
37
38 /* Don't use `fancy_abort' here even if config.h says to use it.  */
39 #ifdef abort
40 #undef abort
41 #endif
42
43 /* Permit the tm.h file to select the endianness to use just for this
44    file.  This is used when the endianness is determined when the
45    compiler is run.  */
46
47 #ifndef LIBGCC2_WORDS_BIG_ENDIAN
48 #define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
49 #endif
50
51 /* In the first part of this file, we are interfacing to calls generated
52    by the compiler itself.  These calls pass values into these routines
53    which have very specific modes (rather than very specific types), and
54    these compiler-generated calls also expect any return values to have
55    very specific modes (rather than very specific types).  Thus, we need
56    to avoid using regular C language type names in this part of the file
57    because the sizes for those types can be configured to be anything.
58    Instead we use the following special type names.  */
59
60 typedef unsigned int UQItype    __attribute__ ((mode (QI)));
61 typedef          int SItype     __attribute__ ((mode (SI)));
62 typedef unsigned int USItype    __attribute__ ((mode (SI)));
63 typedef          int DItype     __attribute__ ((mode (DI)));
64 typedef unsigned int UDItype    __attribute__ ((mode (DI)));
65
66 typedef         float SFtype    __attribute__ ((mode (SF)));
67 typedef         float DFtype    __attribute__ ((mode (DF)));
68
69 #if LONG_DOUBLE_TYPE_SIZE == 96
70 typedef         float XFtype    __attribute__ ((mode (XF)));
71 #endif
72 #if LONG_DOUBLE_TYPE_SIZE == 128
73 typedef         float TFtype    __attribute__ ((mode (TF)));
74 #endif
75
76 typedef int word_type __attribute__ ((mode (__word__)));
77
78 /* Make sure that we don't accidentally use any normal C language built-in
79    type names in the first part of this file.  Instead we want to use *only*
80    the type names defined above.  The following macro definitions insure
81    that if we *do* accidentally use some normal C language built-in type name,
82    we will get a syntax error.  */
83
84 #define char bogus_type
85 #define short bogus_type
86 #define int bogus_type
87 #define long bogus_type
88 #define unsigned bogus_type
89 #define float bogus_type
90 #define double bogus_type
91
92 #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
93
94 /* DIstructs are pairs of SItype values in the order determined by
95    LIBGCC2_WORDS_BIG_ENDIAN.  */
96
97 #if LIBGCC2_WORDS_BIG_ENDIAN
98   struct DIstruct {SItype high, low;};
99 #else
100   struct DIstruct {SItype low, high;};
101 #endif
102
103 /* We need this union to unpack/pack DImode values, since we don't have
104    any arithmetic yet.  Incoming DImode parameters are stored into the
105    `ll' field, and the unpacked result is read from the struct `s'.  */
106
107 typedef union
108 {
109   struct DIstruct s;
110   DItype ll;
111 } DIunion;
112
113 #if defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)
114
115 #include "longlong.h"
116
117 #endif /* udiv or mul */
118
119 extern DItype __fixunssfdi (SFtype a);
120 extern DItype __fixunsdfdi (DFtype a);
121 #if LONG_DOUBLE_TYPE_SIZE == 96
122 extern DItype __fixunsxfdi (XFtype a);
123 #endif
124 #if LONG_DOUBLE_TYPE_SIZE == 128
125 extern DItype __fixunstfdi (TFtype a);
126 #endif
127 \f
128 #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
129 #if defined (L_divdi3) || defined (L_moddi3)
130 static inline
131 #endif
132 DItype
133 __negdi2 (u)
134      DItype u;
135 {
136   DIunion w;
137   DIunion uu;
138
139   uu.ll = u;
140
141   w.s.low = -uu.s.low;
142   w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
143
144   return w.ll;
145 }
146 #endif
147 \f
148 #ifdef L_lshrdi3
149 DItype
150 __lshrdi3 (u, b)
151      DItype u;
152      word_type b;
153 {
154   DIunion w;
155   word_type bm;
156   DIunion uu;
157
158   if (b == 0)
159     return u;
160
161   uu.ll = u;
162
163   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
164   if (bm <= 0)
165     {
166       w.s.high = 0;
167       w.s.low = (USItype)uu.s.high >> -bm;
168     }
169   else
170     {
171       USItype carries = (USItype)uu.s.high << bm;
172       w.s.high = (USItype)uu.s.high >> b;
173       w.s.low = ((USItype)uu.s.low >> b) | carries;
174     }
175
176   return w.ll;
177 }
178 #endif
179
180 #ifdef L_ashldi3
181 DItype
182 __ashldi3 (u, b)
183      DItype u;
184      word_type b;
185 {
186   DIunion w;
187   word_type bm;
188   DIunion uu;
189
190   if (b == 0)
191     return u;
192
193   uu.ll = u;
194
195   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
196   if (bm <= 0)
197     {
198       w.s.low = 0;
199       w.s.high = (USItype)uu.s.low << -bm;
200     }
201   else
202     {
203       USItype carries = (USItype)uu.s.low >> bm;
204       w.s.low = (USItype)uu.s.low << b;
205       w.s.high = ((USItype)uu.s.high << b) | carries;
206     }
207
208   return w.ll;
209 }
210 #endif
211
212 #ifdef L_ashrdi3
213 DItype
214 __ashrdi3 (u, b)
215      DItype u;
216      word_type b;
217 {
218   DIunion w;
219   word_type bm;
220   DIunion uu;
221
222   if (b == 0)
223     return u;
224
225   uu.ll = u;
226
227   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
228   if (bm <= 0)
229     {
230       /* w.s.high = 1..1 or 0..0 */
231       w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
232       w.s.low = uu.s.high >> -bm;
233     }
234   else
235     {
236       USItype carries = (USItype)uu.s.high << bm;
237       w.s.high = uu.s.high >> b;
238       w.s.low = ((USItype)uu.s.low >> b) | carries;
239     }
240
241   return w.ll;
242 }
243 #endif
244 \f
245 #ifdef L_ffsdi2
246 DItype
247 __ffsdi2 (u)
248      DItype u;
249 {
250   DIunion uu, w;
251   uu.ll = u;
252   w.s.high = 0;
253   w.s.low = ffs (uu.s.low);
254   if (w.s.low != 0)
255     return w.ll;
256   w.s.low = ffs (uu.s.high);
257   if (w.s.low != 0)
258     {
259       w.s.low += BITS_PER_UNIT * sizeof (SItype);
260       return w.ll;
261     }
262   return w.ll;
263 }
264 #endif
265 \f
266 #ifdef L_muldi3
267 DItype
268 __muldi3 (u, v)
269      DItype u, v;
270 {
271   DIunion w;
272   DIunion uu, vv;
273
274   uu.ll = u,
275   vv.ll = v;
276
277   w.ll = __umulsidi3 (uu.s.low, vv.s.low);
278   w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
279                + (USItype) uu.s.high * (USItype) vv.s.low);
280
281   return w.ll;
282 }
283 #endif
284 \f
285 #ifdef L_udiv_w_sdiv
286 USItype
287 __udiv_w_sdiv (rp, a1, a0, d)
288      USItype *rp, a1, a0, d;
289 {
290   USItype q, r;
291   USItype c0, c1, b1;
292
293   if ((SItype) d >= 0)
294     {
295       if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
296         {
297           /* dividend, divisor, and quotient are nonnegative */
298           sdiv_qrnnd (q, r, a1, a0, d);
299         }
300       else
301         {
302           /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
303           sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
304           /* Divide (c1*2^32 + c0) by d */
305           sdiv_qrnnd (q, r, c1, c0, d);
306           /* Add 2^31 to quotient */
307           q += (USItype) 1 << (SI_TYPE_SIZE - 1);
308         }
309     }
310   else
311     {
312       b1 = d >> 1;                      /* d/2, between 2^30 and 2^31 - 1 */
313       c1 = a1 >> 1;                     /* A/2 */
314       c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
315
316       if (a1 < b1)                      /* A < 2^32*b1, so A/2 < 2^31*b1 */
317         {
318           sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
319
320           r = 2*r + (a0 & 1);           /* Remainder from A/(2*b1) */
321           if ((d & 1) != 0)
322             {
323               if (r >= q)
324                 r = r - q;
325               else if (q - r <= d)
326                 {
327                   r = r - q + d;
328                   q--;
329                 }
330               else
331                 {
332                   r = r - q + 2*d;
333                   q -= 2;
334                 }
335             }
336         }
337       else if (c1 < b1)                 /* So 2^31 <= (A/2)/b1 < 2^32 */
338         {
339           c1 = (b1 - 1) - c1;
340           c0 = ~c0;                     /* logical NOT */
341
342           sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
343
344           q = ~q;                       /* (A/2)/b1 */
345           r = (b1 - 1) - r;
346
347           r = 2*r + (a0 & 1);           /* A/(2*b1) */
348
349           if ((d & 1) != 0)
350             {
351               if (r >= q)
352                 r = r - q;
353               else if (q - r <= d)
354                 {
355                   r = r - q + d;
356                   q--;
357                 }
358               else
359                 {
360                   r = r - q + 2*d;
361                   q -= 2;
362                 }
363             }
364         }
365       else                              /* Implies c1 = b1 */
366         {                               /* Hence a1 = d - 1 = 2*b1 - 1 */
367           if (a0 >= -d)
368             {
369               q = -1;
370               r = a0 + d;
371             }
372           else
373             {
374               q = -2;
375               r = a0 + 2*d;
376             }
377         }
378     }
379
380   *rp = r;
381   return q;
382 }
383 #endif
384 \f
385 #ifdef L_udivmoddi4
386 static const UQItype __clz_tab[] =
387 {
388   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,
389   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,
390   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,
391   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,
392   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,
393   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,
394   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,
395   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,
396 };
397
398 UDItype
399 __udivmoddi4 (n, d, rp)
400      UDItype n, d;
401      UDItype *rp;
402 {
403   DIunion ww;
404   DIunion nn, dd;
405   DIunion rr;
406   USItype d0, d1, n0, n1, n2;
407   USItype q0, q1;
408   USItype b, bm;
409
410   nn.ll = n;
411   dd.ll = d;
412
413   d0 = dd.s.low;
414   d1 = dd.s.high;
415   n0 = nn.s.low;
416   n1 = nn.s.high;
417
418 #if !UDIV_NEEDS_NORMALIZATION
419   if (d1 == 0)
420     {
421       if (d0 > n1)
422         {
423           /* 0q = nn / 0D */
424
425           udiv_qrnnd (q0, n0, n1, n0, d0);
426           q1 = 0;
427
428           /* Remainder in n0.  */
429         }
430       else
431         {
432           /* qq = NN / 0d */
433
434           if (d0 == 0)
435             d0 = 1 / d0;        /* Divide intentionally by zero.  */
436
437           udiv_qrnnd (q1, n1, 0, n1, d0);
438           udiv_qrnnd (q0, n0, n1, n0, d0);
439
440           /* Remainder in n0.  */
441         }
442
443       if (rp != 0)
444         {
445           rr.s.low = n0;
446           rr.s.high = 0;
447           *rp = rr.ll;
448         }
449     }
450
451 #else /* UDIV_NEEDS_NORMALIZATION */
452
453   if (d1 == 0)
454     {
455       if (d0 > n1)
456         {
457           /* 0q = nn / 0D */
458
459           count_leading_zeros (bm, d0);
460
461           if (bm != 0)
462             {
463               /* Normalize, i.e. make the most significant bit of the
464                  denominator set.  */
465
466               d0 = d0 << bm;
467               n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
468               n0 = n0 << bm;
469             }
470
471           udiv_qrnnd (q0, n0, n1, n0, d0);
472           q1 = 0;
473
474           /* Remainder in n0 >> bm.  */
475         }
476       else
477         {
478           /* qq = NN / 0d */
479
480           if (d0 == 0)
481             d0 = 1 / d0;        /* Divide intentionally by zero.  */
482
483           count_leading_zeros (bm, d0);
484
485           if (bm == 0)
486             {
487               /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
488                  conclude (the most significant bit of n1 is set) /\ (the
489                  leading quotient digit q1 = 1).
490
491                  This special case is necessary, not an optimization.
492                  (Shifts counts of SI_TYPE_SIZE are undefined.)  */
493
494               n1 -= d0;
495               q1 = 1;
496             }
497           else
498             {
499               /* Normalize.  */
500
501               b = SI_TYPE_SIZE - bm;
502
503               d0 = d0 << bm;
504               n2 = n1 >> b;
505               n1 = (n1 << bm) | (n0 >> b);
506               n0 = n0 << bm;
507
508               udiv_qrnnd (q1, n1, n2, n1, d0);
509             }
510
511           /* n1 != d0... */
512
513           udiv_qrnnd (q0, n0, n1, n0, d0);
514
515           /* Remainder in n0 >> bm.  */
516         }
517
518       if (rp != 0)
519         {
520           rr.s.low = n0 >> bm;
521           rr.s.high = 0;
522           *rp = rr.ll;
523         }
524     }
525 #endif /* UDIV_NEEDS_NORMALIZATION */
526
527   else
528     {
529       if (d1 > n1)
530         {
531           /* 00 = nn / DD */
532
533           q0 = 0;
534           q1 = 0;
535
536           /* Remainder in n1n0.  */
537           if (rp != 0)
538             {
539               rr.s.low = n0;
540               rr.s.high = n1;
541               *rp = rr.ll;
542             }
543         }
544       else
545         {
546           /* 0q = NN / dd */
547
548           count_leading_zeros (bm, d1);
549           if (bm == 0)
550             {
551               /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
552                  conclude (the most significant bit of n1 is set) /\ (the
553                  quotient digit q0 = 0 or 1).
554
555                  This special case is necessary, not an optimization.  */
556
557               /* The condition on the next line takes advantage of that
558                  n1 >= d1 (true due to program flow).  */
559               if (n1 > d1 || n0 >= d0)
560                 {
561                   q0 = 1;
562                   sub_ddmmss (n1, n0, n1, n0, d1, d0);
563                 }
564               else
565                 q0 = 0;
566
567               q1 = 0;
568
569               if (rp != 0)
570                 {
571                   rr.s.low = n0;
572                   rr.s.high = n1;
573                   *rp = rr.ll;
574                 }
575             }
576           else
577             {
578               USItype m1, m0;
579               /* Normalize.  */
580
581               b = SI_TYPE_SIZE - bm;
582
583               d1 = (d1 << bm) | (d0 >> b);
584               d0 = d0 << bm;
585               n2 = n1 >> b;
586               n1 = (n1 << bm) | (n0 >> b);
587               n0 = n0 << bm;
588
589               udiv_qrnnd (q0, n1, n2, n1, d1);
590               umul_ppmm (m1, m0, q0, d0);
591
592               if (m1 > n1 || (m1 == n1 && m0 > n0))
593                 {
594                   q0--;
595                   sub_ddmmss (m1, m0, m1, m0, d1, d0);
596                 }
597
598               q1 = 0;
599
600               /* Remainder in (n1n0 - m1m0) >> bm.  */
601               if (rp != 0)
602                 {
603                   sub_ddmmss (n1, n0, n1, n0, m1, m0);
604                   rr.s.low = (n1 << b) | (n0 >> bm);
605                   rr.s.high = n1 >> bm;
606                   *rp = rr.ll;
607                 }
608             }
609         }
610     }
611
612   ww.s.low = q0;
613   ww.s.high = q1;
614   return ww.ll;
615 }
616 #endif
617
618 #ifdef L_divdi3
619 UDItype __udivmoddi4 ();
620
621 DItype
622 __divdi3 (u, v)
623      DItype u, v;
624 {
625   word_type c = 0;
626   DIunion uu, vv;
627   DItype w;
628
629   uu.ll = u;
630   vv.ll = v;
631
632   if (uu.s.high < 0)
633     c = ~c,
634     uu.ll = __negdi2 (uu.ll);
635   if (vv.s.high < 0)
636     c = ~c,
637     vv.ll = __negdi2 (vv.ll);
638
639   w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
640   if (c)
641     w = __negdi2 (w);
642
643   return w;
644 }
645 #endif
646
647 #ifdef L_moddi3
648 UDItype __udivmoddi4 ();
649 DItype
650 __moddi3 (u, v)
651      DItype u, v;
652 {
653   word_type c = 0;
654   DIunion uu, vv;
655   DItype w;
656
657   uu.ll = u;
658   vv.ll = v;
659
660   if (uu.s.high < 0)
661     c = ~c,
662     uu.ll = __negdi2 (uu.ll);
663   if (vv.s.high < 0)
664     vv.ll = __negdi2 (vv.ll);
665
666   (void) __udivmoddi4 (uu.ll, vv.ll, &w);
667   if (c)
668     w = __negdi2 (w);
669
670   return w;
671 }
672 #endif
673
674 #ifdef L_umoddi3
675 UDItype __udivmoddi4 ();
676 UDItype
677 __umoddi3 (u, v)
678      UDItype u, v;
679 {
680   UDItype w;
681
682   (void) __udivmoddi4 (u, v, &w);
683
684   return w;
685 }
686 #endif
687
688 #ifdef L_udivdi3
689 UDItype __udivmoddi4 ();
690 UDItype
691 __udivdi3 (n, d)
692      UDItype n, d;
693 {
694   return __udivmoddi4 (n, d, (UDItype *) 0);
695 }
696 #endif
697 \f
698 #ifdef L_cmpdi2
699 word_type
700 __cmpdi2 (a, b)
701      DItype a, b;
702 {
703   DIunion au, bu;
704
705   au.ll = a, bu.ll = b;
706
707   if (au.s.high < bu.s.high)
708     return 0;
709   else if (au.s.high > bu.s.high)
710     return 2;
711   if ((USItype) au.s.low < (USItype) bu.s.low)
712     return 0;
713   else if ((USItype) au.s.low > (USItype) bu.s.low)
714     return 2;
715   return 1;
716 }
717 #endif
718
719 #ifdef L_ucmpdi2
720 word_type
721 __ucmpdi2 (a, b)
722      DItype a, b;
723 {
724   DIunion au, bu;
725
726   au.ll = a, bu.ll = b;
727
728   if ((USItype) au.s.high < (USItype) bu.s.high)
729     return 0;
730   else if ((USItype) au.s.high > (USItype) bu.s.high)
731     return 2;
732   if ((USItype) au.s.low < (USItype) bu.s.low)
733     return 0;
734   else if ((USItype) au.s.low > (USItype) bu.s.low)
735     return 2;
736   return 1;
737 }
738 #endif
739 \f
740 #if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
741 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
742 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
743
744 DItype
745 __fixunstfdi (a)
746      TFtype a;
747 {
748   TFtype b;
749   UDItype v;
750
751   if (a < 0)
752     return 0;
753
754   /* Compute high word of result, as a flonum.  */
755   b = (a / HIGH_WORD_COEFF);
756   /* Convert that to fixed (but not to DItype!),
757      and shift it into the high word.  */
758   v = (USItype) b;
759   v <<= WORD_SIZE;
760   /* Remove high part from the TFtype, leaving the low part as flonum.  */
761   a -= (TFtype)v;
762   /* Convert that to fixed (but not to DItype!) and add it in.
763      Sometimes A comes out negative.  This is significant, since
764      A has more bits than a long int does.  */
765   if (a < 0)
766     v -= (USItype) (- a);
767   else
768     v += (USItype) a;
769   return v;
770 }
771 #endif
772
773 #if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
774 DItype
775 __fixtfdi (a)
776      TFtype a;
777 {
778   if (a < 0)
779     return - __fixunstfdi (-a);
780   return __fixunstfdi (a);
781 }
782 #endif
783
784 #if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
785 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
786 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
787
788 DItype
789 __fixunsxfdi (a)
790      XFtype a;
791 {
792   XFtype b;
793   UDItype v;
794
795   if (a < 0)
796     return 0;
797
798   /* Compute high word of result, as a flonum.  */
799   b = (a / HIGH_WORD_COEFF);
800   /* Convert that to fixed (but not to DItype!),
801      and shift it into the high word.  */
802   v = (USItype) b;
803   v <<= WORD_SIZE;
804   /* Remove high part from the XFtype, leaving the low part as flonum.  */
805   a -= (XFtype)v;
806   /* Convert that to fixed (but not to DItype!) and add it in.
807      Sometimes A comes out negative.  This is significant, since
808      A has more bits than a long int does.  */
809   if (a < 0)
810     v -= (USItype) (- a);
811   else
812     v += (USItype) a;
813   return v;
814 }
815 #endif
816
817 #if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
818 DItype
819 __fixxfdi (a)
820      XFtype a;
821 {
822   if (a < 0)
823     return - __fixunsxfdi (-a);
824   return __fixunsxfdi (a);
825 }
826 #endif
827
828 #ifdef L_fixunsdfdi
829 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
830 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
831
832 DItype
833 __fixunsdfdi (a)
834      DFtype a;
835 {
836   DFtype b;
837   UDItype v;
838
839   if (a < 0)
840     return 0;
841
842   /* Compute high word of result, as a flonum.  */
843   b = (a / HIGH_WORD_COEFF);
844   /* Convert that to fixed (but not to DItype!),
845      and shift it into the high word.  */
846   v = (USItype) b;
847   v <<= WORD_SIZE;
848   /* Remove high part from the DFtype, leaving the low part as flonum.  */
849   a -= (DFtype)v;
850   /* Convert that to fixed (but not to DItype!) and add it in.
851      Sometimes A comes out negative.  This is significant, since
852      A has more bits than a long int does.  */
853   if (a < 0)
854     v -= (USItype) (- a);
855   else
856     v += (USItype) a;
857   return v;
858 }
859 #endif
860
861 #ifdef L_fixdfdi
862 DItype
863 __fixdfdi (a)
864      DFtype a;
865 {
866   if (a < 0)
867     return - __fixunsdfdi (-a);
868   return __fixunsdfdi (a);
869 }
870 #endif
871
872 #ifdef L_fixunssfdi
873 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
874 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
875
876 DItype
877 __fixunssfdi (SFtype original_a)
878 {
879   /* Convert the SFtype to a DFtype, because that is surely not going
880      to lose any bits.  Some day someone else can write a faster version
881      that avoids converting to DFtype, and verify it really works right.  */
882   DFtype a = original_a;
883   DFtype b;
884   UDItype v;
885
886   if (a < 0)
887     return 0;
888
889   /* Compute high word of result, as a flonum.  */
890   b = (a / HIGH_WORD_COEFF);
891   /* Convert that to fixed (but not to DItype!),
892      and shift it into the high word.  */
893   v = (USItype) b;
894   v <<= WORD_SIZE;
895   /* Remove high part from the DFtype, leaving the low part as flonum.  */
896   a -= (DFtype)v;
897   /* Convert that to fixed (but not to DItype!) and add it in.
898      Sometimes A comes out negative.  This is significant, since
899      A has more bits than a long int does.  */
900   if (a < 0)
901     v -= (USItype) (- a);
902   else
903     v += (USItype) a;
904   return v;
905 }
906 #endif
907
908 #ifdef L_fixsfdi
909 DItype
910 __fixsfdi (SFtype a)
911 {
912   if (a < 0)
913     return - __fixunssfdi (-a);
914   return __fixunssfdi (a);
915 }
916 #endif
917
918 #if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
919 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
920 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
921 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
922
923 XFtype
924 __floatdixf (u)
925      DItype u;
926 {
927   XFtype d;
928   SItype negate = 0;
929
930   if (u < 0)
931     u = -u, negate = 1;
932
933   d = (USItype) (u >> WORD_SIZE);
934   d *= HIGH_HALFWORD_COEFF;
935   d *= HIGH_HALFWORD_COEFF;
936   d += (USItype) (u & (HIGH_WORD_COEFF - 1));
937
938   return (negate ? -d : d);
939 }
940 #endif
941
942 #if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
943 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
944 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
945 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
946
947 TFtype
948 __floatditf (u)
949      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 (u)
973      DItype u;
974 {
975   DFtype d;
976   SItype negate = 0;
977
978   if (u < 0)
979     u = -u, negate = 1;
980
981   d = (USItype) (u >> WORD_SIZE);
982   d *= HIGH_HALFWORD_COEFF;
983   d *= HIGH_HALFWORD_COEFF;
984   d += (USItype) (u & (HIGH_WORD_COEFF - 1));
985
986   return (negate ? -d : d);
987 }
988 #endif
989
990 #ifdef L_floatdisf
991 #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
992 #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
993 #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
994 #define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
995 #if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
996 #define DF_SIZE 53
997 #define SF_SIZE 24
998 #else
999 #if TARGET_FLOAT_FORMAT == IBM_FLOAT_FORMAT
1000 #define DF_SIZE 56
1001 #define SF_SIZE 24
1002 #else
1003 #if TARGET_FLOAT_FORMAT == VAX_FLOAT_FORMAT
1004 #define DF_SIZE 56
1005 #define SF_SIZE 24
1006 #else
1007 #define DF_SIZE 0
1008 #define SF_SIZE 0
1009 #endif
1010 #endif
1011 #endif
1012
1013
1014 SFtype
1015 __floatdisf (u)
1016      DItype u;
1017 {
1018   /* Do the calculation in DFmode
1019      so that we don't lose any of the precision of the high word
1020      while multiplying it.  */
1021   DFtype f;
1022   SItype negate = 0;
1023
1024   if (u < 0)
1025     u = -u, negate = 1;
1026
1027   /* Protect against double-rounding error.
1028      Represent any low-order bits, that might be truncated in DFmode,
1029      by a bit that won't be lost.  The bit can go in anywhere below the
1030      rounding position of the SFmode.  A fixed mask and bit position
1031      handles all usual configurations.  It doesn't handle the case
1032      of 128-bit DImode, however.  */
1033   if (DF_SIZE < DI_SIZE
1034       && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1035     {
1036 #define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
1037       if (u >= ((UDItype) 1 << DF_SIZE))
1038         {
1039           if ((USItype) u & (REP_BIT - 1))
1040             u |= REP_BIT;
1041         }
1042     }
1043   f = (USItype) (u >> WORD_SIZE);
1044   f *= HIGH_HALFWORD_COEFF;
1045   f *= HIGH_HALFWORD_COEFF;
1046   f += (USItype) (u & (HIGH_WORD_COEFF - 1));
1047
1048   return (SFtype) (negate ? -f : f);
1049 }
1050 #endif
1051
1052 #if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
1053 /* Reenable the normal types, in case limits.h needs them.  */
1054 #undef char
1055 #undef short
1056 #undef int
1057 #undef long
1058 #undef unsigned
1059 #undef float
1060 #undef double
1061 #include <limits.h>
1062
1063 USItype
1064 __fixunsxfsi (a)
1065      XFtype a;
1066 {
1067   if (a >= - (DFtype) LONG_MIN)
1068     return (SItype) (a + LONG_MIN) - LONG_MIN;
1069   return (SItype) a;
1070 }
1071 #endif
1072
1073 #ifdef L_fixunsdfsi
1074 /* Reenable the normal types, in case limits.h needs them.  */
1075 #undef char
1076 #undef short
1077 #undef int
1078 #undef long
1079 #undef unsigned
1080 #undef float
1081 #undef double
1082 #include <limits.h>
1083
1084 USItype
1085 __fixunsdfsi (a)
1086      DFtype a;
1087 {
1088   if (a >= - (DFtype) LONG_MIN)
1089     return (SItype) (a + LONG_MIN) - LONG_MIN;
1090   return (SItype) a;
1091 }
1092 #endif
1093
1094 #ifdef L_fixunssfsi
1095 /* Reenable the normal types, in case limits.h needs them.  */
1096 #undef char
1097 #undef short
1098 #undef int
1099 #undef long
1100 #undef unsigned
1101 #undef float
1102 #undef double
1103 #include <limits.h>
1104
1105 USItype
1106 __fixunssfsi (SFtype a)
1107 {
1108   if (a >= - (SFtype) LONG_MIN)
1109     return (SItype) (a + LONG_MIN) - LONG_MIN;
1110   return (SItype) a;
1111 }
1112 #endif
1113 \f
1114 /* From here on down, the routines use normal data types.  */
1115
1116 #define SItype bogus_type
1117 #define USItype bogus_type
1118 #define DItype bogus_type
1119 #define UDItype bogus_type
1120 #define SFtype bogus_type
1121 #define DFtype bogus_type
1122
1123 #undef char
1124 #undef short
1125 #undef int
1126 #undef long
1127 #undef unsigned
1128 #undef float
1129 #undef double
1130 \f
1131 #ifdef L__gcc_bcmp
1132
1133 /* Like bcmp except the sign is meaningful.
1134    Reult is negative if S1 is less than S2,
1135    positive if S1 is greater, 0 if S1 and S2 are equal.  */
1136
1137 int
1138 __gcc_bcmp (s1, s2, size)
1139      unsigned char *s1, *s2;
1140      size_t size;
1141 {
1142   while (size > 0)
1143     {
1144       unsigned char c1 = *s1++, c2 = *s2++;
1145       if (c1 != c2)
1146         return c1 - c2;
1147       size--;
1148     }
1149   return 0;
1150 }
1151
1152 #endif
1153 \f\f
1154 #ifdef L_varargs
1155 #ifdef __i860__
1156 #if defined(__svr4__) || defined(__alliant__)
1157         asm ("  .text");
1158         asm ("  .align  4");
1159
1160 /* The Alliant needs the added underscore.  */
1161         asm (".globl    __builtin_saveregs");
1162 asm ("__builtin_saveregs:");
1163         asm (".globl    ___builtin_saveregs");
1164 asm ("___builtin_saveregs:");
1165
1166         asm ("  andnot  0x0f,%sp,%sp"); /* round down to 16-byte boundary */
1167         asm ("  adds    -96,%sp,%sp");  /* allocate stack space for reg save
1168                                            area and also for a new va_list
1169                                            structure */
1170         /* Save all argument registers in the arg reg save area.  The
1171            arg reg save area must have the following layout (according
1172            to the svr4 ABI):
1173
1174                 struct {
1175                   union  {
1176                     float freg[8];
1177                     double dreg[4];
1178                   } float_regs;
1179                   long  ireg[12];
1180                 };
1181         */
1182
1183         asm ("  fst.q   %f8,  0(%sp)"); /* save floating regs (f8-f15)  */
1184         asm ("  fst.q   %f12,16(%sp)"); 
1185
1186         asm ("  st.l    %r16,32(%sp)"); /* save integer regs (r16-r27) */
1187         asm ("  st.l    %r17,36(%sp)"); 
1188         asm ("  st.l    %r18,40(%sp)");
1189         asm ("  st.l    %r19,44(%sp)");
1190         asm ("  st.l    %r20,48(%sp)");
1191         asm ("  st.l    %r21,52(%sp)");
1192         asm ("  st.l    %r22,56(%sp)");
1193         asm ("  st.l    %r23,60(%sp)");
1194         asm ("  st.l    %r24,64(%sp)");
1195         asm ("  st.l    %r25,68(%sp)");
1196         asm ("  st.l    %r26,72(%sp)");
1197         asm ("  st.l    %r27,76(%sp)");
1198
1199         asm ("  adds    80,%sp,%r16");  /* compute the address of the new
1200                                            va_list structure.  Put in into
1201                                            r16 so that it will be returned
1202                                            to the caller.  */
1203
1204         /* Initialize all fields of the new va_list structure.  This
1205            structure looks like:
1206
1207                 typedef struct {
1208                     unsigned long       ireg_used;
1209                     unsigned long       freg_used;
1210                     long                *reg_base;
1211                     long                *mem_ptr;
1212                 } va_list;
1213         */
1214
1215         asm ("  st.l    %r0, 0(%r16)"); /* nfixed */
1216         asm ("  st.l    %r0, 4(%r16)"); /* nfloating */
1217         asm ("  st.l    %sp, 8(%r16)"); /* __va_ctl points to __va_struct.  */
1218         asm ("  bri     %r1");          /* delayed return */
1219         asm ("  st.l    %r28,12(%r16)"); /* pointer to overflow args */
1220
1221 #else /* not __svr4__ */
1222 #if defined(__PARAGON__)
1223         /*
1224          *      we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1225          *      and we stand a better chance of hooking into libraries
1226          *      compiled by PGI.  [andyp@ssd.intel.com]
1227          */
1228         asm ("  .text");
1229         asm ("  .align  4");
1230         asm (".globl    __builtin_saveregs");
1231 asm ("__builtin_saveregs:");
1232         asm (".globl    ___builtin_saveregs");
1233 asm ("___builtin_saveregs:");
1234
1235         asm ("  andnot  0x0f,sp,sp");   /* round down to 16-byte boundary */
1236         asm ("  adds    -96,sp,sp");    /* allocate stack space for reg save
1237                                            area and also for a new va_list
1238                                            structure */
1239         /* Save all argument registers in the arg reg save area.  The
1240            arg reg save area must have the following layout (according
1241            to the svr4 ABI):
1242
1243                 struct {
1244                   union  {
1245                     float freg[8];
1246                     double dreg[4];
1247                   } float_regs;
1248                   long  ireg[12];
1249                 };
1250         */
1251
1252         asm ("  fst.q   f8,  0(sp)");
1253         asm ("  fst.q   f12,16(sp)"); 
1254         asm ("  st.l    r16,32(sp)");
1255         asm ("  st.l    r17,36(sp)"); 
1256         asm ("  st.l    r18,40(sp)");
1257         asm ("  st.l    r19,44(sp)");
1258         asm ("  st.l    r20,48(sp)");
1259         asm ("  st.l    r21,52(sp)");
1260         asm ("  st.l    r22,56(sp)");
1261         asm ("  st.l    r23,60(sp)");
1262         asm ("  st.l    r24,64(sp)");
1263         asm ("  st.l    r25,68(sp)");
1264         asm ("  st.l    r26,72(sp)");
1265         asm ("  st.l    r27,76(sp)");
1266
1267         asm ("  adds    80,sp,r16");  /* compute the address of the new
1268                                            va_list structure.  Put in into
1269                                            r16 so that it will be returned
1270                                            to the caller.  */
1271
1272         /* Initialize all fields of the new va_list structure.  This
1273            structure looks like:
1274
1275                 typedef struct {
1276                     unsigned long       ireg_used;
1277                     unsigned long       freg_used;
1278                     long                *reg_base;
1279                     long                *mem_ptr;
1280                 } va_list;
1281         */
1282
1283         asm ("  st.l    r0, 0(r16)"); /* nfixed */
1284         asm ("  st.l    r0, 4(r16)"); /* nfloating */
1285         asm ("  st.l    sp, 8(r16)"); /* __va_ctl points to __va_struct.  */
1286         asm ("  bri     r1");           /* delayed return */
1287         asm ("   st.l   r28,12(r16)"); /* pointer to overflow args */
1288 #else /* not __PARAGON__ */
1289         asm ("  .text");
1290         asm ("  .align  4");
1291
1292         asm (".globl    ___builtin_saveregs");
1293         asm ("___builtin_saveregs:");
1294         asm ("  mov     sp,r30");
1295         asm ("  andnot  0x0f,sp,sp");
1296         asm ("  adds    -96,sp,sp");  /* allocate sufficient space on the stack */
1297
1298 /* Fill in the __va_struct.  */
1299         asm ("  st.l    r16, 0(sp)"); /* save integer regs (r16-r27) */
1300         asm ("  st.l    r17, 4(sp)"); /* int    fixed[12] */
1301         asm ("  st.l    r18, 8(sp)");
1302         asm ("  st.l    r19,12(sp)");
1303         asm ("  st.l    r20,16(sp)");
1304         asm ("  st.l    r21,20(sp)");
1305         asm ("  st.l    r22,24(sp)");
1306         asm ("  st.l    r23,28(sp)");
1307         asm ("  st.l    r24,32(sp)");
1308         asm ("  st.l    r25,36(sp)");
1309         asm ("  st.l    r26,40(sp)");
1310         asm ("  st.l    r27,44(sp)");
1311
1312         asm ("  fst.q   f8, 48(sp)"); /* save floating regs (f8-f15) */
1313         asm ("  fst.q   f12,64(sp)"); /* int floating[8] */
1314
1315 /* Fill in the __va_ctl.  */
1316         asm ("  st.l    sp, 80(sp)"); /* __va_ctl points to __va_struct.  */
1317         asm ("  st.l    r28,84(sp)"); /* pointer to more args */
1318         asm ("  st.l    r0, 88(sp)"); /* nfixed */
1319         asm ("  st.l    r0, 92(sp)"); /* nfloating */
1320
1321         asm ("  adds    80,sp,r16");  /* return address of the __va_ctl.  */
1322         asm ("  bri     r1");
1323         asm ("  mov     r30,sp");
1324                                 /* recover stack and pass address to start 
1325                                    of data.  */
1326 #endif /* not __PARAGON__ */
1327 #endif /* not __svr4__ */
1328 #else /* not __i860__ */
1329 #ifdef __sparc__
1330         asm (".global __builtin_saveregs");
1331         asm ("__builtin_saveregs:");
1332         asm (".global ___builtin_saveregs");
1333         asm ("___builtin_saveregs:");
1334 #ifdef NEED_PROC_COMMAND
1335         asm (".proc 020");
1336 #endif
1337         asm ("st %i0,[%fp+68]");
1338         asm ("st %i1,[%fp+72]");
1339         asm ("st %i2,[%fp+76]");
1340         asm ("st %i3,[%fp+80]");
1341         asm ("st %i4,[%fp+84]");
1342         asm ("retl");
1343         asm ("st %i5,[%fp+88]");
1344 #ifdef NEED_TYPE_COMMAND
1345         asm (".type __builtin_saveregs,#function");
1346         asm (".size __builtin_saveregs,.-__builtin_saveregs");
1347 #endif
1348 #else /* not __sparc__ */
1349 #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1350
1351   asm ("        .text");
1352   asm ("        .ent __builtin_saveregs");
1353   asm ("        .globl __builtin_saveregs");
1354   asm ("__builtin_saveregs:");
1355   asm ("        sw      $4,0($30)");
1356   asm ("        sw      $5,4($30)");
1357   asm ("        sw      $6,8($30)");
1358   asm ("        sw      $7,12($30)");
1359   asm ("        j       $31");
1360   asm ("        .end __builtin_saveregs");
1361 #else /* not __mips__, etc. */
1362
1363 void *
1364 __builtin_saveregs ()
1365 {
1366   abort ();
1367 }
1368
1369 #endif /* not __mips__ */
1370 #endif /* not __sparc__ */
1371 #endif /* not __i860__ */
1372 #endif
1373 \f
1374 #ifdef L_eprintf
1375 #ifndef inhibit_libc
1376
1377 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1378 #include <stdio.h>
1379 /* This is used by the `assert' macro.  */
1380 void
1381 __eprintf (string, expression, line, filename)
1382      const char *string;
1383      const char *expression;
1384      int line;
1385      const char *filename;
1386 {
1387   fprintf (stderr, string, expression, line, filename);
1388   fflush (stderr);
1389   abort ();
1390 }
1391
1392 #endif
1393 #endif
1394
1395 #ifdef L_bb
1396
1397 /* Structure emitted by -a  */
1398 struct bb
1399 {
1400   long zero_word;
1401   const char *filename;
1402   long *counts;
1403   long ncounts;
1404   struct bb *next;
1405   const unsigned long *addresses;
1406
1407   /* Older GCC's did not emit these fields.  */
1408   long nwords;
1409   const char **functions;
1410   const long *line_nums;
1411   const char **filenames;
1412 };
1413
1414 #ifdef BLOCK_PROFILER_CODE
1415 BLOCK_PROFILER_CODE
1416 #else
1417 #ifndef inhibit_libc
1418
1419 /* Simple minded basic block profiling output dumper for
1420    systems that don't provde tcov support.  At present,
1421    it requires atexit and stdio.  */
1422
1423 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1424 #include <stdio.h>
1425 char *ctime ();
1426
1427 #ifdef HAVE_ATEXIT
1428 #ifdef WINNT
1429 extern int atexit (void (*) (void));
1430 #else
1431 extern void atexit (void (*) (void));
1432 #endif
1433 #define ON_EXIT(FUNC,ARG) atexit ((FUNC))
1434 #else
1435 #ifdef sun
1436 extern void on_exit (void*, void*);
1437 #define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
1438 #endif
1439 #endif
1440
1441 static struct bb *bb_head = (struct bb *)0;
1442
1443 /* Return the number of digits needed to print a value */
1444 /* __inline__ */ static int num_digits (long value, int base)
1445 {
1446   int minus = (value < 0 && base != 16);
1447   unsigned long v = (minus) ? -value : value;
1448   int ret = minus;
1449
1450   do
1451     {
1452       v /= base;
1453       ret++;
1454     }
1455   while (v);
1456
1457   return ret;
1458 }
1459
1460 void
1461 __bb_exit_func (void)
1462 {
1463   FILE *file = fopen ("bb.out", "a");
1464   long time_value;
1465
1466   if (!file)
1467     perror ("bb.out");
1468
1469   else
1470     {
1471       struct bb *ptr;
1472
1473       /* This is somewhat type incorrect, but it avoids worrying about
1474          exactly where time.h is included from.  It should be ok unless
1475          a void * differs from other pointer formats, or if sizeof(long)
1476          is < sizeof (time_t).  It would be nice if we could assume the
1477          use of rationale standards here.  */
1478
1479       time((void *) &time_value);
1480       fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1481
1482       /* We check the length field explicitly in order to allow compatibility
1483          with older GCC's which did not provide it.  */
1484
1485       for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
1486         {
1487           int i;
1488           int func_p    = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
1489           int line_p    = (func_p && ptr->line_nums);
1490           int file_p    = (func_p && ptr->filenames);
1491           long ncounts  = ptr->ncounts;
1492           long cnt_max  = 0;
1493           long line_max = 0;
1494           long addr_max = 0;
1495           int file_len  = 0;
1496           int func_len  = 0;
1497           int blk_len   = num_digits (ncounts, 10);
1498           int cnt_len;
1499           int line_len;
1500           int addr_len;
1501
1502           fprintf (file, "File %s, %ld basic blocks \n\n",
1503                    ptr->filename, ncounts);
1504
1505           /* Get max values for each field.  */
1506           for (i = 0; i < ncounts; i++)
1507             {
1508               const char *p;
1509               int len;
1510
1511               if (cnt_max < ptr->counts[i])
1512                 cnt_max = ptr->counts[i];
1513
1514               if (addr_max < ptr->addresses[i])
1515                 addr_max = ptr->addresses[i];
1516
1517               if (line_p && line_max < ptr->line_nums[i])
1518                 line_max = ptr->line_nums[i];
1519
1520               if (func_p)
1521                 {
1522                   p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1523                   len = strlen (p);
1524                   if (func_len < len)
1525                     func_len = len;
1526                 }
1527
1528               if (file_p)
1529                 {
1530                   p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1531                   len = strlen (p);
1532                   if (file_len < len)
1533                     file_len = len;
1534                 }
1535             }
1536
1537           addr_len = num_digits (addr_max, 16);
1538           cnt_len  = num_digits (cnt_max, 10);
1539           line_len = num_digits (line_max, 10);
1540
1541           /* Now print out the basic block information.  */
1542           for (i = 0; i < ncounts; i++)
1543             {
1544               fprintf (file,
1545                        "    Block #%*d: executed %*ld time(s) address= 0x%.*lx",
1546                        blk_len, i+1,
1547                        cnt_len, ptr->counts[i],
1548                        addr_len, ptr->addresses[i]);
1549
1550               if (func_p)
1551                 fprintf (file, " function= %-*s", func_len,
1552                          (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1553
1554               if (line_p)
1555                 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1556
1557               if (file_p)
1558                 fprintf (file, " file= %s",
1559                          (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1560
1561               fprintf (file, "\n");
1562             }
1563
1564           fprintf (file, "\n");
1565           fflush (file);
1566         }
1567
1568       fprintf (file, "\n\n");
1569       fclose (file);
1570     }
1571 }
1572
1573 void
1574 __bb_init_func (struct bb *blocks)
1575 {
1576   /* User is supposed to check whether the first word is non-0,
1577      but just in case.... */
1578
1579   if (blocks->zero_word)
1580     return;
1581
1582 #ifdef ON_EXIT
1583   /* Initialize destructor.  */
1584   if (!bb_head)
1585     ON_EXIT (__bb_exit_func, 0);
1586 #endif
1587
1588   /* Set up linked list.  */
1589   blocks->zero_word = 1;
1590   blocks->next = bb_head;
1591   bb_head = blocks;
1592 }
1593
1594 #endif /* not inhibit_libc */
1595 #endif /* not BLOCK_PROFILER_CODE */
1596 #endif /* L_bb */
1597 \f
1598 /* Default free-store management functions for C++, per sections 12.5 and
1599    17.3.3 of the Working Paper. */
1600
1601 #ifdef L_op_new
1602 /* operator new (size_t), described in 17.3.3.5.  This function is used by
1603    C++ programs to allocate a block of memory to hold a single object. */
1604
1605 typedef void (*vfp)(void);
1606 extern vfp __new_handler;
1607 extern void __default_new_handler (void);
1608
1609 void *
1610 __builtin_new (size_t sz)
1611 {
1612   void *p;
1613   vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
1614
1615   /* malloc (0) is unpredictable; avoid it.  */
1616   if (sz == 0)
1617     sz = 1;
1618   p = (void *) malloc (sz);
1619   while (p == 0)
1620     {
1621       (*handler) ();
1622       p = (void *) malloc (sz);
1623     }
1624   
1625   return p;
1626 }
1627 #endif /* L_op_new */
1628
1629 #ifdef L_op_vnew
1630 /* void * operator new [] (size_t), described in 17.3.3.6.  This function
1631    is used by C++ programs to allocate a block of memory for an array.  */
1632
1633 extern void * __builtin_new (size_t);
1634
1635 void *
1636 __builtin_vec_new (size_t sz)
1637 {
1638   return __builtin_new (sz);
1639 }
1640 #endif /* L_op_vnew */
1641
1642 #ifdef L_new_handler
1643 /* set_new_handler (fvoid_t *) and the default new handler, described in
1644    17.3.3.2 and 17.3.3.5.  These functions define the result of a failure
1645    to allocate the amount of memory requested from operator new or new []. */
1646
1647 #ifndef inhibit_libc
1648 /* This gets us __GNU_LIBRARY__.  */
1649 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1650 #include <stdio.h>
1651
1652 #ifdef __GNU_LIBRARY__
1653   /* Avoid forcing the library's meaning of `write' on the user program
1654      by using the "internal" name (for use within the library)  */
1655 #define write(fd, buf, n)       __write((fd), (buf), (n))
1656 #endif
1657 #endif /* inhibit_libc */
1658
1659 typedef void (*vfp)(void);
1660 void __default_new_handler (void);
1661
1662 vfp __new_handler = (vfp)0;
1663
1664 vfp
1665 set_new_handler (vfp handler)
1666 {
1667   vfp prev_handler;
1668
1669   prev_handler = __new_handler;
1670   if (handler == 0) handler = __default_new_handler;
1671   __new_handler = handler;
1672   return prev_handler;
1673 }
1674
1675 #define MESSAGE "Virtual memory exceeded in `new'\n"
1676
1677 void
1678 __default_new_handler ()
1679 {
1680 #ifndef inhibit_libc
1681   /* don't use fprintf (stderr, ...) because it may need to call malloc.  */
1682   /* This should really print the name of the program, but that is hard to
1683      do.  We need a standard, clean way to get at the name.  */
1684   write (2, MESSAGE, sizeof (MESSAGE));
1685 #endif
1686   /* don't call exit () because that may call global destructors which
1687      may cause a loop.  */
1688   _exit (-1);
1689 }
1690 #endif
1691
1692 #ifdef L_op_delete
1693 /* operator delete (void *), described in 17.3.3.3.  This function is used
1694    by C++ programs to return to the free store a block of memory allocated
1695    as a single object. */
1696
1697 void
1698 __builtin_delete (void *ptr)
1699 {
1700   if (ptr)
1701     free (ptr);
1702 }
1703 #endif
1704
1705 #ifdef L_op_vdel
1706 /* operator delete [] (void *), described in 17.3.3.4.  This function is
1707    used by C++ programs to return to the free store a block of memory
1708    allocated as an array. */
1709
1710 extern void __builtin_delete (void *);
1711
1712 void
1713 __builtin_vec_delete (void *ptr)
1714 {
1715   __builtin_delete (ptr);
1716 }
1717 #endif
1718
1719 /* End of C++ free-store management functions */
1720 \f
1721 #ifdef L_shtab
1722 unsigned int __shtab[] = {
1723     0x00000001, 0x00000002, 0x00000004, 0x00000008,
1724     0x00000010, 0x00000020, 0x00000040, 0x00000080,
1725     0x00000100, 0x00000200, 0x00000400, 0x00000800,
1726     0x00001000, 0x00002000, 0x00004000, 0x00008000,
1727     0x00010000, 0x00020000, 0x00040000, 0x00080000,
1728     0x00100000, 0x00200000, 0x00400000, 0x00800000,
1729     0x01000000, 0x02000000, 0x04000000, 0x08000000,
1730     0x10000000, 0x20000000, 0x40000000, 0x80000000
1731   };
1732 #endif
1733 \f
1734 #ifdef L_clear_cache
1735 /* Clear part of an instruction cache.  */
1736
1737 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1738
1739 void
1740 __clear_cache (beg, end)
1741      char *beg, *end;
1742 {
1743 #ifdef CLEAR_INSN_CACHE 
1744   CLEAR_INSN_CACHE (beg, end);
1745 #else
1746 #ifdef INSN_CACHE_SIZE
1747   static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1748   static int initialized = 0;
1749   int offset;
1750   void *start_addr
1751   void *end_addr;
1752   typedef (*function_ptr) ();
1753
1754 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1755   /* It's cheaper to clear the whole cache.
1756      Put in a series of jump instructions so that calling the beginning
1757      of the cache will clear the whole thing.  */
1758
1759   if (! initialized)
1760     {
1761       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1762                  & -INSN_CACHE_LINE_WIDTH);
1763       int end_ptr = ptr + INSN_CACHE_SIZE;
1764
1765       while (ptr < end_ptr)
1766         {
1767           *(INSTRUCTION_TYPE *)ptr
1768             = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1769           ptr += INSN_CACHE_LINE_WIDTH;
1770         }
1771       *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1772
1773       initialized = 1;
1774     }
1775
1776   /* Call the beginning of the sequence.  */
1777   (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1778                     & -INSN_CACHE_LINE_WIDTH))
1779    ());
1780
1781 #else /* Cache is large.  */
1782
1783   if (! initialized)
1784     {
1785       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1786                  & -INSN_CACHE_LINE_WIDTH);
1787
1788       while (ptr < (int) array + sizeof array)
1789         {
1790           *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1791           ptr += INSN_CACHE_LINE_WIDTH;
1792         }
1793
1794       initialized = 1;
1795     }
1796
1797   /* Find the location in array that occupies the same cache line as BEG.  */
1798
1799   offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1800   start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1801                  & -INSN_CACHE_PLANE_SIZE)
1802                 + offset);
1803
1804   /* Compute the cache alignment of the place to stop clearing.  */
1805 #if 0  /* This is not needed for gcc's purposes.  */
1806   /* If the block to clear is bigger than a cache plane,
1807      we clear the entire cache, and OFFSET is already correct.  */ 
1808   if (end < beg + INSN_CACHE_PLANE_SIZE)
1809 #endif
1810     offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1811                & -INSN_CACHE_LINE_WIDTH)
1812               & (INSN_CACHE_PLANE_SIZE - 1));
1813
1814 #if INSN_CACHE_DEPTH > 1
1815   end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1816   if (end_addr <= start_addr)
1817     end_addr += INSN_CACHE_PLANE_SIZE;
1818
1819   for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1820     {
1821       int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1822       int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1823
1824       while (addr != stop)
1825         {
1826           /* Call the return instruction at ADDR.  */
1827           ((function_ptr) addr) ();
1828
1829           addr += INSN_CACHE_LINE_WIDTH;
1830         }
1831     }
1832 #else /* just one plane */
1833   do
1834     {
1835       /* Call the return instruction at START_ADDR.  */
1836       ((function_ptr) start_addr) ();
1837
1838       start_addr += INSN_CACHE_LINE_WIDTH;
1839     }
1840   while ((start_addr % INSN_CACHE_SIZE) != offset);
1841 #endif /* just one plane */
1842 #endif /* Cache is large */
1843 #endif /* Cache exists */
1844 #endif /* CLEAR_INSN_CACHE */
1845 }
1846
1847 #endif /* L_clear_cache */
1848 \f
1849 #ifdef L_trampoline
1850
1851 /* Jump to a trampoline, loading the static chain address.  */
1852
1853 #ifdef TRANSFER_FROM_TRAMPOLINE 
1854 TRANSFER_FROM_TRAMPOLINE 
1855 #endif
1856
1857 #if defined (NeXT) && defined (__MACH__)
1858
1859 /* Make stack executable so we can call trampolines on stack.
1860    This is called from INITIALIZE_TRAMPOLINE in next.h.  */
1861 #ifdef NeXTStep21
1862  #include <mach.h>
1863 #else
1864  #include <mach/mach.h>
1865 #endif
1866
1867 void
1868 __enable_execute_stack (addr)
1869      char *addr;
1870 {
1871   kern_return_t r;
1872   char *eaddr = addr + TRAMPOLINE_SIZE;
1873   vm_address_t a = (vm_address_t) addr;
1874
1875   /* turn on execute access on stack */
1876   r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
1877   if (r != KERN_SUCCESS)
1878     {
1879       mach_error("vm_protect VM_PROT_ALL", r);
1880       exit(1);
1881     }
1882
1883   /* We inline the i-cache invalidation for speed */
1884
1885 #ifdef CLEAR_INSN_CACHE
1886   CLEAR_INSN_CACHE (addr, eaddr);
1887 #else
1888   __clear_cache ((int) addr, (int) eaddr);
1889 #endif
1890
1891
1892 #endif /* defined (NeXT) && defined (__MACH__) */
1893
1894 #ifdef __convex__
1895
1896 /* Make stack executable so we can call trampolines on stack.
1897    This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
1898
1899 #include <sys/mman.h>
1900 #include <sys/vmparam.h>
1901 #include <machine/machparam.h>
1902
1903 void
1904 __enable_execute_stack ()
1905 {
1906   int fp;
1907   static unsigned lowest = USRSTACK;
1908   unsigned current = (unsigned) &fp & -NBPG;
1909
1910   if (lowest > current)
1911     {
1912       unsigned len = lowest - current;
1913       mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1914       lowest = current;
1915     }
1916
1917   /* Clear instruction cache in case an old trampoline is in it. */
1918   asm ("pich");
1919 }
1920 #endif /* __convex__ */
1921
1922 #ifdef __DOLPHIN__
1923
1924 /* Modified from the convex -code above. */
1925
1926 #include <sys/param.h>
1927 #include <errno.h>
1928 #include <sys/m88kbcs.h>
1929
1930 void
1931 __enable_execute_stack ()
1932 {
1933   int save_errno;
1934   static unsigned long lowest = USRSTACK;
1935   unsigned long current = (unsigned long) &save_errno & -NBPC;
1936   
1937   /* Ignore errno being set. memctl sets errno to EINVAL whenever the
1938      address is seen as 'negative'. That is the case with the stack.   */
1939
1940   save_errno=errno;
1941   if (lowest > current)
1942     {
1943       unsigned len=lowest-current;
1944       memctl(current,len,MCT_TEXT);
1945       lowest = current;
1946     }
1947   else
1948     memctl(current,NBPC,MCT_TEXT);
1949   errno=save_errno;
1950 }
1951
1952 #endif /* __DOLPHIN__ */
1953
1954 #ifdef __pyr__
1955
1956 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1957 #include <stdio.h>
1958 #include <sys/mman.h>
1959 #include <sys/types.h>
1960 #include <sys/param.h>
1961 #include <sys/vmmac.h>
1962
1963 /* Modified from the convex -code above.
1964    mremap promises to clear the i-cache. */
1965
1966 void
1967 __enable_execute_stack ()
1968 {
1969   int fp;
1970   if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
1971                 PROT_READ|PROT_WRITE|PROT_EXEC))
1972     {
1973       perror ("mprotect in __enable_execute_stack");
1974       fflush (stderr);
1975       abort ();
1976     }
1977 }
1978 #endif /* __pyr__ */
1979 #endif /* L_trampoline */
1980 \f
1981 #ifdef L__main
1982
1983 #include "gbl-ctors.h"
1984 /* Some systems use __main in a way incompatible with its use in gcc, in these
1985    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
1986    give the same symbol without quotes for an alternative entry point.  You
1987    must define both, or niether. */
1988 #ifndef NAME__MAIN
1989 #define NAME__MAIN "__main"
1990 #define SYMBOL__MAIN __main
1991 #endif
1992
1993 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
1994 /* Run all the global destructors on exit from the program.  */
1995
1996 void
1997 __do_global_dtors ()
1998 {
1999 #ifdef DO_GLOBAL_DTORS_BODY
2000   DO_GLOBAL_DTORS_BODY;
2001 #else
2002   func_ptr *p;
2003   for (p = __DTOR_LIST__ + 1; *p; )
2004     (*p++) ();
2005 #endif
2006 }
2007 #endif
2008
2009 #ifndef INIT_SECTION_ASM_OP
2010 /* Run all the global constructors on entry to the program.  */
2011
2012 #ifndef ON_EXIT
2013 #define ON_EXIT(a, b)
2014 #else
2015 /* Make sure the exit routine is pulled in to define the globals as
2016    bss symbols, just in case the linker does not automatically pull
2017    bss definitions from the library.  */
2018
2019 extern int _exit_dummy_decl;
2020 int *_exit_dummy_ref = &_exit_dummy_decl;
2021 #endif /* ON_EXIT */
2022
2023 void
2024 __do_global_ctors ()
2025 {
2026   DO_GLOBAL_CTORS_BODY;
2027   ON_EXIT (__do_global_dtors, 0);
2028 }
2029 #endif /* no INIT_SECTION_ASM_OP */
2030
2031 #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
2032 /* Subroutine called automatically by `main'.
2033    Compiling a global function named `main'
2034    produces an automatic call to this function at the beginning.
2035
2036    For many systems, this routine calls __do_global_ctors.
2037    For systems which support a .init section we use the .init section
2038    to run __do_global_ctors, so we need not do anything here.  */
2039
2040 void
2041 SYMBOL__MAIN ()
2042 {
2043   /* Support recursive calls to `main': run initializers just once.  */
2044   static int initialized = 0;
2045   if (! initialized)
2046     {
2047       initialized = 1;
2048       __do_global_ctors ();
2049     }
2050 }
2051 #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
2052
2053 #endif /* L__main */
2054 \f
2055 #ifdef L_ctors
2056
2057 #include "gbl-ctors.h"
2058
2059 /* Provide default definitions for the lists of constructors and
2060    destructors, so that we don't get linker errors.  These symbols are
2061    intentionally bss symbols, so that gld and/or collect will provide
2062    the right values.  */
2063
2064 /* We declare the lists here with two elements each,
2065    so that they are valid empty lists if no other definition is loaded.  */
2066 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2067 #ifdef __NeXT__
2068 /* After 2.3, try this definition on all systems.  */
2069 func_ptr __CTOR_LIST__[2] = {0, 0};
2070 func_ptr __DTOR_LIST__[2] = {0, 0};
2071 #else
2072 func_ptr __CTOR_LIST__[2];
2073 func_ptr __DTOR_LIST__[2];
2074 #endif
2075 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2076 #endif /* L_ctors */
2077 \f
2078 #ifdef L_exit
2079
2080 #include "gbl-ctors.h"
2081
2082 #ifndef ON_EXIT
2083
2084 /* If we have no known way of registering our own __do_global_dtors
2085    routine so that it will be invoked at program exit time, then we
2086    have to define our own exit routine which will get this to happen.  */
2087
2088 extern void __do_global_dtors ();
2089 extern void _cleanup ();
2090 extern void _exit () __attribute__ ((noreturn));
2091
2092 void 
2093 exit (status)
2094      int status;
2095 {
2096 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
2097   __do_global_dtors ();
2098 #endif
2099 #ifdef EXIT_BODY
2100   EXIT_BODY;
2101 #else
2102   _cleanup ();
2103 #endif
2104   _exit (status);
2105 }
2106
2107 #else
2108 int _exit_dummy_decl = 0;       /* prevent compiler & linker warnings */
2109 #endif
2110
2111 #endif /* L_exit */
2112 \f
2113 #ifdef L_eh
2114 typedef struct {
2115   void *start;
2116   void *end;
2117   void *exception_handler;
2118 } exception_table;
2119
2120 struct exception_table_node {
2121   exception_table *table;
2122   void *start;
2123   void *end;
2124   struct exception_table_node *next;
2125 };
2126
2127 static int except_table_pos = 0;
2128 static void *except_pc = (void *)0;
2129 static struct exception_table_node *exception_table_list = 0;
2130
2131 static exception_table *
2132 find_exception_table (pc)
2133      void* pc;
2134 {
2135   register struct exception_table_node *table = exception_table_list;
2136   for ( ; table != 0; table = table->next)
2137     {
2138       if (table->start <= pc && table->end > pc)
2139         return table->table;
2140     }
2141   return 0;
2142 }
2143
2144 /* this routine takes a pc, and the address of the exception handler associated
2145    with the closest exception table handler entry associated with that PC,
2146    or 0 if there are no table entries the PC fits in.  The algorithm works
2147    something like this:
2148
2149     while(current_entry exists) {
2150         if(current_entry.start < pc )
2151             current_entry = next_entry;
2152         else {
2153             if(prev_entry.start <= pc && prev_entry.end > pc) {
2154                 save pointer to prev_entry;
2155                 return prev_entry.exception_handler;
2156              }
2157             else return 0;
2158          }
2159      }
2160     return 0;
2161
2162    Assuming a correctly sorted table (ascending order) this routine should
2163    return the tighest match...
2164
2165    In the advent of a tie, we have to give the last entry, as it represents
2166    an inner block.
2167  */
2168
2169
2170 void *
2171 __find_first_exception_table_match(pc)
2172 void *pc;
2173 {
2174   exception_table *table = find_exception_table (pc);
2175   int pos = 0;
2176   int best = 0;
2177   if (table == 0)
2178     return (void*)0;
2179 #if 0
2180   printf("find_first_exception_table_match(): pc = %x!\n",pc);
2181 #endif
2182
2183   except_pc = pc;
2184
2185 #if 0
2186   /* We can't do this yet, as we don't know that the table is sorted.  */
2187   do {
2188     ++pos;
2189     if (table[pos].start > except_pc)
2190       /* found the first table[pos].start > except_pc, so the previous
2191          entry better be the one we want! */
2192       break;
2193   } while(table[pos].exception_handler != (void*)-1);
2194
2195   --pos;
2196   if (table[pos].start <= except_pc && table[pos].end > except_pc)
2197     {
2198       except_table_pos = pos;
2199 #if 0
2200       printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
2201 #endif
2202       return table[pos].exception_handler;
2203     }
2204 #else
2205   while (table[++pos].exception_handler != (void*)-1) {
2206     if (table[pos].start <= except_pc && table[pos].end > except_pc)
2207       {
2208         /* This can apply.  Make sure it is better or as good as the previous
2209            best.  */
2210         /* The best one ends first. */
2211         if (best == 0 || (table[pos].end <= table[best].end
2212                           /* The best one starts last.  */
2213                           && table[pos].start >= table[best].start))
2214           best = pos;
2215       }
2216   }
2217   if (best != 0)
2218     return table[best].exception_handler;
2219 #endif
2220
2221 #if 0
2222   printf("find_first_eh_table_match(): else: returning NULL!\n");
2223 #endif
2224   return (void*)0;
2225 }
2226
2227 int
2228 __throw_type_match (const char *catch_type, const char *throw_type)
2229 {
2230 #if 0
2231  printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
2232         catch_type, throw_type);
2233 #endif
2234  return strcmp (catch_type, throw_type);
2235 }
2236
2237 void
2238 __register_exceptions (exception_table *table)
2239 {
2240   struct exception_table_node *node;
2241   exception_table *range = table + 1;
2242
2243   if (range->start == (void*)-1)
2244     return;
2245
2246   node = (struct exception_table_node*)
2247     malloc (sizeof (struct exception_table_node));
2248   node->table = table;
2249
2250   /* This look can be optimized away either if the table
2251      is sorted, or if we pass in extra parameters. */
2252   node->start = range->start;
2253   node->end = range->end;
2254   for (range++ ; range->start != (void*)(-1); range++)
2255     {
2256       if (range->start < node->start)
2257         node->start = range->start;
2258       if (range->end > node->end)
2259         node->end = range->end;
2260     }
2261
2262   node->next = exception_table_list;
2263   exception_table_list = node;
2264 }
2265
2266 #if #machine(i386)
2267 void
2268 __unwind_function(void *ptr)
2269 {
2270   asm("movl 8(%esp),%ecx");
2271   /* Undo current frame */
2272   asm("movl %ebp,%esp");
2273   asm("popl %ebp");
2274   asm("# like ret, but stay here");
2275   asm("addl $4,%esp");
2276   
2277   /* Now, undo previous frame. */
2278   /* This is a test routine, as we have to dynamically probe to find out
2279      what to pop for certain, this is just a guess. */
2280   asm("leal -16(%ebp),%esp");
2281   asm("pop %eax # really for popl %ebx");
2282   asm("pop %eax # really for popl %esi");
2283   asm("pop %eax # really for popl %edi");
2284   asm("movl %ebp,%esp");
2285   asm("popl %ebp");
2286
2287   asm("movl %ecx,0(%esp)");
2288   asm("ret");
2289 }
2290 #endif
2291
2292 #if #machine(rs6000)
2293 __unwind_function(void *ptr)
2294 {
2295   asm("mr 31,1");
2296   asm("l 1,0(1)");
2297   asm("l 31,-4(1)");
2298   asm("# br");
2299
2300   asm("mr 31,1");
2301   asm("l 1,0(1)");
2302   /* use 31 as a scratch register to restore the link register. */
2303   asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
2304   asm("l 31,-4(1)");
2305   asm("# br");
2306   asm("mtctr 3;bctr # b 3");
2307 }
2308 #endif /* rs6000 */
2309
2310 #if #machine(powerpc)
2311 __unwind_function(void *ptr)
2312 {
2313   asm("mr 31,1");
2314   asm("lwz 1,0(1)");
2315   asm("lwz 31,-4(1)");
2316   asm("# br");
2317
2318   asm("mr 31,1");
2319   asm("lwz 1,0(1)");
2320   /* use 31 as a scratch register to restore the link register. */
2321   asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
2322   asm("lwz 31,-4(1)");
2323   asm("# br");
2324   asm("mtctr 3;bctr # b 3");
2325 }
2326 #endif /* powerpc */
2327 #endif /* L_eh */
2328 \f
2329 #ifdef L_pure
2330 #ifndef inhibit_libc
2331 /* This gets us __GNU_LIBRARY__.  */
2332 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2333 #include <stdio.h>
2334
2335 #ifdef __GNU_LIBRARY__
2336   /* Avoid forcing the library's meaning of `write' on the user program
2337      by using the "internal" name (for use within the library)  */
2338 #define write(fd, buf, n)       __write((fd), (buf), (n))
2339 #endif
2340 #endif /* inhibit_libc */
2341
2342 #define MESSAGE "pure virtual method called\n"
2343
2344 void
2345 __pure_virtual ()
2346 {
2347 #ifndef inhibit_libc
2348   write (2, MESSAGE, sizeof (MESSAGE) - 1);
2349 #endif
2350   _exit (-1);
2351 }
2352 #endif