OSDN Git Service

* libgcc2.c (__bb_exit_func): Fix line wrap problems.
[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, 1996, 1997, 1998, 1999,
4    2000, 2001  Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 In addition to the permissions in the GNU General Public License, the
14 Free Software Foundation gives you unlimited permission to link the
15 compiled version of this file into combinations with other programs,
16 and to distribute those combinations without any restriction coming
17 from the use of this file.  (The General Public License restrictions
18 do apply in other respects; for example, they cover modification of
19 the file, and distribution when not linked into a combine
20 executable.)
21
22 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23 WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
25 for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING.  If not, write to the Free
29 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
30 02111-1307, USA.  */
31
32 /* It is incorrect to include config.h here, because this file is being
33    compiled for the target, and hence definitions concerning only the host
34    do not apply.  */
35
36 #include "tconfig.h"
37 #include "tsystem.h"
38
39 #include "machmode.h"
40
41 /* Don't use `fancy_abort' here even if config.h says to use it.  */
42 #ifdef abort
43 #undef abort
44 #endif
45
46 #include "libgcc2.h"
47 \f
48 #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
49 #if defined (L_divdi3) || defined (L_moddi3)
50 static inline
51 #endif
52 DWtype
53 __negdi2 (DWtype u)
54 {
55   DWunion w;
56   DWunion uu;
57
58   uu.ll = u;
59
60   w.s.low = -uu.s.low;
61   w.s.high = -uu.s.high - ((UWtype) w.s.low > 0);
62
63   return w.ll;
64 }
65 #endif
66
67 #ifdef L_addvsi3
68 Wtype
69 __addvsi3 (Wtype a, Wtype b)
70 {
71   Wtype w;
72
73   w = a + b;
74
75   if (b >= 0 ? w < a : w > a)
76     abort ();
77
78   return w;
79 }
80 #endif
81 \f
82 #ifdef L_addvdi3
83 DWtype
84 __addvdi3 (DWtype a, DWtype b)
85 {
86   DWtype w;
87
88   w = a + b;
89
90   if (b >= 0 ? w < a : w > a)
91     abort ();
92
93   return w;
94 }
95 #endif
96 \f
97 #ifdef L_subvsi3
98 Wtype
99 __subvsi3 (Wtype a, Wtype b)
100 {
101 #ifdef L_addvsi3
102   return __addvsi3 (a, (-b));
103 #else
104   DWtype w;
105
106   w = a - b;
107
108   if (b >= 0 ? w > a : w < a)
109     abort ();
110
111   return w;
112 #endif
113 }
114 #endif
115 \f
116 #ifdef L_subvdi3
117 DWtype
118 __subvdi3 (DWtype a, DWtype b)
119 {
120 #ifdef L_addvdi3
121   return (a, (-b));
122 #else
123   DWtype w;
124
125   w = a - b;
126
127   if (b >= 0 ? w > a : w < a)
128     abort ();
129
130   return w;
131 #endif
132 }
133 #endif
134 \f
135 #ifdef L_mulvsi3
136 Wtype
137 __mulvsi3 (Wtype a, Wtype b)
138 {
139   DWtype w;
140
141   w = a * b;
142
143   if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0)
144     abort ();
145
146   return w;
147 }
148 #endif
149 \f
150 #ifdef L_negvsi2
151 Wtype
152 __negvsi2 (Wtype a)
153 {
154    Wtype w;
155
156    w  = -a;
157
158   if (a >= 0 ? w > 0 : w < 0)
159     abort ();
160
161    return w;
162 }
163 #endif
164 \f
165 #ifdef L_negvdi2
166 DWtype
167 __negvdi2 (DWtype a)
168 {
169    DWtype w;
170
171    w  = -a;
172
173   if (a >= 0 ? w > 0 : w < 0)
174     abort ();
175
176    return w;
177 }
178 #endif
179 \f
180 #ifdef L_absvsi2
181 Wtype
182 __absvsi2 (Wtype a)
183 {
184    Wtype w = a;
185
186    if (a < 0)
187 #ifdef L_negvsi2
188      w = __negvsi2 (a);
189 #else
190      w = -a;
191
192    if (w < 0)
193      abort ();
194 #endif
195
196    return w;
197 }
198 #endif
199 \f
200 #ifdef L_absvdi2
201 DWtype
202 __absvdi2 (DWtype a)
203 {
204    DWtype w = a;
205
206    if (a < 0)
207 #ifdef L_negvsi2
208      w = __negvsi2 (a);
209 #else
210      w = -a;
211
212    if (w < 0)
213      abort ();
214 #endif
215
216    return w;
217 }
218 #endif
219 \f
220 #ifdef L_mulvdi3
221 DWtype
222 __mulvdi3 (DWtype u, DWtype v)
223 {
224    DWtype w;
225
226   w = u * v;
227
228   if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0)
229     abort ();
230
231   return w;
232 }
233 #endif
234 \f
235
236 /* Unless shift functions are defined whith full ANSI prototypes,
237    parameter b will be promoted to int if word_type is smaller than an int.  */
238 #ifdef L_lshrdi3
239 DWtype
240 __lshrdi3 (DWtype u, word_type b)
241 {
242   DWunion w;
243   word_type bm;
244   DWunion uu;
245
246   if (b == 0)
247     return u;
248
249   uu.ll = u;
250
251   bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
252   if (bm <= 0)
253     {
254       w.s.high = 0;
255       w.s.low = (UWtype) uu.s.high >> -bm;
256     }
257   else
258     {
259       UWtype carries = (UWtype) uu.s.high << bm;
260
261       w.s.high = (UWtype) uu.s.high >> b;
262       w.s.low = ((UWtype) uu.s.low >> b) | carries;
263     }
264
265   return w.ll;
266 }
267 #endif
268
269 #ifdef L_ashldi3
270 DWtype
271 __ashldi3 (DWtype u, word_type b)
272 {
273   DWunion w;
274   word_type bm;
275   DWunion uu;
276
277   if (b == 0)
278     return u;
279
280   uu.ll = u;
281
282   bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
283   if (bm <= 0)
284     {
285       w.s.low = 0;
286       w.s.high = (UWtype) uu.s.low << -bm;
287     }
288   else
289     {
290       UWtype carries = (UWtype) uu.s.low >> bm;
291
292       w.s.low = (UWtype) uu.s.low << b;
293       w.s.high = ((UWtype) uu.s.high << b) | carries;
294     }
295
296   return w.ll;
297 }
298 #endif
299
300 #ifdef L_ashrdi3
301 DWtype
302 __ashrdi3 (DWtype u, word_type b)
303 {
304   DWunion w;
305   word_type bm;
306   DWunion uu;
307
308   if (b == 0)
309     return u;
310
311   uu.ll = u;
312
313   bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
314   if (bm <= 0)
315     {
316       /* w.s.high = 1..1 or 0..0 */
317       w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1);
318       w.s.low = uu.s.high >> -bm;
319     }
320   else
321     {
322       UWtype carries = (UWtype) uu.s.high << bm;
323
324       w.s.high = uu.s.high >> b;
325       w.s.low = ((UWtype) uu.s.low >> b) | carries;
326     }
327
328   return w.ll;
329 }
330 #endif
331 \f
332 #ifdef L_ffsdi2
333 DWtype
334 __ffsdi2 (DWtype u)
335 {
336   DWunion uu;
337   UWtype word, count, add;
338
339   uu.ll = u;
340   if (uu.s.low != 0)
341     word = uu.s.low, add = 0;
342   else if (uu.s.high != 0)
343     word = uu.s.high, add = BITS_PER_UNIT * sizeof (Wtype);
344   else
345     return 0;
346
347   count_trailing_zeros (count, word);
348   return count + add + 1;
349 }
350 #endif
351 \f
352 #ifdef L_muldi3
353 DWtype
354 __muldi3 (DWtype u, DWtype v)
355 {
356   DWunion w;
357   DWunion uu, vv;
358
359   uu.ll = u,
360   vv.ll = v;
361
362   w.ll = __umulsidi3 (uu.s.low, vv.s.low);
363   w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
364                + (UWtype) uu.s.high * (UWtype) vv.s.low);
365
366   return w.ll;
367 }
368 #endif
369 \f
370 #ifdef L_udiv_w_sdiv
371 #if defined (sdiv_qrnnd)
372 UWtype
373 __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
374 {
375   UWtype q, r;
376   UWtype c0, c1, b1;
377
378   if ((Wtype) d >= 0)
379     {
380       if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
381         {
382           /* dividend, divisor, and quotient are nonnegative */
383           sdiv_qrnnd (q, r, a1, a0, d);
384         }
385       else
386         {
387           /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
388           sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
389           /* Divide (c1*2^32 + c0) by d */
390           sdiv_qrnnd (q, r, c1, c0, d);
391           /* Add 2^31 to quotient */
392           q += (UWtype) 1 << (W_TYPE_SIZE - 1);
393         }
394     }
395   else
396     {
397       b1 = d >> 1;                      /* d/2, between 2^30 and 2^31 - 1 */
398       c1 = a1 >> 1;                     /* A/2 */
399       c0 = (a1 << (W_TYPE_SIZE - 1)) + (a0 >> 1);
400
401       if (a1 < b1)                      /* A < 2^32*b1, so A/2 < 2^31*b1 */
402         {
403           sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
404
405           r = 2*r + (a0 & 1);           /* Remainder from A/(2*b1) */
406           if ((d & 1) != 0)
407             {
408               if (r >= q)
409                 r = r - q;
410               else if (q - r <= d)
411                 {
412                   r = r - q + d;
413                   q--;
414                 }
415               else
416                 {
417                   r = r - q + 2*d;
418                   q -= 2;
419                 }
420             }
421         }
422       else if (c1 < b1)                 /* So 2^31 <= (A/2)/b1 < 2^32 */
423         {
424           c1 = (b1 - 1) - c1;
425           c0 = ~c0;                     /* logical NOT */
426
427           sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
428
429           q = ~q;                       /* (A/2)/b1 */
430           r = (b1 - 1) - r;
431
432           r = 2*r + (a0 & 1);           /* A/(2*b1) */
433
434           if ((d & 1) != 0)
435             {
436               if (r >= q)
437                 r = r - q;
438               else if (q - r <= d)
439                 {
440                   r = r - q + d;
441                   q--;
442                 }
443               else
444                 {
445                   r = r - q + 2*d;
446                   q -= 2;
447                 }
448             }
449         }
450       else                              /* Implies c1 = b1 */
451         {                               /* Hence a1 = d - 1 = 2*b1 - 1 */
452           if (a0 >= -d)
453             {
454               q = -1;
455               r = a0 + d;
456             }
457           else
458             {
459               q = -2;
460               r = a0 + 2*d;
461             }
462         }
463     }
464
465   *rp = r;
466   return q;
467 }
468 #else
469 /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv.  */
470 UWtype
471 __udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
472                UWtype a1 __attribute__ ((__unused__)),
473                UWtype a0 __attribute__ ((__unused__)),
474                UWtype d __attribute__ ((__unused__)))
475 {
476   return 0;
477 }
478 #endif
479 #endif
480 \f
481 #if (defined (L_udivdi3) || defined (L_divdi3) || \
482      defined (L_umoddi3) || defined (L_moddi3))
483 #define L_udivmoddi4
484 #endif
485
486 #ifdef L_clz
487 const UQItype __clz_tab[] =
488 {
489   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,
490   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,
491   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,
492   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,
493   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,
494   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,
495   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,
496   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,
497 };
498 #endif
499
500 #ifdef L_udivmoddi4
501
502 #if (defined (L_udivdi3) || defined (L_divdi3) || \
503      defined (L_umoddi3) || defined (L_moddi3))
504 static inline
505 #endif
506 UDWtype
507 __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
508 {
509   DWunion ww;
510   DWunion nn, dd;
511   DWunion rr;
512   UWtype d0, d1, n0, n1, n2;
513   UWtype q0, q1;
514   UWtype b, bm;
515
516   nn.ll = n;
517   dd.ll = d;
518
519   d0 = dd.s.low;
520   d1 = dd.s.high;
521   n0 = nn.s.low;
522   n1 = nn.s.high;
523
524 #if !UDIV_NEEDS_NORMALIZATION
525   if (d1 == 0)
526     {
527       if (d0 > n1)
528         {
529           /* 0q = nn / 0D */
530
531           udiv_qrnnd (q0, n0, n1, n0, d0);
532           q1 = 0;
533
534           /* Remainder in n0.  */
535         }
536       else
537         {
538           /* qq = NN / 0d */
539
540           if (d0 == 0)
541             d0 = 1 / d0;        /* Divide intentionally by zero.  */
542
543           udiv_qrnnd (q1, n1, 0, n1, d0);
544           udiv_qrnnd (q0, n0, n1, n0, d0);
545
546           /* Remainder in n0.  */
547         }
548
549       if (rp != 0)
550         {
551           rr.s.low = n0;
552           rr.s.high = 0;
553           *rp = rr.ll;
554         }
555     }
556
557 #else /* UDIV_NEEDS_NORMALIZATION */
558
559   if (d1 == 0)
560     {
561       if (d0 > n1)
562         {
563           /* 0q = nn / 0D */
564
565           count_leading_zeros (bm, d0);
566
567           if (bm != 0)
568             {
569               /* Normalize, i.e. make the most significant bit of the
570                  denominator set.  */
571
572               d0 = d0 << bm;
573               n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
574               n0 = n0 << bm;
575             }
576
577           udiv_qrnnd (q0, n0, n1, n0, d0);
578           q1 = 0;
579
580           /* Remainder in n0 >> bm.  */
581         }
582       else
583         {
584           /* qq = NN / 0d */
585
586           if (d0 == 0)
587             d0 = 1 / d0;        /* Divide intentionally by zero.  */
588
589           count_leading_zeros (bm, d0);
590
591           if (bm == 0)
592             {
593               /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
594                  conclude (the most significant bit of n1 is set) /\ (the
595                  leading quotient digit q1 = 1).
596
597                  This special case is necessary, not an optimization.
598                  (Shifts counts of W_TYPE_SIZE are undefined.)  */
599
600               n1 -= d0;
601               q1 = 1;
602             }
603           else
604             {
605               /* Normalize.  */
606
607               b = W_TYPE_SIZE - bm;
608
609               d0 = d0 << bm;
610               n2 = n1 >> b;
611               n1 = (n1 << bm) | (n0 >> b);
612               n0 = n0 << bm;
613
614               udiv_qrnnd (q1, n1, n2, n1, d0);
615             }
616
617           /* n1 != d0...  */
618
619           udiv_qrnnd (q0, n0, n1, n0, d0);
620
621           /* Remainder in n0 >> bm.  */
622         }
623
624       if (rp != 0)
625         {
626           rr.s.low = n0 >> bm;
627           rr.s.high = 0;
628           *rp = rr.ll;
629         }
630     }
631 #endif /* UDIV_NEEDS_NORMALIZATION */
632
633   else
634     {
635       if (d1 > n1)
636         {
637           /* 00 = nn / DD */
638
639           q0 = 0;
640           q1 = 0;
641
642           /* Remainder in n1n0.  */
643           if (rp != 0)
644             {
645               rr.s.low = n0;
646               rr.s.high = n1;
647               *rp = rr.ll;
648             }
649         }
650       else
651         {
652           /* 0q = NN / dd */
653
654           count_leading_zeros (bm, d1);
655           if (bm == 0)
656             {
657               /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
658                  conclude (the most significant bit of n1 is set) /\ (the
659                  quotient digit q0 = 0 or 1).
660
661                  This special case is necessary, not an optimization.  */
662
663               /* The condition on the next line takes advantage of that
664                  n1 >= d1 (true due to program flow).  */
665               if (n1 > d1 || n0 >= d0)
666                 {
667                   q0 = 1;
668                   sub_ddmmss (n1, n0, n1, n0, d1, d0);
669                 }
670               else
671                 q0 = 0;
672
673               q1 = 0;
674
675               if (rp != 0)
676                 {
677                   rr.s.low = n0;
678                   rr.s.high = n1;
679                   *rp = rr.ll;
680                 }
681             }
682           else
683             {
684               UWtype m1, m0;
685               /* Normalize.  */
686
687               b = W_TYPE_SIZE - bm;
688
689               d1 = (d1 << bm) | (d0 >> b);
690               d0 = d0 << bm;
691               n2 = n1 >> b;
692               n1 = (n1 << bm) | (n0 >> b);
693               n0 = n0 << bm;
694
695               udiv_qrnnd (q0, n1, n2, n1, d1);
696               umul_ppmm (m1, m0, q0, d0);
697
698               if (m1 > n1 || (m1 == n1 && m0 > n0))
699                 {
700                   q0--;
701                   sub_ddmmss (m1, m0, m1, m0, d1, d0);
702                 }
703
704               q1 = 0;
705
706               /* Remainder in (n1n0 - m1m0) >> bm.  */
707               if (rp != 0)
708                 {
709                   sub_ddmmss (n1, n0, n1, n0, m1, m0);
710                   rr.s.low = (n1 << b) | (n0 >> bm);
711                   rr.s.high = n1 >> bm;
712                   *rp = rr.ll;
713                 }
714             }
715         }
716     }
717
718   ww.s.low = q0;
719   ww.s.high = q1;
720   return ww.ll;
721 }
722 #endif
723
724 #ifdef L_divdi3
725 DWtype
726 __divdi3 (DWtype u, DWtype v)
727 {
728   word_type c = 0;
729   DWunion uu, vv;
730   DWtype w;
731
732   uu.ll = u;
733   vv.ll = v;
734
735   if (uu.s.high < 0)
736     c = ~c,
737     uu.ll = __negdi2 (uu.ll);
738   if (vv.s.high < 0)
739     c = ~c,
740     vv.ll = __negdi2 (vv.ll);
741
742   w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
743   if (c)
744     w = __negdi2 (w);
745
746   return w;
747 }
748 #endif
749
750 #ifdef L_moddi3
751 DWtype
752 __moddi3 (DWtype u, DWtype v)
753 {
754   word_type c = 0;
755   DWunion uu, vv;
756   DWtype w;
757
758   uu.ll = u;
759   vv.ll = v;
760
761   if (uu.s.high < 0)
762     c = ~c,
763     uu.ll = __negdi2 (uu.ll);
764   if (vv.s.high < 0)
765     vv.ll = __negdi2 (vv.ll);
766
767   (void) __udivmoddi4 (uu.ll, vv.ll, &w);
768   if (c)
769     w = __negdi2 (w);
770
771   return w;
772 }
773 #endif
774
775 #ifdef L_umoddi3
776 UDWtype
777 __umoddi3 (UDWtype u, UDWtype v)
778 {
779   UDWtype w;
780
781   (void) __udivmoddi4 (u, v, &w);
782
783   return w;
784 }
785 #endif
786
787 #ifdef L_udivdi3
788 UDWtype
789 __udivdi3 (UDWtype n, UDWtype d)
790 {
791   return __udivmoddi4 (n, d, (UDWtype *) 0);
792 }
793 #endif
794 \f
795 #ifdef L_cmpdi2
796 word_type
797 __cmpdi2 (DWtype a, DWtype b)
798 {
799   DWunion au, bu;
800
801   au.ll = a, bu.ll = b;
802
803   if (au.s.high < bu.s.high)
804     return 0;
805   else if (au.s.high > bu.s.high)
806     return 2;
807   if ((UWtype) au.s.low < (UWtype) bu.s.low)
808     return 0;
809   else if ((UWtype) au.s.low > (UWtype) bu.s.low)
810     return 2;
811   return 1;
812 }
813 #endif
814
815 #ifdef L_ucmpdi2
816 word_type
817 __ucmpdi2 (DWtype a, DWtype b)
818 {
819   DWunion au, bu;
820
821   au.ll = a, bu.ll = b;
822
823   if ((UWtype) au.s.high < (UWtype) bu.s.high)
824     return 0;
825   else if ((UWtype) au.s.high > (UWtype) bu.s.high)
826     return 2;
827   if ((UWtype) au.s.low < (UWtype) bu.s.low)
828     return 0;
829   else if ((UWtype) au.s.low > (UWtype) bu.s.low)
830     return 2;
831   return 1;
832 }
833 #endif
834 \f
835 #if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
836 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
837 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
838
839 DWtype
840 __fixunstfDI (TFtype a)
841 {
842   TFtype b;
843   UDWtype v;
844
845   if (a < 0)
846     return 0;
847
848   /* Compute high word of result, as a flonum.  */
849   b = (a / HIGH_WORD_COEFF);
850   /* Convert that to fixed (but not to DWtype!),
851      and shift it into the high word.  */
852   v = (UWtype) b;
853   v <<= WORD_SIZE;
854   /* Remove high part from the TFtype, leaving the low part as flonum.  */
855   a -= (TFtype)v;
856   /* Convert that to fixed (but not to DWtype!) and add it in.
857      Sometimes A comes out negative.  This is significant, since
858      A has more bits than a long int does.  */
859   if (a < 0)
860     v -= (UWtype) (- a);
861   else
862     v += (UWtype) a;
863   return v;
864 }
865 #endif
866
867 #if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
868 DWtype
869 __fixtfdi (TFtype a)
870 {
871   if (a < 0)
872     return - __fixunstfDI (-a);
873   return __fixunstfDI (a);
874 }
875 #endif
876
877 #if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
878 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
879 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
880
881 DWtype
882 __fixunsxfDI (XFtype a)
883 {
884   XFtype b;
885   UDWtype v;
886
887   if (a < 0)
888     return 0;
889
890   /* Compute high word of result, as a flonum.  */
891   b = (a / HIGH_WORD_COEFF);
892   /* Convert that to fixed (but not to DWtype!),
893      and shift it into the high word.  */
894   v = (UWtype) b;
895   v <<= WORD_SIZE;
896   /* Remove high part from the XFtype, leaving the low part as flonum.  */
897   a -= (XFtype)v;
898   /* Convert that to fixed (but not to DWtype!) and add it in.
899      Sometimes A comes out negative.  This is significant, since
900      A has more bits than a long int does.  */
901   if (a < 0)
902     v -= (UWtype) (- a);
903   else
904     v += (UWtype) a;
905   return v;
906 }
907 #endif
908
909 #if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
910 DWtype
911 __fixxfdi (XFtype a)
912 {
913   if (a < 0)
914     return - __fixunsxfDI (-a);
915   return __fixunsxfDI (a);
916 }
917 #endif
918
919 #ifdef L_fixunsdfdi
920 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
921 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
922
923 DWtype
924 __fixunsdfDI (DFtype a)
925 {
926   DFtype b;
927   UDWtype v;
928
929   if (a < 0)
930     return 0;
931
932   /* Compute high word of result, as a flonum.  */
933   b = (a / HIGH_WORD_COEFF);
934   /* Convert that to fixed (but not to DWtype!),
935      and shift it into the high word.  */
936   v = (UWtype) b;
937   v <<= WORD_SIZE;
938   /* Remove high part from the DFtype, leaving the low part as flonum.  */
939   a -= (DFtype)v;
940   /* Convert that to fixed (but not to DWtype!) and add it in.
941      Sometimes A comes out negative.  This is significant, since
942      A has more bits than a long int does.  */
943   if (a < 0)
944     v -= (UWtype) (- a);
945   else
946     v += (UWtype) a;
947   return v;
948 }
949 #endif
950
951 #ifdef L_fixdfdi
952 DWtype
953 __fixdfdi (DFtype a)
954 {
955   if (a < 0)
956     return - __fixunsdfDI (-a);
957   return __fixunsdfDI (a);
958 }
959 #endif
960
961 #ifdef L_fixunssfdi
962 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
963 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
964
965 DWtype
966 __fixunssfDI (SFtype original_a)
967 {
968   /* Convert the SFtype to a DFtype, because that is surely not going
969      to lose any bits.  Some day someone else can write a faster version
970      that avoids converting to DFtype, and verify it really works right.  */
971   DFtype a = original_a;
972   DFtype b;
973   UDWtype v;
974
975   if (a < 0)
976     return 0;
977
978   /* Compute high word of result, as a flonum.  */
979   b = (a / HIGH_WORD_COEFF);
980   /* Convert that to fixed (but not to DWtype!),
981      and shift it into the high word.  */
982   v = (UWtype) b;
983   v <<= WORD_SIZE;
984   /* Remove high part from the DFtype, leaving the low part as flonum.  */
985   a -= (DFtype) v;
986   /* Convert that to fixed (but not to DWtype!) and add it in.
987      Sometimes A comes out negative.  This is significant, since
988      A has more bits than a long int does.  */
989   if (a < 0)
990     v -= (UWtype) (- a);
991   else
992     v += (UWtype) a;
993   return v;
994 }
995 #endif
996
997 #ifdef L_fixsfdi
998 DWtype
999 __fixsfdi (SFtype a)
1000 {
1001   if (a < 0)
1002     return - __fixunssfDI (-a);
1003   return __fixunssfDI (a);
1004 }
1005 #endif
1006
1007 #if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
1008 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1009 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1010 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1011
1012 XFtype
1013 __floatdixf (DWtype u)
1014 {
1015   XFtype d;
1016
1017   d = (Wtype) (u >> WORD_SIZE);
1018   d *= HIGH_HALFWORD_COEFF;
1019   d *= HIGH_HALFWORD_COEFF;
1020   d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1021
1022   return d;
1023 }
1024 #endif
1025
1026 #if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
1027 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1028 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1029 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1030
1031 TFtype
1032 __floatditf (DWtype u)
1033 {
1034   TFtype d;
1035
1036   d = (Wtype) (u >> WORD_SIZE);
1037   d *= HIGH_HALFWORD_COEFF;
1038   d *= HIGH_HALFWORD_COEFF;
1039   d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1040
1041   return d;
1042 }
1043 #endif
1044
1045 #ifdef L_floatdidf
1046 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1047 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1048 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1049
1050 DFtype
1051 __floatdidf (DWtype u)
1052 {
1053   DFtype d;
1054
1055   d = (Wtype) (u >> WORD_SIZE);
1056   d *= HIGH_HALFWORD_COEFF;
1057   d *= HIGH_HALFWORD_COEFF;
1058   d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1059
1060   return d;
1061 }
1062 #endif
1063
1064 #ifdef L_floatdisf
1065 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1066 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1067 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1068 #define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
1069
1070 /* Define codes for all the float formats that we know of.  Note
1071    that this is copied from real.h.  */
1072
1073 #define UNKNOWN_FLOAT_FORMAT 0
1074 #define IEEE_FLOAT_FORMAT 1
1075 #define VAX_FLOAT_FORMAT 2
1076 #define IBM_FLOAT_FORMAT 3
1077
1078 /* Default to IEEE float if not specified.  Nearly all machines use it.  */
1079 #ifndef HOST_FLOAT_FORMAT
1080 #define HOST_FLOAT_FORMAT       IEEE_FLOAT_FORMAT
1081 #endif
1082
1083 #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
1084 #define DF_SIZE 53
1085 #define SF_SIZE 24
1086 #endif
1087
1088 #if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
1089 #define DF_SIZE 56
1090 #define SF_SIZE 24
1091 #endif
1092
1093 #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
1094 #define DF_SIZE 56
1095 #define SF_SIZE 24
1096 #endif
1097
1098 SFtype
1099 __floatdisf (DWtype u)
1100 {
1101   /* Do the calculation in DFmode
1102      so that we don't lose any of the precision of the high word
1103      while multiplying it.  */
1104   DFtype f;
1105
1106   /* Protect against double-rounding error.
1107      Represent any low-order bits, that might be truncated in DFmode,
1108      by a bit that won't be lost.  The bit can go in anywhere below the
1109      rounding position of the SFmode.  A fixed mask and bit position
1110      handles all usual configurations.  It doesn't handle the case
1111      of 128-bit DImode, however.  */
1112   if (DF_SIZE < DI_SIZE
1113       && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1114     {
1115 #define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
1116       if (! (- ((DWtype) 1 << DF_SIZE) < u
1117              && u < ((DWtype) 1 << DF_SIZE)))
1118         {
1119           if ((UDWtype) u & (REP_BIT - 1))
1120             u |= REP_BIT;
1121         }
1122     }
1123   f = (Wtype) (u >> WORD_SIZE);
1124   f *= HIGH_HALFWORD_COEFF;
1125   f *= HIGH_HALFWORD_COEFF;
1126   f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1127
1128   return (SFtype) f;
1129 }
1130 #endif
1131
1132 #if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
1133 /* Reenable the normal types, in case limits.h needs them.  */
1134 #undef char
1135 #undef short
1136 #undef int
1137 #undef long
1138 #undef unsigned
1139 #undef float
1140 #undef double
1141 #undef MIN
1142 #undef MAX
1143 #include <limits.h>
1144
1145 UWtype
1146 __fixunsxfSI (XFtype a)
1147 {
1148   if (a >= - (DFtype) Wtype_MIN)
1149     return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1150   return (Wtype) a;
1151 }
1152 #endif
1153
1154 #ifdef L_fixunsdfsi
1155 /* Reenable the normal types, in case limits.h needs them.  */
1156 #undef char
1157 #undef short
1158 #undef int
1159 #undef long
1160 #undef unsigned
1161 #undef float
1162 #undef double
1163 #undef MIN
1164 #undef MAX
1165 #include <limits.h>
1166
1167 UWtype
1168 __fixunsdfSI (DFtype a)
1169 {
1170   if (a >= - (DFtype) Wtype_MIN)
1171     return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1172   return (Wtype) a;
1173 }
1174 #endif
1175
1176 #ifdef L_fixunssfsi
1177 /* Reenable the normal types, in case limits.h needs them.  */
1178 #undef char
1179 #undef short
1180 #undef int
1181 #undef long
1182 #undef unsigned
1183 #undef float
1184 #undef double
1185 #undef MIN
1186 #undef MAX
1187 #include <limits.h>
1188
1189 UWtype
1190 __fixunssfSI (SFtype a)
1191 {
1192   if (a >= - (SFtype) Wtype_MIN)
1193     return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1194   return (Wtype) a;
1195 }
1196 #endif
1197 \f
1198 /* From here on down, the routines use normal data types.  */
1199
1200 #define SItype bogus_type
1201 #define USItype bogus_type
1202 #define DItype bogus_type
1203 #define UDItype bogus_type
1204 #define SFtype bogus_type
1205 #define DFtype bogus_type
1206 #undef Wtype
1207 #undef UWtype
1208 #undef HWtype
1209 #undef UHWtype
1210 #undef DWtype
1211 #undef UDWtype
1212
1213 #undef char
1214 #undef short
1215 #undef int
1216 #undef long
1217 #undef unsigned
1218 #undef float
1219 #undef double
1220 \f
1221 #ifdef L__gcc_bcmp
1222
1223 /* Like bcmp except the sign is meaningful.
1224    Result is negative if S1 is less than S2,
1225    positive if S1 is greater, 0 if S1 and S2 are equal.  */
1226
1227 int
1228 __gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
1229 {
1230   while (size > 0)
1231     {
1232       unsigned char c1 = *s1++, c2 = *s2++;
1233       if (c1 != c2)
1234         return c1 - c2;
1235       size--;
1236     }
1237   return 0;
1238 }
1239
1240 #endif
1241 \f
1242 /* __eprintf used to be used by GCC's private version of <assert.h>.
1243    We no longer provide that header, but this routine remains in libgcc.a
1244    for binary backward compatibility.  Note that it is not included in
1245    the shared version of libgcc.  */
1246 #ifdef L_eprintf
1247 #ifndef inhibit_libc
1248
1249 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1250 #include <stdio.h>
1251
1252 void
1253 __eprintf (const char *string, const char *expression,
1254            unsigned int line, const char *filename)
1255 {
1256   fprintf (stderr, string, expression, line, filename);
1257   fflush (stderr);
1258   abort ();
1259 }
1260
1261 #endif
1262 #endif
1263
1264 #ifdef L_bb
1265
1266 #if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
1267 typedef long gcov_type;
1268 #else
1269 typedef long long gcov_type;
1270 #endif
1271
1272
1273 /* Structure emitted by -a  */
1274 struct bb
1275 {
1276   long zero_word;
1277   const char *filename;
1278   gcov_type *counts;
1279   long ncounts;
1280   struct bb *next;
1281   const unsigned long *addresses;
1282
1283   /* Older GCC's did not emit these fields.  */
1284   long nwords;
1285   const char **functions;
1286   const long *line_nums;
1287   const char **filenames;
1288   char *flags;
1289 };
1290
1291 #ifdef BLOCK_PROFILER_CODE
1292 BLOCK_PROFILER_CODE
1293 #else
1294 #ifndef inhibit_libc
1295
1296 /* Simple minded basic block profiling output dumper for
1297    systems that don't provide tcov support.  At present,
1298    it requires atexit and stdio.  */
1299
1300 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1301 #include <stdio.h>
1302 char *ctime PARAMS ((const time_t *));
1303
1304 #include "gbl-ctors.h"
1305 #include "gcov-io.h"
1306 #include <string.h>
1307 #ifdef TARGET_HAS_F_SETLKW
1308 #include <fcntl.h>
1309 #include <errno.h>
1310 #endif
1311
1312 static struct bb *bb_head;
1313
1314 static int num_digits (long long value, int base) __attribute__ ((const));
1315
1316 /* Return the number of digits needed to print a value */
1317 /* __inline__ */ static int num_digits (long long value, int base)
1318 {
1319   int minus = (value < 0 && base != 16);
1320   unsigned long long v = (minus) ? -value : value;
1321   int ret = minus;
1322
1323   do
1324     {
1325       v /= base;
1326       ret++;
1327     }
1328   while (v);
1329
1330   return ret;
1331 }
1332
1333 void
1334 __bb_exit_func (void)
1335 {
1336   FILE *da_file, *file;
1337   long time_value;
1338   int i;
1339
1340   if (bb_head == 0)
1341     return;
1342
1343   i = strlen (bb_head->filename) - 3;
1344
1345   if (!strcmp (bb_head->filename+i, ".da"))
1346     {
1347       /* Must be -fprofile-arcs not -a.
1348          Dump data in a form that gcov expects.  */
1349
1350       struct bb *ptr;
1351
1352       for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1353         {
1354           int firstchar;
1355
1356           /* Make sure the output file exists -
1357              but don't clobber exiting data.  */
1358           if ((da_file = fopen (ptr->filename, "a")) != 0)
1359             fclose (da_file);
1360
1361           /* Need to re-open in order to be able to write from the start.  */
1362           da_file = fopen (ptr->filename, "r+b");
1363           /* Some old systems might not allow the 'b' mode modifier.
1364              Therefore, try to open without it.  This can lead to a race
1365              condition so that when you delete and re-create the file, the
1366              file might be opened in text mode, but then, you shouldn't
1367              delete the file in the first place.  */
1368           if (da_file == 0)
1369             da_file = fopen (ptr->filename, "r+");
1370           if (da_file == 0)
1371             {
1372               fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1373                        ptr->filename);
1374               continue;
1375             }
1376
1377           /* After a fork, another process might try to read and/or write
1378              the same file simultanously.  So if we can, lock the file to
1379              avoid race conditions.  */
1380 #if defined (TARGET_HAS_F_SETLKW)
1381           {
1382             struct flock s_flock;
1383
1384             s_flock.l_type = F_WRLCK;
1385             s_flock.l_whence = SEEK_SET;
1386             s_flock.l_start = 0;
1387             s_flock.l_len = 1;
1388             s_flock.l_pid = getpid ();
1389
1390             while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
1391                    && errno == EINTR);
1392           }
1393 #endif
1394
1395           /* If the file is not empty, and the number of counts in it is the
1396              same, then merge them in.  */
1397           firstchar = fgetc (da_file);
1398           if (firstchar == EOF)
1399             {
1400               if (ferror (da_file))
1401                 {
1402                   fprintf (stderr, "arc profiling: Can't read output file ");
1403                   perror (ptr->filename);
1404                 }
1405             }
1406           else
1407             {
1408               long n_counts = 0;
1409
1410               if (ungetc (firstchar, da_file) == EOF)
1411                 rewind (da_file);
1412               if (__read_long (&n_counts, da_file, 8) != 0)
1413                 {
1414                   fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1415                            ptr->filename);
1416                   continue;
1417                 }
1418
1419               if (n_counts == ptr->ncounts)
1420                 {
1421                   int i;
1422
1423                   for (i = 0; i < n_counts; i++)
1424                     {
1425                       gcov_type v = 0;
1426
1427                       if (__read_gcov_type (&v, da_file, 8) != 0)
1428                         {
1429                           fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1430                                    ptr->filename);
1431                           break;
1432                         }
1433                       ptr->counts[i] += v;
1434                     }
1435                 }
1436
1437             }
1438
1439           rewind (da_file);
1440
1441           /* ??? Should first write a header to the file.  Preferably, a 4 byte
1442              magic number, 4 bytes containing the time the program was
1443              compiled, 4 bytes containing the last modification time of the
1444              source file, and 4 bytes indicating the compiler options used.
1445
1446              That way we can easily verify that the proper source/executable/
1447              data file combination is being used from gcov.  */
1448
1449           if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0)
1450             {
1451
1452               fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1453                        ptr->filename);
1454             }
1455           else
1456             {
1457               int j;
1458               gcov_type *count_ptr = ptr->counts;
1459               int ret = 0;
1460               for (j = ptr->ncounts; j > 0; j--)
1461                 {
1462                   if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
1463                     {
1464                       ret=1;
1465                       break;
1466                     }
1467                   count_ptr++;
1468                 }
1469               if (ret)
1470                 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1471                          ptr->filename);
1472             }
1473
1474           if (fclose (da_file) == EOF)
1475             fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1476                      ptr->filename);
1477         }
1478
1479       return;
1480     }
1481
1482   /* Must be basic block profiling.  Emit a human readable output file.  */
1483
1484   file = fopen ("bb.out", "a");
1485
1486   if (!file)
1487     perror ("bb.out");
1488
1489   else
1490     {
1491       struct bb *ptr;
1492
1493       /* This is somewhat type incorrect, but it avoids worrying about
1494          exactly where time.h is included from.  It should be ok unless
1495          a void * differs from other pointer formats, or if sizeof (long)
1496          is < sizeof (time_t).  It would be nice if we could assume the
1497          use of rationale standards here.  */
1498
1499       time ((void *) &time_value);
1500       fprintf (file, "Basic block profiling finished on %s\n",
1501                ctime ((void *) &time_value));
1502
1503       /* We check the length field explicitly in order to allow compatibility
1504          with older GCC's which did not provide it.  */
1505
1506       for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1507         {
1508           int i;
1509           int func_p    = (ptr->nwords >= (long) sizeof (struct bb)
1510                            && ptr->nwords <= 1000
1511                            && ptr->functions);
1512           int line_p    = (func_p && ptr->line_nums);
1513           int file_p    = (func_p && ptr->filenames);
1514           int addr_p    = (ptr->addresses != 0);
1515           long ncounts  = ptr->ncounts;
1516           gcov_type cnt_max  = 0;
1517           long line_max = 0;
1518           long addr_max = 0;
1519           int file_len  = 0;
1520           int func_len  = 0;
1521           int blk_len   = num_digits (ncounts, 10);
1522           int cnt_len;
1523           int line_len;
1524           int addr_len;
1525
1526           fprintf (file, "File %s, %ld basic blocks \n\n",
1527                    ptr->filename, ncounts);
1528
1529           /* Get max values for each field.  */
1530           for (i = 0; i < ncounts; i++)
1531             {
1532               const char *p;
1533               int len;
1534
1535               if (cnt_max < ptr->counts[i])
1536                 cnt_max = ptr->counts[i];
1537
1538               if (addr_p && (unsigned long) addr_max < ptr->addresses[i])
1539                 addr_max = ptr->addresses[i];
1540
1541               if (line_p && line_max < ptr->line_nums[i])
1542                 line_max = ptr->line_nums[i];
1543
1544               if (func_p)
1545                 {
1546                   p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1547                   len = strlen (p);
1548                   if (func_len < len)
1549                     func_len = len;
1550                 }
1551
1552               if (file_p)
1553                 {
1554                   p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1555                   len = strlen (p);
1556                   if (file_len < len)
1557                     file_len = len;
1558                 }
1559             }
1560
1561           addr_len = num_digits (addr_max, 16);
1562           cnt_len  = num_digits (cnt_max, 10);
1563           line_len = num_digits (line_max, 10);
1564
1565           /* Now print out the basic block information.  */
1566           for (i = 0; i < ncounts; i++)
1567             {
1568 #if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
1569               fprintf (file,
1570                        "    Block #%*d: executed %*ld time(s)",
1571                        blk_len, i+1,
1572                        cnt_len, ptr->counts[i]);
1573 #else
1574               fprintf (file,
1575                        "    Block #%*d: executed %*lld time(s)",
1576                        blk_len, i+1,
1577                        cnt_len, ptr->counts[i]);
1578 #endif
1579
1580               if (addr_p)
1581                 fprintf (file, " address= 0x%.*lx", addr_len,
1582                          ptr->addresses[i]);
1583
1584               if (func_p)
1585                 fprintf (file, " function= %-*s", func_len,
1586                          (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1587
1588               if (line_p)
1589                 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1590
1591               if (file_p)
1592                 fprintf (file, " file= %s",
1593                          (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1594
1595               fprintf (file, "\n");
1596             }
1597
1598           fprintf (file, "\n");
1599           fflush (file);
1600         }
1601
1602       fprintf (file, "\n\n");
1603       fclose (file);
1604     }
1605 }
1606
1607 void
1608 __bb_init_func (struct bb *blocks)
1609 {
1610   /* User is supposed to check whether the first word is non-0,
1611      but just in case....  */
1612
1613   if (blocks->zero_word)
1614     return;
1615
1616   /* Initialize destructor.  */
1617   if (!bb_head)
1618     atexit (__bb_exit_func);
1619
1620   /* Set up linked list.  */
1621   blocks->zero_word = 1;
1622   blocks->next = bb_head;
1623   bb_head = blocks;
1624 }
1625
1626 /* Called before fork or exec - write out profile information gathered so
1627    far and reset it to zero.  This avoids duplication or loss of the
1628    profile information gathered so far.  */
1629 void
1630 __bb_fork_func (void)
1631 {
1632   struct bb *ptr;
1633
1634   __bb_exit_func ();
1635   for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1636     {
1637       long i;
1638       for (i = ptr->ncounts - 1; i >= 0; i--)
1639         ptr->counts[i] = 0;
1640     }
1641 }
1642
1643 #ifndef MACHINE_STATE_SAVE
1644 #define MACHINE_STATE_SAVE(ID)
1645 #endif
1646 #ifndef MACHINE_STATE_RESTORE
1647 #define MACHINE_STATE_RESTORE(ID)
1648 #endif
1649
1650 /* Number of buckets in hashtable of basic block addresses.  */
1651
1652 #define BB_BUCKETS 311
1653
1654 /* Maximum length of string in file bb.in.  */
1655
1656 #define BBINBUFSIZE 500
1657
1658 struct bb_edge
1659 {
1660   struct bb_edge *next;
1661   unsigned long src_addr;
1662   unsigned long dst_addr;
1663   unsigned long count;
1664 };
1665
1666 enum bb_func_mode
1667 {
1668   TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1669 };
1670
1671 struct bb_func
1672 {
1673   struct bb_func *next;
1674   char *funcname;
1675   char *filename;
1676   enum bb_func_mode mode;
1677 };
1678
1679 /* This is the connection to the outside world.
1680    The BLOCK_PROFILER macro must set __bb.blocks
1681    and __bb.blockno.  */
1682
1683 struct {
1684   unsigned long blockno;
1685   struct bb *blocks;
1686 } __bb;
1687
1688 /* Vars to store addrs of source and destination basic blocks
1689    of a jump.  */
1690
1691 static unsigned long bb_src = 0;
1692 static unsigned long bb_dst = 0;
1693
1694 static FILE *bb_tracefile = (FILE *) 0;
1695 static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1696 static struct bb_func *bb_func_head = (struct bb_func *) 0;
1697 static unsigned long bb_callcount = 0;
1698 static int bb_mode = 0;
1699
1700 static unsigned long *bb_stack = (unsigned long *) 0;
1701 static size_t bb_stacksize = 0;
1702
1703 static int reported = 0;
1704
1705 /* Trace modes:
1706 Always             :   Print execution frequencies of basic blocks
1707                        to file bb.out.
1708 bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
1709 bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
1710 bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
1711 bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
1712 */
1713
1714 #ifdef HAVE_POPEN
1715
1716 /*#include <sys/types.h>*/
1717 #include <sys/stat.h>
1718 /*#include <malloc.h>*/
1719
1720 /* Commands executed by gopen.  */
1721
1722 #define GOPENDECOMPRESS "gzip -cd "
1723 #define GOPENCOMPRESS "gzip -c >"
1724
1725 /* Like fopen but pipes through gzip.  mode may only be "r" or "w".
1726    If it does not compile, simply replace gopen by fopen and delete
1727    '.gz' from any first parameter to gopen.  */
1728
1729 static FILE *
1730 gopen (char *fn, char *mode)
1731 {
1732   int use_gzip;
1733   char *p;
1734
1735   if (mode[1])
1736     return (FILE *) 0;
1737
1738   if (mode[0] != 'r' && mode[0] != 'w')
1739     return (FILE *) 0;
1740
1741   p = fn + strlen (fn)-1;
1742   use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
1743               || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1744
1745   if (use_gzip)
1746     {
1747       if (mode[0]=='r')
1748         {
1749           FILE *f;
1750           char *s = (char *) malloc (sizeof (char) * strlen (fn)
1751                                      + sizeof (GOPENDECOMPRESS));
1752           strcpy (s, GOPENDECOMPRESS);
1753           strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1754           f = popen (s, mode);
1755           free (s);
1756           return f;
1757         }
1758
1759       else
1760         {
1761           FILE *f;
1762           char *s = (char *) malloc (sizeof (char) * strlen (fn)
1763                                      + sizeof (GOPENCOMPRESS));
1764           strcpy (s, GOPENCOMPRESS);
1765           strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1766           if (!(f = popen (s, mode)))
1767             f = fopen (s, mode);
1768           free (s);
1769           return f;
1770         }
1771     }
1772
1773   else
1774     return fopen (fn, mode);
1775 }
1776
1777 static int
1778 gclose (FILE *f)
1779 {
1780   struct stat buf;
1781
1782   if (f != 0)
1783     {
1784       if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1785         return pclose (f);
1786
1787       return fclose (f);
1788     }
1789   return 0;
1790 }
1791
1792 #endif /* HAVE_POPEN */
1793
1794 /* Called once per program.  */
1795
1796 static void
1797 __bb_exit_trace_func (void)
1798 {
1799   FILE *file = fopen ("bb.out", "a");
1800   struct bb_func *f;
1801   struct bb *b;
1802
1803   if (!file)
1804     perror ("bb.out");
1805
1806   if (bb_mode & 1)
1807     {
1808       if (!bb_tracefile)
1809         perror ("bbtrace");
1810       else
1811 #ifdef HAVE_POPEN
1812         gclose (bb_tracefile);
1813 #else
1814         fclose (bb_tracefile);
1815 #endif /* HAVE_POPEN */
1816     }
1817
1818   /* Check functions in `bb.in'.  */
1819
1820   if (file)
1821     {
1822       long time_value;
1823       const struct bb_func *p;
1824       int printed_something = 0;
1825       struct bb *ptr;
1826       long blk;
1827
1828       /* This is somewhat type incorrect.  */
1829       time ((void *) &time_value);
1830
1831       for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
1832         {
1833           for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1834             {
1835               if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
1836                 continue;
1837               for (blk = 0; blk < ptr->ncounts; blk++)
1838                 {
1839                   if (!strcmp (p->funcname, ptr->functions[blk]))
1840                     goto found;
1841                 }
1842             }
1843
1844           if (!printed_something)
1845             {
1846               fprintf (file,
1847       "Functions in `bb.in' not executed during basic block profiling on %s\n",
1848                        ctime ((void *) &time_value));
1849               printed_something = 1;
1850             }
1851
1852           fprintf (file, "\tFunction %s", p->funcname);
1853           if (p->filename)
1854               fprintf (file, " of file %s", p->filename);
1855           fprintf (file, "\n" );
1856
1857 found:        ;
1858         }
1859
1860       if (printed_something)
1861        fprintf (file, "\n");
1862
1863     }
1864
1865   if (bb_mode & 2)
1866     {
1867       if (!bb_hashbuckets)
1868         {
1869           if (!reported)
1870             {
1871               fprintf (stderr, "Profiler: out of memory\n");
1872               reported = 1;
1873             }
1874           return;
1875         }
1876
1877       else if (file)
1878         {
1879           long time_value;
1880           int i;
1881           unsigned long addr_max = 0;
1882           unsigned long cnt_max  = 0;
1883           int cnt_len;
1884           int addr_len;
1885
1886           /* This is somewhat type incorrect, but it avoids worrying about
1887              exactly where time.h is included from.  It should be ok unless
1888              a void * differs from other pointer formats, or if sizeof (long)
1889              is < sizeof (time_t).  It would be nice if we could assume the
1890              use of rationale standards here.  */
1891
1892           time ((void *) &time_value);
1893           fprintf (file, "Basic block jump tracing");
1894
1895           switch (bb_mode & 12)
1896             {
1897               case 0:
1898                 fprintf (file, " (with call)");
1899               break;
1900
1901               case 4:
1902                 /* Print nothing.  */
1903               break;
1904
1905               case 8:
1906                 fprintf (file, " (with call & ret)");
1907               break;
1908
1909               case 12:
1910                 fprintf (file, " (with ret)");
1911               break;
1912             }
1913
1914           fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1915
1916           for (i = 0; i < BB_BUCKETS; i++)
1917             {
1918                struct bb_edge *bucket = bb_hashbuckets[i];
1919                for ( ; bucket; bucket = bucket->next )
1920                  {
1921                    if (addr_max < bucket->src_addr)
1922                      addr_max = bucket->src_addr;
1923                    if (addr_max < bucket->dst_addr)
1924                      addr_max = bucket->dst_addr;
1925                    if (cnt_max < bucket->count)
1926                      cnt_max = bucket->count;
1927                  }
1928             }
1929           addr_len = num_digits (addr_max, 16);
1930           cnt_len  = num_digits (cnt_max, 10);
1931
1932           for ( i = 0; i < BB_BUCKETS; i++)
1933             {
1934                struct bb_edge *bucket = bb_hashbuckets[i];
1935                for ( ; bucket; bucket = bucket->next )
1936                  {
1937                    fprintf (file,
1938         "Jump from block 0x%.*lx to block 0x%.*lx executed %*lu time(s)\n",
1939                             addr_len, bucket->src_addr,
1940                             addr_len, bucket->dst_addr,
1941                             cnt_len, bucket->count);
1942                  }
1943             }
1944
1945           fprintf (file, "\n");
1946
1947         }
1948     }
1949
1950    if (file)
1951      fclose (file);
1952
1953    /* Free allocated memory.  */
1954
1955    f = bb_func_head;
1956    while (f)
1957      {
1958        struct bb_func *old = f;
1959
1960        f = f->next;
1961        if (old->funcname) free (old->funcname);
1962        if (old->filename) free (old->filename);
1963        free (old);
1964      }
1965
1966    if (bb_stack)
1967      free (bb_stack);
1968
1969    if (bb_hashbuckets)
1970      {
1971        int i;
1972
1973        for (i = 0; i < BB_BUCKETS; i++)
1974          {
1975            struct bb_edge *old, *bucket = bb_hashbuckets[i];
1976
1977            while (bucket)
1978              {
1979                old = bucket;
1980                bucket = bucket->next;
1981                free (old);
1982              }
1983          }
1984        free (bb_hashbuckets);
1985      }
1986
1987    for (b = bb_head; b; b = b->next)
1988      if (b->flags) free (b->flags);
1989 }
1990
1991 /* Called once per program.  */
1992
1993 static void
1994 __bb_init_prg (void)
1995 {
1996   FILE *file;
1997   char buf[BBINBUFSIZE];
1998   const char *p;
1999   const char *pos;
2000   enum bb_func_mode m;
2001   int i;
2002
2003   /* Initialize destructor.  */
2004   atexit (__bb_exit_func);
2005
2006   if (!(file = fopen ("bb.in", "r")))
2007     return;
2008
2009   while(fgets (buf, BBINBUFSIZE, file) != 0)
2010     {
2011       i = strlen (buf);
2012       if (buf[i] == '\n')
2013         buf[i--] = '\0';
2014
2015       p = buf;
2016       if (*p == '-')
2017         {
2018           m = TRACE_OFF;
2019           p++;
2020         }
2021       else
2022         {
2023           m = TRACE_ON;
2024         }
2025       if (!strcmp (p, "__bb_trace__"))
2026         bb_mode |= 1;
2027       else if (!strcmp (p, "__bb_jumps__"))
2028         bb_mode |= 2;
2029       else if (!strcmp (p, "__bb_hidecall__"))
2030         bb_mode |= 4;
2031       else if (!strcmp (p, "__bb_showret__"))
2032         bb_mode |= 8;
2033       else
2034         {
2035           struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
2036           if (f)
2037             {
2038               unsigned long l;
2039               f->next = bb_func_head;
2040               if ((pos = strchr (p, ':')))
2041                 {
2042                   if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
2043                     continue;
2044                   strcpy (f->funcname, pos+1);
2045                   l = pos-p;
2046                   if ((f->filename = (char *) malloc (l+1)))
2047                     {
2048                       strncpy (f->filename, p, l);
2049                       f->filename[l] = '\0';
2050                     }
2051                   else
2052                     f->filename = (char *) 0;
2053                 }
2054               else
2055                 {
2056                   if (!(f->funcname = (char *) malloc (strlen (p)+1)))
2057                     continue;
2058                   strcpy (f->funcname, p);
2059                   f->filename = (char *) 0;
2060                 }
2061               f->mode = m;
2062               bb_func_head = f;
2063             }
2064          }
2065     }
2066   fclose (file);
2067
2068 #ifdef HAVE_POPEN
2069
2070   if (bb_mode & 1)
2071       bb_tracefile = gopen ("bbtrace.gz", "w");
2072
2073 #else
2074
2075   if (bb_mode & 1)
2076       bb_tracefile = fopen ("bbtrace", "w");
2077
2078 #endif /* HAVE_POPEN */
2079
2080   if (bb_mode & 2)
2081     {
2082       bb_hashbuckets = (struct bb_edge **)
2083                    malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2084       if (bb_hashbuckets)
2085         /* Use a loop here rather than calling bzero to avoid having to
2086            conditionalize its existence.  */
2087         for (i = 0; i < BB_BUCKETS; i++)
2088           bb_hashbuckets[i] = 0;
2089     }
2090
2091   if (bb_mode & 12)
2092     {
2093       bb_stacksize = 10;
2094       bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2095     }
2096
2097   /* Initialize destructor.  */
2098   atexit (__bb_exit_trace_func);
2099 }
2100
2101 /* Called upon entering a basic block.  */
2102
2103 void
2104 __bb_trace_func (void)
2105 {
2106   struct bb_edge *bucket;
2107
2108   MACHINE_STATE_SAVE("1")
2109
2110   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2111     goto skip;
2112
2113   bb_dst = __bb.blocks->addresses[__bb.blockno];
2114   __bb.blocks->counts[__bb.blockno]++;
2115
2116   if (bb_tracefile)
2117     {
2118       fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2119     }
2120
2121   if (bb_hashbuckets)
2122     {
2123       struct bb_edge **startbucket, **oldnext;
2124
2125       oldnext = startbucket
2126         = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
2127       bucket = *startbucket;
2128
2129       for (bucket = *startbucket; bucket;
2130            oldnext = &(bucket->next), bucket = *oldnext)
2131         {
2132           if (bucket->src_addr == bb_src
2133               && bucket->dst_addr == bb_dst)
2134             {
2135               bucket->count++;
2136               *oldnext = bucket->next;
2137               bucket->next = *startbucket;
2138               *startbucket = bucket;
2139               goto ret;
2140             }
2141         }
2142
2143       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2144
2145       if (!bucket)
2146         {
2147           if (!reported)
2148             {
2149               fprintf (stderr, "Profiler: out of memory\n");
2150               reported = 1;
2151             }
2152         }
2153
2154       else
2155         {
2156           bucket->src_addr = bb_src;
2157           bucket->dst_addr = bb_dst;
2158           bucket->next = *startbucket;
2159           *startbucket = bucket;
2160           bucket->count = 1;
2161         }
2162     }
2163
2164 ret:
2165   bb_src = bb_dst;
2166
2167 skip:
2168   ;
2169
2170   MACHINE_STATE_RESTORE("1")
2171
2172 }
2173
2174 /* Called when returning from a function and `__bb_showret__' is set.  */
2175
2176 static void
2177 __bb_trace_func_ret (void)
2178 {
2179   struct bb_edge *bucket;
2180
2181   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2182     goto skip;
2183
2184   if (bb_hashbuckets)
2185     {
2186       struct bb_edge **startbucket, **oldnext;
2187
2188       oldnext = startbucket
2189         = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
2190       bucket = *startbucket;
2191
2192       for (bucket = *startbucket; bucket;
2193            oldnext = &(bucket->next), bucket = *oldnext)
2194         {
2195           if (bucket->src_addr == bb_dst
2196                && bucket->dst_addr == bb_src)
2197             {
2198               bucket->count++;
2199               *oldnext = bucket->next;
2200               bucket->next = *startbucket;
2201               *startbucket = bucket;
2202               goto ret;
2203             }
2204         }
2205
2206       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2207
2208       if (!bucket)
2209         {
2210           if (!reported)
2211             {
2212               fprintf (stderr, "Profiler: out of memory\n");
2213               reported = 1;
2214             }
2215         }
2216
2217       else
2218         {
2219           bucket->src_addr = bb_dst;
2220           bucket->dst_addr = bb_src;
2221           bucket->next = *startbucket;
2222           *startbucket = bucket;
2223           bucket->count = 1;
2224         }
2225     }
2226
2227 ret:
2228   bb_dst = bb_src;
2229
2230 skip:
2231   ;
2232
2233 }
2234
2235 /* Called upon entering the first function of a file.  */
2236
2237 static void
2238 __bb_init_file (struct bb *blocks)
2239 {
2240
2241   const struct bb_func *p;
2242   long blk, ncounts = blocks->ncounts;
2243   const char **functions = blocks->functions;
2244
2245   /* Set up linked list.  */
2246   blocks->zero_word = 1;
2247   blocks->next = bb_head;
2248   bb_head = blocks;
2249
2250   blocks->flags = 0;
2251   if (!bb_func_head
2252       || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
2253     return;
2254
2255   for (blk = 0; blk < ncounts; blk++)
2256     blocks->flags[blk] = 0;
2257
2258   for (blk = 0; blk < ncounts; blk++)
2259     {
2260       for (p = bb_func_head; p; p = p->next)
2261         {
2262           if (!strcmp (p->funcname, functions[blk])
2263               && (!p->filename || !strcmp (p->filename, blocks->filename)))
2264             {
2265               blocks->flags[blk] |= p->mode;
2266             }
2267         }
2268     }
2269
2270 }
2271
2272 /* Called when exiting from a function.  */
2273
2274 void
2275 __bb_trace_ret (void)
2276 {
2277
2278   MACHINE_STATE_SAVE("2")
2279
2280   if (bb_callcount)
2281     {
2282       if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2283         {
2284           bb_src = bb_stack[bb_callcount];
2285           if (bb_mode & 8)
2286             __bb_trace_func_ret ();
2287         }
2288
2289       bb_callcount -= 1;
2290     }
2291
2292   MACHINE_STATE_RESTORE("2")
2293
2294 }
2295
2296 /* Called when entering a function.  */
2297
2298 void
2299 __bb_init_trace_func (struct bb *blocks, unsigned long blockno)
2300 {
2301   static int trace_init = 0;
2302
2303   MACHINE_STATE_SAVE("3")
2304
2305   if (!blocks->zero_word)
2306     {
2307       if (!trace_init)
2308         {
2309           trace_init = 1;
2310           __bb_init_prg ();
2311         }
2312       __bb_init_file (blocks);
2313     }
2314
2315   if (bb_callcount)
2316     {
2317
2318       bb_callcount += 1;
2319
2320       if (bb_mode & 12)
2321         {
2322           if (bb_callcount >= bb_stacksize)
2323             {
2324               size_t newsize = bb_callcount + 100;
2325
2326               bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2327               if (! bb_stack)
2328                 {
2329                   if (!reported)
2330                     {
2331                       fprintf (stderr, "Profiler: out of memory\n");
2332                       reported = 1;
2333                     }
2334                   bb_stacksize = 0;
2335                   goto stack_overflow;
2336                 }
2337               bb_stacksize = newsize;
2338             }
2339           bb_stack[bb_callcount] = bb_src;
2340
2341           if (bb_mode & 4)
2342             bb_src = 0;
2343
2344         }
2345
2346 stack_overflow:;
2347
2348     }
2349
2350   else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2351     {
2352       bb_callcount = 1;
2353       bb_src = 0;
2354
2355       if (bb_stack)
2356           bb_stack[bb_callcount] = bb_src;
2357     }
2358
2359   MACHINE_STATE_RESTORE("3")
2360 }
2361
2362 #endif /* not inhibit_libc */
2363 #endif /* not BLOCK_PROFILER_CODE */
2364 #endif /* L_bb */
2365 \f
2366 #ifdef L_clear_cache
2367 /* Clear part of an instruction cache.  */
2368
2369 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2370
2371 void
2372 __clear_cache (char *beg __attribute__((__unused__)),
2373                char *end __attribute__((__unused__)))
2374 {
2375 #ifdef CLEAR_INSN_CACHE
2376   CLEAR_INSN_CACHE (beg, end);
2377 #else
2378 #ifdef INSN_CACHE_SIZE
2379   static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
2380   static int initialized;
2381   int offset;
2382   void *start_addr
2383   void *end_addr;
2384   typedef (*function_ptr) (void);
2385
2386 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2387   /* It's cheaper to clear the whole cache.
2388      Put in a series of jump instructions so that calling the beginning
2389      of the cache will clear the whole thing.  */
2390
2391   if (! initialized)
2392     {
2393       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2394                  & -INSN_CACHE_LINE_WIDTH);
2395       int end_ptr = ptr + INSN_CACHE_SIZE;
2396
2397       while (ptr < end_ptr)
2398         {
2399           *(INSTRUCTION_TYPE *)ptr
2400             = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2401           ptr += INSN_CACHE_LINE_WIDTH;
2402         }
2403       *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
2404
2405       initialized = 1;
2406     }
2407
2408   /* Call the beginning of the sequence.  */
2409   (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2410                     & -INSN_CACHE_LINE_WIDTH))
2411    ());
2412
2413 #else /* Cache is large.  */
2414
2415   if (! initialized)
2416     {
2417       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2418                  & -INSN_CACHE_LINE_WIDTH);
2419
2420       while (ptr < (int) array + sizeof array)
2421         {
2422           *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2423           ptr += INSN_CACHE_LINE_WIDTH;
2424         }
2425
2426       initialized = 1;
2427     }
2428
2429   /* Find the location in array that occupies the same cache line as BEG.  */
2430
2431   offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2432   start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2433                  & -INSN_CACHE_PLANE_SIZE)
2434                 + offset);
2435
2436   /* Compute the cache alignment of the place to stop clearing.  */
2437 #if 0  /* This is not needed for gcc's purposes.  */
2438   /* If the block to clear is bigger than a cache plane,
2439      we clear the entire cache, and OFFSET is already correct.  */
2440   if (end < beg + INSN_CACHE_PLANE_SIZE)
2441 #endif
2442     offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2443                & -INSN_CACHE_LINE_WIDTH)
2444               & (INSN_CACHE_PLANE_SIZE - 1));
2445
2446 #if INSN_CACHE_DEPTH > 1
2447   end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2448   if (end_addr <= start_addr)
2449     end_addr += INSN_CACHE_PLANE_SIZE;
2450
2451   for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2452     {
2453       int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2454       int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2455
2456       while (addr != stop)
2457         {
2458           /* Call the return instruction at ADDR.  */
2459           ((function_ptr) addr) ();
2460
2461           addr += INSN_CACHE_LINE_WIDTH;
2462         }
2463     }
2464 #else /* just one plane */
2465   do
2466     {
2467       /* Call the return instruction at START_ADDR.  */
2468       ((function_ptr) start_addr) ();
2469
2470       start_addr += INSN_CACHE_LINE_WIDTH;
2471     }
2472   while ((start_addr % INSN_CACHE_SIZE) != offset);
2473 #endif /* just one plane */
2474 #endif /* Cache is large */
2475 #endif /* Cache exists */
2476 #endif /* CLEAR_INSN_CACHE */
2477 }
2478
2479 #endif /* L_clear_cache */
2480 \f
2481 #ifdef L_trampoline
2482
2483 /* Jump to a trampoline, loading the static chain address.  */
2484
2485 #if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
2486
2487 long
2488 getpagesize (void)
2489 {
2490 #ifdef _ALPHA_
2491   return 8192;
2492 #else
2493   return 4096;
2494 #endif
2495 }
2496
2497 #ifdef __i386__
2498 extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
2499 #endif
2500
2501 int
2502 mprotect (char *addr, int len, int prot)
2503 {
2504   int np, op;
2505
2506   if (prot == 7)
2507     np = 0x40;
2508   else if (prot == 5)
2509     np = 0x20;
2510   else if (prot == 4)
2511     np = 0x10;
2512   else if (prot == 3)
2513     np = 0x04;
2514   else if (prot == 1)
2515     np = 0x02;
2516   else if (prot == 0)
2517     np = 0x01;
2518
2519   if (VirtualProtect (addr, len, np, &op))
2520     return 0;
2521   else
2522     return -1;
2523 }
2524
2525 #endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
2526
2527 #ifdef TRANSFER_FROM_TRAMPOLINE
2528 TRANSFER_FROM_TRAMPOLINE
2529 #endif
2530
2531 #if defined (NeXT) && defined (__MACH__)
2532
2533 /* Make stack executable so we can call trampolines on stack.
2534    This is called from INITIALIZE_TRAMPOLINE in next.h.  */
2535 #ifdef NeXTStep21
2536  #include <mach.h>
2537 #else
2538  #include <mach/mach.h>
2539 #endif
2540
2541 void
2542 __enable_execute_stack (char *addr)
2543 {
2544   kern_return_t r;
2545   char *eaddr = addr + TRAMPOLINE_SIZE;
2546   vm_address_t a = (vm_address_t) addr;
2547
2548   /* turn on execute access on stack */
2549   r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2550   if (r != KERN_SUCCESS)
2551     {
2552       mach_error("vm_protect VM_PROT_ALL", r);
2553       exit(1);
2554     }
2555
2556   /* We inline the i-cache invalidation for speed */
2557
2558 #ifdef CLEAR_INSN_CACHE
2559   CLEAR_INSN_CACHE (addr, eaddr);
2560 #else
2561   __clear_cache ((int) addr, (int) eaddr);
2562 #endif
2563 }
2564
2565 #endif /* defined (NeXT) && defined (__MACH__) */
2566
2567 #ifdef __convex__
2568
2569 /* Make stack executable so we can call trampolines on stack.
2570    This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
2571
2572 #include <sys/mman.h>
2573 #include <sys/vmparam.h>
2574 #include <machine/machparam.h>
2575
2576 void
2577 __enable_execute_stack (void)
2578 {
2579   int fp;
2580   static unsigned lowest = USRSTACK;
2581   unsigned current = (unsigned) &fp & -NBPG;
2582
2583   if (lowest > current)
2584     {
2585       unsigned len = lowest - current;
2586       mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2587       lowest = current;
2588     }
2589
2590   /* Clear instruction cache in case an old trampoline is in it.  */
2591   asm ("pich");
2592 }
2593 #endif /* __convex__ */
2594
2595 #ifdef __sysV88__
2596
2597 /* Modified from the convex -code above.  */
2598
2599 #include <sys/param.h>
2600 #include <errno.h>
2601 #include <sys/m88kbcs.h>
2602
2603 void
2604 __enable_execute_stack (void)
2605 {
2606   int save_errno;
2607   static unsigned long lowest = USRSTACK;
2608   unsigned long current = (unsigned long) &save_errno & -NBPC;
2609
2610   /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2611      address is seen as 'negative'. That is the case with the stack.  */
2612
2613   save_errno=errno;
2614   if (lowest > current)
2615     {
2616       unsigned len=lowest-current;
2617       memctl(current,len,MCT_TEXT);
2618       lowest = current;
2619     }
2620   else
2621     memctl(current,NBPC,MCT_TEXT);
2622   errno=save_errno;
2623 }
2624
2625 #endif /* __sysV88__ */
2626
2627 #ifdef __sysV68__
2628
2629 #include <sys/signal.h>
2630 #include <errno.h>
2631
2632 /* Motorola forgot to put memctl.o in the libp version of libc881.a,
2633    so define it here, because we need it in __clear_insn_cache below */
2634 /* On older versions of this OS, no memctl or MCT_TEXT are defined;
2635    hence we enable this stuff only if MCT_TEXT is #define'd.  */
2636
2637 #ifdef MCT_TEXT
2638 asm("\n\
2639         global memctl\n\
2640 memctl:\n\
2641         movq &75,%d0\n\
2642         trap &0\n\
2643         bcc.b noerror\n\
2644         jmp cerror%\n\
2645 noerror:\n\
2646         movq &0,%d0\n\
2647         rts");
2648 #endif
2649
2650 /* Clear instruction cache so we can call trampolines on stack.
2651    This is called from FINALIZE_TRAMPOLINE in mot3300.h.  */
2652
2653 void
2654 __clear_insn_cache (void)
2655 {
2656 #ifdef MCT_TEXT
2657   int save_errno;
2658
2659   /* Preserve errno, because users would be surprised to have
2660   errno changing without explicitly calling any system-call.  */
2661   save_errno = errno;
2662
2663   /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
2664      No need to use an address derived from _start or %sp, as 0 works also.  */
2665   memctl(0, 4096, MCT_TEXT);
2666   errno = save_errno;
2667 #endif
2668 }
2669
2670 #endif /* __sysV68__ */
2671
2672 #ifdef __pyr__
2673
2674 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2675 #include <stdio.h>
2676 #include <sys/mman.h>
2677 #include <sys/types.h>
2678 #include <sys/param.h>
2679 #include <sys/vmmac.h>
2680
2681 /* Modified from the convex -code above.
2682    mremap promises to clear the i-cache.  */
2683
2684 void
2685 __enable_execute_stack (void)
2686 {
2687   int fp;
2688   if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2689                 PROT_READ|PROT_WRITE|PROT_EXEC))
2690     {
2691       perror ("mprotect in __enable_execute_stack");
2692       fflush (stderr);
2693       abort ();
2694     }
2695 }
2696 #endif /* __pyr__ */
2697
2698 #if defined (sony_news) && defined (SYSTYPE_BSD)
2699
2700 #include <stdio.h>
2701 #include <sys/types.h>
2702 #include <sys/param.h>
2703 #include <syscall.h>
2704 #include <machine/sysnews.h>
2705
2706 /* cacheflush function for NEWS-OS 4.2.
2707    This function is called from trampoline-initialize code
2708    defined in config/mips/mips.h.  */
2709
2710 void
2711 cacheflush (char *beg, int size, int flag)
2712 {
2713   if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
2714     {
2715       perror ("cache_flush");
2716       fflush (stderr);
2717       abort ();
2718     }
2719 }
2720
2721 #endif /* sony_news */
2722 #endif /* L_trampoline */
2723 \f
2724 #ifndef __CYGWIN__
2725 #ifdef L__main
2726
2727 #include "gbl-ctors.h"
2728 /* Some systems use __main in a way incompatible with its use in gcc, in these
2729    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2730    give the same symbol without quotes for an alternative entry point.  You
2731    must define both, or neither.  */
2732 #ifndef NAME__MAIN
2733 #define NAME__MAIN "__main"
2734 #define SYMBOL__MAIN __main
2735 #endif
2736
2737 #ifdef INIT_SECTION_ASM_OP
2738 #undef HAS_INIT_SECTION
2739 #define HAS_INIT_SECTION
2740 #endif
2741
2742 #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
2743
2744 /* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
2745    code to run constructors.  In that case, we need to handle EH here, too.  */
2746
2747 #ifdef EH_FRAME_SECTION_NAME
2748 #include "unwind-dw2-fde.h"
2749 extern unsigned char __EH_FRAME_BEGIN__[];
2750 #endif
2751
2752 /* Run all the global destructors on exit from the program.  */
2753
2754 void
2755 __do_global_dtors (void)
2756 {
2757 #ifdef DO_GLOBAL_DTORS_BODY
2758   DO_GLOBAL_DTORS_BODY;
2759 #else
2760   static func_ptr *p = __DTOR_LIST__ + 1;
2761   while (*p)
2762     {
2763       p++;
2764       (*(p-1)) ();
2765     }
2766 #endif
2767 #if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
2768   {
2769     static int completed = 0;
2770     if (! completed)
2771       {
2772         completed = 1;
2773         __deregister_frame_info (__EH_FRAME_BEGIN__);
2774       }
2775   }
2776 #endif
2777 }
2778 #endif
2779
2780 #ifndef HAS_INIT_SECTION
2781 /* Run all the global constructors on entry to the program.  */
2782
2783 void
2784 __do_global_ctors (void)
2785 {
2786 #ifdef EH_FRAME_SECTION_NAME
2787   {
2788     static struct object object;
2789     __register_frame_info (__EH_FRAME_BEGIN__, &object);
2790   }
2791 #endif
2792   DO_GLOBAL_CTORS_BODY;
2793   atexit (__do_global_dtors);
2794 }
2795 #endif /* no HAS_INIT_SECTION */
2796
2797 #if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
2798 /* Subroutine called automatically by `main'.
2799    Compiling a global function named `main'
2800    produces an automatic call to this function at the beginning.
2801
2802    For many systems, this routine calls __do_global_ctors.
2803    For systems which support a .init section we use the .init section
2804    to run __do_global_ctors, so we need not do anything here.  */
2805
2806 void
2807 SYMBOL__MAIN ()
2808 {
2809   /* Support recursive calls to `main': run initializers just once.  */
2810   static int initialized;
2811   if (! initialized)
2812     {
2813       initialized = 1;
2814       __do_global_ctors ();
2815     }
2816 }
2817 #endif /* no HAS_INIT_SECTION or INVOKE__main */
2818
2819 #endif /* L__main */
2820 #endif /* __CYGWIN__ */
2821 \f
2822 #ifdef L_ctors
2823
2824 #include "gbl-ctors.h"
2825
2826 /* Provide default definitions for the lists of constructors and
2827    destructors, so that we don't get linker errors.  These symbols are
2828    intentionally bss symbols, so that gld and/or collect will provide
2829    the right values.  */
2830
2831 /* We declare the lists here with two elements each,
2832    so that they are valid empty lists if no other definition is loaded.
2833
2834    If we are using the old "set" extensions to have the gnu linker
2835    collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
2836    must be in the bss/common section.
2837
2838    Long term no port should use those extensions.  But many still do.  */
2839 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2840 #if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
2841 func_ptr __CTOR_LIST__[2] = {0, 0};
2842 func_ptr __DTOR_LIST__[2] = {0, 0};
2843 #else
2844 func_ptr __CTOR_LIST__[2];
2845 func_ptr __DTOR_LIST__[2];
2846 #endif
2847 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2848 #endif /* L_ctors */
2849 \f
2850 #ifdef L_exit
2851
2852 #include "gbl-ctors.h"
2853
2854 #ifdef NEED_ATEXIT
2855
2856 #ifndef ON_EXIT
2857
2858 # include <errno.h>
2859
2860 static func_ptr *atexit_chain = 0;
2861 static long atexit_chain_length = 0;
2862 static volatile long last_atexit_chain_slot = -1;
2863
2864 int
2865 atexit (func_ptr func)
2866 {
2867   if (++last_atexit_chain_slot == atexit_chain_length)
2868     {
2869       atexit_chain_length += 32;
2870       if (atexit_chain)
2871         atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2872                                              * sizeof (func_ptr));
2873       else
2874         atexit_chain = (func_ptr *) malloc (atexit_chain_length
2875                                             * sizeof (func_ptr));
2876       if (! atexit_chain)
2877         {
2878           atexit_chain_length = 0;
2879           last_atexit_chain_slot = -1;
2880           errno = ENOMEM;
2881           return (-1);
2882         }
2883     }
2884   atexit_chain[last_atexit_chain_slot] = func;
2885   return (0);
2886 }
2887
2888 extern void _cleanup (void);
2889 extern void _exit (int) __attribute__ ((__noreturn__));
2890
2891 void
2892 exit (int status)
2893 {
2894   if (atexit_chain)
2895     {
2896       for ( ; last_atexit_chain_slot-- >= 0; )
2897         {
2898           (*atexit_chain[last_atexit_chain_slot + 1]) ();
2899           atexit_chain[last_atexit_chain_slot + 1] = 0;
2900         }
2901       free (atexit_chain);
2902       atexit_chain = 0;
2903     }
2904 #ifdef EXIT_BODY
2905   EXIT_BODY;
2906 #else
2907   _cleanup ();
2908 #endif
2909   _exit (status);
2910 }
2911
2912 #else /* ON_EXIT */
2913
2914 /* Simple; we just need a wrapper for ON_EXIT.  */
2915 int
2916 atexit (func_ptr func)
2917 {
2918   return ON_EXIT (func);
2919 }
2920
2921 #endif /* ON_EXIT */
2922 #endif /* NEED_ATEXIT */
2923
2924 #endif /* L_exit */