OSDN Git Service

Add fix test from irix_stdio_dummy_va_list
[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 GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later 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 GNU CC is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 GNU General Public License for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with GNU CC; see the file COPYING.  If not, write to
29 the Free Software Foundation, 59 Temple Place - Suite 330,
30 Boston, MA 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 /* Structure emitted by -a  */
1267 struct bb
1268 {
1269   long zero_word;
1270   const char *filename;
1271   long *counts;
1272   long ncounts;
1273   struct bb *next;
1274   const unsigned long *addresses;
1275
1276   /* Older GCC's did not emit these fields.  */
1277   long nwords;
1278   const char **functions;
1279   const long *line_nums;
1280   const char **filenames;
1281   char *flags;
1282 };
1283
1284 #ifdef BLOCK_PROFILER_CODE
1285 BLOCK_PROFILER_CODE
1286 #else
1287 #ifndef inhibit_libc
1288
1289 /* Simple minded basic block profiling output dumper for
1290    systems that don't provide tcov support.  At present,
1291    it requires atexit and stdio.  */
1292
1293 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1294 #include <stdio.h>
1295 char *ctime PARAMS ((const time_t *));
1296
1297 #include "gbl-ctors.h"
1298 #include "gcov-io.h"
1299 #include <string.h>
1300 #ifdef TARGET_HAS_F_SETLKW
1301 #include <fcntl.h>
1302 #include <errno.h>
1303 #endif
1304
1305 static struct bb *bb_head;
1306
1307 static int num_digits (long value, int base) __attribute__ ((const));
1308
1309 /* Return the number of digits needed to print a value */
1310 /* __inline__ */ static int num_digits (long value, int base)
1311 {
1312   int minus = (value < 0 && base != 16);
1313   unsigned long v = (minus) ? -value : value;
1314   int ret = minus;
1315
1316   do
1317     {
1318       v /= base;
1319       ret++;
1320     }
1321   while (v);
1322
1323   return ret;
1324 }
1325
1326 void
1327 __bb_exit_func (void)
1328 {
1329   FILE *da_file, *file;
1330   long time_value;
1331   int i;
1332
1333   if (bb_head == 0)
1334     return;
1335
1336   i = strlen (bb_head->filename) - 3;
1337
1338   if (!strcmp (bb_head->filename+i, ".da"))
1339     {
1340       /* Must be -fprofile-arcs not -a.
1341          Dump data in a form that gcov expects.  */
1342
1343       struct bb *ptr;
1344
1345       for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1346         {
1347           int firstchar;
1348
1349           /* Make sure the output file exists -
1350              but don't clobber exiting data.  */
1351           if ((da_file = fopen (ptr->filename, "a")) != 0)
1352             fclose (da_file);
1353
1354           /* Need to re-open in order to be able to write from the start.  */
1355           da_file = fopen (ptr->filename, "r+b");
1356           /* Some old systems might not allow the 'b' mode modifier.
1357              Therefore, try to open without it.  This can lead to a race
1358              condition so that when you delete and re-create the file, the
1359              file might be opened in text mode, but then, you shouldn't
1360              delete the file in the first place.  */
1361           if (da_file == 0)
1362             da_file = fopen (ptr->filename, "r+");
1363           if (da_file == 0)
1364             {
1365               fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1366                        ptr->filename);
1367               continue;
1368             }
1369
1370           /* After a fork, another process might try to read and/or write
1371              the same file simultanously.  So if we can, lock the file to
1372              avoid race conditions.  */
1373 #if defined (TARGET_HAS_F_SETLKW)
1374           {
1375             struct flock s_flock;
1376
1377             s_flock.l_type = F_WRLCK;
1378             s_flock.l_whence = SEEK_SET;
1379             s_flock.l_start = 0;
1380             s_flock.l_len = 1;
1381             s_flock.l_pid = getpid ();
1382
1383             while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
1384                    && errno == EINTR);
1385           }
1386 #endif
1387
1388           /* If the file is not empty, and the number of counts in it is the
1389              same, then merge them in.  */
1390           firstchar = fgetc (da_file);
1391           if (firstchar == EOF)
1392             {
1393               if (ferror (da_file))
1394                 {
1395                   fprintf (stderr, "arc profiling: Can't read output file ");
1396                   perror (ptr->filename);
1397                 }
1398             }
1399           else
1400             {
1401               long n_counts = 0;
1402               
1403               if (ungetc (firstchar, da_file) == EOF)
1404                 rewind (da_file);
1405               if (__read_long (&n_counts, da_file, 8) != 0)
1406                 {
1407                   fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1408                            ptr->filename);
1409                   continue;
1410                 }
1411
1412               if (n_counts == ptr->ncounts)
1413                 {
1414                   int i;
1415
1416                   for (i = 0; i < n_counts; i++)
1417                     {
1418                       long v = 0;
1419
1420                       if (__read_long (&v, da_file, 8) != 0)
1421                         {
1422                           fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1423                                    ptr->filename);
1424                           break;
1425                         }
1426                       ptr->counts[i] += v;
1427                     }
1428                 }
1429
1430             }
1431
1432           rewind (da_file);
1433
1434           /* ??? Should first write a header to the file.  Preferably, a 4 byte
1435              magic number, 4 bytes containing the time the program was
1436              compiled, 4 bytes containing the last modification time of the
1437              source file, and 4 bytes indicating the compiler options used.
1438
1439              That way we can easily verify that the proper source/executable/
1440              data file combination is being used from gcov.  */
1441
1442           if (__write_long (ptr->ncounts, da_file, 8) != 0)
1443             {
1444               
1445               fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1446                        ptr->filename);
1447             }
1448           else
1449             {
1450               int j;
1451               long *count_ptr = ptr->counts;
1452               int ret = 0;
1453               for (j = ptr->ncounts; j > 0; j--)
1454                 {
1455                   if (__write_long (*count_ptr, da_file, 8) != 0)
1456                     {
1457                       ret=1;
1458                       break;
1459                     }
1460                   count_ptr++;
1461                 }
1462               if (ret)
1463                 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1464                          ptr->filename);
1465             }
1466           
1467           if (fclose (da_file) == EOF)
1468             fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1469                      ptr->filename);
1470         }
1471
1472       return;
1473     }
1474
1475   /* Must be basic block profiling.  Emit a human readable output file.  */
1476
1477   file = fopen ("bb.out", "a");
1478
1479   if (!file)
1480     perror ("bb.out");
1481
1482   else
1483     {
1484       struct bb *ptr;
1485
1486       /* This is somewhat type incorrect, but it avoids worrying about
1487          exactly where time.h is included from.  It should be ok unless
1488          a void * differs from other pointer formats, or if sizeof (long)
1489          is < sizeof (time_t).  It would be nice if we could assume the
1490          use of rationale standards here.  */
1491
1492       time ((void *) &time_value);
1493       fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1494
1495       /* We check the length field explicitly in order to allow compatibility
1496          with older GCC's which did not provide it.  */
1497
1498       for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1499         {
1500           int i;
1501           int func_p    = (ptr->nwords >= (long) sizeof (struct bb)
1502                            && ptr->nwords <= 1000
1503                            && ptr->functions);
1504           int line_p    = (func_p && ptr->line_nums);
1505           int file_p    = (func_p && ptr->filenames);
1506           int addr_p    = (ptr->addresses != 0);
1507           long ncounts  = ptr->ncounts;
1508           long cnt_max  = 0;
1509           long line_max = 0;
1510           long addr_max = 0;
1511           int file_len  = 0;
1512           int func_len  = 0;
1513           int blk_len   = num_digits (ncounts, 10);
1514           int cnt_len;
1515           int line_len;
1516           int addr_len;
1517
1518           fprintf (file, "File %s, %ld basic blocks \n\n",
1519                    ptr->filename, ncounts);
1520
1521           /* Get max values for each field.  */
1522           for (i = 0; i < ncounts; i++)
1523             {
1524               const char *p;
1525               int len;
1526
1527               if (cnt_max < ptr->counts[i])
1528                 cnt_max = ptr->counts[i];
1529
1530               if (addr_p && (unsigned long) addr_max < ptr->addresses[i])
1531                 addr_max = ptr->addresses[i];
1532
1533               if (line_p && line_max < ptr->line_nums[i])
1534                 line_max = ptr->line_nums[i];
1535
1536               if (func_p)
1537                 {
1538                   p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1539                   len = strlen (p);
1540                   if (func_len < len)
1541                     func_len = len;
1542                 }
1543
1544               if (file_p)
1545                 {
1546                   p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1547                   len = strlen (p);
1548                   if (file_len < len)
1549                     file_len = len;
1550                 }
1551             }
1552
1553           addr_len = num_digits (addr_max, 16);
1554           cnt_len  = num_digits (cnt_max, 10);
1555           line_len = num_digits (line_max, 10);
1556
1557           /* Now print out the basic block information.  */
1558           for (i = 0; i < ncounts; i++)
1559             {
1560               fprintf (file,
1561                        "    Block #%*d: executed %*ld time(s)",
1562                        blk_len, i+1,
1563                        cnt_len, ptr->counts[i]);
1564
1565               if (addr_p)
1566                 fprintf (file, " address= 0x%.*lx", addr_len,
1567                          ptr->addresses[i]);
1568
1569               if (func_p)
1570                 fprintf (file, " function= %-*s", func_len,
1571                          (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1572
1573               if (line_p)
1574                 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1575
1576               if (file_p)
1577                 fprintf (file, " file= %s",
1578                          (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1579
1580               fprintf (file, "\n");
1581             }
1582
1583           fprintf (file, "\n");
1584           fflush (file);
1585         }
1586
1587       fprintf (file, "\n\n");
1588       fclose (file);
1589     }
1590 }
1591
1592 void
1593 __bb_init_func (struct bb *blocks)
1594 {
1595   /* User is supposed to check whether the first word is non-0,
1596      but just in case....  */
1597
1598   if (blocks->zero_word)
1599     return;
1600
1601   /* Initialize destructor.  */
1602   if (!bb_head)
1603     atexit (__bb_exit_func);
1604
1605   /* Set up linked list.  */
1606   blocks->zero_word = 1;
1607   blocks->next = bb_head;
1608   bb_head = blocks;
1609 }
1610
1611 /* Called before fork or exec - write out profile information gathered so
1612    far and reset it to zero.  This avoids duplication or loss of the
1613    profile information gathered so far.  */
1614 void
1615 __bb_fork_func (void)
1616 {
1617   struct bb *ptr;
1618
1619   __bb_exit_func ();
1620   for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1621     {
1622       long i;
1623       for (i = ptr->ncounts - 1; i >= 0; i--)
1624         ptr->counts[i] = 0;
1625     }
1626 }
1627
1628 #ifndef MACHINE_STATE_SAVE
1629 #define MACHINE_STATE_SAVE(ID)
1630 #endif
1631 #ifndef MACHINE_STATE_RESTORE
1632 #define MACHINE_STATE_RESTORE(ID)
1633 #endif
1634
1635 /* Number of buckets in hashtable of basic block addresses.  */
1636
1637 #define BB_BUCKETS 311
1638
1639 /* Maximum length of string in file bb.in.  */
1640
1641 #define BBINBUFSIZE 500
1642
1643 struct bb_edge
1644 {
1645   struct bb_edge *next;
1646   unsigned long src_addr;
1647   unsigned long dst_addr;
1648   unsigned long count;
1649 };
1650
1651 enum bb_func_mode
1652 {
1653   TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1654 };
1655
1656 struct bb_func
1657 {
1658   struct bb_func *next;
1659   char *funcname;
1660   char *filename;
1661   enum bb_func_mode mode;
1662 };
1663
1664 /* This is the connection to the outside world.
1665    The BLOCK_PROFILER macro must set __bb.blocks
1666    and __bb.blockno.  */
1667
1668 struct {
1669   unsigned long blockno;
1670   struct bb *blocks;
1671 } __bb;
1672
1673 /* Vars to store addrs of source and destination basic blocks 
1674    of a jump.  */
1675
1676 static unsigned long bb_src = 0;
1677 static unsigned long bb_dst = 0;
1678
1679 static FILE *bb_tracefile = (FILE *) 0;
1680 static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1681 static struct bb_func *bb_func_head = (struct bb_func *) 0;
1682 static unsigned long bb_callcount = 0;
1683 static int bb_mode = 0;
1684
1685 static unsigned long *bb_stack = (unsigned long *) 0;
1686 static size_t bb_stacksize = 0;
1687
1688 static int reported = 0;
1689
1690 /* Trace modes:
1691 Always             :   Print execution frequencies of basic blocks
1692                        to file bb.out.
1693 bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
1694 bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
1695 bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
1696 bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
1697 */
1698
1699 #ifdef HAVE_POPEN
1700
1701 /*#include <sys/types.h>*/
1702 #include <sys/stat.h>
1703 /*#include <malloc.h>*/
1704
1705 /* Commands executed by gopen.  */
1706
1707 #define GOPENDECOMPRESS "gzip -cd "
1708 #define GOPENCOMPRESS "gzip -c >"
1709
1710 /* Like fopen but pipes through gzip.  mode may only be "r" or "w".
1711    If it does not compile, simply replace gopen by fopen and delete
1712    '.gz' from any first parameter to gopen.  */
1713
1714 static FILE *
1715 gopen (char *fn, char *mode)
1716 {
1717   int use_gzip;
1718   char *p;
1719
1720   if (mode[1])
1721     return (FILE *) 0;
1722
1723   if (mode[0] != 'r' && mode[0] != 'w') 
1724     return (FILE *) 0;
1725
1726   p = fn + strlen (fn)-1;
1727   use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
1728               || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1729
1730   if (use_gzip)
1731     {
1732       if (mode[0]=='r')
1733         {
1734           FILE *f;
1735           char *s = (char *) malloc (sizeof (char) * strlen (fn)
1736                                      + sizeof (GOPENDECOMPRESS));
1737           strcpy (s, GOPENDECOMPRESS);
1738           strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1739           f = popen (s, mode);
1740           free (s);
1741           return f;
1742         }
1743
1744       else
1745         {
1746           FILE *f;
1747           char *s = (char *) malloc (sizeof (char) * strlen (fn)
1748                                      + sizeof (GOPENCOMPRESS));
1749           strcpy (s, GOPENCOMPRESS);
1750           strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1751           if (!(f = popen (s, mode)))
1752             f = fopen (s, mode);
1753           free (s);
1754           return f;
1755         }
1756     }
1757
1758   else
1759     return fopen (fn, mode);
1760 }
1761
1762 static int
1763 gclose (FILE *f)
1764 {
1765   struct stat buf;
1766
1767   if (f != 0)
1768     {
1769       if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1770         return pclose (f);
1771
1772       return fclose (f);
1773     }
1774   return 0;
1775 }
1776
1777 #endif /* HAVE_POPEN */
1778
1779 /* Called once per program.  */
1780
1781 static void
1782 __bb_exit_trace_func (void)
1783 {
1784   FILE *file = fopen ("bb.out", "a");
1785   struct bb_func *f;
1786   struct bb *b;
1787         
1788   if (!file)
1789     perror ("bb.out");
1790
1791   if (bb_mode & 1)
1792     {
1793       if (!bb_tracefile)
1794         perror ("bbtrace");
1795       else
1796 #ifdef HAVE_POPEN
1797         gclose (bb_tracefile);
1798 #else
1799         fclose (bb_tracefile);
1800 #endif /* HAVE_POPEN */
1801     }
1802
1803   /* Check functions in `bb.in'.  */
1804
1805   if (file)
1806     {
1807       long time_value;
1808       const struct bb_func *p;
1809       int printed_something = 0;
1810       struct bb *ptr;
1811       long blk;
1812
1813       /* This is somewhat type incorrect.  */
1814       time ((void *) &time_value);
1815
1816       for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
1817         {
1818           for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1819             {
1820               if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
1821                 continue;
1822               for (blk = 0; blk < ptr->ncounts; blk++)
1823                 {
1824                   if (!strcmp (p->funcname, ptr->functions[blk]))
1825                     goto found;
1826                 }
1827             }
1828   
1829           if (!printed_something)
1830             {
1831               fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1832               printed_something = 1;
1833             }
1834
1835           fprintf (file, "\tFunction %s", p->funcname);
1836           if (p->filename)
1837               fprintf (file, " of file %s", p->filename);
1838           fprintf (file, "\n" );
1839   
1840 found:        ;
1841         }
1842
1843       if (printed_something)
1844        fprintf (file, "\n");
1845
1846     }
1847
1848   if (bb_mode & 2)
1849     {
1850       if (!bb_hashbuckets)
1851         {
1852           if (!reported)
1853             {
1854               fprintf (stderr, "Profiler: out of memory\n");
1855               reported = 1;
1856             }
1857           return;
1858         }
1859     
1860       else if (file)
1861         {
1862           long time_value;
1863           int i;
1864           unsigned long addr_max = 0;
1865           unsigned long cnt_max  = 0;
1866           int cnt_len;
1867           int addr_len;
1868     
1869           /* This is somewhat type incorrect, but it avoids worrying about
1870              exactly where time.h is included from.  It should be ok unless
1871              a void * differs from other pointer formats, or if sizeof (long)
1872              is < sizeof (time_t).  It would be nice if we could assume the
1873              use of rationale standards here.  */
1874     
1875           time ((void *) &time_value);
1876           fprintf (file, "Basic block jump tracing");
1877
1878           switch (bb_mode & 12)
1879             {
1880               case 0:
1881                 fprintf (file, " (with call)");
1882               break;
1883
1884               case 4:
1885                 /* Print nothing.  */
1886               break;
1887
1888               case 8:
1889                 fprintf (file, " (with call & ret)");
1890               break;
1891
1892               case 12:
1893                 fprintf (file, " (with ret)");
1894               break;
1895             }
1896
1897           fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1898     
1899           for (i = 0; i < BB_BUCKETS; i++)
1900             {
1901                struct bb_edge *bucket = bb_hashbuckets[i];
1902                for ( ; bucket; bucket = bucket->next )
1903                  {
1904                    if (addr_max < bucket->src_addr) 
1905                      addr_max = bucket->src_addr;
1906                    if (addr_max < bucket->dst_addr) 
1907                      addr_max = bucket->dst_addr;
1908                    if (cnt_max < bucket->count) 
1909                      cnt_max = bucket->count;
1910                  }
1911             }
1912           addr_len = num_digits (addr_max, 16);
1913           cnt_len  = num_digits (cnt_max, 10);
1914     
1915           for ( i = 0; i < BB_BUCKETS; i++)
1916             {
1917                struct bb_edge *bucket = bb_hashbuckets[i];
1918                for ( ; bucket; bucket = bucket->next )
1919                  {
1920                    fprintf (file,
1921         "Jump from block 0x%.*lx to block 0x%.*lx executed %*lu time(s)\n", 
1922                             addr_len, bucket->src_addr, 
1923                             addr_len, bucket->dst_addr, 
1924                             cnt_len, bucket->count);
1925                  }
1926             }
1927   
1928           fprintf (file, "\n");
1929
1930         }
1931     }
1932
1933    if (file)
1934      fclose (file);
1935
1936    /* Free allocated memory.  */
1937
1938    f = bb_func_head;
1939    while (f)
1940      {
1941        struct bb_func *old = f;
1942
1943        f = f->next;
1944        if (old->funcname) free (old->funcname);
1945        if (old->filename) free (old->filename);
1946        free (old);
1947      }
1948
1949    if (bb_stack)
1950      free (bb_stack);
1951
1952    if (bb_hashbuckets)
1953      {
1954        int i;
1955
1956        for (i = 0; i < BB_BUCKETS; i++)
1957          {
1958            struct bb_edge *old, *bucket = bb_hashbuckets[i];
1959
1960            while (bucket)
1961              {
1962                old = bucket;
1963                bucket = bucket->next;
1964                free (old);
1965              }
1966          }
1967        free (bb_hashbuckets);
1968      }
1969
1970    for (b = bb_head; b; b = b->next)
1971      if (b->flags) free (b->flags);
1972 }
1973
1974 /* Called once per program.  */
1975
1976 static void
1977 __bb_init_prg (void)
1978 {
1979   FILE *file;
1980   char buf[BBINBUFSIZE];
1981   const char *p;
1982   const char *pos;
1983   enum bb_func_mode m;
1984   int i;
1985
1986   /* Initialize destructor.  */
1987   atexit (__bb_exit_func);
1988
1989   if (!(file = fopen ("bb.in", "r")))
1990     return;
1991
1992   while(fgets (buf, BBINBUFSIZE, file) != 0)
1993     {
1994       i = strlen (buf);
1995       if (buf[i] == '\n')
1996         buf[i--] = '\0';
1997
1998       p = buf;
1999       if (*p == '-') 
2000         { 
2001           m = TRACE_OFF; 
2002           p++; 
2003         }
2004       else 
2005         { 
2006           m = TRACE_ON; 
2007         }
2008       if (!strcmp (p, "__bb_trace__"))
2009         bb_mode |= 1;
2010       else if (!strcmp (p, "__bb_jumps__"))
2011         bb_mode |= 2;
2012       else if (!strcmp (p, "__bb_hidecall__"))
2013         bb_mode |= 4;
2014       else if (!strcmp (p, "__bb_showret__"))
2015         bb_mode |= 8;
2016       else 
2017         {
2018           struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
2019           if (f)
2020             {
2021               unsigned long l;
2022               f->next = bb_func_head;
2023               if ((pos = strchr (p, ':')))
2024                 {
2025                   if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
2026                     continue;
2027                   strcpy (f->funcname, pos+1);
2028                   l = pos-p;
2029                   if ((f->filename = (char *) malloc (l+1)))
2030                     {
2031                       strncpy (f->filename, p, l);
2032                       f->filename[l] = '\0';
2033                     }
2034                   else
2035                     f->filename = (char *) 0;
2036                 }
2037               else
2038                 {
2039                   if (!(f->funcname = (char *) malloc (strlen (p)+1)))
2040                     continue;
2041                   strcpy (f->funcname, p);
2042                   f->filename = (char *) 0;
2043                 }
2044               f->mode = m;
2045               bb_func_head = f;
2046             }
2047          }
2048     }
2049   fclose (file);
2050
2051 #ifdef HAVE_POPEN 
2052
2053   if (bb_mode & 1)
2054       bb_tracefile = gopen ("bbtrace.gz", "w");
2055
2056 #else
2057
2058   if (bb_mode & 1)
2059       bb_tracefile = fopen ("bbtrace", "w");
2060
2061 #endif /* HAVE_POPEN */
2062
2063   if (bb_mode & 2)
2064     {
2065       bb_hashbuckets = (struct bb_edge **) 
2066                    malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2067       if (bb_hashbuckets)
2068         /* Use a loop here rather than calling bzero to avoid having to
2069            conditionalize its existance.  */
2070         for (i = 0; i < BB_BUCKETS; i++)
2071           bb_hashbuckets[i] = 0;
2072     }
2073
2074   if (bb_mode & 12)
2075     {
2076       bb_stacksize = 10;
2077       bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2078     }
2079
2080   /* Initialize destructor.  */
2081   atexit (__bb_exit_trace_func);
2082 }
2083
2084 /* Called upon entering a basic block.  */
2085
2086 void
2087 __bb_trace_func (void)
2088 {
2089   struct bb_edge *bucket;
2090
2091   MACHINE_STATE_SAVE("1")
2092
2093   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2094     goto skip;
2095
2096   bb_dst = __bb.blocks->addresses[__bb.blockno];
2097   __bb.blocks->counts[__bb.blockno]++;
2098
2099   if (bb_tracefile)
2100     {
2101       fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2102     }
2103
2104   if (bb_hashbuckets)
2105     {
2106       struct bb_edge **startbucket, **oldnext;
2107
2108       oldnext = startbucket
2109         = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
2110       bucket = *startbucket;
2111
2112       for (bucket = *startbucket; bucket; 
2113            oldnext = &(bucket->next), bucket = *oldnext)
2114         {
2115           if (bucket->src_addr == bb_src
2116               && bucket->dst_addr == bb_dst)
2117             {
2118               bucket->count++;
2119               *oldnext = bucket->next;
2120               bucket->next = *startbucket;
2121               *startbucket = bucket;
2122               goto ret;
2123             }
2124         }
2125
2126       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2127
2128       if (!bucket)
2129         {
2130           if (!reported)
2131             {
2132               fprintf (stderr, "Profiler: out of memory\n");
2133               reported = 1;
2134             }
2135         }
2136
2137       else
2138         {
2139           bucket->src_addr = bb_src;
2140           bucket->dst_addr = bb_dst;
2141           bucket->next = *startbucket;
2142           *startbucket = bucket;
2143           bucket->count = 1;
2144         }
2145     }
2146
2147 ret:
2148   bb_src = bb_dst;
2149
2150 skip:
2151   ;
2152
2153   MACHINE_STATE_RESTORE("1")
2154
2155 }
2156
2157 /* Called when returning from a function and `__bb_showret__' is set.  */
2158
2159 static void
2160 __bb_trace_func_ret (void)
2161 {
2162   struct bb_edge *bucket;
2163
2164   if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2165     goto skip;
2166
2167   if (bb_hashbuckets)
2168     {
2169       struct bb_edge **startbucket, **oldnext;
2170
2171       oldnext = startbucket
2172         = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
2173       bucket = *startbucket;
2174
2175       for (bucket = *startbucket; bucket; 
2176            oldnext = &(bucket->next), bucket = *oldnext)
2177         {
2178           if (bucket->src_addr == bb_dst
2179                && bucket->dst_addr == bb_src)
2180             {
2181               bucket->count++;
2182               *oldnext = bucket->next;
2183               bucket->next = *startbucket;
2184               *startbucket = bucket;
2185               goto ret;
2186             }
2187         }
2188
2189       bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2190
2191       if (!bucket)
2192         {
2193           if (!reported)
2194             {
2195               fprintf (stderr, "Profiler: out of memory\n");
2196               reported = 1;
2197             }
2198         }
2199
2200       else
2201         {
2202           bucket->src_addr = bb_dst;
2203           bucket->dst_addr = bb_src;
2204           bucket->next = *startbucket;
2205           *startbucket = bucket;
2206           bucket->count = 1;
2207         }
2208     }
2209
2210 ret:
2211   bb_dst = bb_src;
2212
2213 skip:
2214   ;
2215
2216 }
2217
2218 /* Called upon entering the first function of a file.  */
2219
2220 static void
2221 __bb_init_file (struct bb *blocks)
2222 {
2223
2224   const struct bb_func *p;
2225   long blk, ncounts = blocks->ncounts;
2226   const char **functions = blocks->functions;
2227
2228   /* Set up linked list.  */
2229   blocks->zero_word = 1;
2230   blocks->next = bb_head;
2231   bb_head = blocks;
2232
2233   blocks->flags = 0;
2234   if (!bb_func_head
2235       || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
2236     return;
2237
2238   for (blk = 0; blk < ncounts; blk++)
2239     blocks->flags[blk] = 0;
2240
2241   for (blk = 0; blk < ncounts; blk++)
2242     {
2243       for (p = bb_func_head; p; p = p->next)
2244         {
2245           if (!strcmp (p->funcname, functions[blk])
2246               && (!p->filename || !strcmp (p->filename, blocks->filename)))
2247             {
2248               blocks->flags[blk] |= p->mode;
2249             }
2250         }
2251     }
2252
2253 }
2254
2255 /* Called when exiting from a function.  */
2256
2257 void
2258 __bb_trace_ret (void)
2259 {
2260
2261   MACHINE_STATE_SAVE("2")
2262
2263   if (bb_callcount)
2264     {
2265       if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2266         {
2267           bb_src = bb_stack[bb_callcount];
2268           if (bb_mode & 8)
2269             __bb_trace_func_ret ();
2270         }
2271
2272       bb_callcount -= 1;
2273     }
2274
2275   MACHINE_STATE_RESTORE("2")
2276
2277 }
2278
2279 /* Called when entering a function.  */
2280
2281 void
2282 __bb_init_trace_func (struct bb *blocks, unsigned long blockno)
2283 {
2284   static int trace_init = 0;
2285
2286   MACHINE_STATE_SAVE("3")
2287
2288   if (!blocks->zero_word)
2289     { 
2290       if (!trace_init)
2291         { 
2292           trace_init = 1;
2293           __bb_init_prg ();
2294         }
2295       __bb_init_file (blocks);
2296     }
2297
2298   if (bb_callcount)
2299     {
2300
2301       bb_callcount += 1;
2302
2303       if (bb_mode & 12)
2304         {
2305           if (bb_callcount >= bb_stacksize)
2306             {
2307               size_t newsize = bb_callcount + 100;
2308
2309               bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2310               if (! bb_stack)
2311                 {
2312                   if (!reported)
2313                     {
2314                       fprintf (stderr, "Profiler: out of memory\n");
2315                       reported = 1;
2316                     }
2317                   bb_stacksize = 0;
2318                   goto stack_overflow;
2319                 }
2320               bb_stacksize = newsize;
2321             }
2322           bb_stack[bb_callcount] = bb_src;
2323
2324           if (bb_mode & 4)
2325             bb_src = 0;
2326
2327         }
2328
2329 stack_overflow:;
2330
2331     }
2332
2333   else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2334     {
2335       bb_callcount = 1;
2336       bb_src = 0;
2337
2338       if (bb_stack)
2339           bb_stack[bb_callcount] = bb_src;
2340     }
2341
2342   MACHINE_STATE_RESTORE("3")
2343 }
2344
2345 #endif /* not inhibit_libc */
2346 #endif /* not BLOCK_PROFILER_CODE */
2347 #endif /* L_bb */
2348 \f
2349 #ifdef L_clear_cache
2350 /* Clear part of an instruction cache.  */
2351
2352 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2353
2354 void
2355 __clear_cache (char *beg __attribute__((__unused__)),
2356                char *end __attribute__((__unused__)))
2357 {
2358 #ifdef CLEAR_INSN_CACHE 
2359   CLEAR_INSN_CACHE (beg, end);
2360 #else
2361 #ifdef INSN_CACHE_SIZE
2362   static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
2363   static int initialized;
2364   int offset;
2365   void *start_addr
2366   void *end_addr;
2367   typedef (*function_ptr) (void);
2368
2369 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2370   /* It's cheaper to clear the whole cache.
2371      Put in a series of jump instructions so that calling the beginning
2372      of the cache will clear the whole thing.  */
2373
2374   if (! initialized)
2375     {
2376       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2377                  & -INSN_CACHE_LINE_WIDTH);
2378       int end_ptr = ptr + INSN_CACHE_SIZE;
2379
2380       while (ptr < end_ptr)
2381         {
2382           *(INSTRUCTION_TYPE *)ptr
2383             = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2384           ptr += INSN_CACHE_LINE_WIDTH;
2385         }
2386       *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
2387
2388       initialized = 1;
2389     }
2390
2391   /* Call the beginning of the sequence.  */
2392   (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2393                     & -INSN_CACHE_LINE_WIDTH))
2394    ());
2395
2396 #else /* Cache is large.  */
2397
2398   if (! initialized)
2399     {
2400       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2401                  & -INSN_CACHE_LINE_WIDTH);
2402
2403       while (ptr < (int) array + sizeof array)
2404         {
2405           *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2406           ptr += INSN_CACHE_LINE_WIDTH;
2407         }
2408
2409       initialized = 1;
2410     }
2411
2412   /* Find the location in array that occupies the same cache line as BEG.  */
2413
2414   offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2415   start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2416                  & -INSN_CACHE_PLANE_SIZE)
2417                 + offset);
2418
2419   /* Compute the cache alignment of the place to stop clearing.  */
2420 #if 0  /* This is not needed for gcc's purposes.  */
2421   /* If the block to clear is bigger than a cache plane,
2422      we clear the entire cache, and OFFSET is already correct.  */ 
2423   if (end < beg + INSN_CACHE_PLANE_SIZE)
2424 #endif
2425     offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2426                & -INSN_CACHE_LINE_WIDTH)
2427               & (INSN_CACHE_PLANE_SIZE - 1));
2428
2429 #if INSN_CACHE_DEPTH > 1
2430   end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2431   if (end_addr <= start_addr)
2432     end_addr += INSN_CACHE_PLANE_SIZE;
2433
2434   for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2435     {
2436       int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2437       int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2438
2439       while (addr != stop)
2440         {
2441           /* Call the return instruction at ADDR.  */
2442           ((function_ptr) addr) ();
2443
2444           addr += INSN_CACHE_LINE_WIDTH;
2445         }
2446     }
2447 #else /* just one plane */
2448   do
2449     {
2450       /* Call the return instruction at START_ADDR.  */
2451       ((function_ptr) start_addr) ();
2452
2453       start_addr += INSN_CACHE_LINE_WIDTH;
2454     }
2455   while ((start_addr % INSN_CACHE_SIZE) != offset);
2456 #endif /* just one plane */
2457 #endif /* Cache is large */
2458 #endif /* Cache exists */
2459 #endif /* CLEAR_INSN_CACHE */
2460 }
2461
2462 #endif /* L_clear_cache */
2463 \f
2464 #ifdef L_trampoline
2465
2466 /* Jump to a trampoline, loading the static chain address.  */
2467
2468 #if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
2469
2470 long
2471 getpagesize (void)
2472 {
2473 #ifdef _ALPHA_
2474   return 8192;
2475 #else
2476   return 4096;
2477 #endif
2478 }
2479
2480 #ifdef __i386__
2481 extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
2482 #endif
2483
2484 int
2485 mprotect (char *addr, int len, int prot)
2486 {
2487   int np, op;
2488
2489   if (prot == 7)
2490     np = 0x40;
2491   else if (prot == 5)
2492     np = 0x20;
2493   else if (prot == 4)
2494     np = 0x10;
2495   else if (prot == 3)
2496     np = 0x04;
2497   else if (prot == 1)
2498     np = 0x02;
2499   else if (prot == 0)
2500     np = 0x01;
2501
2502   if (VirtualProtect (addr, len, np, &op))
2503     return 0;
2504   else
2505     return -1;
2506 }
2507
2508 #endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
2509
2510 #ifdef TRANSFER_FROM_TRAMPOLINE 
2511 TRANSFER_FROM_TRAMPOLINE 
2512 #endif
2513
2514 #if defined (NeXT) && defined (__MACH__)
2515
2516 /* Make stack executable so we can call trampolines on stack.
2517    This is called from INITIALIZE_TRAMPOLINE in next.h.  */
2518 #ifdef NeXTStep21
2519  #include <mach.h>
2520 #else
2521  #include <mach/mach.h>
2522 #endif
2523
2524 void
2525 __enable_execute_stack (char *addr)
2526 {
2527   kern_return_t r;
2528   char *eaddr = addr + TRAMPOLINE_SIZE;
2529   vm_address_t a = (vm_address_t) addr;
2530
2531   /* turn on execute access on stack */
2532   r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2533   if (r != KERN_SUCCESS)
2534     {
2535       mach_error("vm_protect VM_PROT_ALL", r);
2536       exit(1);
2537     }
2538
2539   /* We inline the i-cache invalidation for speed */
2540
2541 #ifdef CLEAR_INSN_CACHE
2542   CLEAR_INSN_CACHE (addr, eaddr);
2543 #else
2544   __clear_cache ((int) addr, (int) eaddr);
2545 #endif
2546
2547
2548 #endif /* defined (NeXT) && defined (__MACH__) */
2549
2550 #ifdef __convex__
2551
2552 /* Make stack executable so we can call trampolines on stack.
2553    This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
2554
2555 #include <sys/mman.h>
2556 #include <sys/vmparam.h>
2557 #include <machine/machparam.h>
2558
2559 void
2560 __enable_execute_stack (void)
2561 {
2562   int fp;
2563   static unsigned lowest = USRSTACK;
2564   unsigned current = (unsigned) &fp & -NBPG;
2565
2566   if (lowest > current)
2567     {
2568       unsigned len = lowest - current;
2569       mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2570       lowest = current;
2571     }
2572
2573   /* Clear instruction cache in case an old trampoline is in it.  */
2574   asm ("pich");
2575 }
2576 #endif /* __convex__ */
2577
2578 #ifdef __sysV88__
2579
2580 /* Modified from the convex -code above.  */
2581
2582 #include <sys/param.h>
2583 #include <errno.h>
2584 #include <sys/m88kbcs.h>
2585
2586 void
2587 __enable_execute_stack (void)
2588 {
2589   int save_errno;
2590   static unsigned long lowest = USRSTACK;
2591   unsigned long current = (unsigned long) &save_errno & -NBPC;
2592   
2593   /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2594      address is seen as 'negative'. That is the case with the stack.   */
2595
2596   save_errno=errno;
2597   if (lowest > current)
2598     {
2599       unsigned len=lowest-current;
2600       memctl(current,len,MCT_TEXT);
2601       lowest = current;
2602     }
2603   else
2604     memctl(current,NBPC,MCT_TEXT);
2605   errno=save_errno;
2606 }
2607
2608 #endif /* __sysV88__ */
2609
2610 #ifdef __sysV68__
2611
2612 #include <sys/signal.h>
2613 #include <errno.h>
2614
2615 /* Motorola forgot to put memctl.o in the libp version of libc881.a,
2616    so define it here, because we need it in __clear_insn_cache below */
2617 /* On older versions of this OS, no memctl or MCT_TEXT are defined;
2618    hence we enable this stuff only if MCT_TEXT is #define'd.  */
2619
2620 #ifdef MCT_TEXT
2621 asm("\n\
2622         global memctl\n\
2623 memctl:\n\
2624         movq &75,%d0\n\
2625         trap &0\n\
2626         bcc.b noerror\n\
2627         jmp cerror%\n\
2628 noerror:\n\
2629         movq &0,%d0\n\
2630         rts");
2631 #endif
2632
2633 /* Clear instruction cache so we can call trampolines on stack.
2634    This is called from FINALIZE_TRAMPOLINE in mot3300.h.  */
2635
2636 void
2637 __clear_insn_cache (void)
2638 {
2639 #ifdef MCT_TEXT
2640   int save_errno;
2641
2642   /* Preserve errno, because users would be surprised to have
2643   errno changing without explicitly calling any system-call. */
2644   save_errno = errno;
2645
2646   /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache. 
2647      No need to use an address derived from _start or %sp, as 0 works also. */
2648   memctl(0, 4096, MCT_TEXT);
2649   errno = save_errno;
2650 #endif
2651 }
2652
2653 #endif /* __sysV68__ */
2654
2655 #ifdef __pyr__
2656
2657 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2658 #include <stdio.h>
2659 #include <sys/mman.h>
2660 #include <sys/types.h>
2661 #include <sys/param.h>
2662 #include <sys/vmmac.h>
2663
2664 /* Modified from the convex -code above.
2665    mremap promises to clear the i-cache.  */
2666
2667 void
2668 __enable_execute_stack (void)
2669 {
2670   int fp;
2671   if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2672                 PROT_READ|PROT_WRITE|PROT_EXEC))
2673     {
2674       perror ("mprotect in __enable_execute_stack");
2675       fflush (stderr);
2676       abort ();
2677     }
2678 }
2679 #endif /* __pyr__ */
2680
2681 #if defined (sony_news) && defined (SYSTYPE_BSD)
2682
2683 #include <stdio.h>
2684 #include <sys/types.h>
2685 #include <sys/param.h>
2686 #include <syscall.h>
2687 #include <machine/sysnews.h>
2688
2689 /* cacheflush function for NEWS-OS 4.2.
2690    This function is called from trampoline-initialize code
2691    defined in config/mips/mips.h.  */
2692
2693 void
2694 cacheflush (char *beg, int size, int flag)
2695 {
2696   if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
2697     {
2698       perror ("cache_flush");
2699       fflush (stderr);
2700       abort ();
2701     }
2702 }
2703
2704 #endif /* sony_news */
2705 #endif /* L_trampoline */
2706 \f
2707 #ifndef __CYGWIN__
2708 #ifdef L__main
2709
2710 #include "gbl-ctors.h"
2711 /* Some systems use __main in a way incompatible with its use in gcc, in these
2712    cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2713    give the same symbol without quotes for an alternative entry point.  You
2714    must define both, or neither.  */
2715 #ifndef NAME__MAIN
2716 #define NAME__MAIN "__main"
2717 #define SYMBOL__MAIN __main
2718 #endif
2719
2720 #ifdef INIT_SECTION_ASM_OP
2721 #undef HAS_INIT_SECTION
2722 #define HAS_INIT_SECTION
2723 #endif
2724
2725 #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
2726
2727 /* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
2728    code to run constructors.  In that case, we need to handle EH here, too.  */
2729
2730 #ifdef EH_FRAME_SECTION
2731 #include "unwind-dw2-fde.h"
2732 extern unsigned char __EH_FRAME_BEGIN__[];
2733 #endif
2734
2735 /* Run all the global destructors on exit from the program.  */
2736
2737 void
2738 __do_global_dtors (void)
2739 {
2740 #ifdef DO_GLOBAL_DTORS_BODY
2741   DO_GLOBAL_DTORS_BODY;
2742 #else
2743   static func_ptr *p = __DTOR_LIST__ + 1;
2744   while (*p)
2745     {
2746       p++;
2747       (*(p-1)) ();
2748     }
2749 #endif
2750 #if defined (EH_FRAME_SECTION) && !defined (HAS_INIT_SECTION)
2751   {
2752     static int completed = 0;
2753     if (! completed)
2754       {
2755         completed = 1;
2756         __deregister_frame_info (__EH_FRAME_BEGIN__);
2757       }
2758   }
2759 #endif
2760 }
2761 #endif
2762
2763 #ifndef HAS_INIT_SECTION
2764 /* Run all the global constructors on entry to the program.  */
2765
2766 void
2767 __do_global_ctors (void)
2768 {
2769 #ifdef EH_FRAME_SECTION
2770   {
2771     static struct object object;
2772     __register_frame_info (__EH_FRAME_BEGIN__, &object);
2773   }
2774 #endif
2775   DO_GLOBAL_CTORS_BODY;
2776   atexit (__do_global_dtors);
2777 }
2778 #endif /* no HAS_INIT_SECTION */
2779
2780 #if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
2781 /* Subroutine called automatically by `main'.
2782    Compiling a global function named `main'
2783    produces an automatic call to this function at the beginning.
2784
2785    For many systems, this routine calls __do_global_ctors.
2786    For systems which support a .init section we use the .init section
2787    to run __do_global_ctors, so we need not do anything here.  */
2788
2789 void
2790 SYMBOL__MAIN ()
2791 {
2792   /* Support recursive calls to `main': run initializers just once.  */
2793   static int initialized;
2794   if (! initialized)
2795     {
2796       initialized = 1;
2797       __do_global_ctors ();
2798     }
2799 }
2800 #endif /* no HAS_INIT_SECTION or INVOKE__main */
2801
2802 #endif /* L__main */
2803 #endif /* __CYGWIN__ */
2804 \f
2805 #ifdef L_ctors
2806
2807 #include "gbl-ctors.h"
2808
2809 /* Provide default definitions for the lists of constructors and
2810    destructors, so that we don't get linker errors.  These symbols are
2811    intentionally bss symbols, so that gld and/or collect will provide
2812    the right values.  */
2813
2814 /* We declare the lists here with two elements each,
2815    so that they are valid empty lists if no other definition is loaded.
2816
2817    If we are using the old "set" extensions to have the gnu linker
2818    collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
2819    must be in the bss/common section.
2820
2821    Long term no port should use those extensions.  But many still do.  */
2822 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2823 #if defined (ASM_OUTPUT_CONSTRUCTOR) || defined (USE_COLLECT2)
2824 func_ptr __CTOR_LIST__[2] = {0, 0};
2825 func_ptr __DTOR_LIST__[2] = {0, 0};
2826 #else
2827 func_ptr __CTOR_LIST__[2];
2828 func_ptr __DTOR_LIST__[2];
2829 #endif
2830 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2831 #endif /* L_ctors */
2832 \f
2833 #ifdef L_exit
2834
2835 #include "gbl-ctors.h"
2836
2837 #ifdef NEED_ATEXIT
2838
2839 #ifndef ON_EXIT
2840
2841 # include <errno.h>
2842
2843 static func_ptr *atexit_chain = 0;
2844 static long atexit_chain_length = 0;
2845 static volatile long last_atexit_chain_slot = -1;
2846
2847 int
2848 atexit (func_ptr func)
2849 {
2850   if (++last_atexit_chain_slot == atexit_chain_length)
2851     {
2852       atexit_chain_length += 32;
2853       if (atexit_chain)
2854         atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2855                                              * sizeof (func_ptr));
2856       else
2857         atexit_chain = (func_ptr *) malloc (atexit_chain_length
2858                                             * sizeof (func_ptr));
2859       if (! atexit_chain)
2860         {
2861           atexit_chain_length = 0;
2862           last_atexit_chain_slot = -1;
2863           errno = ENOMEM;
2864           return (-1);
2865         }
2866     }
2867   atexit_chain[last_atexit_chain_slot] = func;
2868   return (0);
2869 }
2870
2871 extern void _cleanup (void);
2872 extern void _exit (int) __attribute__ ((__noreturn__));
2873
2874 void 
2875 exit (int status)
2876 {
2877   if (atexit_chain)
2878     {
2879       for ( ; last_atexit_chain_slot-- >= 0; )
2880         {
2881           (*atexit_chain[last_atexit_chain_slot + 1]) ();
2882           atexit_chain[last_atexit_chain_slot + 1] = 0;
2883         }
2884       free (atexit_chain);
2885       atexit_chain = 0;
2886     }
2887 #ifdef EXIT_BODY
2888   EXIT_BODY;
2889 #else
2890   _cleanup ();
2891 #endif
2892   _exit (status);
2893 }
2894
2895 #else /* ON_EXIT */
2896
2897 /* Simple; we just need a wrapper for ON_EXIT.  */
2898 int
2899 atexit (func_ptr func)
2900 {
2901   return ON_EXIT (func);
2902 }
2903
2904 #endif /* ON_EXIT */
2905 #endif /* NEED_ATEXIT */
2906
2907 #endif /* L_exit */