]> gcc.gnu.org Git - gcc.git/blame - gcc/libgcc2.c
libgcc2.c (__bb_exit_func): Remove unused variable.
[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)
1068#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
cac896d8
RK
1069
1070/* Define codes for all the float formats that we know of. Note
1071 that this is copied from real.h. */
23190837 1072
cac896d8
RK
1073#define UNKNOWN_FLOAT_FORMAT 0
1074#define IEEE_FLOAT_FORMAT 1
1075#define VAX_FLOAT_FORMAT 2
1076#define IBM_FLOAT_FORMAT 3
1077
1078/* Default to IEEE float if not specified. Nearly all machines use it. */
1079#ifndef HOST_FLOAT_FORMAT
1080#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
1081#endif
1082
1083#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
d9e1ab8d
RK
1084#define DF_SIZE 53
1085#define SF_SIZE 24
cac896d8
RK
1086#endif
1087
1088#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
d9e1ab8d
RK
1089#define DF_SIZE 56
1090#define SF_SIZE 24
cac896d8
RK
1091#endif
1092
1093#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
d9e1ab8d
RK
1094#define DF_SIZE 56
1095#define SF_SIZE 24
d9e1ab8d 1096#endif
203b91b9 1097
ab495388 1098SFtype
996ed075 1099__floatdisf (DWtype u)
203b91b9 1100{
56b03d5f
RS
1101 /* Do the calculation in DFmode
1102 so that we don't lose any of the precision of the high word
1103 while multiplying it. */
1104 DFtype f;
203b91b9 1105
d9e1ab8d
RK
1106 /* Protect against double-rounding error.
1107 Represent any low-order bits, that might be truncated in DFmode,
1108 by a bit that won't be lost. The bit can go in anywhere below the
1109 rounding position of the SFmode. A fixed mask and bit position
1110 handles all usual configurations. It doesn't handle the case
1111 of 128-bit DImode, however. */
1112 if (DF_SIZE < DI_SIZE
1113 && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1114 {
6da9c622 1115#define REP_BIT ((UDWtype) 1 << (DI_SIZE - DF_SIZE))
996ed075
JJ
1116 if (! (- ((DWtype) 1 << DF_SIZE) < u
1117 && u < ((DWtype) 1 << DF_SIZE)))
d9e1ab8d 1118 {
6da9c622 1119 if ((UDWtype) u & (REP_BIT - 1))
d9e1ab8d
RK
1120 u |= REP_BIT;
1121 }
1122 }
996ed075 1123 f = (Wtype) (u >> WORD_SIZE);
203b91b9
RS
1124 f *= HIGH_HALFWORD_COEFF;
1125 f *= HIGH_HALFWORD_COEFF;
996ed075 1126 f += (UWtype) (u & (HIGH_WORD_COEFF - 1));
203b91b9 1127
e5e809f4 1128 return (SFtype) f;
203b91b9
RS
1129}
1130#endif
1131
eaa4b44c 1132#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
3f3d2ec8
JW
1133/* Reenable the normal types, in case limits.h needs them. */
1134#undef char
1135#undef short
1136#undef int
1137#undef long
1138#undef unsigned
1139#undef float
1140#undef double
c07e26bd
RK
1141#undef MIN
1142#undef MAX
a99598c9 1143#include <limits.h>
e0799b34 1144
996ed075 1145UWtype
6da9c622 1146__fixunsxfSI (XFtype a)
e0799b34 1147{
5d0e6486
AO
1148 if (a >= - (DFtype) Wtype_MIN)
1149 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
996ed075 1150 return (Wtype) a;
e0799b34
RS
1151}
1152#endif
1153
203b91b9 1154#ifdef L_fixunsdfsi
3f3d2ec8
JW
1155/* Reenable the normal types, in case limits.h needs them. */
1156#undef char
1157#undef short
1158#undef int
1159#undef long
1160#undef unsigned
1161#undef float
1162#undef double
c07e26bd
RK
1163#undef MIN
1164#undef MAX
a99598c9 1165#include <limits.h>
203b91b9 1166
996ed075 1167UWtype
6da9c622 1168__fixunsdfSI (DFtype a)
203b91b9 1169{
5d0e6486
AO
1170 if (a >= - (DFtype) Wtype_MIN)
1171 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
996ed075 1172 return (Wtype) a;
203b91b9
RS
1173}
1174#endif
1175
1176#ifdef L_fixunssfsi
3f3d2ec8
JW
1177/* Reenable the normal types, in case limits.h needs them. */
1178#undef char
1179#undef short
1180#undef int
1181#undef long
1182#undef unsigned
1183#undef float
1184#undef double
c07e26bd
RK
1185#undef MIN
1186#undef MAX
a99598c9 1187#include <limits.h>
203b91b9 1188
996ed075 1189UWtype
6da9c622 1190__fixunssfSI (SFtype a)
203b91b9 1191{
5d0e6486
AO
1192 if (a >= - (SFtype) Wtype_MIN)
1193 return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
996ed075 1194 return (Wtype) a;
203b91b9
RS
1195}
1196#endif
1197\f
ab495388
RS
1198/* From here on down, the routines use normal data types. */
1199
1200#define SItype bogus_type
1201#define USItype bogus_type
1202#define DItype bogus_type
1203#define UDItype bogus_type
1204#define SFtype bogus_type
1205#define DFtype bogus_type
996ed075
JJ
1206#undef Wtype
1207#undef UWtype
1208#undef HWtype
1209#undef UHWtype
1210#undef DWtype
1211#undef UDWtype
ab495388
RS
1212
1213#undef char
1214#undef short
1215#undef int
1216#undef long
1217#undef unsigned
1218#undef float
1219#undef double
9bd23d2c
RS
1220\f
1221#ifdef L__gcc_bcmp
1222
1223/* Like bcmp except the sign is meaningful.
9faa82d8 1224 Result is negative if S1 is less than S2,
9bd23d2c
RS
1225 positive if S1 is greater, 0 if S1 and S2 are equal. */
1226
1227int
299b83b7 1228__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size)
9bd23d2c
RS
1229{
1230 while (size > 0)
1231 {
78e33213 1232 unsigned char c1 = *s1++, c2 = *s2++;
9bd23d2c
RS
1233 if (c1 != c2)
1234 return c1 - c2;
1235 size--;
1236 }
1237 return 0;
1238}
ab495388 1239
3fe68d0a
ZW
1240#endif
1241\f
1242/* __eprintf used to be used by GCC's private version of <assert.h>.
1243 We no longer provide that header, but this routine remains in libgcc.a
1244 for binary backward compatibility. Note that it is not included in
1245 the shared version of libgcc. */
1246#ifdef L_eprintf
1247#ifndef inhibit_libc
1248
1249#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1250#include <stdio.h>
1251
1252void
1253__eprintf (const char *string, const char *expression,
1254 unsigned int line, const char *filename)
1255{
1256 fprintf (stderr, string, expression, line, filename);
1257 fflush (stderr);
1258 abort ();
1259}
1260
1261#endif
203b91b9
RS
1262#endif
1263
1264#ifdef L_bb
203b91b9 1265
b2aec5c0
JH
1266#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
1267typedef long gcov_type;
1268#else
1269typedef long long gcov_type;
1270#endif
1271
1272
92832bb5 1273/* Structure emitted by -a */
203b91b9
RS
1274struct bb
1275{
92832bb5
MM
1276 long zero_word;
1277 const char *filename;
b2aec5c0 1278 gcov_type *counts;
92832bb5
MM
1279 long ncounts;
1280 struct bb *next;
1281 const unsigned long *addresses;
1282
1283 /* Older GCC's did not emit these fields. */
1284 long nwords;
1285 const char **functions;
1286 const long *line_nums;
1287 const char **filenames;
90b4a764 1288 char *flags;
203b91b9
RS
1289};
1290
92832bb5
MM
1291#ifdef BLOCK_PROFILER_CODE
1292BLOCK_PROFILER_CODE
1293#else
c7544ff7 1294#ifndef inhibit_libc
92832bb5
MM
1295
1296/* Simple minded basic block profiling output dumper for
9faa82d8 1297 systems that don't provide tcov support. At present,
92832bb5
MM
1298 it requires atexit and stdio. */
1299
ebd41309 1300#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
92832bb5 1301#include <stdio.h>
203b91b9 1302
8b7677be 1303#include "gbl-ctors.h"
65f7a653 1304#include "gcov-io.h"
ac957f13 1305#include <string.h>
e09d24ff
R
1306#ifdef TARGET_HAS_F_SETLKW
1307#include <fcntl.h>
1308#include <errno.h>
1309#endif
92832bb5 1310
7e6f1890 1311static struct bb *bb_head;
92832bb5 1312
92832bb5
MM
1313void
1314__bb_exit_func (void)
1315{
114e78f8 1316 FILE *da_file;
65f7a653 1317 int i;
114e78f8 1318 struct bb *ptr;
65f7a653
DE
1319
1320 if (bb_head == 0)
1321 return;
1322
1323 i = strlen (bb_head->filename) - 3;
1324
65f7a653 1325
114e78f8
JH
1326 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1327 {
1328 int firstchar;
1329
1330 /* Make sure the output file exists -
1331 but don't clobber exiting data. */
1332 if ((da_file = fopen (ptr->filename, "a")) != 0)
1333 fclose (da_file);
1334
1335 /* Need to re-open in order to be able to write from the start. */
1336 da_file = fopen (ptr->filename, "r+b");
1337 /* Some old systems might not allow the 'b' mode modifier.
1338 Therefore, try to open without it. This can lead to a race
1339 condition so that when you delete and re-create the file, the
1340 file might be opened in text mode, but then, you shouldn't
1341 delete the file in the first place. */
1342 if (da_file == 0)
1343 da_file = fopen (ptr->filename, "r+");
1344 if (da_file == 0)
65f7a653 1345 {
114e78f8
JH
1346 fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1347 ptr->filename);
1348 continue;
1349 }
e09d24ff 1350
114e78f8
JH
1351 /* After a fork, another process might try to read and/or write
1352 the same file simultanously. So if we can, lock the file to
1353 avoid race conditions. */
e09d24ff 1354#if defined (TARGET_HAS_F_SETLKW)
114e78f8
JH
1355 {
1356 struct flock s_flock;
1357
1358 s_flock.l_type = F_WRLCK;
1359 s_flock.l_whence = SEEK_SET;
1360 s_flock.l_start = 0;
1361 s_flock.l_len = 1;
1362 s_flock.l_pid = getpid ();
1363
1364 while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
1365 && errno == EINTR);
1366 }
e09d24ff
R
1367#endif
1368
114e78f8
JH
1369 /* If the file is not empty, and the number of counts in it is the
1370 same, then merge them in. */
1371 firstchar = fgetc (da_file);
1372 if (firstchar == EOF)
1373 {
1374 if (ferror (da_file))
65f7a653 1375 {
114e78f8
JH
1376 fprintf (stderr, "arc profiling: Can't read output file ");
1377 perror (ptr->filename);
65f7a653 1378 }
114e78f8
JH
1379 }
1380 else
1381 {
1382 long n_counts = 0;
65f7a653 1383
114e78f8
JH
1384 if (ungetc (firstchar, da_file) == EOF)
1385 rewind (da_file);
1386 if (__read_long (&n_counts, da_file, 8) != 0)
65f7a653 1387 {
114e78f8 1388 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
65f7a653 1389 ptr->filename);
114e78f8 1390 continue;
65f7a653 1391 }
114e78f8
JH
1392
1393 if (n_counts == ptr->ncounts)
65f7a653 1394 {
114e78f8
JH
1395 int i;
1396
1397 for (i = 0; i < n_counts; i++)
65f7a653 1398 {
114e78f8
JH
1399 gcov_type v = 0;
1400
1401 if (__read_gcov_type (&v, da_file, 8) != 0)
65f7a653 1402 {
114e78f8
JH
1403 fprintf (stderr,
1404 "arc profiling: Can't read output file %s.\n",
1405 ptr->filename);
65f7a653
DE
1406 break;
1407 }
114e78f8 1408 ptr->counts[i] += v;
65f7a653 1409 }
65f7a653 1410 }
23190837 1411
65f7a653
DE
1412 }
1413
114e78f8 1414 rewind (da_file);
92832bb5 1415
114e78f8
JH
1416 /* ??? Should first write a header to the file. Preferably, a 4 byte
1417 magic number, 4 bytes containing the time the program was
1418 compiled, 4 bytes containing the last modification time of the
1419 source file, and 4 bytes indicating the compiler options used.
92832bb5 1420
114e78f8
JH
1421 That way we can easily verify that the proper source/executable/
1422 data file combination is being used from gcov. */
92832bb5 1423
114e78f8
JH
1424 if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0)
1425 {
92832bb5 1426
114e78f8
JH
1427 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1428 ptr->filename);
1429 }
1430 else
92832bb5 1431 {
114e78f8
JH
1432 int j;
1433 gcov_type *count_ptr = ptr->counts;
1434 int ret = 0;
1435 for (j = ptr->ncounts; j > 0; j--)
92832bb5 1436 {
114e78f8 1437 if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
92832bb5 1438 {
114e78f8
JH
1439 ret = 1;
1440 break;
92832bb5 1441 }
114e78f8 1442 count_ptr++;
92832bb5 1443 }
114e78f8
JH
1444 if (ret)
1445 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1446 ptr->filename);
92832bb5
MM
1447 }
1448
114e78f8
JH
1449 if (fclose (da_file) == EOF)
1450 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1451 ptr->filename);
92832bb5 1452 }
114e78f8
JH
1453
1454 return;
92832bb5
MM
1455}
1456
1457void
1458__bb_init_func (struct bb *blocks)
1459{
1460 /* User is supposed to check whether the first word is non-0,
0f41302f 1461 but just in case.... */
92832bb5
MM
1462
1463 if (blocks->zero_word)
1464 return;
1465
92832bb5
MM
1466 /* Initialize destructor. */
1467 if (!bb_head)
c063dc98 1468 atexit (__bb_exit_func);
92832bb5
MM
1469
1470 /* Set up linked list. */
1471 blocks->zero_word = 1;
1472 blocks->next = bb_head;
1473 bb_head = blocks;
1474}
1475
e09d24ff
R
1476/* Called before fork or exec - write out profile information gathered so
1477 far and reset it to zero. This avoids duplication or loss of the
1478 profile information gathered so far. */
1479void
1480__bb_fork_func (void)
1481{
1482 struct bb *ptr;
1483
1484 __bb_exit_func ();
1485 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1486 {
1487 long i;
1488 for (i = ptr->ncounts - 1; i >= 0; i--)
1489 ptr->counts[i] = 0;
1490 }
1491}
1492
c7544ff7
RS
1493#endif /* not inhibit_libc */
1494#endif /* not BLOCK_PROFILER_CODE */
1495#endif /* L_bb */
203b91b9 1496\f
203b91b9
RS
1497#ifdef L_clear_cache
1498/* Clear part of an instruction cache. */
1499
1500#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1501
1502void
139fa6f8
MM
1503__clear_cache (char *beg __attribute__((__unused__)),
1504 char *end __attribute__((__unused__)))
203b91b9 1505{
23190837 1506#ifdef CLEAR_INSN_CACHE
e1178973
KKT
1507 CLEAR_INSN_CACHE (beg, end);
1508#else
203b91b9
RS
1509#ifdef INSN_CACHE_SIZE
1510 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
7e6f1890 1511 static int initialized;
203b91b9 1512 int offset;
b6422cca
RS
1513 void *start_addr
1514 void *end_addr;
3e7d8ef1 1515 typedef (*function_ptr) (void);
203b91b9
RS
1516
1517#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1518 /* It's cheaper to clear the whole cache.
1519 Put in a series of jump instructions so that calling the beginning
1520 of the cache will clear the whole thing. */
1521
1522 if (! initialized)
1523 {
1524 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1525 & -INSN_CACHE_LINE_WIDTH);
1526 int end_ptr = ptr + INSN_CACHE_SIZE;
1527
1528 while (ptr < end_ptr)
1529 {
1530 *(INSTRUCTION_TYPE *)ptr
1531 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1532 ptr += INSN_CACHE_LINE_WIDTH;
1533 }
0f41302f 1534 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
203b91b9
RS
1535
1536 initialized = 1;
1537 }
1538
1539 /* Call the beginning of the sequence. */
1540 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1541 & -INSN_CACHE_LINE_WIDTH))
1542 ());
1543
1544#else /* Cache is large. */
1545
1546 if (! initialized)
1547 {
1548 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1549 & -INSN_CACHE_LINE_WIDTH);
1550
1551 while (ptr < (int) array + sizeof array)
1552 {
1553 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1554 ptr += INSN_CACHE_LINE_WIDTH;
1555 }
1556
1557 initialized = 1;
1558 }
1559
1560 /* Find the location in array that occupies the same cache line as BEG. */
1561
1562 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1563 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1564 & -INSN_CACHE_PLANE_SIZE)
1565 + offset);
1566
1567 /* Compute the cache alignment of the place to stop clearing. */
1568#if 0 /* This is not needed for gcc's purposes. */
1569 /* If the block to clear is bigger than a cache plane,
23190837 1570 we clear the entire cache, and OFFSET is already correct. */
203b91b9
RS
1571 if (end < beg + INSN_CACHE_PLANE_SIZE)
1572#endif
1573 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1574 & -INSN_CACHE_LINE_WIDTH)
1575 & (INSN_CACHE_PLANE_SIZE - 1));
1576
1577#if INSN_CACHE_DEPTH > 1
1578 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1579 if (end_addr <= start_addr)
1580 end_addr += INSN_CACHE_PLANE_SIZE;
1581
1582 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1583 {
1584 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1585 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1586
1587 while (addr != stop)
1588 {
1589 /* Call the return instruction at ADDR. */
1590 ((function_ptr) addr) ();
1591
1592 addr += INSN_CACHE_LINE_WIDTH;
1593 }
1594 }
1595#else /* just one plane */
1596 do
1597 {
1598 /* Call the return instruction at START_ADDR. */
1599 ((function_ptr) start_addr) ();
1600
1601 start_addr += INSN_CACHE_LINE_WIDTH;
1602 }
1603 while ((start_addr % INSN_CACHE_SIZE) != offset);
1604#endif /* just one plane */
1605#endif /* Cache is large */
1606#endif /* Cache exists */
e1178973 1607#endif /* CLEAR_INSN_CACHE */
203b91b9
RS
1608}
1609
1610#endif /* L_clear_cache */
1611\f
1612#ifdef L_trampoline
1613
1614/* Jump to a trampoline, loading the static chain address. */
1615
b27d2bd5 1616#if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
e3367a77 1617
3e7d8ef1
KG
1618long
1619getpagesize (void)
f5ea9817
RK
1620{
1621#ifdef _ALPHA_
1622 return 8192;
1623#else
1624 return 4096;
1625#endif
1626}
1627
d7ebf9ea 1628#ifdef __i386__
e4b15106
RK
1629extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
1630#endif
1631
272e2587
RK
1632int
1633mprotect (char *addr, int len, int prot)
f5ea9817
RK
1634{
1635 int np, op;
1636
272e2587
RK
1637 if (prot == 7)
1638 np = 0x40;
1639 else if (prot == 5)
1640 np = 0x20;
1641 else if (prot == 4)
1642 np = 0x10;
1643 else if (prot == 3)
1644 np = 0x04;
1645 else if (prot == 1)
1646 np = 0x02;
1647 else if (prot == 0)
1648 np = 0x01;
f5ea9817
RK
1649
1650 if (VirtualProtect (addr, len, np, &op))
1651 return 0;
1652 else
1653 return -1;
f5ea9817
RK
1654}
1655
b27d2bd5 1656#endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
f5ea9817 1657
23190837
AJ
1658#ifdef TRANSFER_FROM_TRAMPOLINE
1659TRANSFER_FROM_TRAMPOLINE
203b91b9
RS
1660#endif
1661
c1381fd3
KKT
1662#if defined (NeXT) && defined (__MACH__)
1663
1664/* Make stack executable so we can call trampolines on stack.
1665 This is called from INITIALIZE_TRAMPOLINE in next.h. */
c5df463e
RK
1666#ifdef NeXTStep21
1667 #include <mach.h>
1668#else
1669 #include <mach/mach.h>
1670#endif
c1381fd3
KKT
1671
1672void
37ef1054 1673__enable_execute_stack (char *addr)
c1381fd3
KKT
1674{
1675 kern_return_t r;
1676 char *eaddr = addr + TRAMPOLINE_SIZE;
1677 vm_address_t a = (vm_address_t) addr;
1678
1679 /* turn on execute access on stack */
1680 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
1681 if (r != KERN_SUCCESS)
1682 {
1683 mach_error("vm_protect VM_PROT_ALL", r);
1684 exit(1);
1685 }
1686
1687 /* We inline the i-cache invalidation for speed */
1688
1689#ifdef CLEAR_INSN_CACHE
1690 CLEAR_INSN_CACHE (addr, eaddr);
1691#else
1692 __clear_cache ((int) addr, (int) eaddr);
1693#endif
23190837 1694}
c1381fd3
KKT
1695
1696#endif /* defined (NeXT) && defined (__MACH__) */
1697
203b91b9
RS
1698#ifdef __convex__
1699
1700/* Make stack executable so we can call trampolines on stack.
1701 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
1702
1703#include <sys/mman.h>
1704#include <sys/vmparam.h>
1705#include <machine/machparam.h>
1706
1707void
3e7d8ef1 1708__enable_execute_stack (void)
203b91b9
RS
1709{
1710 int fp;
1711 static unsigned lowest = USRSTACK;
1712 unsigned current = (unsigned) &fp & -NBPG;
1713
1714 if (lowest > current)
1715 {
1716 unsigned len = lowest - current;
1717 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1718 lowest = current;
1719 }
1720
0f41302f 1721 /* Clear instruction cache in case an old trampoline is in it. */
203b91b9
RS
1722 asm ("pich");
1723}
1724#endif /* __convex__ */
b335c2cc 1725
db87ec0b 1726#ifdef __sysV88__
0c8ae3d3 1727
0f41302f 1728/* Modified from the convex -code above. */
0c8ae3d3
RK
1729
1730#include <sys/param.h>
1731#include <errno.h>
1732#include <sys/m88kbcs.h>
1733
1734void
3e7d8ef1 1735__enable_execute_stack (void)
0c8ae3d3
RK
1736{
1737 int save_errno;
1738 static unsigned long lowest = USRSTACK;
1739 unsigned long current = (unsigned long) &save_errno & -NBPC;
23190837 1740
0c8ae3d3 1741 /* Ignore errno being set. memctl sets errno to EINVAL whenever the
6d2f8887 1742 address is seen as 'negative'. That is the case with the stack. */
0c8ae3d3
RK
1743
1744 save_errno=errno;
1745 if (lowest > current)
1746 {
1747 unsigned len=lowest-current;
1748 memctl(current,len,MCT_TEXT);
1749 lowest = current;
1750 }
1751 else
1752 memctl(current,NBPC,MCT_TEXT);
1753 errno=save_errno;
1754}
1755
db87ec0b 1756#endif /* __sysV88__ */
0c8ae3d3 1757
c85f7c16
JL
1758#ifdef __sysV68__
1759
1760#include <sys/signal.h>
1761#include <errno.h>
1762
1763/* Motorola forgot to put memctl.o in the libp version of libc881.a,
1764 so define it here, because we need it in __clear_insn_cache below */
3698f44e
MH
1765/* On older versions of this OS, no memctl or MCT_TEXT are defined;
1766 hence we enable this stuff only if MCT_TEXT is #define'd. */
c85f7c16 1767
3698f44e 1768#ifdef MCT_TEXT
c85f7c16
JL
1769asm("\n\
1770 global memctl\n\
1771memctl:\n\
1772 movq &75,%d0\n\
1773 trap &0\n\
1774 bcc.b noerror\n\
1775 jmp cerror%\n\
1776noerror:\n\
1777 movq &0,%d0\n\
1778 rts");
3698f44e 1779#endif
c85f7c16
JL
1780
1781/* Clear instruction cache so we can call trampolines on stack.
1782 This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
1783
1784void
3e7d8ef1 1785__clear_insn_cache (void)
c85f7c16 1786{
3698f44e 1787#ifdef MCT_TEXT
c85f7c16
JL
1788 int save_errno;
1789
1790 /* Preserve errno, because users would be surprised to have
dc297297 1791 errno changing without explicitly calling any system-call. */
c85f7c16
JL
1792 save_errno = errno;
1793
23190837 1794 /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
dc297297 1795 No need to use an address derived from _start or %sp, as 0 works also. */
c85f7c16
JL
1796 memctl(0, 4096, MCT_TEXT);
1797 errno = save_errno;
3698f44e 1798#endif
c85f7c16
JL
1799}
1800
1801#endif /* __sysV68__ */
1802
b335c2cc
TW
1803#ifdef __pyr__
1804
98126ed6 1805#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
b335c2cc
TW
1806#include <stdio.h>
1807#include <sys/mman.h>
1808#include <sys/types.h>
1809#include <sys/param.h>
1810#include <sys/vmmac.h>
1811
1812/* Modified from the convex -code above.
0f41302f 1813 mremap promises to clear the i-cache. */
b335c2cc
TW
1814
1815void
3e7d8ef1 1816__enable_execute_stack (void)
b335c2cc
TW
1817{
1818 int fp;
1819 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
1820 PROT_READ|PROT_WRITE|PROT_EXEC))
1821 {
1822 perror ("mprotect in __enable_execute_stack");
1823 fflush (stderr);
1824 abort ();
1825 }
1826}
1827#endif /* __pyr__ */
7d41c411
RK
1828
1829#if defined (sony_news) && defined (SYSTYPE_BSD)
1830
1831#include <stdio.h>
1832#include <sys/types.h>
1833#include <sys/param.h>
1834#include <syscall.h>
1835#include <machine/sysnews.h>
1836
1837/* cacheflush function for NEWS-OS 4.2.
1838 This function is called from trampoline-initialize code
1839 defined in config/mips/mips.h. */
1840
1841void
37ef1054 1842cacheflush (char *beg, int size, int flag)
7d41c411
RK
1843{
1844 if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
1845 {
1846 perror ("cache_flush");
1847 fflush (stderr);
1848 abort ();
1849 }
1850}
1851
1852#endif /* sony_news */
203b91b9
RS
1853#endif /* L_trampoline */
1854\f
cae21ae8 1855#ifndef __CYGWIN__
203b91b9
RS
1856#ifdef L__main
1857
1858#include "gbl-ctors.h"
c06cff95
RS
1859/* Some systems use __main in a way incompatible with its use in gcc, in these
1860 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
1861 give the same symbol without quotes for an alternative entry point. You
0f41302f 1862 must define both, or neither. */
c06cff95
RS
1863#ifndef NAME__MAIN
1864#define NAME__MAIN "__main"
1865#define SYMBOL__MAIN __main
1866#endif
203b91b9 1867
fe1fd353
JM
1868#ifdef INIT_SECTION_ASM_OP
1869#undef HAS_INIT_SECTION
1870#define HAS_INIT_SECTION
1871#endif
1872
1873#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
31cf0144
JM
1874
1875/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
1876 code to run constructors. In that case, we need to handle EH here, too. */
1877
540ceb67 1878#ifdef EH_FRAME_SECTION_NAME
e4b776a6 1879#include "unwind-dw2-fde.h"
31cf0144
JM
1880extern unsigned char __EH_FRAME_BEGIN__[];
1881#endif
1882
203b91b9
RS
1883/* Run all the global destructors on exit from the program. */
1884
1885void
3e7d8ef1 1886__do_global_dtors (void)
203b91b9 1887{
89cf554b
RS
1888#ifdef DO_GLOBAL_DTORS_BODY
1889 DO_GLOBAL_DTORS_BODY;
1890#else
b40b9d93
MS
1891 static func_ptr *p = __DTOR_LIST__ + 1;
1892 while (*p)
1893 {
1894 p++;
1895 (*(p-1)) ();
1896 }
89cf554b 1897#endif
540ceb67 1898#if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION)
a4ebb0e6
GRK
1899 {
1900 static int completed = 0;
1901 if (! completed)
1902 {
1903 completed = 1;
1904 __deregister_frame_info (__EH_FRAME_BEGIN__);
1905 }
1906 }
31cf0144 1907#endif
203b91b9 1908}
68d69835 1909#endif
203b91b9 1910
fe1fd353 1911#ifndef HAS_INIT_SECTION
203b91b9
RS
1912/* Run all the global constructors on entry to the program. */
1913
203b91b9 1914void
3e7d8ef1 1915__do_global_ctors (void)
203b91b9 1916{
540ceb67 1917#ifdef EH_FRAME_SECTION_NAME
31cf0144
JM
1918 {
1919 static struct object object;
1920 __register_frame_info (__EH_FRAME_BEGIN__, &object);
1921 }
1922#endif
203b91b9 1923 DO_GLOBAL_CTORS_BODY;
a218d5ba 1924 atexit (__do_global_dtors);
203b91b9 1925}
fe1fd353 1926#endif /* no HAS_INIT_SECTION */
203b91b9 1927
fe1fd353 1928#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
203b91b9
RS
1929/* Subroutine called automatically by `main'.
1930 Compiling a global function named `main'
1931 produces an automatic call to this function at the beginning.
1932
1933 For many systems, this routine calls __do_global_ctors.
1934 For systems which support a .init section we use the .init section
1935 to run __do_global_ctors, so we need not do anything here. */
1936
1937void
c06cff95 1938SYMBOL__MAIN ()
203b91b9
RS
1939{
1940 /* Support recursive calls to `main': run initializers just once. */
7e6f1890 1941 static int initialized;
203b91b9
RS
1942 if (! initialized)
1943 {
1944 initialized = 1;
1945 __do_global_ctors ();
1946 }
1947}
fe1fd353 1948#endif /* no HAS_INIT_SECTION or INVOKE__main */
203b91b9
RS
1949
1950#endif /* L__main */
cae21ae8 1951#endif /* __CYGWIN__ */
203b91b9 1952\f
ad38743d 1953#ifdef L_ctors
203b91b9
RS
1954
1955#include "gbl-ctors.h"
1956
1957/* Provide default definitions for the lists of constructors and
657be7af
JL
1958 destructors, so that we don't get linker errors. These symbols are
1959 intentionally bss symbols, so that gld and/or collect will provide
1960 the right values. */
203b91b9
RS
1961
1962/* We declare the lists here with two elements each,
657be7af
JL
1963 so that they are valid empty lists if no other definition is loaded.
1964
1965 If we are using the old "set" extensions to have the gnu linker
1966 collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
1967 must be in the bss/common section.
1968
1969 Long term no port should use those extensions. But many still do. */
b335c2cc 1970#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
aa6ad1a6 1971#if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2)
d15d0264
RS
1972func_ptr __CTOR_LIST__[2] = {0, 0};
1973func_ptr __DTOR_LIST__[2] = {0, 0};
657be7af
JL
1974#else
1975func_ptr __CTOR_LIST__[2];
1976func_ptr __DTOR_LIST__[2];
1977#endif
b335c2cc 1978#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
ad38743d
RS
1979#endif /* L_ctors */
1980\f
1981#ifdef L_exit
1982
1983#include "gbl-ctors.h"
203b91b9 1984
8b7677be 1985#ifdef NEED_ATEXIT
8b7677be 1986
f75e8946 1987#ifndef ON_EXIT
203b91b9 1988
8b7677be
RK
1989# include <errno.h>
1990
920b13cc 1991static func_ptr *atexit_chain = 0;
8b7677be
RK
1992static long atexit_chain_length = 0;
1993static volatile long last_atexit_chain_slot = -1;
1994
c063dc98
JM
1995int
1996atexit (func_ptr func)
8b7677be
RK
1997{
1998 if (++last_atexit_chain_slot == atexit_chain_length)
1999 {
2000 atexit_chain_length += 32;
2001 if (atexit_chain)
a25cea96
RK
2002 atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2003 * sizeof (func_ptr));
8b7677be 2004 else
a25cea96
RK
2005 atexit_chain = (func_ptr *) malloc (atexit_chain_length
2006 * sizeof (func_ptr));
8b7677be
RK
2007 if (! atexit_chain)
2008 {
2009 atexit_chain_length = 0;
2010 last_atexit_chain_slot = -1;
2011 errno = ENOMEM;
2012 return (-1);
2013 }
2014 }
2015 atexit_chain[last_atexit_chain_slot] = func;
2016 return (0);
2017}
8b7677be 2018
3e7d8ef1
KG
2019extern void _cleanup (void);
2020extern void _exit (int) __attribute__ ((__noreturn__));
203b91b9 2021
23190837 2022void
37ef1054 2023exit (int status)
203b91b9 2024{
8b7677be
RK
2025 if (atexit_chain)
2026 {
2027 for ( ; last_atexit_chain_slot-- >= 0; )
2028 {
2029 (*atexit_chain[last_atexit_chain_slot + 1]) ();
920b13cc 2030 atexit_chain[last_atexit_chain_slot + 1] = 0;
8b7677be
RK
2031 }
2032 free (atexit_chain);
920b13cc 2033 atexit_chain = 0;
8b7677be 2034 }
203b91b9
RS
2035#ifdef EXIT_BODY
2036 EXIT_BODY;
2037#else
2038 _cleanup ();
2039#endif
2040 _exit (status);
2041}
2042
f75e8946 2043#else /* ON_EXIT */
bceb30e7 2044
c063dc98
JM
2045/* Simple; we just need a wrapper for ON_EXIT. */
2046int
2047atexit (func_ptr func)
bceb30e7 2048{
c063dc98 2049 return ON_EXIT (func);
bceb30e7 2050}
c063dc98 2051
f75e8946 2052#endif /* ON_EXIT */
c063dc98 2053#endif /* NEED_ATEXIT */
203b91b9
RS
2054
2055#endif /* L_exit */
This page took 1.812948 seconds and 5 git commands to generate.