Makefile.in (LIB2FUNCS_ST): Remove _gcov.
[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, 2002 Free Software Foundation, Inc.
5
6 This file is part of GCC.
7
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
12
13 In addition to the permissions in the GNU General Public License, the
14 Free Software Foundation gives you unlimited permission to link the
15 compiled version of this file into combinations with other programs,
16 and to distribute those combinations without any restriction coming
17 from the use of this file. (The General Public License restrictions
18 do apply in other respects; for example, they cover modification of
19 the file, and distribution when not linked into a combine
20 executable.)
21
22 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23 WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25 for more details.
26
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING. If not, write to the Free
29 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
30 02111-1307, USA. */
31
32 /* It is incorrect to include config.h here, because this file is being
33 compiled for the target, and hence definitions concerning only the host
34 do not apply. */
35
36 #include "tconfig.h"
37 #include "tsystem.h"
38 #include "coretypes.h"
39 #include "tm.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 #ifdef DECLARE_LIBRARY_RENAMES
49 DECLARE_LIBRARY_RENAMES
50 #endif
51
52 #if defined (L_negdi2)
53 DWtype
54 __negdi2 (DWtype u)
55 {
56 DWunion w;
57 DWunion uu;
58
59 uu.ll = u;
60
61 w.s.low = -uu.s.low;
62 w.s.high = -uu.s.high - ((UWtype) w.s.low > 0);
63
64 return w.ll;
65 }
66 #endif
67
68 #ifdef L_addvsi3
69 Wtype
70 __addvsi3 (Wtype a, Wtype b)
71 {
72 Wtype w;
73
74 w = a + b;
75
76 if (b >= 0 ? w < a : w > a)
77 abort ();
78
79 return w;
80 }
81 #endif
82 \f
83 #ifdef L_addvdi3
84 DWtype
85 __addvdi3 (DWtype a, DWtype b)
86 {
87 DWtype w;
88
89 w = a + b;
90
91 if (b >= 0 ? w < a : w > a)
92 abort ();
93
94 return w;
95 }
96 #endif
97 \f
98 #ifdef L_subvsi3
99 Wtype
100 __subvsi3 (Wtype a, Wtype b)
101 {
102 #ifdef L_addvsi3
103 return __addvsi3 (a, (-b));
104 #else
105 DWtype w;
106
107 w = a - b;
108
109 if (b >= 0 ? w > a : w < a)
110 abort ();
111
112 return w;
113 #endif
114 }
115 #endif
116 \f
117 #ifdef L_subvdi3
118 DWtype
119 __subvdi3 (DWtype a, DWtype b)
120 {
121 #ifdef L_addvdi3
122 return (a, (-b));
123 #else
124 DWtype w;
125
126 w = a - b;
127
128 if (b >= 0 ? w > a : w < a)
129 abort ();
130
131 return w;
132 #endif
133 }
134 #endif
135 \f
136 #ifdef L_mulvsi3
137 Wtype
138 __mulvsi3 (Wtype a, Wtype b)
139 {
140 DWtype w;
141
142 w = a * b;
143
144 if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0)
145 abort ();
146
147 return w;
148 }
149 #endif
150 \f
151 #ifdef L_negvsi2
152 Wtype
153 __negvsi2 (Wtype a)
154 {
155 Wtype w;
156
157 w = -a;
158
159 if (a >= 0 ? w > 0 : w < 0)
160 abort ();
161
162 return w;
163 }
164 #endif
165 \f
166 #ifdef L_negvdi2
167 DWtype
168 __negvdi2 (DWtype a)
169 {
170 DWtype w;
171
172 w = -a;
173
174 if (a >= 0 ? w > 0 : w < 0)
175 abort ();
176
177 return w;
178 }
179 #endif
180 \f
181 #ifdef L_absvsi2
182 Wtype
183 __absvsi2 (Wtype a)
184 {
185 Wtype w = a;
186
187 if (a < 0)
188 #ifdef L_negvsi2
189 w = __negvsi2 (a);
190 #else
191 w = -a;
192
193 if (w < 0)
194 abort ();
195 #endif
196
197 return w;
198 }
199 #endif
200 \f
201 #ifdef L_absvdi2
202 DWtype
203 __absvdi2 (DWtype a)
204 {
205 DWtype w = a;
206
207 if (a < 0)
208 #ifdef L_negvsi2
209 w = __negvsi2 (a);
210 #else
211 w = -a;
212
213 if (w < 0)
214 abort ();
215 #endif
216
217 return w;
218 }
219 #endif
220 \f
221 #ifdef L_mulvdi3
222 DWtype
223 __mulvdi3 (DWtype u, DWtype v)
224 {
225 DWtype w;
226
227 w = u * v;
228
229 if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0)
230 abort ();
231
232 return w;
233 }
234 #endif
235 \f
236
237 /* Unless shift functions are defined with 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)
242 {
243 DWunion w;
244 word_type bm;
245 DWunion uu;
246
247 if (b == 0)
248 return u;
249
250 uu.ll = u;
251
252 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
253 if (bm <= 0)
254 {
255 w.s.high = 0;
256 w.s.low = (UWtype) uu.s.high >> -bm;
257 }
258 else
259 {
260 UWtype carries = (UWtype) uu.s.high << bm;
261
262 w.s.high = (UWtype) uu.s.high >> b;
263 w.s.low = ((UWtype) uu.s.low >> b) | carries;
264 }
265
266 return w.ll;
267 }
268 #endif
269
270 #ifdef L_ashldi3
271 DWtype
272 __ashldi3 (DWtype u, word_type b)
273 {
274 DWunion w;
275 word_type bm;
276 DWunion uu;
277
278 if (b == 0)
279 return u;
280
281 uu.ll = u;
282
283 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
284 if (bm <= 0)
285 {
286 w.s.low = 0;
287 w.s.high = (UWtype) uu.s.low << -bm;
288 }
289 else
290 {
291 UWtype carries = (UWtype) uu.s.low >> bm;
292
293 w.s.low = (UWtype) uu.s.low << b;
294 w.s.high = ((UWtype) uu.s.high << b) | carries;
295 }
296
297 return w.ll;
298 }
299 #endif
300
301 #ifdef L_ashrdi3
302 DWtype
303 __ashrdi3 (DWtype u, word_type b)
304 {
305 DWunion w;
306 word_type bm;
307 DWunion uu;
308
309 if (b == 0)
310 return u;
311
312 uu.ll = u;
313
314 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
315 if (bm <= 0)
316 {
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;
320 }
321 else
322 {
323 UWtype carries = (UWtype) uu.s.high << bm;
324
325 w.s.high = uu.s.high >> b;
326 w.s.low = ((UWtype) uu.s.low >> b) | carries;
327 }
328
329 return w.ll;
330 }
331 #endif
332 \f
333 #ifdef L_ffsdi2
334 DWtype
335 __ffsdi2 (DWtype u)
336 {
337 DWunion uu;
338 UWtype word, count, add;
339
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;
347
348 count_trailing_zeros (count, word);
349 return count + add + 1;
350 }
351 #endif
352 \f
353 #ifdef L_muldi3
354 DWtype
355 __muldi3 (DWtype u, DWtype v)
356 {
357 DWunion w;
358 DWunion uu, vv;
359
360 uu.ll = u,
361 vv.ll = v;
362
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);
366
367 return w.ll;
368 }
369 #endif
370 \f
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
377
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)
386 {
387 UWtype q, r;
388 UWtype c0, c1, b1;
389
390 if ((Wtype) d >= 0)
391 {
392 if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
393 {
394 /* dividend, divisor, and quotient are nonnegative */
395 sdiv_qrnnd (q, r, a1, a0, d);
396 }
397 else
398 {
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);
405 }
406 }
407 else
408 {
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);
412
413 if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
414 {
415 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
416
417 r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
418 if ((d & 1) != 0)
419 {
420 if (r >= q)
421 r = r - q;
422 else if (q - r <= d)
423 {
424 r = r - q + d;
425 q--;
426 }
427 else
428 {
429 r = r - q + 2*d;
430 q -= 2;
431 }
432 }
433 }
434 else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
435 {
436 c1 = (b1 - 1) - c1;
437 c0 = ~c0; /* logical NOT */
438
439 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
440
441 q = ~q; /* (A/2)/b1 */
442 r = (b1 - 1) - r;
443
444 r = 2*r + (a0 & 1); /* A/(2*b1) */
445
446 if ((d & 1) != 0)
447 {
448 if (r >= q)
449 r = r - q;
450 else if (q - r <= d)
451 {
452 r = r - q + d;
453 q--;
454 }
455 else
456 {
457 r = r - q + 2*d;
458 q -= 2;
459 }
460 }
461 }
462 else /* Implies c1 = b1 */
463 { /* Hence a1 = d - 1 = 2*b1 - 1 */
464 if (a0 >= -d)
465 {
466 q = -1;
467 r = a0 + d;
468 }
469 else
470 {
471 q = -2;
472 r = a0 + 2*d;
473 }
474 }
475 }
476
477 *rp = r;
478 return q;
479 }
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__)))
487 {
488 return 0;
489 }
490 #endif
491 #endif
492 \f
493 #if (defined (L_udivdi3) || defined (L_divdi3) || \
494 defined (L_umoddi3) || defined (L_moddi3))
495 #define L_udivmoddi4
496 #endif
497
498 #ifdef L_clz
499 const UQItype __clz_tab[] =
500 {
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,
509 };
510 #endif
511
512 #ifdef L_udivmoddi4
513
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)
520 {
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;
527
528 nn.ll = n;
529 dd.ll = d;
530
531 d0 = dd.s.low;
532 d1 = dd.s.high;
533 n0 = nn.s.low;
534 n1 = nn.s.high;
535
536 #if !UDIV_NEEDS_NORMALIZATION
537 if (d1 == 0)
538 {
539 if (d0 > n1)
540 {
541 /* 0q = nn / 0D */
542
543 udiv_qrnnd (q0, n0, n1, n0, d0);
544 q1 = 0;
545
546 /* Remainder in n0. */
547 }
548 else
549 {
550 /* qq = NN / 0d */
551
552 if (d0 == 0)
553 d0 = 1 / d0; /* Divide intentionally by zero. */
554
555 udiv_qrnnd (q1, n1, 0, n1, d0);
556 udiv_qrnnd (q0, n0, n1, n0, d0);
557
558 /* Remainder in n0. */
559 }
560
561 if (rp != 0)
562 {
563 rr.s.low = n0;
564 rr.s.high = 0;
565 *rp = rr.ll;
566 }
567 }
568
569 #else /* UDIV_NEEDS_NORMALIZATION */
570
571 if (d1 == 0)
572 {
573 if (d0 > n1)
574 {
575 /* 0q = nn / 0D */
576
577 count_leading_zeros (bm, d0);
578
579 if (bm != 0)
580 {
581 /* Normalize, i.e. make the most significant bit of the
582 denominator set. */
583
584 d0 = d0 << bm;
585 n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
586 n0 = n0 << bm;
587 }
588
589 udiv_qrnnd (q0, n0, n1, n0, d0);
590 q1 = 0;
591
592 /* Remainder in n0 >> bm. */
593 }
594 else
595 {
596 /* qq = NN / 0d */
597
598 if (d0 == 0)
599 d0 = 1 / d0; /* Divide intentionally by zero. */
600
601 count_leading_zeros (bm, d0);
602
603 if (bm == 0)
604 {
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).
608
609 This special case is necessary, not an optimization.
610 (Shifts counts of W_TYPE_SIZE are undefined.) */
611
612 n1 -= d0;
613 q1 = 1;
614 }
615 else
616 {
617 /* Normalize. */
618
619 b = W_TYPE_SIZE - bm;
620
621 d0 = d0 << bm;
622 n2 = n1 >> b;
623 n1 = (n1 << bm) | (n0 >> b);
624 n0 = n0 << bm;
625
626 udiv_qrnnd (q1, n1, n2, n1, d0);
627 }
628
629 /* n1 != d0... */
630
631 udiv_qrnnd (q0, n0, n1, n0, d0);
632
633 /* Remainder in n0 >> bm. */
634 }
635
636 if (rp != 0)
637 {
638 rr.s.low = n0 >> bm;
639 rr.s.high = 0;
640 *rp = rr.ll;
641 }
642 }
643 #endif /* UDIV_NEEDS_NORMALIZATION */
644
645 else
646 {
647 if (d1 > n1)
648 {
649 /* 00 = nn / DD */
650
651 q0 = 0;
652 q1 = 0;
653
654 /* Remainder in n1n0. */
655 if (rp != 0)
656 {
657 rr.s.low = n0;
658 rr.s.high = n1;
659 *rp = rr.ll;
660 }
661 }
662 else
663 {
664 /* 0q = NN / dd */
665
666 count_leading_zeros (bm, d1);
667 if (bm == 0)
668 {
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).
672
673 This special case is necessary, not an optimization. */
674
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)
678 {
679 q0 = 1;
680 sub_ddmmss (n1, n0, n1, n0, d1, d0);
681 }
682 else
683 q0 = 0;
684
685 q1 = 0;
686
687 if (rp != 0)
688 {
689 rr.s.low = n0;
690 rr.s.high = n1;
691 *rp = rr.ll;
692 }
693 }
694 else
695 {
696 UWtype m1, m0;
697 /* Normalize. */
698
699 b = W_TYPE_SIZE - bm;
700
701 d1 = (d1 << bm) | (d0 >> b);
702 d0 = d0 << bm;
703 n2 = n1 >> b;
704 n1 = (n1 << bm) | (n0 >> b);
705 n0 = n0 << bm;
706
707 udiv_qrnnd (q0, n1, n2, n1, d1);
708 umul_ppmm (m1, m0, q0, d0);
709
710 if (m1 > n1 || (m1 == n1 && m0 > n0))
711 {
712 q0--;
713 sub_ddmmss (m1, m0, m1, m0, d1, d0);
714 }
715
716 q1 = 0;
717
718 /* Remainder in (n1n0 - m1m0) >> bm. */
719 if (rp != 0)
720 {
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;
725 }
726 }
727 }
728 }
729
730 ww.s.low = q0;
731 ww.s.high = q1;
732 return ww.ll;
733 }
734 #endif
735
736 #ifdef L_divdi3
737 DWtype
738 __divdi3 (DWtype u, DWtype v)
739 {
740 word_type c = 0;
741 DWunion uu, vv;
742 DWtype w;
743
744 uu.ll = u;
745 vv.ll = v;
746
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;
753
754 w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
755 if (c)
756 w = -w;
757
758 return w;
759 }
760 #endif
761
762 #ifdef L_moddi3
763 DWtype
764 __moddi3 (DWtype u, DWtype v)
765 {
766 word_type c = 0;
767 DWunion uu, vv;
768 DWtype w;
769
770 uu.ll = u;
771 vv.ll = v;
772
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;
778
779 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
780 if (c)
781 w = -w;
782
783 return w;
784 }
785 #endif
786
787 #ifdef L_umoddi3
788 UDWtype
789 __umoddi3 (UDWtype u, UDWtype v)
790 {
791 UDWtype w;
792
793 (void) __udivmoddi4 (u, v, &w);
794
795 return w;
796 }
797 #endif
798
799 #ifdef L_udivdi3
800 UDWtype
801 __udivdi3 (UDWtype n, UDWtype d)
802 {
803 return __udivmoddi4 (n, d, (UDWtype *) 0);
804 }
805 #endif
806 \f
807 #ifdef L_cmpdi2
808 word_type
809 __cmpdi2 (DWtype a, DWtype b)
810 {
811 DWunion au, bu;
812
813 au.ll = a, bu.ll = b;
814
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;
824 }
825 #endif
826
827 #ifdef L_ucmpdi2
828 word_type
829 __ucmpdi2 (DWtype a, DWtype b)
830 {
831 DWunion au, bu;
832
833 au.ll = a, bu.ll = b;
834
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;
844 }
845 #endif
846 \f
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)
850
851 DWtype
852 __fixunstfDI (TFtype a)
853 {
854 TFtype b;
855 UDWtype v;
856
857 if (a < 0)
858 return 0;
859
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;
876 }
877 #endif
878
879 #if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
880 DWtype
881 __fixtfdi (TFtype a)
882 {
883 if (a < 0)
884 return - __fixunstfDI (-a);
885 return __fixunstfDI (a);
886 }
887 #endif
888
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)
892
893 DWtype
894 __fixunsxfDI (XFtype a)
895 {
896 XFtype b;
897 UDWtype v;
898
899 if (a < 0)
900 return 0;
901
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;
918 }
919 #endif
920
921 #if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
922 DWtype
923 __fixxfdi (XFtype a)
924 {
925 if (a < 0)
926 return - __fixunsxfDI (-a);
927 return __fixunsxfDI (a);
928 }
929 #endif
930
931 #ifdef L_fixunsdfdi
932 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
933 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
934
935 DWtype
936 __fixunsdfDI (DFtype a)
937 {
938 UWtype hi, lo;
939
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;
944
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);
949
950 /* Assemble result from the two parts. */
951 return ((UDWtype) hi << WORD_SIZE) | lo;
952 }
953 #endif
954
955 #ifdef L_fixdfdi
956 DWtype
957 __fixdfdi (DFtype a)
958 {
959 if (a < 0)
960 return - __fixunsdfDI (-a);
961 return __fixunsdfDI (a);
962 }
963 #endif
964
965 #ifdef L_fixunssfdi
966 #define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
967 #define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
968
969 DWtype
970 __fixunssfDI (SFtype original_a)
971 {
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;
977
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;
982
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);
987
988 /* Assemble result from the two parts. */
989 return ((UDWtype) hi << WORD_SIZE) | lo;
990 }
991 #endif
992
993 #ifdef L_fixsfdi
994 DWtype
995 __fixsfdi (SFtype a)
996 {
997 if (a < 0)
998 return - __fixunssfDI (-a);
999 return __fixunssfDI (a);
1000 }
1001 #endif
1002
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)
1007
1008 XFtype
1009 __floatdixf (DWtype u)
1010 {
1011 XFtype d;
1012
1013 d = (Wtype) (u >> WORD_SIZE);
1014 d *= HIGH_HALFWORD_COEFF;
1015 d *= HIGH_HALFWORD_COEFF;
1016 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1017
1018 return d;
1019 }
1020 #endif
1021
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)
1026
1027 TFtype
1028 __floatditf (DWtype u)
1029 {
1030 TFtype d;
1031
1032 d = (Wtype) (u >> WORD_SIZE);
1033 d *= HIGH_HALFWORD_COEFF;
1034 d *= HIGH_HALFWORD_COEFF;
1035 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1036
1037 return d;
1038 }
1039 #endif
1040
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)
1045
1046 DFtype
1047 __floatdidf (DWtype u)
1048 {
1049 DFtype d;
1050
1051 d = (Wtype) (u >> WORD_SIZE);
1052 d *= HIGH_HALFWORD_COEFF;
1053 d *= HIGH_HALFWORD_COEFF;
1054 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1055
1056 return d;
1057 }
1058 #endif
1059
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)
1064
1065 #define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
1066 #define DF_SIZE DBL_MANT_DIG
1067 #define SF_SIZE FLT_MANT_DIG
1068
1069 SFtype
1070 __floatdisf (DWtype u)
1071 {
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;
1076
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))
1085 {
1086 #define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
1087 if (! (- ((DWtype) 1 << DF_SIZE) < u
1088 && u < ((DWtype) 1 << DF_SIZE)))
1089 {
1090 if ((UDWtype) u & (REP_BIT - 1))
1091 {
1092 u &= ~ (REP_BIT - 1);
1093 u |= REP_BIT;
1094 }
1095 }
1096 }
1097 f = (Wtype) (u >> WORD_SIZE);
1098 f *= HIGH_HALFWORD_COEFF;
1099 f *= HIGH_HALFWORD_COEFF;
1100 f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
1101
1102 return (SFtype) f;
1103 }
1104 #endif
1105
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>
1118
1119 UWtype
1120 __fixunsxfSI (XFtype a)
1121 {
1122 if (a >= - (DFtype) Wtype_MIN)
1123 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1124 return (Wtype) a;
1125 }
1126 #endif
1127
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>
1140
1141 UWtype
1142 __fixunsdfSI (DFtype a)
1143 {
1144 if (a >= - (DFtype) Wtype_MIN)
1145 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1146 return (Wtype) a;
1147 }
1148 #endif
1149
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>
1162
1163 UWtype
1164 __fixunssfSI (SFtype a)
1165 {
1166 if (a >= - (SFtype) Wtype_MIN)
1167 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
1168 return (Wtype) a;
1169 }
1170 #endif
1171 \f
1172 /* From here on down, the routines use normal data types. */
1173
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
1186
1187 #undef char
1188 #undef short
1189 #undef int
1190 #undef long
1191 #undef unsigned
1192 #undef float
1193 #undef double
1194 \f
1195 #ifdef L__gcc_bcmp
1196
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. */
1200
1201 int
1202 __gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
1203 {
1204 while (size > 0)
1205 {
1206 unsigned char c1 = *s1++, c2 = *s2++;
1207 if (c1 != c2)
1208 return c1 - c2;
1209 size--;
1210 }
1211 return 0;
1212 }
1213
1214 #endif
1215 \f
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
1222
1223 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1224 #include <stdio.h>
1225
1226 void
1227 __eprintf (const char *string, const char *expression,
1228 unsigned int line, const char *filename)
1229 {
1230 fprintf (stderr, string, expression, line, filename);
1231 fflush (stderr);
1232 abort ();
1233 }
1234
1235 #endif
1236 #endif
1237
1238 \f
1239 #ifdef L_clear_cache
1240 /* Clear part of an instruction cache. */
1241
1242 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1243
1244 void
1245 __clear_cache (char *beg __attribute__((__unused__)),
1246 char *end __attribute__((__unused__)))
1247 {
1248 #ifdef CLEAR_INSN_CACHE
1249 CLEAR_INSN_CACHE (beg, end);
1250 #else
1251 #ifdef INSN_CACHE_SIZE
1252 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1253 static int initialized;
1254 int offset;
1255 void *start_addr
1256 void *end_addr;
1257 typedef (*function_ptr) (void);
1258
1259 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1260 /* It's cheaper to clear the whole cache.
1261 Put in a series of jump instructions so that calling the beginning
1262 of the cache will clear the whole thing. */
1263
1264 if (! initialized)
1265 {
1266 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1267 & -INSN_CACHE_LINE_WIDTH);
1268 int end_ptr = ptr + INSN_CACHE_SIZE;
1269
1270 while (ptr < end_ptr)
1271 {
1272 *(INSTRUCTION_TYPE *)ptr
1273 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1274 ptr += INSN_CACHE_LINE_WIDTH;
1275 }
1276 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1277
1278 initialized = 1;
1279 }
1280
1281 /* Call the beginning of the sequence. */
1282 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1283 & -INSN_CACHE_LINE_WIDTH))
1284 ());
1285
1286 #else /* Cache is large. */
1287
1288 if (! initialized)
1289 {
1290 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1291 & -INSN_CACHE_LINE_WIDTH);
1292
1293 while (ptr < (int) array + sizeof array)
1294 {
1295 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1296 ptr += INSN_CACHE_LINE_WIDTH;
1297 }
1298
1299 initialized = 1;
1300 }
1301
1302 /* Find the location in array that occupies the same cache line as BEG. */
1303
1304 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1305 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1306 & -INSN_CACHE_PLANE_SIZE)
1307 + offset);
1308
1309 /* Compute the cache alignment of the place to stop clearing. */
1310 #if 0 /* This is not needed for gcc's purposes. */
1311 /* If the block to clear is bigger than a cache plane,
1312 we clear the entire cache, and OFFSET is already correct. */
1313 if (end < beg + INSN_CACHE_PLANE_SIZE)
1314 #endif
1315 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1316 & -INSN_CACHE_LINE_WIDTH)
1317 & (INSN_CACHE_PLANE_SIZE - 1));
1318
1319 #if INSN_CACHE_DEPTH > 1
1320 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1321 if (end_addr <= start_addr)
1322 end_addr += INSN_CACHE_PLANE_SIZE;
1323
1324 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1325 {
1326 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1327 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1328
1329 while (addr != stop)
1330 {
1331 /* Call the return instruction at ADDR. */
1332 ((function_ptr) addr) ();
1333
1334 addr += INSN_CACHE_LINE_WIDTH;
1335 }
1336 }
1337 #else /* just one plane */
1338 do
1339 {
1340 /* Call the return instruction at START_ADDR. */
1341 ((function_ptr) start_addr) ();
1342
1343 start_addr += INSN_CACHE_LINE_WIDTH;
1344 }
1345 while ((start_addr % INSN_CACHE_SIZE) != offset);
1346 #endif /* just one plane */
1347 #endif /* Cache is large */
1348 #endif /* Cache exists */
1349 #endif /* CLEAR_INSN_CACHE */
1350 }
1351
1352 #endif /* L_clear_cache */
1353 \f
1354 #ifdef L_trampoline
1355
1356 /* Jump to a trampoline, loading the static chain address. */
1357
1358 #if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
1359
1360 long
1361 getpagesize (void)
1362 {
1363 #ifdef _ALPHA_
1364 return 8192;
1365 #else
1366 return 4096;
1367 #endif
1368 }
1369
1370 #ifdef __i386__
1371 extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
1372 #endif
1373
1374 int
1375 mprotect (char *addr, int len, int prot)
1376 {
1377 int np, op;
1378
1379 if (prot == 7)
1380 np = 0x40;
1381 else if (prot == 5)
1382 np = 0x20;
1383 else if (prot == 4)
1384 np = 0x10;
1385 else if (prot == 3)
1386 np = 0x04;
1387 else if (prot == 1)
1388 np = 0x02;
1389 else if (prot == 0)
1390 np = 0x01;
1391
1392 if (VirtualProtect (addr, len, np, &op))
1393 return 0;
1394 else
1395 return -1;
1396 }
1397
1398 #endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
1399
1400 #ifdef TRANSFER_FROM_TRAMPOLINE
1401 TRANSFER_FROM_TRAMPOLINE
1402 #endif
1403
1404 #ifdef __sysV68__
1405
1406 #include <sys/signal.h>
1407 #include <errno.h>
1408
1409 /* Motorola forgot to put memctl.o in the libp version of libc881.a,
1410 so define it here, because we need it in __clear_insn_cache below */
1411 /* On older versions of this OS, no memctl or MCT_TEXT are defined;
1412 hence we enable this stuff only if MCT_TEXT is #define'd. */
1413
1414 #ifdef MCT_TEXT
1415 asm("\n\
1416 global memctl\n\
1417 memctl:\n\
1418 movq &75,%d0\n\
1419 trap &0\n\
1420 bcc.b noerror\n\
1421 jmp cerror%\n\
1422 noerror:\n\
1423 movq &0,%d0\n\
1424 rts");
1425 #endif
1426
1427 /* Clear instruction cache so we can call trampolines on stack.
1428 This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
1429
1430 void
1431 __clear_insn_cache (void)
1432 {
1433 #ifdef MCT_TEXT
1434 int save_errno;
1435
1436 /* Preserve errno, because users would be surprised to have
1437 errno changing without explicitly calling any system-call. */
1438 save_errno = errno;
1439
1440 /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
1441 No need to use an address derived from _start or %sp, as 0 works also. */
1442 memctl(0, 4096, MCT_TEXT);
1443 errno = save_errno;
1444 #endif
1445 }
1446
1447 #endif /* __sysV68__ */
1448 #endif /* L_trampoline */
1449 \f
1450 #ifndef __CYGWIN__
1451 #ifdef L__main
1452
1453 #include "gbl-ctors.h"
1454 /* Some systems use __main in a way incompatible with its use in gcc, in these
1455 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
1456 give the same symbol without quotes for an alternative entry point. You
1457 must define both, or neither. */
1458 #ifndef NAME__MAIN
1459 #define NAME__MAIN "__main"
1460 #define SYMBOL__MAIN __main
1461 #endif
1462
1463 #ifdef INIT_SECTION_ASM_OP
1464 #undef HAS_INIT_SECTION
1465 #define HAS_INIT_SECTION
1466 #endif
1467
1468 #if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
1469
1470 /* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
1471 code to run constructors. In that case, we need to handle EH here, too. */
1472
1473 #ifdef EH_FRAME_SECTION_NAME
1474 #include "unwind-dw2-fde.h"
1475 extern unsigned char __EH_FRAME_BEGIN__[];
1476 #endif
1477
1478 /* Run all the global destructors on exit from the program. */
1479
1480 void
1481 __do_global_dtors (void)
1482 {
1483 #ifdef DO_GLOBAL_DTORS_BODY
1484 DO_GLOBAL_DTORS_BODY;
1485 #else
1486 static func_ptr *p = __DTOR_LIST__ + 1;
1487 while (*p)
1488 {
1489 p++;
1490 (*(p-1)) ();
1491 }
1492 #endif
1493 #if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
1494 {
1495 static int completed = 0;
1496 if (! completed)
1497 {
1498 completed = 1;
1499 __deregister_frame_info (__EH_FRAME_BEGIN__);
1500 }
1501 }
1502 #endif
1503 }
1504 #endif
1505
1506 #ifndef HAS_INIT_SECTION
1507 /* Run all the global constructors on entry to the program. */
1508
1509 void
1510 __do_global_ctors (void)
1511 {
1512 #ifdef EH_FRAME_SECTION_NAME
1513 {
1514 static struct object object;
1515 __register_frame_info (__EH_FRAME_BEGIN__, &object);
1516 }
1517 #endif
1518 DO_GLOBAL_CTORS_BODY;
1519 atexit (__do_global_dtors);
1520 }
1521 #endif /* no HAS_INIT_SECTION */
1522
1523 #if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
1524 /* Subroutine called automatically by `main'.
1525 Compiling a global function named `main'
1526 produces an automatic call to this function at the beginning.
1527
1528 For many systems, this routine calls __do_global_ctors.
1529 For systems which support a .init section we use the .init section
1530 to run __do_global_ctors, so we need not do anything here. */
1531
1532 void
1533 SYMBOL__MAIN ()
1534 {
1535 /* Support recursive calls to `main': run initializers just once. */
1536 static int initialized;
1537 if (! initialized)
1538 {
1539 initialized = 1;
1540 __do_global_ctors ();
1541 }
1542 }
1543 #endif /* no HAS_INIT_SECTION or INVOKE__main */
1544
1545 #endif /* L__main */
1546 #endif /* __CYGWIN__ */
1547 \f
1548 #ifdef L_ctors
1549
1550 #include "gbl-ctors.h"
1551
1552 /* Provide default definitions for the lists of constructors and
1553 destructors, so that we don't get linker errors. These symbols are
1554 intentionally bss symbols, so that gld and/or collect will provide
1555 the right values. */
1556
1557 /* We declare the lists here with two elements each,
1558 so that they are valid empty lists if no other definition is loaded.
1559
1560 If we are using the old "set" extensions to have the gnu linker
1561 collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
1562 must be in the bss/common section.
1563
1564 Long term no port should use those extensions. But many still do. */
1565 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
1566 #if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
1567 func_ptr __CTOR_LIST__[2] = {0, 0};
1568 func_ptr __DTOR_LIST__[2] = {0, 0};
1569 #else
1570 func_ptr __CTOR_LIST__[2];
1571 func_ptr __DTOR_LIST__[2];
1572 #endif
1573 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
1574 #endif /* L_ctors */
1575 \f
1576 #ifdef L_exit
1577
1578 #include "gbl-ctors.h"
1579
1580 #ifdef NEED_ATEXIT
1581
1582 #ifndef ON_EXIT
1583
1584 # include <errno.h>
1585
1586 static func_ptr *atexit_chain = 0;
1587 static long atexit_chain_length = 0;
1588 static volatile long last_atexit_chain_slot = -1;
1589
1590 int
1591 atexit (func_ptr func)
1592 {
1593 if (++last_atexit_chain_slot == atexit_chain_length)
1594 {
1595 atexit_chain_length += 32;
1596 if (atexit_chain)
1597 atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
1598 * sizeof (func_ptr));
1599 else
1600 atexit_chain = (func_ptr *) malloc (atexit_chain_length
1601 * sizeof (func_ptr));
1602 if (! atexit_chain)
1603 {
1604 atexit_chain_length = 0;
1605 last_atexit_chain_slot = -1;
1606 errno = ENOMEM;
1607 return (-1);
1608 }
1609 }
1610 atexit_chain[last_atexit_chain_slot] = func;
1611 return (0);
1612 }
1613
1614 extern void _cleanup (void);
1615 extern void _exit (int) __attribute__ ((__noreturn__));
1616
1617 void
1618 exit (int status)
1619 {
1620 if (atexit_chain)
1621 {
1622 for ( ; last_atexit_chain_slot-- >= 0; )
1623 {
1624 (*atexit_chain[last_atexit_chain_slot + 1]) ();
1625 atexit_chain[last_atexit_chain_slot + 1] = 0;
1626 }
1627 free (atexit_chain);
1628 atexit_chain = 0;
1629 }
1630 #ifdef EXIT_BODY
1631 EXIT_BODY;
1632 #else
1633 _cleanup ();
1634 #endif
1635 _exit (status);
1636 }
1637
1638 #else /* ON_EXIT */
1639
1640 /* Simple; we just need a wrapper for ON_EXIT. */
1641 int
1642 atexit (func_ptr func)
1643 {
1644 return ON_EXIT (func);
1645 }
1646
1647 #endif /* ON_EXIT */
1648 #endif /* NEED_ATEXIT */
1649
1650 #endif /* L_exit */