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