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