OSDN Git Service

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