OSDN Git Service

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