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