re PR target/8343 ([m68k] [3.2 regression] m68k-elf/rtems ICE at instantiate_virtual_...
[official-gcc.git] / gcc / libgcc2.c
blobac978ab48ad75ef44e7c59b47d3e99db9d15a36c
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, 2002 Free Software Foundation, Inc.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
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.)
22 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23 WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 for more details.
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING. If not, write to the Free
29 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
30 02111-1307, USA. */
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. */
36 #include "tconfig.h"
37 #include "tsystem.h"
38 #include "coretypes.h"
39 #include "tm.h"
41 /* Don't use `fancy_abort' here even if config.h says to use it. */
42 #ifdef abort
43 #undef abort
44 #endif
46 #include "libgcc2.h"
48 #ifdef DECLARE_LIBRARY_RENAMES
49 DECLARE_LIBRARY_RENAMES
50 #endif
52 #if defined (L_negdi2)
53 DWtype
54 __negdi2 (DWtype u)
56 DWunion w;
57 DWunion uu;
59 uu.ll = u;
61 w.s.low = -uu.s.low;
62 w.s.high = -uu.s.high - ((UWtype) w.s.low > 0);
64 return w.ll;
66 #endif
68 #ifdef L_addvsi3
69 Wtype
70 __addvsi3 (Wtype a, Wtype b)
72 Wtype w;
74 w = a + b;
76 if (b >= 0 ? w < a : w > a)
77 abort ();
79 return w;
81 #endif
83 #ifdef L_addvdi3
84 DWtype
85 __addvdi3 (DWtype a, DWtype b)
87 DWtype w;
89 w = a + b;
91 if (b >= 0 ? w < a : w > a)
92 abort ();
94 return w;
96 #endif
98 #ifdef L_subvsi3
99 Wtype
100 __subvsi3 (Wtype a, Wtype b)
102 #ifdef L_addvsi3
103 return __addvsi3 (a, (-b));
104 #else
105 DWtype w;
107 w = a - b;
109 if (b >= 0 ? w > a : w < a)
110 abort ();
112 return w;
113 #endif
115 #endif
117 #ifdef L_subvdi3
118 DWtype
119 __subvdi3 (DWtype a, DWtype b)
121 #ifdef L_addvdi3
122 return (a, (-b));
123 #else
124 DWtype w;
126 w = a - b;
128 if (b >= 0 ? w > a : w < a)
129 abort ();
131 return w;
132 #endif
134 #endif
136 #ifdef L_mulvsi3
137 Wtype
138 __mulvsi3 (Wtype a, Wtype b)
140 DWtype w;
142 w = a * b;
144 if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0)
145 abort ();
147 return w;
149 #endif
151 #ifdef L_negvsi2
152 Wtype
153 __negvsi2 (Wtype a)
155 Wtype w;
157 w = -a;
159 if (a >= 0 ? w > 0 : w < 0)
160 abort ();
162 return w;
164 #endif
166 #ifdef L_negvdi2
167 DWtype
168 __negvdi2 (DWtype a)
170 DWtype w;
172 w = -a;
174 if (a >= 0 ? w > 0 : w < 0)
175 abort ();
177 return w;
179 #endif
181 #ifdef L_absvsi2
182 Wtype
183 __absvsi2 (Wtype a)
185 Wtype w = a;
187 if (a < 0)
188 #ifdef L_negvsi2
189 w = __negvsi2 (a);
190 #else
191 w = -a;
193 if (w < 0)
194 abort ();
195 #endif
197 return w;
199 #endif
201 #ifdef L_absvdi2
202 DWtype
203 __absvdi2 (DWtype a)
205 DWtype w = a;
207 if (a < 0)
208 #ifdef L_negvsi2
209 w = __negvsi2 (a);
210 #else
211 w = -a;
213 if (w < 0)
214 abort ();
215 #endif
217 return w;
219 #endif
221 #ifdef L_mulvdi3
222 DWtype
223 __mulvdi3 (DWtype u, DWtype v)
225 DWtype w;
227 w = u * v;
229 if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0)
230 abort ();
232 return w;
234 #endif
237 /* Unless shift functions are defined whith full ANSI prototypes,
238 parameter b will be promoted to int if word_type is smaller than an int. */
239 #ifdef L_lshrdi3
240 DWtype
241 __lshrdi3 (DWtype u, word_type b)
243 DWunion w;
244 word_type bm;
245 DWunion uu;
247 if (b == 0)
248 return u;
250 uu.ll = u;
252 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
253 if (bm <= 0)
255 w.s.high = 0;
256 w.s.low = (UWtype) uu.s.high >> -bm;
258 else
260 UWtype carries = (UWtype) uu.s.high << bm;
262 w.s.high = (UWtype) uu.s.high >> b;
263 w.s.low = ((UWtype) uu.s.low >> b) | carries;
266 return w.ll;
268 #endif
270 #ifdef L_ashldi3
271 DWtype
272 __ashldi3 (DWtype u, word_type b)
274 DWunion w;
275 word_type bm;
276 DWunion uu;
278 if (b == 0)
279 return u;
281 uu.ll = u;
283 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
284 if (bm <= 0)
286 w.s.low = 0;
287 w.s.high = (UWtype) uu.s.low << -bm;
289 else
291 UWtype carries = (UWtype) uu.s.low >> bm;
293 w.s.low = (UWtype) uu.s.low << b;
294 w.s.high = ((UWtype) uu.s.high << b) | carries;
297 return w.ll;
299 #endif
301 #ifdef L_ashrdi3
302 DWtype
303 __ashrdi3 (DWtype u, word_type b)
305 DWunion w;
306 word_type bm;
307 DWunion uu;
309 if (b == 0)
310 return u;
312 uu.ll = u;
314 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
315 if (bm <= 0)
317 /* w.s.high = 1..1 or 0..0 */
318 w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1);
319 w.s.low = uu.s.high >> -bm;
321 else
323 UWtype carries = (UWtype) uu.s.high << bm;
325 w.s.high = uu.s.high >> b;
326 w.s.low = ((UWtype) uu.s.low >> b) | carries;
329 return w.ll;
331 #endif
333 #ifdef L_ffsdi2
334 DWtype
335 __ffsdi2 (DWtype u)
337 DWunion uu;
338 UWtype word, count, add;
340 uu.ll = u;
341 if (uu.s.low != 0)
342 word = uu.s.low, add = 0;
343 else if (uu.s.high != 0)
344 word = uu.s.high, add = BITS_PER_UNIT * sizeof (Wtype);
345 else
346 return 0;
348 count_trailing_zeros (count, word);
349 return count + add + 1;
351 #endif
353 #ifdef L_muldi3
354 DWtype
355 __muldi3 (DWtype u, DWtype v)
357 DWunion w;
358 DWunion uu, vv;
360 uu.ll = u,
361 vv.ll = v;
363 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
364 w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
365 + (UWtype) uu.s.high * (UWtype) vv.s.low);
367 return w.ll;
369 #endif
371 #if (defined (L_udivdi3) || defined (L_divdi3) || \
372 defined (L_umoddi3) || defined (L_moddi3))
373 #if defined (sdiv_qrnnd)
374 #define L_udiv_w_sdiv
375 #endif
376 #endif
378 #ifdef L_udiv_w_sdiv
379 #if defined (sdiv_qrnnd)
380 #if (defined (L_udivdi3) || defined (L_divdi3) || \
381 defined (L_umoddi3) || defined (L_moddi3))
382 static inline __attribute__ ((__always_inline__))
383 #endif
384 UWtype
385 __udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
387 UWtype q, r;
388 UWtype c0, c1, b1;
390 if ((Wtype) d >= 0)
392 if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
394 /* dividend, divisor, and quotient are nonnegative */
395 sdiv_qrnnd (q, r, a1, a0, d);
397 else
399 /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
400 sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
401 /* Divide (c1*2^32 + c0) by d */
402 sdiv_qrnnd (q, r, c1, c0, d);
403 /* Add 2^31 to quotient */
404 q += (UWtype) 1 << (W_TYPE_SIZE - 1);
407 else
409 b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
410 c1 = a1 >> 1; /* A/2 */
411 c0 = (a1 << (W_TYPE_SIZE - 1)) + (a0 >> 1);
413 if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
415 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
417 r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
418 if ((d & 1) != 0)
420 if (r >= q)
421 r = r - q;
422 else if (q - r <= d)
424 r = r - q + d;
425 q--;
427 else
429 r = r - q + 2*d;
430 q -= 2;
434 else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
436 c1 = (b1 - 1) - c1;
437 c0 = ~c0; /* logical NOT */
439 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
441 q = ~q; /* (A/2)/b1 */
442 r = (b1 - 1) - r;
444 r = 2*r + (a0 & 1); /* A/(2*b1) */
446 if ((d & 1) != 0)
448 if (r >= q)
449 r = r - q;
450 else if (q - r <= d)
452 r = r - q + d;
453 q--;
455 else
457 r = r - q + 2*d;
458 q -= 2;
462 else /* Implies c1 = b1 */
463 { /* Hence a1 = d - 1 = 2*b1 - 1 */
464 if (a0 >= -d)
466 q = -1;
467 r = a0 + d;
469 else
471 q = -2;
472 r = a0 + 2*d;
477 *rp = r;
478 return q;
480 #else
481 /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
482 UWtype
483 __udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
484 UWtype a1 __attribute__ ((__unused__)),
485 UWtype a0 __attribute__ ((__unused__)),
486 UWtype d __attribute__ ((__unused__)))
488 return 0;
490 #endif
491 #endif
493 #if (defined (L_udivdi3) || defined (L_divdi3) || \
494 defined (L_umoddi3) || defined (L_moddi3))
495 #define L_udivmoddi4
496 #endif
498 #ifdef L_clz
499 const UQItype __clz_tab[] =
501 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,
502 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,
503 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,
504 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,
505 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,
506 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,
507 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,
508 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,
510 #endif
512 #ifdef L_udivmoddi4
514 #if (defined (L_udivdi3) || defined (L_divdi3) || \
515 defined (L_umoddi3) || defined (L_moddi3))
516 static inline __attribute__ ((__always_inline__))
517 #endif
518 UDWtype
519 __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
521 DWunion ww;
522 DWunion nn, dd;
523 DWunion rr;
524 UWtype d0, d1, n0, n1, n2;
525 UWtype q0, q1;
526 UWtype b, bm;
528 nn.ll = n;
529 dd.ll = d;
531 d0 = dd.s.low;
532 d1 = dd.s.high;
533 n0 = nn.s.low;
534 n1 = nn.s.high;
536 #if !UDIV_NEEDS_NORMALIZATION
537 if (d1 == 0)
539 if (d0 > n1)
541 /* 0q = nn / 0D */
543 udiv_qrnnd (q0, n0, n1, n0, d0);
544 q1 = 0;
546 /* Remainder in n0. */
548 else
550 /* qq = NN / 0d */
552 if (d0 == 0)
553 d0 = 1 / d0; /* Divide intentionally by zero. */
555 udiv_qrnnd (q1, n1, 0, n1, d0);
556 udiv_qrnnd (q0, n0, n1, n0, d0);
558 /* Remainder in n0. */
561 if (rp != 0)
563 rr.s.low = n0;
564 rr.s.high = 0;
565 *rp = rr.ll;
569 #else /* UDIV_NEEDS_NORMALIZATION */
571 if (d1 == 0)
573 if (d0 > n1)
575 /* 0q = nn / 0D */
577 count_leading_zeros (bm, d0);
579 if (bm != 0)
581 /* Normalize, i.e. make the most significant bit of the
582 denominator set. */
584 d0 = d0 << bm;
585 n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
586 n0 = n0 << bm;
589 udiv_qrnnd (q0, n0, n1, n0, d0);
590 q1 = 0;
592 /* Remainder in n0 >> bm. */
594 else
596 /* qq = NN / 0d */
598 if (d0 == 0)
599 d0 = 1 / d0; /* Divide intentionally by zero. */
601 count_leading_zeros (bm, d0);
603 if (bm == 0)
605 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
606 conclude (the most significant bit of n1 is set) /\ (the
607 leading quotient digit q1 = 1).
609 This special case is necessary, not an optimization.
610 (Shifts counts of W_TYPE_SIZE are undefined.) */
612 n1 -= d0;
613 q1 = 1;
615 else
617 /* Normalize. */
619 b = W_TYPE_SIZE - bm;
621 d0 = d0 << bm;
622 n2 = n1 >> b;
623 n1 = (n1 << bm) | (n0 >> b);
624 n0 = n0 << bm;
626 udiv_qrnnd (q1, n1, n2, n1, d0);
629 /* n1 != d0... */
631 udiv_qrnnd (q0, n0, n1, n0, d0);
633 /* Remainder in n0 >> bm. */
636 if (rp != 0)
638 rr.s.low = n0 >> bm;
639 rr.s.high = 0;
640 *rp = rr.ll;
643 #endif /* UDIV_NEEDS_NORMALIZATION */
645 else
647 if (d1 > n1)
649 /* 00 = nn / DD */
651 q0 = 0;
652 q1 = 0;
654 /* Remainder in n1n0. */
655 if (rp != 0)
657 rr.s.low = n0;
658 rr.s.high = n1;
659 *rp = rr.ll;
662 else
664 /* 0q = NN / dd */
666 count_leading_zeros (bm, d1);
667 if (bm == 0)
669 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
670 conclude (the most significant bit of n1 is set) /\ (the
671 quotient digit q0 = 0 or 1).
673 This special case is necessary, not an optimization. */
675 /* The condition on the next line takes advantage of that
676 n1 >= d1 (true due to program flow). */
677 if (n1 > d1 || n0 >= d0)
679 q0 = 1;
680 sub_ddmmss (n1, n0, n1, n0, d1, d0);
682 else
683 q0 = 0;
685 q1 = 0;
687 if (rp != 0)
689 rr.s.low = n0;
690 rr.s.high = n1;
691 *rp = rr.ll;
694 else
696 UWtype m1, m0;
697 /* Normalize. */
699 b = W_TYPE_SIZE - bm;
701 d1 = (d1 << bm) | (d0 >> b);
702 d0 = d0 << bm;
703 n2 = n1 >> b;
704 n1 = (n1 << bm) | (n0 >> b);
705 n0 = n0 << bm;
707 udiv_qrnnd (q0, n1, n2, n1, d1);
708 umul_ppmm (m1, m0, q0, d0);
710 if (m1 > n1 || (m1 == n1 && m0 > n0))
712 q0--;
713 sub_ddmmss (m1, m0, m1, m0, d1, d0);
716 q1 = 0;
718 /* Remainder in (n1n0 - m1m0) >> bm. */
719 if (rp != 0)
721 sub_ddmmss (n1, n0, n1, n0, m1, m0);
722 rr.s.low = (n1 << b) | (n0 >> bm);
723 rr.s.high = n1 >> bm;
724 *rp = rr.ll;
730 ww.s.low = q0;
731 ww.s.high = q1;
732 return ww.ll;
734 #endif
736 #ifdef L_divdi3
737 DWtype
738 __divdi3 (DWtype u, DWtype v)
740 word_type c = 0;
741 DWunion uu, vv;
742 DWtype w;
744 uu.ll = u;
745 vv.ll = v;
747 if (uu.s.high < 0)
748 c = ~c,
749 uu.ll = -uu.ll;
750 if (vv.s.high < 0)
751 c = ~c,
752 vv.ll = -vv.ll;
754 w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
755 if (c)
756 w = -w;
758 return w;
760 #endif
762 #ifdef L_moddi3
763 DWtype
764 __moddi3 (DWtype u, DWtype v)
766 word_type c = 0;
767 DWunion uu, vv;
768 DWtype w;
770 uu.ll = u;
771 vv.ll = v;
773 if (uu.s.high < 0)
774 c = ~c,
775 uu.ll = -uu.ll;
776 if (vv.s.high < 0)
777 vv.ll = -vv.ll;
779 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
780 if (c)
781 w = -w;
783 return w;
785 #endif
787 #ifdef L_umoddi3
788 UDWtype
789 __umoddi3 (UDWtype u, UDWtype v)
791 UDWtype w;
793 (void) __udivmoddi4 (u, v, &w);
795 return w;
797 #endif
799 #ifdef L_udivdi3
800 UDWtype
801 __udivdi3 (UDWtype n, UDWtype d)
803 return __udivmoddi4 (n, d, (UDWtype *) 0);
805 #endif
807 #ifdef L_cmpdi2
808 word_type
809 __cmpdi2 (DWtype a, DWtype b)
811 DWunion au, bu;
813 au.ll = a, bu.ll = b;
815 if (au.s.high < bu.s.high)
816 return 0;
817 else if (au.s.high > bu.s.high)
818 return 2;
819 if ((UWtype) au.s.low < (UWtype) bu.s.low)
820 return 0;
821 else if ((UWtype) au.s.low > (UWtype) bu.s.low)
822 return 2;
823 return 1;
825 #endif
827 #ifdef L_ucmpdi2
828 word_type
829 __ucmpdi2 (DWtype a, DWtype b)
831 DWunion au, bu;
833 au.ll = a, bu.ll = b;
835 if ((UWtype) au.s.high < (UWtype) bu.s.high)
836 return 0;
837 else if ((UWtype) au.s.high > (UWtype) bu.s.high)
838 return 2;
839 if ((UWtype) au.s.low < (UWtype) bu.s.low)
840 return 0;
841 else if ((UWtype) au.s.low > (UWtype) bu.s.low)
842 return 2;
843 return 1;
845 #endif
847 #if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
848 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
849 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
851 DWtype
852 __fixunstfDI (TFtype a)
854 TFtype b;
855 UDWtype v;
857 if (a < 0)
858 return 0;
860 /* Compute high word of result, as a flonum. */
861 b = (a / HIGH_WORD_COEFF);
862 /* Convert that to fixed (but not to DWtype!),
863 and shift it into the high word. */
864 v = (UWtype) b;
865 v <<= WORD_SIZE;
866 /* Remove high part from the TFtype, leaving the low part as flonum. */
867 a -= (TFtype)v;
868 /* Convert that to fixed (but not to DWtype!) and add it in.
869 Sometimes A comes out negative. This is significant, since
870 A has more bits than a long int does. */
871 if (a < 0)
872 v -= (UWtype) (- a);
873 else
874 v += (UWtype) a;
875 return v;
877 #endif
879 #if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
880 DWtype
881 __fixtfdi (TFtype a)
883 if (a < 0)
884 return - __fixunstfDI (-a);
885 return __fixunstfDI (a);
887 #endif
889 #if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
890 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
891 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
893 DWtype
894 __fixunsxfDI (XFtype a)
896 XFtype b;
897 UDWtype v;
899 if (a < 0)
900 return 0;
902 /* Compute high word of result, as a flonum. */
903 b = (a / HIGH_WORD_COEFF);
904 /* Convert that to fixed (but not to DWtype!),
905 and shift it into the high word. */
906 v = (UWtype) b;
907 v <<= WORD_SIZE;
908 /* Remove high part from the XFtype, leaving the low part as flonum. */
909 a -= (XFtype)v;
910 /* Convert that to fixed (but not to DWtype!) and add it in.
911 Sometimes A comes out negative. This is significant, since
912 A has more bits than a long int does. */
913 if (a < 0)
914 v -= (UWtype) (- a);
915 else
916 v += (UWtype) a;
917 return v;
919 #endif
921 #if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
922 DWtype
923 __fixxfdi (XFtype a)
925 if (a < 0)
926 return - __fixunsxfDI (-a);
927 return __fixunsxfDI (a);
929 #endif
931 #ifdef L_fixunsdfdi
932 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
933 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
935 DWtype
936 __fixunsdfDI (DFtype a)
938 UWtype hi, lo;
940 /* Get high part of result. The division here will just moves the radix
941 point and will not cause any rounding. Then the conversion to integral
942 type chops result as desired. */
943 hi = a / HIGH_WORD_COEFF;
945 /* Get low part of result. Convert `hi' to floating type and scale it back,
946 then subtract this from the number being converted. This leaves the low
947 part. Convert that to integral type. */
948 lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
950 /* Assemble result from the two parts. */
951 return ((UDWtype) hi << WORD_SIZE) | lo;
953 #endif
955 #ifdef L_fixdfdi
956 DWtype
957 __fixdfdi (DFtype a)
959 if (a < 0)
960 return - __fixunsdfDI (-a);
961 return __fixunsdfDI (a);
963 #endif
965 #ifdef L_fixunssfdi
966 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
967 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
969 DWtype
970 __fixunssfDI (SFtype original_a)
972 /* Convert the SFtype to a DFtype, because that is surely not going
973 to lose any bits. Some day someone else can write a faster version
974 that avoids converting to DFtype, and verify it really works right. */
975 DFtype a = original_a;
976 UWtype hi, lo;
978 /* Get high part of result. The division here will just moves the radix
979 point and will not cause any rounding. Then the conversion to integral
980 type chops result as desired. */
981 hi = a / HIGH_WORD_COEFF;
983 /* Get low part of result. Convert `hi' to floating type and scale it back,
984 then subtract this from the number being converted. This leaves the low
985 part. Convert that to integral type. */
986 lo = (a - ((DFtype) hi) * HIGH_WORD_COEFF);
988 /* Assemble result from the two parts. */
989 return ((UDWtype) hi << WORD_SIZE) | lo;
991 #endif
993 #ifdef L_fixsfdi
994 DWtype
995 __fixsfdi (SFtype a)
997 if (a < 0)
998 return - __fixunssfDI (-a);
999 return __fixunssfDI (a);
1001 #endif
1003 #if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
1004 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1005 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1006 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1008 XFtype
1009 __floatdixf (DWtype u)
1011 XFtype d;
1013 d = (Wtype) (u >> WORD_SIZE);
1014 d *= HIGH_HALFWORD_COEFF;
1015 d *= HIGH_HALFWORD_COEFF;
1016 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1018 return d;
1020 #endif
1022 #if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
1023 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1024 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1025 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1027 TFtype
1028 __floatditf (DWtype u)
1030 TFtype d;
1032 d = (Wtype) (u >> WORD_SIZE);
1033 d *= HIGH_HALFWORD_COEFF;
1034 d *= HIGH_HALFWORD_COEFF;
1035 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1037 return d;
1039 #endif
1041 #ifdef L_floatdidf
1042 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1043 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1044 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1046 DFtype
1047 __floatdidf (DWtype u)
1049 DFtype d;
1051 d = (Wtype) (u >> WORD_SIZE);
1052 d *= HIGH_HALFWORD_COEFF;
1053 d *= HIGH_HALFWORD_COEFF;
1054 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1056 return d;
1058 #endif
1060 #ifdef L_floatdisf
1061 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
1062 #define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
1063 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
1065 #define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
1066 #define DF_SIZE DBL_MANT_DIG
1067 #define SF_SIZE FLT_MANT_DIG
1069 SFtype
1070 __floatdisf (DWtype u)
1072 /* Do the calculation in DFmode
1073 so that we don't lose any of the precision of the high word
1074 while multiplying it. */
1075 DFtype f;
1077 /* Protect against double-rounding error.
1078 Represent any low-order bits, that might be truncated in DFmode,
1079 by a bit that won't be lost. The bit can go in anywhere below the
1080 rounding position of the SFmode. A fixed mask and bit position
1081 handles all usual configurations. It doesn't handle the case
1082 of 128-bit DImode, however. */
1083 if (DF_SIZE < DI_SIZE
1084 && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1086 #define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
1087 if (! (- ((DWtype) 1 << DF_SIZE) < u
1088 && u < ((DWtype) 1 << DF_SIZE)))
1090 if ((UDWtype) u & (REP_BIT - 1))
1092 u &= ~ (REP_BIT - 1);
1093 u |= REP_BIT;
1097 f = (Wtype) (u >> WORD_SIZE);
1098 f *= HIGH_HALFWORD_COEFF;
1099 f *= HIGH_HALFWORD_COEFF;
1100 f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1102 return (SFtype) f;
1104 #endif
1106 #if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
1107 /* Reenable the normal types, in case limits.h needs them. */
1108 #undef char
1109 #undef short
1110 #undef int
1111 #undef long
1112 #undef unsigned
1113 #undef float
1114 #undef double
1115 #undef MIN
1116 #undef MAX
1117 #include <limits.h>
1119 UWtype
1120 __fixunsxfSI (XFtype a)
1122 if (a >= - (DFtype) Wtype_MIN)
1123 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1124 return (Wtype) a;
1126 #endif
1128 #ifdef L_fixunsdfsi
1129 /* Reenable the normal types, in case limits.h needs them. */
1130 #undef char
1131 #undef short
1132 #undef int
1133 #undef long
1134 #undef unsigned
1135 #undef float
1136 #undef double
1137 #undef MIN
1138 #undef MAX
1139 #include <limits.h>
1141 UWtype
1142 __fixunsdfSI (DFtype a)
1144 if (a >= - (DFtype) Wtype_MIN)
1145 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1146 return (Wtype) a;
1148 #endif
1150 #ifdef L_fixunssfsi
1151 /* Reenable the normal types, in case limits.h needs them. */
1152 #undef char
1153 #undef short
1154 #undef int
1155 #undef long
1156 #undef unsigned
1157 #undef float
1158 #undef double
1159 #undef MIN
1160 #undef MAX
1161 #include <limits.h>
1163 UWtype
1164 __fixunssfSI (SFtype a)
1166 if (a >= - (SFtype) Wtype_MIN)
1167 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1168 return (Wtype) a;
1170 #endif
1172 /* From here on down, the routines use normal data types. */
1174 #define SItype bogus_type
1175 #define USItype bogus_type
1176 #define DItype bogus_type
1177 #define UDItype bogus_type
1178 #define SFtype bogus_type
1179 #define DFtype bogus_type
1180 #undef Wtype
1181 #undef UWtype
1182 #undef HWtype
1183 #undef UHWtype
1184 #undef DWtype
1185 #undef UDWtype
1187 #undef char
1188 #undef short
1189 #undef int
1190 #undef long
1191 #undef unsigned
1192 #undef float
1193 #undef double
1195 #ifdef L__gcc_bcmp
1197 /* Like bcmp except the sign is meaningful.
1198 Result is negative if S1 is less than S2,
1199 positive if S1 is greater, 0 if S1 and S2 are equal. */
1202 __gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
1204 while (size > 0)
1206 unsigned char c1 = *s1++, c2 = *s2++;
1207 if (c1 != c2)
1208 return c1 - c2;
1209 size--;
1211 return 0;
1214 #endif
1216 /* __eprintf used to be used by GCC's private version of <assert.h>.
1217 We no longer provide that header, but this routine remains in libgcc.a
1218 for binary backward compatibility. Note that it is not included in
1219 the shared version of libgcc. */
1220 #ifdef L_eprintf
1221 #ifndef inhibit_libc
1223 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1224 #include <stdio.h>
1226 void
1227 __eprintf (const char *string, const char *expression,
1228 unsigned int line, const char *filename)
1230 fprintf (stderr, string, expression, line, filename);
1231 fflush (stderr);
1232 abort ();
1235 #endif
1236 #endif
1238 #ifdef L_gcov
1240 /* Gcov profile dumper. Requires atexit and stdio. */
1242 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1243 #include <stdio.h>
1245 #include "gcov-io.h"
1246 #include <string.h>
1247 #if defined (TARGET_HAS_F_SETLKW)
1248 #include <fcntl.h>
1249 #include <errno.h>
1250 #endif
1252 /* Chain of per-object gcov structures. */
1253 static struct gcov_info *gcov_list;
1255 /* A program checksum allows us to distinguish program data for an
1256 object file included in multiple programs. */
1257 static unsigned gcov_crc32;
1259 static void
1260 gcov_version_mismatch (struct gcov_info *ptr, unsigned version)
1262 unsigned expected = GCOV_VERSION;
1263 unsigned ix;
1264 char e[4], v[4];
1266 for (ix = 4; ix--; expected >>= 8, version >>= 8)
1268 e[ix] = expected;
1269 v[ix] = version;
1272 fprintf (stderr,
1273 "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
1274 ptr->filename, e, v);
1277 /* Dump the coverage counts. We merge with existing counts when
1278 possible, to avoid growing the .da files ad infinitum. We use this
1279 program's checksum to make sure we only accumulate whole program
1280 statistics to the correct summary. An object file might be embedded
1281 in two separate programs, and we must keep the two program
1282 summaries separate. */
1284 static void
1285 gcov_exit (void)
1287 struct gcov_info *ptr;
1288 unsigned ix, jx;
1289 struct gcov_summary program;
1290 gcov_type program_max_one = 0;
1291 gcov_type program_max_sum = 0;
1292 gcov_type program_sum = 0;
1293 unsigned program_arcs = 0;
1295 #if defined (TARGET_HAS_F_SETLKW)
1296 struct flock s_flock;
1298 s_flock.l_type = F_WRLCK;
1299 s_flock.l_whence = SEEK_SET;
1300 s_flock.l_start = 0;
1301 s_flock.l_len = 0; /* Until EOF. */
1302 s_flock.l_pid = getpid ();
1303 #endif
1305 memset (&program, 0, sizeof (program));
1306 program.checksum = gcov_crc32;
1308 for (ptr = gcov_list; ptr; ptr = ptr->next)
1310 FILE *da_file;
1311 struct gcov_summary object;
1312 struct gcov_summary local_prg;
1313 int merging = 0;
1314 long base;
1315 const struct function_info *fn_info;
1316 gcov_type *count_ptr;
1317 gcov_type object_max_one = 0;
1319 ptr->wkspc = 0;
1320 if (!ptr->filename)
1321 continue;
1323 for (ix = ptr->n_arc_counts, count_ptr = ptr->arc_counts; ix--;)
1325 gcov_type count = *count_ptr++;
1327 if (count > object_max_one)
1328 object_max_one = count;
1330 if (object_max_one > program_max_one)
1331 program_max_one = object_max_one;
1333 memset (&local_prg, 0, sizeof (local_prg));
1334 memset (&object, 0, sizeof (object));
1336 /* Open for modification */
1337 if ((da_file = fopen (ptr->filename, "r+b")))
1338 merging = 1;
1339 else if ((da_file = fopen (ptr->filename, "w+b")))
1341 else
1343 fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
1344 ptr->filename = 0;
1345 continue;
1348 #if defined (TARGET_HAS_F_SETLKW)
1349 /* After a fork, another process might try to read and/or write
1350 the same file simultanously. So if we can, lock the file to
1351 avoid race conditions. */
1352 while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
1353 && errno == EINTR)
1354 continue;
1355 #endif
1356 if (merging)
1358 /* Merge data from file. */
1359 unsigned tag, length;
1361 if (gcov_read_unsigned (da_file, &tag) || tag != GCOV_DATA_MAGIC)
1363 fprintf (stderr, "profiling:%s:Not a gcov data file\n",
1364 ptr->filename);
1365 read_fatal:;
1366 fclose (da_file);
1367 ptr->filename = 0;
1368 continue;
1370 if (gcov_read_unsigned (da_file, &length) || length != GCOV_VERSION)
1372 gcov_version_mismatch (ptr, length);
1373 goto read_fatal;
1376 /* Merge execution counts for each function. */
1377 count_ptr = ptr->arc_counts;
1378 for (ix = ptr->n_functions, fn_info = ptr->functions;
1379 ix--; fn_info++)
1381 if (gcov_read_unsigned (da_file, &tag)
1382 || gcov_read_unsigned (da_file, &length))
1384 read_error:;
1385 fprintf (stderr, "profiling:%s:Error merging\n",
1386 ptr->filename);
1387 goto read_fatal;
1390 /* Check function */
1391 if (tag != GCOV_TAG_FUNCTION)
1393 read_mismatch:;
1394 fprintf (stderr, "profiling:%s:Merge mismatch at %s\n",
1395 ptr->filename, fn_info->name);
1396 goto read_fatal;
1399 unsigned flength, checksum;
1401 if (gcov_read_unsigned (da_file, &flength)
1402 || gcov_skip_string (da_file, flength)
1403 || gcov_read_unsigned (da_file, &checksum))
1404 goto read_error;
1405 if (flength != strlen (fn_info->name)
1406 || checksum != fn_info->checksum)
1407 goto read_mismatch;
1409 /* Check arc counts */
1410 if (gcov_read_unsigned (da_file, &tag)
1411 || gcov_read_unsigned (da_file, &length))
1412 goto read_error;
1413 if (tag != GCOV_TAG_ARC_COUNTS
1414 || length / 8 != fn_info->n_arc_counts)
1415 goto read_mismatch;
1417 gcov_type count;
1419 for (jx = fn_info->n_arc_counts; jx--; count_ptr++)
1420 if (gcov_read_counter (da_file, &count))
1421 goto read_error;
1422 else
1423 *count_ptr += count;
1427 /* Check object summary */
1428 if (gcov_read_unsigned (da_file, &tag)
1429 || gcov_read_unsigned (da_file, &length))
1430 goto read_error;
1431 if (tag != GCOV_TAG_OBJECT_SUMMARY)
1432 goto read_mismatch;
1433 if (gcov_read_summary (da_file, &object))
1434 goto read_error;
1436 /* Check program summary */
1437 while (1)
1439 long base = ftell (da_file);
1441 if (gcov_read_unsigned (da_file, &tag)
1442 || gcov_read_unsigned (da_file, &length))
1444 if (feof (da_file))
1445 break;
1446 goto read_error;
1448 if (tag != GCOV_TAG_PROGRAM_SUMMARY
1449 && tag != GCOV_TAG_PLACEHOLDER_SUMMARY
1450 && tag != GCOV_TAG_INCORRECT_SUMMARY)
1451 goto read_mismatch;
1452 if (gcov_read_summary (da_file, &local_prg))
1453 goto read_error;
1454 if (local_prg.checksum != program.checksum)
1455 continue;
1456 if (tag == GCOV_TAG_PLACEHOLDER_SUMMARY)
1458 fprintf (stderr,
1459 "profiling:%s:Concurrent race detected\n",
1460 ptr->filename);
1461 goto read_fatal;
1463 merging = -1;
1464 if (tag != GCOV_TAG_PROGRAM_SUMMARY)
1465 break;
1467 if (program.runs
1468 && memcmp (&program, &local_prg, sizeof (program)))
1470 fprintf (stderr, "profiling:%s:Invocation mismatch\n",
1471 ptr->filename);
1472 local_prg.runs = 0;
1474 else
1475 memcpy (&program, &local_prg, sizeof (program));
1476 ptr->wkspc = base;
1477 break;
1479 fseek (da_file, 0, SEEK_SET);
1482 object.runs++;
1483 object.arcs = ptr->n_arc_counts;
1484 object.arc_sum = 0;
1485 if (object.arc_max_one < object_max_one)
1486 object.arc_max_one = object_max_one;
1487 object.arc_sum_max += object_max_one;
1489 /* Write out the data. */
1490 if (/* magic */
1491 gcov_write_unsigned (da_file, GCOV_DATA_MAGIC)
1492 /* version number */
1493 || gcov_write_unsigned (da_file, GCOV_VERSION))
1495 write_error:;
1496 fclose (da_file);
1497 fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
1498 ptr->filename = 0;
1499 continue;
1502 /* Write execution counts for each function. */
1503 count_ptr = ptr->arc_counts;
1504 for (ix = ptr->n_functions, fn_info = ptr->functions; ix--; fn_info++)
1506 /* Announce function. */
1507 if (gcov_write_unsigned (da_file, GCOV_TAG_FUNCTION)
1508 || !(base = gcov_reserve_length (da_file))
1509 /* function name */
1510 || gcov_write_string (da_file, fn_info->name,
1511 strlen (fn_info->name))
1512 /* function checksum */
1513 || gcov_write_unsigned (da_file, fn_info->checksum)
1514 || gcov_write_length (da_file, base))
1515 goto write_error;
1517 /* arc counts. */
1518 if (gcov_write_unsigned (da_file, GCOV_TAG_ARC_COUNTS)
1519 || !(base = gcov_reserve_length (da_file)))
1520 goto write_error;
1522 for (jx = fn_info->n_arc_counts; jx--;)
1524 gcov_type count = *count_ptr++;
1526 object.arc_sum += count;
1527 if (object.arc_max_sum < count)
1528 object.arc_max_sum = count;
1529 if (gcov_write_counter (da_file, count))
1530 goto write_error; /* RIP Edsger Dijkstra */
1532 if (gcov_write_length (da_file, base))
1533 goto write_error;
1536 /* Object file summary. */
1537 if (gcov_write_summary (da_file, GCOV_TAG_OBJECT_SUMMARY, &object))
1538 goto write_error;
1540 if (merging >= 0)
1542 if (fseek (da_file, 0, SEEK_END))
1543 goto write_error;
1544 ptr->wkspc = ftell (da_file);
1545 if (gcov_write_summary (da_file, GCOV_TAG_PLACEHOLDER_SUMMARY,
1546 &program))
1547 goto write_error;
1549 else if (ptr->wkspc)
1551 /* Zap trailing program summary */
1552 if (fseek (da_file, ptr->wkspc, SEEK_SET))
1553 goto write_error;
1554 if (!local_prg.runs)
1555 ptr->wkspc = 0;
1556 if (gcov_write_unsigned (da_file,
1557 local_prg.runs ? GCOV_TAG_PLACEHOLDER_SUMMARY
1558 : GCOV_TAG_INCORRECT_SUMMARY))
1559 goto write_error;
1561 if (fflush (da_file))
1562 goto write_error;
1564 if (fclose (da_file))
1566 fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
1567 ptr->filename = 0;
1569 else
1571 program_arcs += ptr->n_arc_counts;
1572 program_sum += object.arc_sum;
1573 if (program_max_sum < object.arc_max_sum)
1574 program_max_sum = object.arc_max_sum;
1578 /* Generate whole program statistics. */
1579 program.runs++;
1580 program.arcs = program_arcs;
1581 program.arc_sum = program_sum;
1582 if (program.arc_max_one < program_max_one)
1583 program.arc_max_one = program_max_one;
1584 if (program.arc_max_sum < program_max_sum)
1585 program.arc_max_sum = program_max_sum;
1586 program.arc_sum_max += program_max_one;
1588 /* Upate whole program statistics. */
1589 for (ptr = gcov_list; ptr; ptr = ptr->next)
1590 if (ptr->filename && ptr->wkspc)
1592 FILE *da_file;
1594 da_file = fopen (ptr->filename, "r+b");
1595 if (!da_file)
1597 fprintf (stderr, "profiling:%s:Cannot open\n", ptr->filename);
1598 continue;
1601 #if defined (TARGET_HAS_F_SETLKW)
1602 while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
1603 && errno == EINTR)
1604 continue;
1605 #endif
1606 if (fseek (da_file, ptr->wkspc, SEEK_SET)
1607 || gcov_write_summary (da_file, GCOV_TAG_PROGRAM_SUMMARY, &program)
1608 || fflush (da_file))
1609 fprintf (stderr, "profiling:%s:Error writing\n", ptr->filename);
1610 if (fclose (da_file))
1611 fprintf (stderr, "profiling:%s:Error closing\n", ptr->filename);
1615 /* Add a new object file onto the bb chain. Invoked automatically
1616 when running an object file's global ctors. */
1618 void
1619 __gcov_init (struct gcov_info *info)
1621 if (!info->version)
1622 return;
1623 if (info->version != GCOV_VERSION)
1624 gcov_version_mismatch (info, info->version);
1625 else
1627 const char *ptr = info->filename;
1628 unsigned crc32 = gcov_crc32;
1632 unsigned ix;
1633 unsigned value = *ptr << 24;
1635 for (ix = 8; ix--; value <<= 1)
1637 unsigned feedback;
1639 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
1640 crc32 <<= 1;
1641 crc32 ^= feedback;
1644 while (*ptr++);
1646 gcov_crc32 = crc32;
1648 if (!gcov_list)
1649 atexit (gcov_exit);
1651 info->next = gcov_list;
1652 gcov_list = info;
1654 info->version = 0;
1657 /* Called before fork or exec - write out profile information gathered so
1658 far and reset it to zero. This avoids duplication or loss of the
1659 profile information gathered so far. */
1661 void
1662 __gcov_flush (void)
1664 struct gcov_info *ptr;
1666 gcov_exit ();
1667 for (ptr = gcov_list; ptr; ptr = ptr->next)
1669 unsigned i;
1671 for (i = ptr->n_arc_counts; i--;)
1672 ptr->arc_counts[i] = 0;
1676 #endif /* L_gcov */
1678 #ifdef L_clear_cache
1679 /* Clear part of an instruction cache. */
1681 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1683 void
1684 __clear_cache (char *beg __attribute__((__unused__)),
1685 char *end __attribute__((__unused__)))
1687 #ifdef CLEAR_INSN_CACHE
1688 CLEAR_INSN_CACHE (beg, end);
1689 #else
1690 #ifdef INSN_CACHE_SIZE
1691 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1692 static int initialized;
1693 int offset;
1694 void *start_addr
1695 void *end_addr;
1696 typedef (*function_ptr) (void);
1698 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1699 /* It's cheaper to clear the whole cache.
1700 Put in a series of jump instructions so that calling the beginning
1701 of the cache will clear the whole thing. */
1703 if (! initialized)
1705 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1706 & -INSN_CACHE_LINE_WIDTH);
1707 int end_ptr = ptr + INSN_CACHE_SIZE;
1709 while (ptr < end_ptr)
1711 *(INSTRUCTION_TYPE *)ptr
1712 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1713 ptr += INSN_CACHE_LINE_WIDTH;
1715 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1717 initialized = 1;
1720 /* Call the beginning of the sequence. */
1721 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1722 & -INSN_CACHE_LINE_WIDTH))
1723 ());
1725 #else /* Cache is large. */
1727 if (! initialized)
1729 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1730 & -INSN_CACHE_LINE_WIDTH);
1732 while (ptr < (int) array + sizeof array)
1734 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1735 ptr += INSN_CACHE_LINE_WIDTH;
1738 initialized = 1;
1741 /* Find the location in array that occupies the same cache line as BEG. */
1743 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1744 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1745 & -INSN_CACHE_PLANE_SIZE)
1746 + offset);
1748 /* Compute the cache alignment of the place to stop clearing. */
1749 #if 0 /* This is not needed for gcc's purposes. */
1750 /* If the block to clear is bigger than a cache plane,
1751 we clear the entire cache, and OFFSET is already correct. */
1752 if (end < beg + INSN_CACHE_PLANE_SIZE)
1753 #endif
1754 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1755 & -INSN_CACHE_LINE_WIDTH)
1756 & (INSN_CACHE_PLANE_SIZE - 1));
1758 #if INSN_CACHE_DEPTH > 1
1759 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1760 if (end_addr <= start_addr)
1761 end_addr += INSN_CACHE_PLANE_SIZE;
1763 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1765 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1766 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1768 while (addr != stop)
1770 /* Call the return instruction at ADDR. */
1771 ((function_ptr) addr) ();
1773 addr += INSN_CACHE_LINE_WIDTH;
1776 #else /* just one plane */
1779 /* Call the return instruction at START_ADDR. */
1780 ((function_ptr) start_addr) ();
1782 start_addr += INSN_CACHE_LINE_WIDTH;
1784 while ((start_addr % INSN_CACHE_SIZE) != offset);
1785 #endif /* just one plane */
1786 #endif /* Cache is large */
1787 #endif /* Cache exists */
1788 #endif /* CLEAR_INSN_CACHE */
1791 #endif /* L_clear_cache */
1793 #ifdef L_trampoline
1795 /* Jump to a trampoline, loading the static chain address. */
1797 #if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
1799 long
1800 getpagesize (void)
1802 #ifdef _ALPHA_
1803 return 8192;
1804 #else
1805 return 4096;
1806 #endif
1809 #ifdef __i386__
1810 extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
1811 #endif
1814 mprotect (char *addr, int len, int prot)
1816 int np, op;
1818 if (prot == 7)
1819 np = 0x40;
1820 else if (prot == 5)
1821 np = 0x20;
1822 else if (prot == 4)
1823 np = 0x10;
1824 else if (prot == 3)
1825 np = 0x04;
1826 else if (prot == 1)
1827 np = 0x02;
1828 else if (prot == 0)
1829 np = 0x01;
1831 if (VirtualProtect (addr, len, np, &op))
1832 return 0;
1833 else
1834 return -1;
1837 #endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
1839 #ifdef TRANSFER_FROM_TRAMPOLINE
1840 TRANSFER_FROM_TRAMPOLINE
1841 #endif
1843 #ifdef __sysV68__
1845 #include <sys/signal.h>
1846 #include <errno.h>
1848 /* Motorola forgot to put memctl.o in the libp version of libc881.a,
1849 so define it here, because we need it in __clear_insn_cache below */
1850 /* On older versions of this OS, no memctl or MCT_TEXT are defined;
1851 hence we enable this stuff only if MCT_TEXT is #define'd. */
1853 #ifdef MCT_TEXT
1854 asm("\n\
1855 global memctl\n\
1856 memctl:\n\
1857 movq &75,%d0\n\
1858 trap &0\n\
1859 bcc.b noerror\n\
1860 jmp cerror%\n\
1861 noerror:\n\
1862 movq &0,%d0\n\
1863 rts");
1864 #endif
1866 /* Clear instruction cache so we can call trampolines on stack.
1867 This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
1869 void
1870 __clear_insn_cache (void)
1872 #ifdef MCT_TEXT
1873 int save_errno;
1875 /* Preserve errno, because users would be surprised to have
1876 errno changing without explicitly calling any system-call. */
1877 save_errno = errno;
1879 /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
1880 No need to use an address derived from _start or %sp, as 0 works also. */
1881 memctl(0, 4096, MCT_TEXT);
1882 errno = save_errno;
1883 #endif
1886 #endif /* __sysV68__ */
1887 #endif /* L_trampoline */
1889 #ifndef __CYGWIN__
1890 #ifdef L__main
1892 #include "gbl-ctors.h"
1893 /* Some systems use __main in a way incompatible with its use in gcc, in these
1894 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
1895 give the same symbol without quotes for an alternative entry point. You
1896 must define both, or neither. */
1897 #ifndef NAME__MAIN
1898 #define NAME__MAIN "__main"
1899 #define SYMBOL__MAIN __main
1900 #endif
1902 #ifdef INIT_SECTION_ASM_OP
1903 #undef HAS_INIT_SECTION
1904 #define HAS_INIT_SECTION
1905 #endif
1907 #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
1909 /* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
1910 code to run constructors. In that case, we need to handle EH here, too. */
1912 #ifdef EH_FRAME_SECTION_NAME
1913 #include "unwind-dw2-fde.h"
1914 extern unsigned char __EH_FRAME_BEGIN__[];
1915 #endif
1917 /* Run all the global destructors on exit from the program. */
1919 void
1920 __do_global_dtors (void)
1922 #ifdef DO_GLOBAL_DTORS_BODY
1923 DO_GLOBAL_DTORS_BODY;
1924 #else
1925 static func_ptr *p = __DTOR_LIST__ + 1;
1926 while (*p)
1928 p++;
1929 (*(p-1)) ();
1931 #endif
1932 #if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
1934 static int completed = 0;
1935 if (! completed)
1937 completed = 1;
1938 __deregister_frame_info (__EH_FRAME_BEGIN__);
1941 #endif
1943 #endif
1945 #ifndef HAS_INIT_SECTION
1946 /* Run all the global constructors on entry to the program. */
1948 void
1949 __do_global_ctors (void)
1951 #ifdef EH_FRAME_SECTION_NAME
1953 static struct object object;
1954 __register_frame_info (__EH_FRAME_BEGIN__, &object);
1956 #endif
1957 DO_GLOBAL_CTORS_BODY;
1958 atexit (__do_global_dtors);
1960 #endif /* no HAS_INIT_SECTION */
1962 #if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
1963 /* Subroutine called automatically by `main'.
1964 Compiling a global function named `main'
1965 produces an automatic call to this function at the beginning.
1967 For many systems, this routine calls __do_global_ctors.
1968 For systems which support a .init section we use the .init section
1969 to run __do_global_ctors, so we need not do anything here. */
1971 void
1972 SYMBOL__MAIN ()
1974 /* Support recursive calls to `main': run initializers just once. */
1975 static int initialized;
1976 if (! initialized)
1978 initialized = 1;
1979 __do_global_ctors ();
1982 #endif /* no HAS_INIT_SECTION or INVOKE__main */
1984 #endif /* L__main */
1985 #endif /* __CYGWIN__ */
1987 #ifdef L_ctors
1989 #include "gbl-ctors.h"
1991 /* Provide default definitions for the lists of constructors and
1992 destructors, so that we don't get linker errors. These symbols are
1993 intentionally bss symbols, so that gld and/or collect will provide
1994 the right values. */
1996 /* We declare the lists here with two elements each,
1997 so that they are valid empty lists if no other definition is loaded.
1999 If we are using the old "set" extensions to have the gnu linker
2000 collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
2001 must be in the bss/common section.
2003 Long term no port should use those extensions. But many still do. */
2004 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2005 #if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
2006 func_ptr __CTOR_LIST__[2] = {0, 0};
2007 func_ptr __DTOR_LIST__[2] = {0, 0};
2008 #else
2009 func_ptr __CTOR_LIST__[2];
2010 func_ptr __DTOR_LIST__[2];
2011 #endif
2012 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2013 #endif /* L_ctors */
2015 #ifdef L_exit
2017 #include "gbl-ctors.h"
2019 #ifdef NEED_ATEXIT
2021 #ifndef ON_EXIT
2023 # include <errno.h>
2025 static func_ptr *atexit_chain = 0;
2026 static long atexit_chain_length = 0;
2027 static volatile long last_atexit_chain_slot = -1;
2030 atexit (func_ptr func)
2032 if (++last_atexit_chain_slot == atexit_chain_length)
2034 atexit_chain_length += 32;
2035 if (atexit_chain)
2036 atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2037 * sizeof (func_ptr));
2038 else
2039 atexit_chain = (func_ptr *) malloc (atexit_chain_length
2040 * sizeof (func_ptr));
2041 if (! atexit_chain)
2043 atexit_chain_length = 0;
2044 last_atexit_chain_slot = -1;
2045 errno = ENOMEM;
2046 return (-1);
2049 atexit_chain[last_atexit_chain_slot] = func;
2050 return (0);
2053 extern void _cleanup (void);
2054 extern void _exit (int) __attribute__ ((__noreturn__));
2056 void
2057 exit (int status)
2059 if (atexit_chain)
2061 for ( ; last_atexit_chain_slot-- >= 0; )
2063 (*atexit_chain[last_atexit_chain_slot + 1]) ();
2064 atexit_chain[last_atexit_chain_slot + 1] = 0;
2066 free (atexit_chain);
2067 atexit_chain = 0;
2069 #ifdef EXIT_BODY
2070 EXIT_BODY;
2071 #else
2072 _cleanup ();
2073 #endif
2074 _exit (status);
2077 #else /* ON_EXIT */
2079 /* Simple; we just need a wrapper for ON_EXIT. */
2081 atexit (func_ptr func)
2083 return ON_EXIT (func);
2086 #endif /* ON_EXIT */
2087 #endif /* NEED_ATEXIT */
2089 #endif /* L_exit */