* libgcc2.c (*): Replace EH_FRAME_SECTION with EH_FRAME_SECTION_NAME.
[gcc.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 #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 */