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