]> gcc.gnu.org Git - gcc.git/blame - gcc/libgcc2.c
configure.in (CROSS): Define NATIVE_CROSS.
[gcc.git] / gcc / libgcc2.c
CommitLineData
203b91b9
RS
1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
5d0e6486
AO
3/* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4 2000, 2001 Free Software Foundation, Inc.
203b91b9 5
1322177d 6This file is part of GCC.
203b91b9 7
1322177d
LB
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 2, or (at your option) any later
11version.
203b91b9 12
f7af368f
JL
13In addition to the permissions in the GNU General Public License, the
14Free Software Foundation gives you unlimited permission to link the
15compiled version of this file into combinations with other programs,
16and to distribute those combinations without any restriction coming
17from the use of this file. (The General Public License restrictions
18do apply in other respects; for example, they cover modification of
19the file, and distribution when not linked into a combine
20executable.)
21
1322177d
LB
22GCC is distributed in the hope that it will be useful, but WITHOUT ANY
23WARRANTY; without even the implied warranty of MERCHANTABILITY or
24FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25for more details.
203b91b9
RS
26
27You should have received a copy of the GNU General Public License
1322177d
LB
28along with GCC; see the file COPYING. If not, write to the Free
29Software Foundation, 59 Temple Place - Suite 330, Boston, MA
3002111-1307, USA. */
203b91b9 31
203b91b9
RS
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
0dadecf6 36#include "tconfig.h"
2e39bdbe 37#include "tsystem.h"
2467749d 38
bfe655f9 39#include "machmode.h"
203b91b9
RS
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
299b83b7 46#include "libgcc2.h"
203b91b9
RS
47\f
48#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
49#if defined (L_divdi3) || defined (L_moddi3)
50static inline
51#endif
3d2adde6
CC
52DWtype
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
91ce572a
CC
66
67#ifdef L_addvsi3
66f77154
MH
68Wtype
69__addvsi3 (Wtype a, Wtype b)
91ce572a 70{
66f77154 71 Wtype w;
91ce572a
CC
72
73 w = a + b;
74
75 if (b >= 0 ? w < a : w > a)
76 abort ();
77
78 return w;
23190837 79}
3d2adde6 80#endif
91ce572a
CC
81\f
82#ifdef L_addvdi3
66f77154
MH
83DWtype
84__addvdi3 (DWtype a, DWtype b)
91ce572a 85{
66f77154 86 DWtype w;
91ce572a
CC
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
66f77154
MH
98Wtype
99__subvsi3 (Wtype a, Wtype b)
91ce572a
CC
100{
101#ifdef L_addvsi3
102 return __addvsi3 (a, (-b));
103#else
66f77154 104 DWtype w;
91ce572a
CC
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
66f77154
MH
117DWtype
118__subvdi3 (DWtype a, DWtype b)
91ce572a
CC
119{
120#ifdef L_addvdi3
121 return (a, (-b));
122#else
66f77154 123 DWtype w;
91ce572a
CC
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
66f77154
MH
136Wtype
137__mulvsi3 (Wtype a, Wtype b)
91ce572a 138{
66f77154 139 DWtype w;
91ce572a
CC
140
141 w = a * b;
142
3cf37281 143 if (((a >= 0) == (b >= 0)) ? w < 0 : w > 0)
91ce572a
CC
144 abort ();
145
146 return w;
147}
148#endif
149\f
150#ifdef L_negvsi2
66f77154
MH
151Wtype
152__negvsi2 (Wtype a)
91ce572a 153{
66f77154 154 Wtype w;
91ce572a
CC
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
66f77154
MH
166DWtype
167__negvdi2 (DWtype a)
91ce572a 168{
66f77154 169 DWtype w;
91ce572a
CC
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
66f77154
MH
181Wtype
182__absvsi2 (Wtype a)
91ce572a 183{
66f77154 184 Wtype w = a;
91ce572a
CC
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
66f77154
MH
201DWtype
202__absvdi2 (DWtype a)
91ce572a 203{
66f77154 204 DWtype w = a;
91ce572a
CC
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
66f77154
MH
221DWtype
222__mulvdi3 (DWtype u, DWtype v)
91ce572a 223{
66f77154 224 DWtype w;
91ce572a
CC
225
226 w = u * v;
227
3d2adde6 228 if (((u >= 0) == (v >= 0)) ? w < 0 : w > 0)
91ce572a
CC
229 abort ();
230
231 return w;
232}
233#endif
234\f
203b91b9 235
37ef1054
RK
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. */
203b91b9 238#ifdef L_lshrdi3
996ed075
JJ
239DWtype
240__lshrdi3 (DWtype u, word_type b)
203b91b9 241{
996ed075 242 DWunion w;
b799cfc3 243 word_type bm;
996ed075 244 DWunion uu;
203b91b9
RS
245
246 if (b == 0)
247 return u;
248
249 uu.ll = u;
250
996ed075 251 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
203b91b9
RS
252 if (bm <= 0)
253 {
254 w.s.high = 0;
6da9c622 255 w.s.low = (UWtype) uu.s.high >> -bm;
203b91b9
RS
256 }
257 else
258 {
6da9c622
RK
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;
203b91b9
RS
263 }
264
265 return w.ll;
266}
267#endif
268
269#ifdef L_ashldi3
996ed075
JJ
270DWtype
271__ashldi3 (DWtype u, word_type b)
203b91b9 272{
996ed075 273 DWunion w;
b799cfc3 274 word_type bm;
996ed075 275 DWunion uu;
203b91b9
RS
276
277 if (b == 0)
278 return u;
279
280 uu.ll = u;
281
996ed075 282 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
203b91b9
RS
283 if (bm <= 0)
284 {
285 w.s.low = 0;
6da9c622 286 w.s.high = (UWtype) uu.s.low << -bm;
203b91b9
RS
287 }
288 else
289 {
6da9c622
RK
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;
203b91b9
RS
294 }
295
296 return w.ll;
297}
298#endif
299
300#ifdef L_ashrdi3
996ed075
JJ
301DWtype
302__ashrdi3 (DWtype u, word_type b)
203b91b9 303{
996ed075 304 DWunion w;
b799cfc3 305 word_type bm;
996ed075 306 DWunion uu;
203b91b9
RS
307
308 if (b == 0)
309 return u;
310
311 uu.ll = u;
312
996ed075 313 bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
203b91b9
RS
314 if (bm <= 0)
315 {
316 /* w.s.high = 1..1 or 0..0 */
996ed075 317 w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1);
203b91b9
RS
318 w.s.low = uu.s.high >> -bm;
319 }
320 else
321 {
6da9c622
RK
322 UWtype carries = (UWtype) uu.s.high << bm;
323
203b91b9 324 w.s.high = uu.s.high >> b;
6da9c622 325 w.s.low = ((UWtype) uu.s.low >> b) | carries;
203b91b9
RS
326 }
327
328 return w.ll;
329}
330#endif
331\f
aa66bd06 332#ifdef L_ffsdi2
996ed075
JJ
333DWtype
334__ffsdi2 (DWtype u)
aa66bd06 335{
d6eacd48
RH
336 DWunion uu;
337 UWtype word, count, add;
338
aa66bd06 339 uu.ll = u;
d6eacd48
RH
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;
aa66bd06
RS
349}
350#endif
351\f
203b91b9 352#ifdef L_muldi3
996ed075
JJ
353DWtype
354__muldi3 (DWtype u, DWtype v)
203b91b9 355{
996ed075
JJ
356 DWunion w;
357 DWunion uu, vv;
203b91b9
RS
358
359 uu.ll = u,
360 vv.ll = v;
361
362 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
996ed075
JJ
363 w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
364 + (UWtype) uu.s.high * (UWtype) vv.s.low);
203b91b9
RS
365
366 return w.ll;
367}
368#endif
369\f
3904131a 370#ifdef L_udiv_w_sdiv
ce13d15f 371#if defined (sdiv_qrnnd)
996ed075
JJ
372UWtype
373__udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
431b1ee0 374{
996ed075
JJ
375 UWtype q, r;
376 UWtype c0, c1, b1;
431b1ee0 377
996ed075 378 if ((Wtype) d >= 0)
431b1ee0 379 {
996ed075 380 if (a1 < d - a1 - (a0 >> (W_TYPE_SIZE - 1)))
431b1ee0
TG
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 */
996ed075 388 sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (W_TYPE_SIZE - 1));
431b1ee0
TG
389 /* Divide (c1*2^32 + c0) by d */
390 sdiv_qrnnd (q, r, c1, c0, d);
391 /* Add 2^31 to quotient */
996ed075 392 q += (UWtype) 1 << (W_TYPE_SIZE - 1);
431b1ee0
TG
393 }
394 }
395 else
396 {
397 b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
398 c1 = a1 >> 1; /* A/2 */
996ed075 399 c0 = (a1 << (W_TYPE_SIZE - 1)) + (a0 >> 1);
431b1ee0
TG
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}
ce13d15f
RK
468#else
469/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
996ed075
JJ
470UWtype
471__udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)),
472 UWtype a1 __attribute__ ((__unused__)),
473 UWtype a0 __attribute__ ((__unused__)),
474 UWtype d __attribute__ ((__unused__)))
081f5e7e
KG
475{
476 return 0;
477}
ce13d15f 478#endif
431b1ee0
TG
479#endif
480\f
536bfcd0
RK
481#if (defined (L_udivdi3) || defined (L_divdi3) || \
482 defined (L_umoddi3) || defined (L_moddi3))
483#define L_udivmoddi4
484#endif
485
d6eacd48
RH
486#ifdef L_clz
487const UQItype __clz_tab[] =
203b91b9
RS
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};
d6eacd48
RH
498#endif
499
500#ifdef L_udivmoddi4
203b91b9 501
536bfcd0
RK
502#if (defined (L_udivdi3) || defined (L_divdi3) || \
503 defined (L_umoddi3) || defined (L_moddi3))
504static inline
505#endif
996ed075
JJ
506UDWtype
507__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
203b91b9 508{
996ed075
JJ
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;
203b91b9
RS
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;
996ed075 573 n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
203b91b9
RS
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.
996ed075 598 (Shifts counts of W_TYPE_SIZE are undefined.) */
203b91b9
RS
599
600 n1 -= d0;
601 q1 = 1;
602 }
603 else
604 {
605 /* Normalize. */
606
996ed075 607 b = W_TYPE_SIZE - bm;
203b91b9
RS
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
0f41302f 617 /* n1 != d0... */
203b91b9
RS
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 {
996ed075 684 UWtype m1, m0;
203b91b9
RS
685 /* Normalize. */
686
996ed075 687 b = W_TYPE_SIZE - bm;
203b91b9
RS
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
996ed075
JJ
725DWtype
726__divdi3 (DWtype u, DWtype v)
203b91b9 727{
b799cfc3 728 word_type c = 0;
996ed075
JJ
729 DWunion uu, vv;
730 DWtype w;
203b91b9
RS
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
996ed075 742 w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
203b91b9
RS
743 if (c)
744 w = __negdi2 (w);
745
746 return w;
747}
748#endif
749
750#ifdef L_moddi3
996ed075
JJ
751DWtype
752__moddi3 (DWtype u, DWtype v)
203b91b9 753{
b799cfc3 754 word_type c = 0;
996ed075
JJ
755 DWunion uu, vv;
756 DWtype w;
203b91b9
RS
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
996ed075
JJ
776UDWtype
777__umoddi3 (UDWtype u, UDWtype v)
203b91b9 778{
996ed075 779 UDWtype w;
203b91b9
RS
780
781 (void) __udivmoddi4 (u, v, &w);
782
783 return w;
784}
785#endif
786
787#ifdef L_udivdi3
996ed075
JJ
788UDWtype
789__udivdi3 (UDWtype n, UDWtype d)
203b91b9 790{
996ed075 791 return __udivmoddi4 (n, d, (UDWtype *) 0);
203b91b9
RS
792}
793#endif
794\f
795#ifdef L_cmpdi2
4be7c28f 796word_type
996ed075 797__cmpdi2 (DWtype a, DWtype b)
203b91b9 798{
996ed075 799 DWunion au, bu;
203b91b9
RS
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;
996ed075 807 if ((UWtype) au.s.low < (UWtype) bu.s.low)
203b91b9 808 return 0;
996ed075 809 else if ((UWtype) au.s.low > (UWtype) bu.s.low)
203b91b9
RS
810 return 2;
811 return 1;
812}
813#endif
814
815#ifdef L_ucmpdi2
4be7c28f 816word_type
996ed075 817__ucmpdi2 (DWtype a, DWtype b)
203b91b9 818{
996ed075 819 DWunion au, bu;
203b91b9
RS
820
821 au.ll = a, bu.ll = b;
822
996ed075 823 if ((UWtype) au.s.high < (UWtype) bu.s.high)
203b91b9 824 return 0;
996ed075 825 else if ((UWtype) au.s.high > (UWtype) bu.s.high)
203b91b9 826 return 2;
996ed075 827 if ((UWtype) au.s.low < (UWtype) bu.s.low)
203b91b9 828 return 0;
996ed075 829 else if ((UWtype) au.s.low > (UWtype) bu.s.low)
203b91b9
RS
830 return 2;
831 return 1;
832}
833#endif
834\f
eaa4b44c 835#if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
996ed075
JJ
836#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
837#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
ab495388 838
996ed075 839DWtype
6da9c622 840__fixunstfDI (TFtype a)
ab495388
RS
841{
842 TFtype b;
996ed075 843 UDWtype v;
ab495388
RS
844
845 if (a < 0)
846 return 0;
847
848 /* Compute high word of result, as a flonum. */
849 b = (a / HIGH_WORD_COEFF);
996ed075 850 /* Convert that to fixed (but not to DWtype!),
ab495388 851 and shift it into the high word. */
996ed075 852 v = (UWtype) b;
ab495388
RS
853 v <<= WORD_SIZE;
854 /* Remove high part from the TFtype, leaving the low part as flonum. */
855 a -= (TFtype)v;
996ed075 856 /* Convert that to fixed (but not to DWtype!) and add it in.
ab495388
RS
857 Sometimes A comes out negative. This is significant, since
858 A has more bits than a long int does. */
859 if (a < 0)
996ed075 860 v -= (UWtype) (- a);
ab495388 861 else
996ed075 862 v += (UWtype) a;
ab495388
RS
863 return v;
864}
865#endif
866
eaa4b44c 867#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
996ed075 868DWtype
37ef1054 869__fixtfdi (TFtype a)
ab495388
RS
870{
871 if (a < 0)
6da9c622
RK
872 return - __fixunstfDI (-a);
873 return __fixunstfDI (a);
ab495388
RS
874}
875#endif
876
eaa4b44c 877#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
996ed075
JJ
878#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
879#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
e0799b34 880
996ed075 881DWtype
6da9c622 882__fixunsxfDI (XFtype a)
e0799b34
RS
883{
884 XFtype b;
996ed075 885 UDWtype v;
e0799b34
RS
886
887 if (a < 0)
888 return 0;
889
890 /* Compute high word of result, as a flonum. */
891 b = (a / HIGH_WORD_COEFF);
996ed075 892 /* Convert that to fixed (but not to DWtype!),
e0799b34 893 and shift it into the high word. */
996ed075 894 v = (UWtype) b;
e0799b34
RS
895 v <<= WORD_SIZE;
896 /* Remove high part from the XFtype, leaving the low part as flonum. */
897 a -= (XFtype)v;
996ed075 898 /* Convert that to fixed (but not to DWtype!) and add it in.
e0799b34
RS
899 Sometimes A comes out negative. This is significant, since
900 A has more bits than a long int does. */
901 if (a < 0)
996ed075 902 v -= (UWtype) (- a);
e0799b34 903 else
996ed075 904 v += (UWtype) a;
e0799b34
RS
905 return v;
906}
907#endif
908
eaa4b44c 909#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
996ed075 910DWtype
37ef1054 911__fixxfdi (XFtype a)
e0799b34
RS
912{
913 if (a < 0)
6da9c622
RK
914 return - __fixunsxfDI (-a);
915 return __fixunsxfDI (a);
e0799b34
RS
916}
917#endif
918
203b91b9 919#ifdef L_fixunsdfdi
996ed075
JJ
920#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
921#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
203b91b9 922
996ed075 923DWtype
6da9c622 924__fixunsdfDI (DFtype a)
203b91b9 925{
ab495388 926 DFtype b;
996ed075 927 UDWtype v;
203b91b9
RS
928
929 if (a < 0)
930 return 0;
931
932 /* Compute high word of result, as a flonum. */
933 b = (a / HIGH_WORD_COEFF);
996ed075 934 /* Convert that to fixed (but not to DWtype!),
203b91b9 935 and shift it into the high word. */
996ed075 936 v = (UWtype) b;
203b91b9 937 v <<= WORD_SIZE;
ab495388
RS
938 /* Remove high part from the DFtype, leaving the low part as flonum. */
939 a -= (DFtype)v;
996ed075 940 /* Convert that to fixed (but not to DWtype!) and add it in.
203b91b9
RS
941 Sometimes A comes out negative. This is significant, since
942 A has more bits than a long int does. */
943 if (a < 0)
996ed075 944 v -= (UWtype) (- a);
203b91b9 945 else
996ed075 946 v += (UWtype) a;
203b91b9
RS
947 return v;
948}
949#endif
950
951#ifdef L_fixdfdi
996ed075 952DWtype
37ef1054 953__fixdfdi (DFtype a)
203b91b9
RS
954{
955 if (a < 0)
6da9c622
RK
956 return - __fixunsdfDI (-a);
957 return __fixunsdfDI (a);
203b91b9
RS
958}
959#endif
960
961#ifdef L_fixunssfdi
996ed075
JJ
962#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
963#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
203b91b9 964
996ed075 965DWtype
6da9c622 966__fixunssfDI (SFtype original_a)
203b91b9 967{
ab495388 968 /* Convert the SFtype to a DFtype, because that is surely not going
203b91b9 969 to lose any bits. Some day someone else can write a faster version
ab495388
RS
970 that avoids converting to DFtype, and verify it really works right. */
971 DFtype a = original_a;
972 DFtype b;
996ed075 973 UDWtype v;
203b91b9
RS
974
975 if (a < 0)
976 return 0;
977
978 /* Compute high word of result, as a flonum. */
979 b = (a / HIGH_WORD_COEFF);
996ed075 980 /* Convert that to fixed (but not to DWtype!),
203b91b9 981 and shift it into the high word. */
996ed075 982 v = (UWtype) b;
203b91b9 983 v <<= WORD_SIZE;
ab495388 984 /* Remove high part from the DFtype, leaving the low part as flonum. */
6da9c622 985 a -= (DFtype) v;
996ed075 986 /* Convert that to fixed (but not to DWtype!) and add it in.
203b91b9
RS
987 Sometimes A comes out negative. This is significant, since
988 A has more bits than a long int does. */
989 if (a < 0)
996ed075 990 v -= (UWtype) (- a);
203b91b9 991 else
996ed075 992 v += (UWtype) a;
203b91b9
RS
993 return v;
994}
995#endif
996
997#ifdef L_fixsfdi
996ed075 998DWtype
ab495388 999__fixsfdi (SFtype a)
203b91b9
RS
1000{
1001 if (a < 0)
6da9c622
RK
1002 return - __fixunssfDI (-a);
1003 return __fixunssfDI (a);
203b91b9
RS
1004}
1005#endif
1006
eaa4b44c 1007#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
996ed075
JJ
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)
e0799b34
RS
1011
1012XFtype
996ed075 1013__floatdixf (DWtype u)
e0799b34
RS
1014{
1015 XFtype d;
e0799b34 1016
996ed075 1017 d = (Wtype) (u >> WORD_SIZE);
e0799b34
RS
1018 d *= HIGH_HALFWORD_COEFF;
1019 d *= HIGH_HALFWORD_COEFF;
996ed075 1020 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
e0799b34 1021
e5e809f4 1022 return d;
e0799b34
RS
1023}
1024#endif
1025
eaa4b44c 1026#if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
996ed075
JJ
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)
ab495388
RS
1030
1031TFtype
996ed075 1032__floatditf (DWtype u)
ab495388
RS
1033{
1034 TFtype d;
ab495388 1035
996ed075 1036 d = (Wtype) (u >> WORD_SIZE);
ab495388
RS
1037 d *= HIGH_HALFWORD_COEFF;
1038 d *= HIGH_HALFWORD_COEFF;
996ed075 1039 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
ab495388 1040
e5e809f4 1041 return d;
ab495388
RS
1042}
1043#endif
1044
203b91b9 1045#ifdef L_floatdidf
996ed075
JJ
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)
203b91b9 1049
ab495388 1050DFtype
996ed075 1051__floatdidf (DWtype u)
203b91b9 1052{
ab495388 1053 DFtype d;
203b91b9 1054
996ed075 1055 d = (Wtype) (u >> WORD_SIZE);
203b91b9
RS
1056 d *= HIGH_HALFWORD_COEFF;
1057 d *= HIGH_HALFWORD_COEFF;
996ed075 1058 d += (UWtype) (u & (HIGH_WORD_COEFF - 1));
203b91b9 1059
e5e809f4 1060 return d;
203b91b9
RS
1061}
1062#endif
1063
1064#ifdef L_floatdisf
996ed075
JJ
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)
23190837 1068
15e5ad76 1069#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
b216cd4a
ZW
1070#define DF_SIZE DBL_MANT_DIG
1071#define SF_SIZE FLT_MANT_DIG
203b91b9 1072
ab495388 1073SFtype
996ed075 1074__floatdisf (DWtype u)
203b91b9 1075{
56b03d5f
RS
1076 /* Do the calculation in DFmode
1077 so that we don't lose any of the precision of the high word
1078 while multiplying it. */
1079 DFtype f;
203b91b9 1080
d9e1ab8d
RK
1081 /* Protect against double-rounding error.
1082 Represent any low-order bits, that might be truncated in DFmode,
1083 by a bit that won't be lost. The bit can go in anywhere below the
1084 rounding position of the SFmode. A fixed mask and bit position
1085 handles all usual configurations. It doesn't handle the case
1086 of 128-bit DImode, however. */
1087 if (DF_SIZE < DI_SIZE
1088 && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1089 {
6da9c622 1090#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
996ed075
JJ
1091 if (! (- ((DWtype) 1 << DF_SIZE) < u
1092 && u < ((DWtype) 1 << DF_SIZE)))
d9e1ab8d 1093 {
6da9c622 1094 if ((UDWtype) u & (REP_BIT - 1))
d9e1ab8d
RK
1095 u |= REP_BIT;
1096 }
1097 }
996ed075 1098 f = (Wtype) (u >> WORD_SIZE);
203b91b9
RS
1099 f *= HIGH_HALFWORD_COEFF;
1100 f *= HIGH_HALFWORD_COEFF;
996ed075 1101 f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
203b91b9 1102
e5e809f4 1103 return (SFtype) f;
203b91b9
RS
1104}
1105#endif
1106
eaa4b44c 1107#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
3f3d2ec8
JW
1108/* Reenable the normal types, in case limits.h needs them. */
1109#undef char
1110#undef short
1111#undef int
1112#undef long
1113#undef unsigned
1114#undef float
1115#undef double
c07e26bd
RK
1116#undef MIN
1117#undef MAX
a99598c9 1118#include <limits.h>
e0799b34 1119
996ed075 1120UWtype
6da9c622 1121__fixunsxfSI (XFtype a)
e0799b34 1122{
5d0e6486
AO
1123 if (a >= - (DFtype) Wtype_MIN)
1124 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
996ed075 1125 return (Wtype) a;
e0799b34
RS
1126}
1127#endif
1128
203b91b9 1129#ifdef L_fixunsdfsi
3f3d2ec8
JW
1130/* Reenable the normal types, in case limits.h needs them. */
1131#undef char
1132#undef short
1133#undef int
1134#undef long
1135#undef unsigned
1136#undef float
1137#undef double
c07e26bd
RK
1138#undef MIN
1139#undef MAX
a99598c9 1140#include <limits.h>
203b91b9 1141
996ed075 1142UWtype
6da9c622 1143__fixunsdfSI (DFtype a)
203b91b9 1144{
5d0e6486
AO
1145 if (a >= - (DFtype) Wtype_MIN)
1146 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
996ed075 1147 return (Wtype) a;
203b91b9
RS
1148}
1149#endif
1150
1151#ifdef L_fixunssfsi
3f3d2ec8
JW
1152/* Reenable the normal types, in case limits.h needs them. */
1153#undef char
1154#undef short
1155#undef int
1156#undef long
1157#undef unsigned
1158#undef float
1159#undef double
c07e26bd
RK
1160#undef MIN
1161#undef MAX
a99598c9 1162#include <limits.h>
203b91b9 1163
996ed075 1164UWtype
6da9c622 1165__fixunssfSI (SFtype a)
203b91b9 1166{
5d0e6486
AO
1167 if (a >= - (SFtype) Wtype_MIN)
1168 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
996ed075 1169 return (Wtype) a;
203b91b9
RS
1170}
1171#endif
1172\f
ab495388
RS
1173/* From here on down, the routines use normal data types. */
1174
1175#define SItype bogus_type
1176#define USItype bogus_type
1177#define DItype bogus_type
1178#define UDItype bogus_type
1179#define SFtype bogus_type
1180#define DFtype bogus_type
996ed075
JJ
1181#undef Wtype
1182#undef UWtype
1183#undef HWtype
1184#undef UHWtype
1185#undef DWtype
1186#undef UDWtype
ab495388
RS
1187
1188#undef char
1189#undef short
1190#undef int
1191#undef long
1192#undef unsigned
1193#undef float
1194#undef double
9bd23d2c
RS
1195\f
1196#ifdef L__gcc_bcmp
1197
1198/* Like bcmp except the sign is meaningful.
9faa82d8 1199 Result is negative if S1 is less than S2,
9bd23d2c
RS
1200 positive if S1 is greater, 0 if S1 and S2 are equal. */
1201
1202int
299b83b7 1203__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
9bd23d2c
RS
1204{
1205 while (size > 0)
1206 {
78e33213 1207 unsigned char c1 = *s1++, c2 = *s2++;
9bd23d2c
RS
1208 if (c1 != c2)
1209 return c1 - c2;
1210 size--;
1211 }
1212 return 0;
1213}
ab495388 1214
3fe68d0a
ZW
1215#endif
1216\f
1217/* __eprintf used to be used by GCC's private version of <assert.h>.
1218 We no longer provide that header, but this routine remains in libgcc.a
1219 for binary backward compatibility. Note that it is not included in
1220 the shared version of libgcc. */
1221#ifdef L_eprintf
1222#ifndef inhibit_libc
1223
1224#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1225#include <stdio.h>
1226
1227void
1228__eprintf (const char *string, const char *expression,
1229 unsigned int line, const char *filename)
1230{
1231 fprintf (stderr, string, expression, line, filename);
1232 fflush (stderr);
1233 abort ();
1234}
1235
1236#endif
203b91b9
RS
1237#endif
1238
1239#ifdef L_bb
203b91b9 1240
b7c9bf28
JH
1241struct bb_function_info {
1242 long checksum;
1243 int arc_count;
1244 const char *name;
1245};
b2aec5c0 1246
92832bb5 1247/* Structure emitted by -a */
203b91b9
RS
1248struct bb
1249{
92832bb5
MM
1250 long zero_word;
1251 const char *filename;
b2aec5c0 1252 gcov_type *counts;
92832bb5
MM
1253 long ncounts;
1254 struct bb *next;
92832bb5
MM
1255
1256 /* Older GCC's did not emit these fields. */
2292e8fc 1257 long sizeof_bb;
b7c9bf28 1258 struct bb_function_info *function_infos;
203b91b9
RS
1259};
1260
c7544ff7 1261#ifndef inhibit_libc
92832bb5
MM
1262
1263/* Simple minded basic block profiling output dumper for
9faa82d8 1264 systems that don't provide tcov support. At present,
92832bb5
MM
1265 it requires atexit and stdio. */
1266
ebd41309 1267#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
92832bb5 1268#include <stdio.h>
203b91b9 1269
8b7677be 1270#include "gbl-ctors.h"
65f7a653 1271#include "gcov-io.h"
ac957f13 1272#include <string.h>
e09d24ff
R
1273#ifdef TARGET_HAS_F_SETLKW
1274#include <fcntl.h>
1275#include <errno.h>
1276#endif
92832bb5 1277
b7c9bf28
JH
1278#include <gthr.h>
1279
7e6f1890 1280static struct bb *bb_head;
92832bb5 1281
b7c9bf28
JH
1282int __global_counters = 0, __gthreads_active = 0;
1283
543828ca 1284void
92832bb5
MM
1285__bb_exit_func (void)
1286{
114e78f8 1287 FILE *da_file;
114e78f8 1288 struct bb *ptr;
b7c9bf28
JH
1289 long n_counters_p = 0;
1290 gcov_type max_counter_p = 0;
1291 gcov_type sum_counters_p = 0;
65f7a653
DE
1292
1293 if (bb_head == 0)
1294 return;
1295
b7c9bf28 1296 /* Calculate overall "statistics". */
65f7a653 1297
b7c9bf28
JH
1298 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1299 {
1300 int i;
1301
1302 n_counters_p += ptr->ncounts;
1303
1304 for (i = 0; i < ptr->ncounts; i++)
1305 {
1306 sum_counters_p += ptr->counts[i];
1307
1308 if (ptr->counts[i] > max_counter_p)
1309 max_counter_p = ptr->counts[i];
1310 }
1311 }
65f7a653 1312
114e78f8
JH
1313 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1314 {
b7c9bf28
JH
1315 gcov_type max_counter_o = 0;
1316 gcov_type sum_counters_o = 0;
1317 int i;
1318
1319 /* Calculate the per-object statistics. */
114e78f8 1320
b7c9bf28
JH
1321 for (i = 0; i < ptr->ncounts; i++)
1322 {
1323 sum_counters_o += ptr->counts[i];
114e78f8 1324
b7c9bf28
JH
1325 if (ptr->counts[i] > max_counter_o)
1326 max_counter_o = ptr->counts[i];
1327 }
1328
1329 /* open the file for appending, creating it if necessary. */
1330 da_file = fopen (ptr->filename, "ab");
114e78f8
JH
1331 /* Some old systems might not allow the 'b' mode modifier.
1332 Therefore, try to open without it. This can lead to a race
1333 condition so that when you delete and re-create the file, the
1334 file might be opened in text mode, but then, you shouldn't
1335 delete the file in the first place. */
1336 if (da_file == 0)
b7c9bf28 1337 da_file = fopen (ptr->filename, "a");
114e78f8 1338 if (da_file == 0)
65f7a653 1339 {
114e78f8
JH
1340 fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1341 ptr->filename);
1342 continue;
1343 }
e09d24ff 1344
114e78f8
JH
1345 /* After a fork, another process might try to read and/or write
1346 the same file simultanously. So if we can, lock the file to
1347 avoid race conditions. */
e09d24ff 1348#if defined (TARGET_HAS_F_SETLKW)
114e78f8
JH
1349 {
1350 struct flock s_flock;
1351
1352 s_flock.l_type = F_WRLCK;
1353 s_flock.l_whence = SEEK_SET;
1354 s_flock.l_start = 0;
1355 s_flock.l_len = 1;
1356 s_flock.l_pid = getpid ();
1357
1358 while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
1359 && errno == EINTR);
1360 }
e09d24ff
R
1361#endif
1362
b7c9bf28 1363 if (__write_long (-123, da_file, 4) != 0) /* magic */
114e78f8 1364 {
b7c9bf28
JH
1365 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1366 ptr->filename);
114e78f8
JH
1367 }
1368 else
1369 {
114e78f8 1370
b7c9bf28
JH
1371 struct bb_function_info *fn_info;
1372 gcov_type *count_ptr = ptr->counts;
1373 int i;
1374 int count_functions = 0;
1375
1376 for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
1377 fn_info++)
1378 count_functions++;
1379
1380 /* number of functions in this block. */
1381 __write_long (count_functions, da_file, 4);
1382
1383 /* length of extra data in bytes. */
1384 __write_long ((4 + 8 + 8) + (4 + 8 + 8), da_file, 4);
1385
1386 /* overall statistics. */
1387 /* number of counters. */
1388 __write_long (n_counters_p, da_file, 4);
1389 /* sum of counters. */
1390 __write_gcov_type (sum_counters_p, da_file, 8);
1391 /* maximal counter. */
1392 __write_gcov_type (max_counter_p, da_file, 8);
1393
1394 /* per-object statistics. */
1395 /* number of counters. */
1396 __write_long (ptr->ncounts, da_file, 4);
1397 /* sum of counters. */
1398 __write_gcov_type (sum_counters_o, da_file, 8);
1399 /* maximal counter. */
1400 __write_gcov_type (max_counter_o, da_file, 8);
1401
1402 /* write execution counts for each function. */
1403
1404 for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
1405 fn_info++)
65f7a653 1406 {
b7c9bf28
JH
1407 /* new function. */
1408 if (__write_gcov_string
1409 (fn_info->name, strlen (fn_info->name), da_file, -1) != 0)
65f7a653 1410 {
b7c9bf28
JH
1411 fprintf (stderr,
1412 "arc profiling: Error writing output file %s.\n",
1413 ptr->filename);
1414 break;
65f7a653 1415 }
23190837 1416
b7c9bf28
JH
1417 if (__write_long (fn_info->checksum, da_file, 4) != 0)
1418 {
1419 fprintf (stderr,
1420 "arc profiling: Error writing output file %s.\n",
1421 ptr->filename);
1422 break;
1423 }
92832bb5 1424
b7c9bf28
JH
1425 if (__write_long (fn_info->arc_count, da_file, 4) != 0)
1426 {
1427 fprintf (stderr,
1428 "arc profiling: Error writing output file %s.\n",
1429 ptr->filename);
1430 break;
1431 }
92832bb5 1432
b7c9bf28
JH
1433 for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
1434 {
1435 if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
1436 break;
1437 }
92832bb5 1438
b7c9bf28 1439 if (i) /* there was an error */
92832bb5 1440 {
b7c9bf28
JH
1441 fprintf (stderr,
1442 "arc profiling: Error writing output file %s.\n",
1443 ptr->filename);
114e78f8 1444 break;
92832bb5
MM
1445 }
1446 }
92832bb5
MM
1447 }
1448
b7c9bf28 1449 if (fclose (da_file) != 0)
114e78f8
JH
1450 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1451 ptr->filename);
92832bb5
MM
1452 }
1453}
1454
1455void
1456__bb_init_func (struct bb *blocks)
1457{
1458 /* User is supposed to check whether the first word is non-0,
0f41302f 1459 but just in case.... */
92832bb5
MM
1460
1461 if (blocks->zero_word)
1462 return;
b7c9bf28
JH
1463
1464 /* Initialize destructor and per-thread data. */
92832bb5 1465 if (!bb_head)
c063dc98 1466 atexit (__bb_exit_func);
92832bb5
MM
1467
1468 /* Set up linked list. */
1469 blocks->zero_word = 1;
1470 blocks->next = bb_head;
1471 bb_head = blocks;
1472}
1473
e09d24ff
R
1474/* Called before fork or exec - write out profile information gathered so
1475 far and reset it to zero. This avoids duplication or loss of the
1476 profile information gathered so far. */
b7c9bf28 1477void
e09d24ff
R
1478__bb_fork_func (void)
1479{
1480 struct bb *ptr;
1481
1482 __bb_exit_func ();
1483 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1484 {
1485 long i;
1486 for (i = ptr->ncounts - 1; i >= 0; i--)
1487 ptr->counts[i] = 0;
1488 }
1489}
1490
c7544ff7 1491#endif /* not inhibit_libc */
c7544ff7 1492#endif /* L_bb */
203b91b9 1493\f
203b91b9
RS
1494#ifdef L_clear_cache
1495/* Clear part of an instruction cache. */
1496
1497#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1498
1499void
139fa6f8
MM
1500__clear_cache (char *beg __attribute__((__unused__)),
1501 char *end __attribute__((__unused__)))
203b91b9 1502{
23190837 1503#ifdef CLEAR_INSN_CACHE
e1178973
KKT
1504 CLEAR_INSN_CACHE (beg, end);
1505#else
203b91b9
RS
1506#ifdef INSN_CACHE_SIZE
1507 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
7e6f1890 1508 static int initialized;
203b91b9 1509 int offset;
b6422cca
RS
1510 void *start_addr
1511 void *end_addr;
3e7d8ef1 1512 typedef (*function_ptr) (void);
203b91b9
RS
1513
1514#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1515 /* It's cheaper to clear the whole cache.
1516 Put in a series of jump instructions so that calling the beginning
1517 of the cache will clear the whole thing. */
1518
1519 if (! initialized)
1520 {
1521 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1522 & -INSN_CACHE_LINE_WIDTH);
1523 int end_ptr = ptr + INSN_CACHE_SIZE;
1524
1525 while (ptr < end_ptr)
1526 {
1527 *(INSTRUCTION_TYPE *)ptr
1528 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1529 ptr += INSN_CACHE_LINE_WIDTH;
1530 }
0f41302f 1531 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
203b91b9
RS
1532
1533 initialized = 1;
1534 }
1535
1536 /* Call the beginning of the sequence. */
1537 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1538 & -INSN_CACHE_LINE_WIDTH))
1539 ());
1540
1541#else /* Cache is large. */
1542
1543 if (! initialized)
1544 {
1545 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1546 & -INSN_CACHE_LINE_WIDTH);
1547
1548 while (ptr < (int) array + sizeof array)
1549 {
1550 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1551 ptr += INSN_CACHE_LINE_WIDTH;
1552 }
1553
1554 initialized = 1;
1555 }
1556
1557 /* Find the location in array that occupies the same cache line as BEG. */
1558
1559 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1560 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1561 & -INSN_CACHE_PLANE_SIZE)
1562 + offset);
1563
1564 /* Compute the cache alignment of the place to stop clearing. */
1565#if 0 /* This is not needed for gcc's purposes. */
1566 /* If the block to clear is bigger than a cache plane,
23190837 1567 we clear the entire cache, and OFFSET is already correct. */
203b91b9
RS
1568 if (end < beg + INSN_CACHE_PLANE_SIZE)
1569#endif
1570 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1571 & -INSN_CACHE_LINE_WIDTH)
1572 & (INSN_CACHE_PLANE_SIZE - 1));
1573
1574#if INSN_CACHE_DEPTH > 1
1575 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1576 if (end_addr <= start_addr)
1577 end_addr += INSN_CACHE_PLANE_SIZE;
1578
1579 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1580 {
1581 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1582 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1583
1584 while (addr != stop)
1585 {
1586 /* Call the return instruction at ADDR. */
1587 ((function_ptr) addr) ();
1588
1589 addr += INSN_CACHE_LINE_WIDTH;
1590 }
1591 }
1592#else /* just one plane */
1593 do
1594 {
1595 /* Call the return instruction at START_ADDR. */
1596 ((function_ptr) start_addr) ();
1597
1598 start_addr += INSN_CACHE_LINE_WIDTH;
1599 }
1600 while ((start_addr % INSN_CACHE_SIZE) != offset);
1601#endif /* just one plane */
1602#endif /* Cache is large */
1603#endif /* Cache exists */
e1178973 1604#endif /* CLEAR_INSN_CACHE */
203b91b9
RS
1605}
1606
1607#endif /* L_clear_cache */
1608\f
1609#ifdef L_trampoline
1610
1611/* Jump to a trampoline, loading the static chain address. */
1612
b27d2bd5 1613#if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
e3367a77 1614
3e7d8ef1
KG
1615long
1616getpagesize (void)
f5ea9817
RK
1617{
1618#ifdef _ALPHA_
1619 return 8192;
1620#else
1621 return 4096;
1622#endif
1623}
1624
d7ebf9ea 1625#ifdef __i386__
e4b15106
RK
1626extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
1627#endif
1628
272e2587
RK
1629int
1630mprotect (char *addr, int len, int prot)
f5ea9817
RK
1631{
1632 int np, op;
1633
272e2587
RK
1634 if (prot == 7)
1635 np = 0x40;
1636 else if (prot == 5)
1637 np = 0x20;
1638 else if (prot == 4)
1639 np = 0x10;
1640 else if (prot == 3)
1641 np = 0x04;
1642 else if (prot == 1)
1643 np = 0x02;
1644 else if (prot == 0)
1645 np = 0x01;
f5ea9817
RK
1646
1647 if (VirtualProtect (addr, len, np, &op))
1648 return 0;
1649 else
1650 return -1;
f5ea9817
RK
1651}
1652
b27d2bd5 1653#endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
f5ea9817 1654
23190837
AJ
1655#ifdef TRANSFER_FROM_TRAMPOLINE
1656TRANSFER_FROM_TRAMPOLINE
203b91b9
RS
1657#endif
1658
c1381fd3
KKT
1659#if defined (NeXT) && defined (__MACH__)
1660
1661/* Make stack executable so we can call trampolines on stack.
1662 This is called from INITIALIZE_TRAMPOLINE in next.h. */
c5df463e
RK
1663#ifdef NeXTStep21
1664 #include <mach.h>
1665#else
1666 #include <mach/mach.h>
1667#endif
c1381fd3
KKT
1668
1669void
37ef1054 1670__enable_execute_stack (char *addr)
c1381fd3
KKT
1671{
1672 kern_return_t r;
1673 char *eaddr = addr + TRAMPOLINE_SIZE;
1674 vm_address_t a = (vm_address_t) addr;
1675
1676 /* turn on execute access on stack */
1677 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
1678 if (r != KERN_SUCCESS)
1679 {
1680 mach_error("vm_protect VM_PROT_ALL", r);
1681 exit(1);
1682 }
1683
1684 /* We inline the i-cache invalidation for speed */
1685
1686#ifdef CLEAR_INSN_CACHE
1687 CLEAR_INSN_CACHE (addr, eaddr);
1688#else
1689 __clear_cache ((int) addr, (int) eaddr);
1690#endif
23190837 1691}
c1381fd3
KKT
1692
1693#endif /* defined (NeXT) && defined (__MACH__) */
1694
203b91b9
RS
1695#ifdef __convex__
1696
1697/* Make stack executable so we can call trampolines on stack.
1698 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
1699
1700#include <sys/mman.h>
1701#include <sys/vmparam.h>
1702#include <machine/machparam.h>
1703
1704void
3e7d8ef1 1705__enable_execute_stack (void)
203b91b9
RS
1706{
1707 int fp;
1708 static unsigned lowest = USRSTACK;
1709 unsigned current = (unsigned) &fp & -NBPG;
1710
1711 if (lowest > current)
1712 {
1713 unsigned len = lowest - current;
1714 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1715 lowest = current;
1716 }
1717
0f41302f 1718 /* Clear instruction cache in case an old trampoline is in it. */
203b91b9
RS
1719 asm ("pich");
1720}
1721#endif /* __convex__ */
b335c2cc 1722
db87ec0b 1723#ifdef __sysV88__
0c8ae3d3 1724
0f41302f 1725/* Modified from the convex -code above. */
0c8ae3d3
RK
1726
1727#include <sys/param.h>
1728#include <errno.h>
1729#include <sys/m88kbcs.h>
1730
1731void
3e7d8ef1 1732__enable_execute_stack (void)
0c8ae3d3
RK
1733{
1734 int save_errno;
1735 static unsigned long lowest = USRSTACK;
1736 unsigned long current = (unsigned long) &save_errno & -NBPC;
23190837 1737
0c8ae3d3 1738 /* Ignore errno being set. memctl sets errno to EINVAL whenever the
6d2f8887 1739 address is seen as 'negative'. That is the case with the stack. */
0c8ae3d3
RK
1740
1741 save_errno=errno;
1742 if (lowest > current)
1743 {
1744 unsigned len=lowest-current;
1745 memctl(current,len,MCT_TEXT);
1746 lowest = current;
1747 }
1748 else
1749 memctl(current,NBPC,MCT_TEXT);
1750 errno=save_errno;
1751}
1752
db87ec0b 1753#endif /* __sysV88__ */
0c8ae3d3 1754
c85f7c16
JL
1755#ifdef __sysV68__
1756
1757#include <sys/signal.h>
1758#include <errno.h>
1759
1760/* Motorola forgot to put memctl.o in the libp version of libc881.a,
1761 so define it here, because we need it in __clear_insn_cache below */
3698f44e
MH
1762/* On older versions of this OS, no memctl or MCT_TEXT are defined;
1763 hence we enable this stuff only if MCT_TEXT is #define'd. */
c85f7c16 1764
3698f44e 1765#ifdef MCT_TEXT
c85f7c16
JL
1766asm("\n\
1767 global memctl\n\
1768memctl:\n\
1769 movq &75,%d0\n\
1770 trap &0\n\
1771 bcc.b noerror\n\
1772 jmp cerror%\n\
1773noerror:\n\
1774 movq &0,%d0\n\
1775 rts");
3698f44e 1776#endif
c85f7c16
JL
1777
1778/* Clear instruction cache so we can call trampolines on stack.
1779 This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
1780
1781void
3e7d8ef1 1782__clear_insn_cache (void)
c85f7c16 1783{
3698f44e 1784#ifdef MCT_TEXT
c85f7c16
JL
1785 int save_errno;
1786
1787 /* Preserve errno, because users would be surprised to have
dc297297 1788 errno changing without explicitly calling any system-call. */
c85f7c16
JL
1789 save_errno = errno;
1790
23190837 1791 /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
dc297297 1792 No need to use an address derived from _start or %sp, as 0 works also. */
c85f7c16
JL
1793 memctl(0, 4096, MCT_TEXT);
1794 errno = save_errno;
3698f44e 1795#endif
c85f7c16
JL
1796}
1797
1798#endif /* __sysV68__ */
1799
b335c2cc
TW
1800#ifdef __pyr__
1801
98126ed6 1802#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
b335c2cc
TW
1803#include <stdio.h>
1804#include <sys/mman.h>
1805#include <sys/types.h>
1806#include <sys/param.h>
1807#include <sys/vmmac.h>
1808
1809/* Modified from the convex -code above.
0f41302f 1810 mremap promises to clear the i-cache. */
b335c2cc
TW
1811
1812void
3e7d8ef1 1813__enable_execute_stack (void)
b335c2cc
TW
1814{
1815 int fp;
1816 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
1817 PROT_READ|PROT_WRITE|PROT_EXEC))
1818 {
1819 perror ("mprotect in __enable_execute_stack");
1820 fflush (stderr);
1821 abort ();
1822 }
1823}
1824#endif /* __pyr__ */
7d41c411
RK
1825
1826#if defined (sony_news) && defined (SYSTYPE_BSD)
1827
1828#include <stdio.h>
1829#include <sys/types.h>
1830#include <sys/param.h>
1831#include <syscall.h>
1832#include <machine/sysnews.h>
1833
1834/* cacheflush function for NEWS-OS 4.2.
1835 This function is called from trampoline-initialize code
1836 defined in config/mips/mips.h. */
1837
1838void
37ef1054 1839cacheflush (char *beg, int size, int flag)
7d41c411
RK
1840{
1841 if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
1842 {
1843 perror ("cache_flush");
1844 fflush (stderr);
1845 abort ();
1846 }
1847}
1848
1849#endif /* sony_news */
203b91b9
RS
1850#endif /* L_trampoline */
1851\f
cae21ae8 1852#ifndef __CYGWIN__
203b91b9
RS
1853#ifdef L__main
1854
1855#include "gbl-ctors.h"
c06cff95
RS
1856/* Some systems use __main in a way incompatible with its use in gcc, in these
1857 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
1858 give the same symbol without quotes for an alternative entry point. You
0f41302f 1859 must define both, or neither. */
c06cff95
RS
1860#ifndef NAME__MAIN
1861#define NAME__MAIN "__main"
1862#define SYMBOL__MAIN __main
1863#endif
203b91b9 1864
fe1fd353
JM
1865#ifdef INIT_SECTION_ASM_OP
1866#undef HAS_INIT_SECTION
1867#define HAS_INIT_SECTION
1868#endif
1869
1870#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
31cf0144
JM
1871
1872/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
1873 code to run constructors. In that case, we need to handle EH here, too. */
1874
540ceb67 1875#ifdef EH_FRAME_SECTION_NAME
e4b776a6 1876#include "unwind-dw2-fde.h"
31cf0144
JM
1877extern unsigned char __EH_FRAME_BEGIN__[];
1878#endif
1879
203b91b9
RS
1880/* Run all the global destructors on exit from the program. */
1881
1882void
3e7d8ef1 1883__do_global_dtors (void)
203b91b9 1884{
89cf554b
RS
1885#ifdef DO_GLOBAL_DTORS_BODY
1886 DO_GLOBAL_DTORS_BODY;
1887#else
b40b9d93
MS
1888 static func_ptr *p = __DTOR_LIST__ + 1;
1889 while (*p)
1890 {
1891 p++;
1892 (*(p-1)) ();
1893 }
89cf554b 1894#endif
540ceb67 1895#if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
a4ebb0e6
GRK
1896 {
1897 static int completed = 0;
1898 if (! completed)
1899 {
1900 completed = 1;
1901 __deregister_frame_info (__EH_FRAME_BEGIN__);
1902 }
1903 }
31cf0144 1904#endif
203b91b9 1905}
68d69835 1906#endif
203b91b9 1907
fe1fd353 1908#ifndef HAS_INIT_SECTION
203b91b9
RS
1909/* Run all the global constructors on entry to the program. */
1910
203b91b9 1911void
3e7d8ef1 1912__do_global_ctors (void)
203b91b9 1913{
540ceb67 1914#ifdef EH_FRAME_SECTION_NAME
31cf0144
JM
1915 {
1916 static struct object object;
1917 __register_frame_info (__EH_FRAME_BEGIN__, &object);
1918 }
1919#endif
203b91b9 1920 DO_GLOBAL_CTORS_BODY;
a218d5ba 1921 atexit (__do_global_dtors);
203b91b9 1922}
fe1fd353 1923#endif /* no HAS_INIT_SECTION */
203b91b9 1924
fe1fd353 1925#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
203b91b9
RS
1926/* Subroutine called automatically by `main'.
1927 Compiling a global function named `main'
1928 produces an automatic call to this function at the beginning.
1929
1930 For many systems, this routine calls __do_global_ctors.
1931 For systems which support a .init section we use the .init section
1932 to run __do_global_ctors, so we need not do anything here. */
1933
1934void
c06cff95 1935SYMBOL__MAIN ()
203b91b9
RS
1936{
1937 /* Support recursive calls to `main': run initializers just once. */
7e6f1890 1938 static int initialized;
203b91b9
RS
1939 if (! initialized)
1940 {
1941 initialized = 1;
1942 __do_global_ctors ();
1943 }
1944}
fe1fd353 1945#endif /* no HAS_INIT_SECTION or INVOKE__main */
203b91b9
RS
1946
1947#endif /* L__main */
cae21ae8 1948#endif /* __CYGWIN__ */
203b91b9 1949\f
ad38743d 1950#ifdef L_ctors
203b91b9
RS
1951
1952#include "gbl-ctors.h"
1953
1954/* Provide default definitions for the lists of constructors and
657be7af
JL
1955 destructors, so that we don't get linker errors. These symbols are
1956 intentionally bss symbols, so that gld and/or collect will provide
1957 the right values. */
203b91b9
RS
1958
1959/* We declare the lists here with two elements each,
657be7af
JL
1960 so that they are valid empty lists if no other definition is loaded.
1961
1962 If we are using the old "set" extensions to have the gnu linker
1963 collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
1964 must be in the bss/common section.
1965
1966 Long term no port should use those extensions. But many still do. */
b335c2cc 1967#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
aa6ad1a6 1968#if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
d15d0264
RS
1969func_ptr __CTOR_LIST__[2] = {0, 0};
1970func_ptr __DTOR_LIST__[2] = {0, 0};
657be7af
JL
1971#else
1972func_ptr __CTOR_LIST__[2];
1973func_ptr __DTOR_LIST__[2];
1974#endif
b335c2cc 1975#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
ad38743d
RS
1976#endif /* L_ctors */
1977\f
1978#ifdef L_exit
1979
1980#include "gbl-ctors.h"
203b91b9 1981
8b7677be 1982#ifdef NEED_ATEXIT
8b7677be 1983
f75e8946 1984#ifndef ON_EXIT
203b91b9 1985
8b7677be
RK
1986# include <errno.h>
1987
920b13cc 1988static func_ptr *atexit_chain = 0;
8b7677be
RK
1989static long atexit_chain_length = 0;
1990static volatile long last_atexit_chain_slot = -1;
1991
c063dc98
JM
1992int
1993atexit (func_ptr func)
8b7677be
RK
1994{
1995 if (++last_atexit_chain_slot == atexit_chain_length)
1996 {
1997 atexit_chain_length += 32;
1998 if (atexit_chain)
a25cea96
RK
1999 atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2000 * sizeof (func_ptr));
8b7677be 2001 else
a25cea96
RK
2002 atexit_chain = (func_ptr *) malloc (atexit_chain_length
2003 * sizeof (func_ptr));
8b7677be
RK
2004 if (! atexit_chain)
2005 {
2006 atexit_chain_length = 0;
2007 last_atexit_chain_slot = -1;
2008 errno = ENOMEM;
2009 return (-1);
2010 }
2011 }
2012 atexit_chain[last_atexit_chain_slot] = func;
2013 return (0);
2014}
8b7677be 2015
3e7d8ef1
KG
2016extern void _cleanup (void);
2017extern void _exit (int) __attribute__ ((__noreturn__));
203b91b9 2018
23190837 2019void
37ef1054 2020exit (int status)
203b91b9 2021{
8b7677be
RK
2022 if (atexit_chain)
2023 {
2024 for ( ; last_atexit_chain_slot-- >= 0; )
2025 {
2026 (*atexit_chain[last_atexit_chain_slot + 1]) ();
920b13cc 2027 atexit_chain[last_atexit_chain_slot + 1] = 0;
8b7677be
RK
2028 }
2029 free (atexit_chain);
920b13cc 2030 atexit_chain = 0;
8b7677be 2031 }
203b91b9
RS
2032#ifdef EXIT_BODY
2033 EXIT_BODY;
2034#else
2035 _cleanup ();
2036#endif
2037 _exit (status);
2038}
2039
f75e8946 2040#else /* ON_EXIT */
bceb30e7 2041
c063dc98
JM
2042/* Simple; we just need a wrapper for ON_EXIT. */
2043int
2044atexit (func_ptr func)
bceb30e7 2045{
c063dc98 2046 return ON_EXIT (func);
bceb30e7 2047}
c063dc98 2048
f75e8946 2049#endif /* ON_EXIT */
c063dc98 2050#endif /* NEED_ATEXIT */
203b91b9
RS
2051
2052#endif /* L_exit */
This page took 2.316283 seconds and 5 git commands to generate.