OSDN Git Service

Don't call write ifdef inhibit_libc.
[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 extern void atexit (void (*) (void));
1429 #define ON_EXIT(FUNC,ARG) atexit ((FUNC))
1430 #else
1431 #ifdef sun
1432 extern void on_exit (void*, void*);
1433 #define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
1434 #endif
1435 #endif
1436
1437 static struct bb *bb_head = (struct bb *)0;
1438
1439 /* Return the number of digits needed to print a value */
1440 /* __inline__ */ static int num_digits (long value, int base)
1441 {
1442   int minus = (value < 0 && base != 16);
1443   unsigned long v = (minus) ? -value : value;
1444   int ret = minus;
1445
1446   do
1447     {
1448       v /= base;
1449       ret++;
1450     }
1451   while (v);
1452
1453   return ret;
1454 }
1455
1456 void
1457 __bb_exit_func (void)
1458 {
1459   FILE *file = fopen ("bb.out", "a");
1460   long time_value;
1461
1462   if (!file)
1463     perror ("bb.out");
1464
1465   else
1466     {
1467       struct bb *ptr;
1468
1469       /* This is somewhat type incorrect, but it avoids worrying about
1470          exactly where time.h is included from.  It should be ok unless
1471          a void * differs from other pointer formats, or if sizeof(long)
1472          is < sizeof (time_t).  It would be nice if we could assume the
1473          use of rationale standards here.  */
1474
1475       time((void *) &time_value);
1476       fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1477
1478       /* We check the length field explicitly in order to allow compatibility
1479          with older GCC's which did not provide it.  */
1480
1481       for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
1482         {
1483           int i;
1484           int func_p    = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
1485           int line_p    = (func_p && ptr->line_nums);
1486           int file_p    = (func_p && ptr->filenames);
1487           long ncounts  = ptr->ncounts;
1488           long cnt_max  = 0;
1489           long line_max = 0;
1490           long addr_max = 0;
1491           int file_len  = 0;
1492           int func_len  = 0;
1493           int blk_len   = num_digits (ncounts, 10);
1494           int cnt_len;
1495           int line_len;
1496           int addr_len;
1497
1498           fprintf (file, "File %s, %ld basic blocks \n\n",
1499                    ptr->filename, ncounts);
1500
1501           /* Get max values for each field.  */
1502           for (i = 0; i < ncounts; i++)
1503             {
1504               const char *p;
1505               int len;
1506
1507               if (cnt_max < ptr->counts[i])
1508                 cnt_max = ptr->counts[i];
1509
1510               if (addr_max < ptr->addresses[i])
1511                 addr_max = ptr->addresses[i];
1512
1513               if (line_p && line_max < ptr->line_nums[i])
1514                 line_max = ptr->line_nums[i];
1515
1516               if (func_p)
1517                 {
1518                   p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1519                   len = strlen (p);
1520                   if (func_len < len)
1521                     func_len = len;
1522                 }
1523
1524               if (file_p)
1525                 {
1526                   p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1527                   len = strlen (p);
1528                   if (file_len < len)
1529                     file_len = len;
1530                 }
1531             }
1532
1533           addr_len = num_digits (addr_max, 16);
1534           cnt_len  = num_digits (cnt_max, 10);
1535           line_len = num_digits (line_max, 10);
1536
1537           /* Now print out the basic block information.  */
1538           for (i = 0; i < ncounts; i++)
1539             {
1540               fprintf (file,
1541                        "    Block #%*d: executed %*ld time(s) address= 0x%.*lx",
1542                        blk_len, i+1,
1543                        cnt_len, ptr->counts[i],
1544                        addr_len, ptr->addresses[i]);
1545
1546               if (func_p)
1547                 fprintf (file, " function= %-*s", func_len,
1548                          (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1549
1550               if (line_p)
1551                 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1552
1553               if (file_p)
1554                 fprintf (file, " file= %s",
1555                          (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1556
1557               fprintf (file, "\n");
1558             }
1559
1560           fprintf (file, "\n");
1561           fflush (file);
1562         }
1563
1564       fprintf (file, "\n\n");
1565       fclose (file);
1566     }
1567 }
1568
1569 void
1570 __bb_init_func (struct bb *blocks)
1571 {
1572   /* User is supposed to check whether the first word is non-0,
1573      but just in case.... */
1574
1575   if (blocks->zero_word)
1576     return;
1577
1578 #ifdef ON_EXIT
1579   /* Initialize destructor.  */
1580   if (!bb_head)
1581     ON_EXIT (__bb_exit_func, 0);
1582 #endif
1583
1584   /* Set up linked list.  */
1585   blocks->zero_word = 1;
1586   blocks->next = bb_head;
1587   bb_head = blocks;
1588 }
1589
1590 #endif /* not inhibit_libc */
1591 #endif /* not BLOCK_PROFILER_CODE */
1592 #endif /* L_bb */
1593 \f
1594 /* Default free-store management functions for C++, per sections 12.5 and
1595    17.3.3 of the Working Paper. */
1596
1597 #ifdef L_op_new
1598 /* operator new (size_t), described in 17.3.3.5.  This function is used by
1599    C++ programs to allocate a block of memory to hold a single object. */
1600
1601 typedef void (*vfp)(void);
1602 extern vfp __new_handler;
1603
1604 void *
1605 __builtin_new (size_t sz)
1606 {
1607   void *p;
1608
1609   /* malloc (0) is unpredictable; avoid it.  */
1610   if (sz == 0)
1611     sz = 1;
1612   p = (void *) malloc (sz);
1613   while (p == 0)
1614     {
1615       (*__new_handler) ();
1616       p = (void *) malloc (sz);
1617     }
1618   
1619   return p;
1620 }
1621 #endif /* L_op_new */
1622
1623 #ifdef L_op_vnew
1624 /* void * operator new [] (size_t), described in 17.3.3.6.  This function
1625    is used by C++ programs to allocate a block of memory for an array.  */
1626
1627 extern void * __builtin_new (size_t);
1628
1629 void *
1630 __builtin_vec_new (size_t sz)
1631 {
1632   return __builtin_new (sz);
1633 }
1634 #endif /* L_op_vnew */
1635
1636 #ifdef L_new_handler
1637 /* set_new_handler (fvoid_t *) and the default new handler, described in
1638    17.3.3.2 and 17.3.3.5.  These functions define the result of a failure
1639    to allocate the amount of memory requested from operator new or new []. */
1640
1641 #ifndef inhibit_libc
1642 /* This gets us __GNU_LIBRARY__.  */
1643 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1644 #include <stdio.h>
1645
1646 #ifdef __GNU_LIBRARY__
1647   /* Avoid forcing the library's meaning of `write' on the user program
1648      by using the "internal" name (for use within the library)  */
1649 #define write(fd, buf, n)       __write((fd), (buf), (n))
1650 #endif
1651 #endif /* inhibit_libc */
1652
1653 typedef void (*vfp)(void);
1654 void __default_new_handler (void);
1655
1656 vfp __new_handler = __default_new_handler;
1657
1658 vfp
1659 set_new_handler (vfp handler)
1660 {
1661   vfp prev_handler;
1662
1663   prev_handler = __new_handler;
1664   if (handler == 0) handler = __default_new_handler;
1665   __new_handler = handler;
1666   return prev_handler;
1667 }
1668
1669 #define MESSAGE "Virtual memory exceeded in `new'\n"
1670
1671 void
1672 __default_new_handler ()
1673 {
1674 #ifndef inhibit_libc
1675   /* don't use fprintf (stderr, ...) because it may need to call malloc.  */
1676   /* This should really print the name of the program, but that is hard to
1677      do.  We need a standard, clean way to get at the name.  */
1678   write (2, MESSAGE, sizeof (MESSAGE));
1679 #endif
1680   /* don't call exit () because that may call global destructors which
1681      may cause a loop.  */
1682   _exit (-1);
1683 }
1684 #endif
1685
1686 #ifdef L_op_delete
1687 /* operator delete (void *), described in 17.3.3.3.  This function is used
1688    by C++ programs to return to the free store a block of memory allocated
1689    as a single object. */
1690
1691 void
1692 __builtin_delete (void *ptr)
1693 {
1694   if (ptr)
1695     free (ptr);
1696 }
1697 #endif
1698
1699 #ifdef L_op_vdel
1700 /* operator delete [] (void *), described in 17.3.3.4.  This function is
1701    used by C++ programs to return to the free store a block of memory
1702    allocated as an array. */
1703
1704 extern void __builtin_delete (void *);
1705
1706 void
1707 __builtin_vec_delete (void *ptr)
1708 {
1709   __builtin_delete (ptr);
1710 }
1711 #endif
1712
1713 /* End of C++ free-store management functions */
1714 \f
1715 #ifdef L_shtab
1716 unsigned int __shtab[] = {
1717     0x00000001, 0x00000002, 0x00000004, 0x00000008,
1718     0x00000010, 0x00000020, 0x00000040, 0x00000080,
1719     0x00000100, 0x00000200, 0x00000400, 0x00000800,
1720     0x00001000, 0x00002000, 0x00004000, 0x00008000,
1721     0x00010000, 0x00020000, 0x00040000, 0x00080000,
1722     0x00100000, 0x00200000, 0x00400000, 0x00800000,
1723     0x01000000, 0x02000000, 0x04000000, 0x08000000,
1724     0x10000000, 0x20000000, 0x40000000, 0x80000000
1725   };
1726 #endif
1727 \f
1728 #ifdef L_clear_cache
1729 /* Clear part of an instruction cache.  */
1730
1731 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1732
1733 void
1734 __clear_cache (beg, end)
1735      char *beg, *end;
1736 {
1737 #ifdef CLEAR_INSN_CACHE 
1738   CLEAR_INSN_CACHE (beg, end);
1739 #else
1740 #ifdef INSN_CACHE_SIZE
1741   static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1742   static int initialized = 0;
1743   int offset;
1744   void *start_addr
1745   void *end_addr;
1746   typedef (*function_ptr) ();
1747
1748 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1749   /* It's cheaper to clear the whole cache.
1750      Put in a series of jump instructions so that calling the beginning
1751      of the cache will clear the whole thing.  */
1752
1753   if (! initialized)
1754     {
1755       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1756                  & -INSN_CACHE_LINE_WIDTH);
1757       int end_ptr = ptr + INSN_CACHE_SIZE;
1758
1759       while (ptr < end_ptr)
1760         {
1761           *(INSTRUCTION_TYPE *)ptr
1762             = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1763           ptr += INSN_CACHE_LINE_WIDTH;
1764         }
1765       *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1766
1767       initialized = 1;
1768     }
1769
1770   /* Call the beginning of the sequence.  */
1771   (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1772                     & -INSN_CACHE_LINE_WIDTH))
1773    ());
1774
1775 #else /* Cache is large.  */
1776
1777   if (! initialized)
1778     {
1779       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1780                  & -INSN_CACHE_LINE_WIDTH);
1781
1782       while (ptr < (int) array + sizeof array)
1783         {
1784           *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1785           ptr += INSN_CACHE_LINE_WIDTH;
1786         }
1787
1788       initialized = 1;
1789     }
1790
1791   /* Find the location in array that occupies the same cache line as BEG.  */
1792
1793   offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1794   start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1795                  & -INSN_CACHE_PLANE_SIZE)
1796                 + offset);
1797
1798   /* Compute the cache alignment of the place to stop clearing.  */
1799 #if 0  /* This is not needed for gcc's purposes.  */
1800   /* If the block to clear is bigger than a cache plane,
1801      we clear the entire cache, and OFFSET is already correct.  */ 
1802   if (end < beg + INSN_CACHE_PLANE_SIZE)
1803 #endif
1804     offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1805                & -INSN_CACHE_LINE_WIDTH)
1806               & (INSN_CACHE_PLANE_SIZE - 1));
1807
1808 #if INSN_CACHE_DEPTH > 1
1809   end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1810   if (end_addr <= start_addr)
1811     end_addr += INSN_CACHE_PLANE_SIZE;
1812
1813   for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1814     {
1815       int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1816       int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1817
1818       while (addr != stop)
1819         {
1820           /* Call the return instruction at ADDR.  */
1821           ((function_ptr) addr) ();
1822
1823           addr += INSN_CACHE_LINE_WIDTH;
1824         }
1825     }
1826 #else /* just one plane */
1827   do
1828     {
1829       /* Call the return instruction at START_ADDR.  */
1830       ((function_ptr) start_addr) ();
1831
1832       start_addr += INSN_CACHE_LINE_WIDTH;
1833     }
1834   while ((start_addr % INSN_CACHE_SIZE) != offset);
1835 #endif /* just one plane */
1836 #endif /* Cache is large */
1837 #endif /* Cache exists */
1838 #endif /* CLEAR_INSN_CACHE */
1839 }
1840
1841 #endif /* L_clear_cache */
1842 \f
1843 #ifdef L_trampoline
1844
1845 /* Jump to a trampoline, loading the static chain address.  */
1846
1847 #ifdef TRANSFER_FROM_TRAMPOLINE 
1848 TRANSFER_FROM_TRAMPOLINE 
1849 #endif
1850
1851 #if defined (NeXT) && defined (__MACH__)
1852
1853 /* Make stack executable so we can call trampolines on stack.
1854    This is called from INITIALIZE_TRAMPOLINE in next.h.  */
1855 #ifdef NeXTStep21
1856  #include <mach.h>
1857 #else
1858  #include <mach/mach.h>
1859 #endif
1860
1861 void
1862 __enable_execute_stack (addr)
1863      char *addr;
1864 {
1865   kern_return_t r;
1866   char *eaddr = addr + TRAMPOLINE_SIZE;
1867   vm_address_t a = (vm_address_t) addr;
1868
1869   /* turn on execute access on stack */
1870   r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
1871   if (r != KERN_SUCCESS)
1872     {
1873       mach_error("vm_protect VM_PROT_ALL", r);
1874       exit(1);
1875     }
1876
1877   /* We inline the i-cache invalidation for speed */
1878
1879 #ifdef CLEAR_INSN_CACHE
1880   CLEAR_INSN_CACHE (addr, eaddr);
1881 #else
1882   __clear_cache ((int) addr, (int) eaddr);
1883 #endif
1884
1885
1886 #endif /* defined (NeXT) && defined (__MACH__) */
1887
1888 #ifdef __convex__
1889
1890 /* Make stack executable so we can call trampolines on stack.
1891    This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
1892
1893 #include <sys/mman.h>
1894 #include <sys/vmparam.h>
1895 #include <machine/machparam.h>
1896
1897 void
1898 __enable_execute_stack ()
1899 {
1900   int fp;
1901   static unsigned lowest = USRSTACK;
1902   unsigned current = (unsigned) &fp & -NBPG;
1903
1904   if (lowest > current)
1905     {
1906       unsigned len = lowest - current;
1907       mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1908       lowest = current;
1909     }
1910
1911   /* Clear instruction cache in case an old trampoline is in it. */
1912   asm ("pich");
1913 }
1914 #endif /* __convex__ */
1915
1916 #ifdef __DOLPHIN__
1917
1918 /* Modified from the convex -code above. */
1919
1920 #include <sys/param.h>
1921 #include <errno.h>
1922 #include <sys/m88kbcs.h>
1923
1924 void
1925 __enable_execute_stack ()
1926 {
1927   int save_errno;
1928   static unsigned long lowest = USRSTACK;
1929   unsigned long current = (unsigned long) &save_errno & -NBPC;
1930   
1931   /* Ignore errno being set. memctl sets errno to EINVAL whenever the
1932      address is seen as 'negative'. That is the case with the stack.   */
1933
1934   save_errno=errno;
1935   if (lowest > current)
1936     {
1937       unsigned len=lowest-current;
1938       memctl(current,len,MCT_TEXT);
1939       lowest = current;
1940     }
1941   else
1942     memctl(current,NBPC,MCT_TEXT);
1943   errno=save_errno;
1944 }
1945
1946 #endif /* __DOLPHIN__ */
1947
1948 #ifdef __pyr__
1949
1950 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1951 #include <stdio.h>
1952 #include <sys/mman.h>
1953 #include <sys/types.h>
1954 #include <sys/param.h>
1955 #include <sys/vmmac.h>
1956
1957 /* Modified from the convex -code above.
1958    mremap promises to clear the i-cache. */
1959
1960 void
1961 __enable_execute_stack ()
1962 {
1963   int fp;
1964   if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
1965                 PROT_READ|PROT_WRITE|PROT_EXEC))
1966     {
1967       perror ("mprotect in __enable_execute_stack");
1968       fflush (stderr);
1969       abort ();
1970     }
1971 }
1972 #endif /* __pyr__ */
1973 #endif /* L_trampoline */
1974 \f
1975 #ifdef L__main
1976
1977 #include "gbl-ctors.h"
1978 /* Some systems use __main in a way incompatible with its use in gcc, in these
1979    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
1980    give the same symbol without quotes for an alternative entry point.  You
1981    must define both, or niether. */
1982 #ifndef NAME__MAIN
1983 #define NAME__MAIN "__main"
1984 #define SYMBOL__MAIN __main
1985 #endif
1986
1987 #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
1988 /* Run all the global destructors on exit from the program.  */
1989
1990 void
1991 __do_global_dtors ()
1992 {
1993 #ifdef DO_GLOBAL_DTORS_BODY
1994   DO_GLOBAL_DTORS_BODY;
1995 #else
1996   func_ptr *p;
1997   for (p = __DTOR_LIST__ + 1; *p; )
1998     (*p++) ();
1999 #endif
2000 }
2001 #endif
2002
2003 #ifndef INIT_SECTION_ASM_OP
2004 /* Run all the global constructors on entry to the program.  */
2005
2006 #ifndef ON_EXIT
2007 #define ON_EXIT(a, b)
2008 #else
2009 /* Make sure the exit routine is pulled in to define the globals as
2010    bss symbols, just in case the linker does not automatically pull
2011    bss definitions from the library.  */
2012
2013 extern int _exit_dummy_decl;
2014 int *_exit_dummy_ref = &_exit_dummy_decl;
2015 #endif /* ON_EXIT */
2016
2017 void
2018 __do_global_ctors ()
2019 {
2020   DO_GLOBAL_CTORS_BODY;
2021   ON_EXIT (__do_global_dtors, 0);
2022 }
2023 #endif /* no INIT_SECTION_ASM_OP */
2024
2025 #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
2026 /* Subroutine called automatically by `main'.
2027    Compiling a global function named `main'
2028    produces an automatic call to this function at the beginning.
2029
2030    For many systems, this routine calls __do_global_ctors.
2031    For systems which support a .init section we use the .init section
2032    to run __do_global_ctors, so we need not do anything here.  */
2033
2034 void
2035 SYMBOL__MAIN ()
2036 {
2037   /* Support recursive calls to `main': run initializers just once.  */
2038   static int initialized = 0;
2039   if (! initialized)
2040     {
2041       initialized = 1;
2042       __do_global_ctors ();
2043     }
2044 }
2045 #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
2046
2047 #endif /* L__main */
2048 \f
2049 #ifdef L_ctors
2050
2051 #include "gbl-ctors.h"
2052
2053 /* Provide default definitions for the lists of constructors and
2054    destructors, so that we don't get linker errors.  These symbols are
2055    intentionally bss symbols, so that gld and/or collect will provide
2056    the right values.  */
2057
2058 /* We declare the lists here with two elements each,
2059    so that they are valid empty lists if no other definition is loaded.  */
2060 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2061 #ifdef __NeXT__
2062 /* After 2.3, try this definition on all systems.  */
2063 func_ptr __CTOR_LIST__[2] = {0, 0};
2064 func_ptr __DTOR_LIST__[2] = {0, 0};
2065 #else
2066 func_ptr __CTOR_LIST__[2];
2067 func_ptr __DTOR_LIST__[2];
2068 #endif
2069 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2070 #endif /* L_ctors */
2071 \f
2072 #ifdef L_exit
2073
2074 #include "gbl-ctors.h"
2075
2076 #ifndef ON_EXIT
2077
2078 /* If we have no known way of registering our own __do_global_dtors
2079    routine so that it will be invoked at program exit time, then we
2080    have to define our own exit routine which will get this to happen.  */
2081
2082 extern void __do_global_dtors ();
2083 extern void _cleanup ();
2084 extern void _exit () __attribute__ ((noreturn));
2085
2086 void 
2087 exit (status)
2088      int status;
2089 {
2090   __do_global_dtors ();
2091 #ifdef EXIT_BODY
2092   EXIT_BODY;
2093 #else
2094   _cleanup ();
2095 #endif
2096   _exit (status);
2097 }
2098
2099 #else
2100 int _exit_dummy_decl = 0;       /* prevent compiler & linker warnings */
2101 #endif
2102
2103 #endif /* L_exit */
2104 \f
2105 #ifdef L_eh
2106 typedef struct {
2107   void *start;
2108   void *end;
2109   void *exception_handler;
2110 } exception_table;
2111
2112 struct exception_table_node {
2113   exception_table *table;
2114   void *start;
2115   void *end;
2116   struct exception_table_node *next;
2117 };
2118
2119 static int except_table_pos = 0;
2120 static void *except_pc = (void *)0;
2121 static struct exception_table_node *exception_table_list = 0;
2122
2123 static exception_table *
2124 find_exception_table (pc)
2125      void* pc;
2126 {
2127   register struct exception_table_node *table = exception_table_list;
2128   for ( ; table != 0; table = table->next)
2129     {
2130       if (table->start <= pc && table->end > pc)
2131         return table->table;
2132     }
2133   return 0;
2134 }
2135
2136 /* this routine takes a pc, and the address of the exception handler associated
2137    with the closest exception table handler entry associated with that PC,
2138    or 0 if there are no table entries the PC fits in.  The algorithm works
2139    something like this:
2140
2141     while(current_entry exists) {
2142         if(current_entry.start < pc )
2143             current_entry = next_entry;
2144         else {
2145             if(prev_entry.start <= pc && prev_entry.end > pc) {
2146                 save pointer to prev_entry;
2147                 return prev_entry.exception_handler;
2148              }
2149             else return 0;
2150          }
2151      }
2152     return 0;
2153
2154    Assuming a correctly sorted table (ascending order) this routine should
2155    return the tighest match...
2156
2157    In the advent of a tie, we have to give the last entry, as it represents
2158    an inner block.
2159  */
2160
2161
2162 void *
2163 __find_first_exception_table_match(pc)
2164 void *pc;
2165 {
2166   exception_table *table = find_exception_table (pc);
2167   int pos = 0;
2168   int best = 0;
2169   if (table == 0)
2170     return (void*)0;
2171 #if 0
2172   printf("find_first_exception_table_match(): pc = %x!\n",pc);
2173 #endif
2174
2175   except_pc = pc;
2176
2177 #if 0
2178   /* We can't do this yet, as we don't know that the table is sorted.  */
2179   do {
2180     ++pos;
2181     if (table[pos].start > except_pc)
2182       /* found the first table[pos].start > except_pc, so the previous
2183          entry better be the one we want! */
2184       break;
2185   } while(table[pos].exception_handler != (void*)-1);
2186
2187   --pos;
2188   if (table[pos].start <= except_pc && table[pos].end > except_pc)
2189     {
2190       except_table_pos = pos;
2191 #if 0
2192       printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
2193 #endif
2194       return table[pos].exception_handler;
2195     }
2196 #else
2197   while (table[++pos].exception_handler != (void*)-1) {
2198     if (table[pos].start <= except_pc && table[pos].end > except_pc)
2199       {
2200         /* This can apply.  Make sure it is better or as good as the previous
2201            best.  */
2202         /* The best one ends first. */
2203         if (best == 0 || (table[pos].end <= table[best].end
2204                           /* The best one starts last.  */
2205                           && table[pos].start >= table[best].start))
2206           best = pos;
2207       }
2208   }
2209   if (best != 0)
2210     return table[best].exception_handler;
2211 #endif
2212
2213 #if 0
2214   printf("find_first_eh_table_match(): else: returning NULL!\n");
2215 #endif
2216   return (void*)0;
2217 }
2218
2219 int
2220 __throw_type_match (const char *catch_type, const char *throw_type)
2221 {
2222 #if 0
2223  printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
2224         catch_type, throw_type);
2225 #endif
2226  return strcmp (catch_type, throw_type);
2227 }
2228
2229 void
2230 __register_exceptions (exception_table *table)
2231 {
2232   struct exception_table_node *node = (struct exception_table_node*)
2233       malloc (sizeof (struct exception_table_node));
2234   exception_table *range = table + 1;
2235   node->table = table;
2236
2237   /* This look can be optimized away either if the table
2238      is sorted, or if we pass in extra parameters. */
2239   node->start = range->start;
2240   node->end = range->end;
2241   for (range++ ; range->start != (void*)(-1); range++)
2242     {
2243       if (range->start < node->start)
2244         node->start = range->start;
2245       if (range->end > node->end)
2246         node->end = range->end;
2247     }
2248
2249   node->next = exception_table_list;
2250   exception_table_list = node;
2251 }
2252
2253 #ifdef __i386
2254 void
2255 __unwind_function(void *ptr)
2256 {
2257   asm("movl 8(%esp),%ecx");
2258   /* Undo current frame */
2259   asm("movl %ebp,%esp");
2260   asm("popl %ebp");
2261   asm("# like ret, but stay here");
2262   asm("addl $4,%esp");
2263   
2264   /* Now, undo previous frame. */
2265   /* This is a test routine, as we have to dynamically probe to find out
2266      what to pop for certain, this is just a guess. */
2267   asm("leal -16(%ebp),%esp");
2268   asm("pop %eax # really for popl %ebx");
2269   asm("pop %eax # really for popl %esi");
2270   asm("pop %eax # really for popl %edi");
2271   asm("movl %ebp,%esp");
2272   asm("popl %ebp");
2273
2274   asm("movl %ecx,0(%esp)");
2275   asm("ret");
2276 }
2277 #endif
2278 #endif /* L_eh */
2279 \f
2280 #ifdef L_pure
2281 #ifndef inhibit_libc
2282 /* This gets us __GNU_LIBRARY__.  */
2283 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2284 #include <stdio.h>
2285
2286 #ifdef __GNU_LIBRARY__
2287   /* Avoid forcing the library's meaning of `write' on the user program
2288      by using the "internal" name (for use within the library)  */
2289 #define write(fd, buf, n)       __write((fd), (buf), (n))
2290 #endif
2291 #endif /* inhibit_libc */
2292
2293 #define MESSAGE "pure virtual method called\n"
2294
2295 void
2296 __pure_virtual ()
2297 {
2298 #ifndef inhibit_libc
2299   write (2, MESSAGE, sizeof (MESSAGE) - 1);
2300 #endif
2301   _exit (-1);
2302 }
2303 #endif