date and time created 93/02/02 14:52:06 by elan
[unix-history] / usr / src / contrib / gcc-2.3.3 / libgcc2.c
CommitLineData
a2446029
EA
1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
3/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21/* As a special exception, if you link this library with files
22 compiled with GCC to produce an executable, this does not cause
23 the resulting executable to be covered by the GNU General Public License.
24 This exception does not however invalidate any other reasons why
25 the executable file might be covered by the GNU General Public License. */
26
27/* It is incorrect to include config.h here, because this file is being
28 compiled for the target, and hence definitions concerning only the host
29 do not apply. */
30
31#include "tconfig.h"
32#include "machmode.h"
33#ifndef L_trampoline
34#include "gstddef.h"
35#endif
36
37/* Don't use `fancy_abort' here even if config.h says to use it. */
38#ifdef abort
39#undef abort
40#endif
41
42/* In the first part of this file, we are interfacing to calls generated
43 by the compiler itself. These calls pass values into these routines
44 which have very specific modes (rather than very specific types), and
45 these compiler-generated calls also expect any return values to have
46 very specific modes (rather than very specific types). Thus, we need
47 to avoid using regular C language type names in this part of the file
48 because the sizes for those types can be configured to be anything.
49 Instead we use the following special type names. */
50
51typedef unsigned int UQItype __attribute__ ((mode (QI)));
52typedef int SItype __attribute__ ((mode (SI)));
53typedef unsigned int USItype __attribute__ ((mode (SI)));
54typedef int DItype __attribute__ ((mode (DI)));
55typedef unsigned int UDItype __attribute__ ((mode (DI)));
56typedef float SFtype __attribute__ ((mode (SF)));
57typedef float DFtype __attribute__ ((mode (DF)));
58#if 0
59typedef float XFtype __attribute__ ((mode (XF)));
60#endif
61#if LONG_DOUBLE_TYPE_SIZE == 128
62typedef float TFtype __attribute__ ((mode (TF)));
63#endif
64
65/* Make sure that we don't accidentaly use any normal C language built-in
66 type names in the first part of this file. Instead we want to use *only*
67 the type names defined above. The following macro definitions insure
68 that if we *do* accidently use soem normal C language built-in type name,
69 we will get a syntax error. */
70
71#define char bogus_type
72#define short bogus_type
73#define int bogus_type
74#define long bogus_type
75#define unsigned bogus_type
76#define float bogus_type
77#define double bogus_type
78
79#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
80
81/* DIstructs are pairs of SItype values in the order determined by
82 WORDS_BIG_ENDIAN. */
83
84#if WORDS_BIG_ENDIAN
85 struct DIstruct {SItype high, low;};
86#else
87 struct DIstruct {SItype low, high;};
88#endif
89
90/* We need this union to unpack/pack DImode values, since we don't have
91 any arithmetic yet. Incoming DImode parameters are stored into the
92 `ll' field, and the unpacked result is read from the struct `s'. */
93
94typedef union
95{
96 struct DIstruct s;
97 DItype ll;
98} DIunion;
99
100#if defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)
101
102#include "longlong.h"
103
104#endif /* udiv or mul */
105
106extern DItype __fixunssfdi (SFtype a);
107extern DItype __fixunsdfdi (DFtype a);
108\f
109#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
110#if defined (L_divdi3) || defined (L_moddi3)
111static inline
112#endif
113DItype
114__negdi2 (u)
115 DItype u;
116{
117 DIunion w;
118 DIunion uu;
119
120 uu.ll = u;
121
122 w.s.low = -uu.s.low;
123 w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
124
125 return w.ll;
126}
127#endif
128\f
129#ifdef L_lshldi3
130DItype
131__lshldi3 (u, b)
132 DItype u;
133 SItype b;
134{
135 DIunion w;
136 SItype bm;
137 DIunion uu;
138
139 if (b == 0)
140 return u;
141
142 uu.ll = u;
143
144 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
145 if (bm <= 0)
146 {
147 w.s.low = 0;
148 w.s.high = (USItype)uu.s.low << -bm;
149 }
150 else
151 {
152 USItype carries = (USItype)uu.s.low >> bm;
153 w.s.low = (USItype)uu.s.low << b;
154 w.s.high = ((USItype)uu.s.high << b) | carries;
155 }
156
157 return w.ll;
158}
159#endif
160
161#ifdef L_lshrdi3
162DItype
163__lshrdi3 (u, b)
164 DItype u;
165 SItype b;
166{
167 DIunion w;
168 SItype bm;
169 DIunion uu;
170
171 if (b == 0)
172 return u;
173
174 uu.ll = u;
175
176 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
177 if (bm <= 0)
178 {
179 w.s.high = 0;
180 w.s.low = (USItype)uu.s.high >> -bm;
181 }
182 else
183 {
184 USItype carries = (USItype)uu.s.high << bm;
185 w.s.high = (USItype)uu.s.high >> b;
186 w.s.low = ((USItype)uu.s.low >> b) | carries;
187 }
188
189 return w.ll;
190}
191#endif
192
193#ifdef L_ashldi3
194DItype
195__ashldi3 (u, b)
196 DItype u;
197 SItype b;
198{
199 DIunion w;
200 SItype bm;
201 DIunion uu;
202
203 if (b == 0)
204 return u;
205
206 uu.ll = u;
207
208 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
209 if (bm <= 0)
210 {
211 w.s.low = 0;
212 w.s.high = (USItype)uu.s.low << -bm;
213 }
214 else
215 {
216 USItype carries = (USItype)uu.s.low >> bm;
217 w.s.low = (USItype)uu.s.low << b;
218 w.s.high = ((USItype)uu.s.high << b) | carries;
219 }
220
221 return w.ll;
222}
223#endif
224
225#ifdef L_ashrdi3
226DItype
227__ashrdi3 (u, b)
228 DItype u;
229 SItype b;
230{
231 DIunion w;
232 SItype bm;
233 DIunion uu;
234
235 if (b == 0)
236 return u;
237
238 uu.ll = u;
239
240 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
241 if (bm <= 0)
242 {
243 /* w.s.high = 1..1 or 0..0 */
244 w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
245 w.s.low = uu.s.high >> -bm;
246 }
247 else
248 {
249 USItype carries = (USItype)uu.s.high << bm;
250 w.s.high = uu.s.high >> b;
251 w.s.low = ((USItype)uu.s.low >> b) | carries;
252 }
253
254 return w.ll;
255}
256#endif
257\f
258#ifdef L_muldi3
259DItype
260__muldi3 (u, v)
261 DItype u, v;
262{
263 DIunion w;
264 DIunion uu, vv;
265
266 uu.ll = u,
267 vv.ll = v;
268
269 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
270 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
271 + (USItype) uu.s.high * (USItype) vv.s.low);
272
273 return w.ll;
274}
275#endif
276\f
277#ifdef L_udiv_w_sdiv
278USItype
279__udiv_w_sdiv (rp, a1, a0, d)
280 USItype *rp, a1, a0, d;
281{
282 USItype q, r;
283 USItype c0, c1, b1;
284
285 if ((SItype) d >= 0)
286 {
287 if (a1 < d - a1 - (a0 >> 31))
288 {
289 /* dividend, divisor, and quotient are nonnegative */
290 sdiv_qrnnd (q, r, a1, a0, d);
291 }
292 else
293 {
294 /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
295 sub_ddmmss (c1, c0, a1, a0, d >> 1, d << 31);
296 /* Divide (c1*2^32 + c0) by d */
297 sdiv_qrnnd (q, r, c1, c0, d);
298 /* Add 2^31 to quotient */
299 q += (USItype) 1 << 31;
300 }
301 }
302 else
303 {
304 b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
305 c1 = a1 >> 1; /* A/2 */
306 c0 = (a1 << 31) + (a0 >> 1);
307
308 if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
309 {
310 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
311
312 r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
313 if ((d & 1) != 0)
314 {
315 if (r >= q)
316 r = r - q;
317 else if (q - r <= d)
318 {
319 r = r - q + d;
320 q--;
321 }
322 else
323 {
324 r = r - q + 2*d;
325 q -= 2;
326 }
327 }
328 }
329 else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
330 {
331 c1 = (b1 - 1) - c1;
332 c0 = ~c0; /* logical NOT */
333
334 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
335
336 q = ~q; /* (A/2)/b1 */
337 r = (b1 - 1) - r;
338
339 r = 2*r + (a0 & 1); /* A/(2*b1) */
340
341 if ((d & 1) != 0)
342 {
343 if (r >= q)
344 r = r - q;
345 else if (q - r <= d)
346 {
347 r = r - q + d;
348 q--;
349 }
350 else
351 {
352 r = r - q + 2*d;
353 q -= 2;
354 }
355 }
356 }
357 else /* Implies c1 = b1 */
358 { /* Hence a1 = d - 1 = 2*b1 - 1 */
359 if (a0 >= -d)
360 {
361 q = -1;
362 r = a0 + d;
363 }
364 else
365 {
366 q = -2;
367 r = a0 + 2*d;
368 }
369 }
370 }
371
372 *rp = r;
373 return q;
374}
375#endif
376\f
377#ifdef L_udivmoddi4
378static const UQItype __clz_tab[] =
379{
380 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,
381 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,
382 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,
383 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,
384 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,
385 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,
386 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,
387 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,
388};
389
390UDItype
391__udivmoddi4 (n, d, rp)
392 UDItype n, d;
393 UDItype *rp;
394{
395 DIunion ww;
396 DIunion nn, dd;
397 DIunion rr;
398 USItype d0, d1, n0, n1, n2;
399 USItype q0, q1;
400 USItype b, bm;
401
402 nn.ll = n;
403 dd.ll = d;
404
405 d0 = dd.s.low;
406 d1 = dd.s.high;
407 n0 = nn.s.low;
408 n1 = nn.s.high;
409
410#if !UDIV_NEEDS_NORMALIZATION
411 if (d1 == 0)
412 {
413 if (d0 > n1)
414 {
415 /* 0q = nn / 0D */
416
417 udiv_qrnnd (q0, n0, n1, n0, d0);
418 q1 = 0;
419
420 /* Remainder in n0. */
421 }
422 else
423 {
424 /* qq = NN / 0d */
425
426 if (d0 == 0)
427 d0 = 1 / d0; /* Divide intentionally by zero. */
428
429 udiv_qrnnd (q1, n1, 0, n1, d0);
430 udiv_qrnnd (q0, n0, n1, n0, d0);
431
432 /* Remainder in n0. */
433 }
434
435 if (rp != 0)
436 {
437 rr.s.low = n0;
438 rr.s.high = 0;
439 *rp = rr.ll;
440 }
441 }
442
443#else /* UDIV_NEEDS_NORMALIZATION */
444
445 if (d1 == 0)
446 {
447 if (d0 > n1)
448 {
449 /* 0q = nn / 0D */
450
451 count_leading_zeros (bm, d0);
452
453 if (bm != 0)
454 {
455 /* Normalize, i.e. make the most significant bit of the
456 denominator set. */
457
458 d0 = d0 << bm;
459 n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
460 n0 = n0 << bm;
461 }
462
463 udiv_qrnnd (q0, n0, n1, n0, d0);
464 q1 = 0;
465
466 /* Remainder in n0 >> bm. */
467 }
468 else
469 {
470 /* qq = NN / 0d */
471
472 if (d0 == 0)
473 d0 = 1 / d0; /* Divide intentionally by zero. */
474
475 count_leading_zeros (bm, d0);
476
477 if (bm == 0)
478 {
479 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
480 conclude (the most significant bit of n1 is set) /\ (the
481 leading quotient digit q1 = 1).
482
483 This special case is necessary, not an optimization.
484 (Shifts counts of SI_TYPE_SIZE are undefined.) */
485
486 n1 -= d0;
487 q1 = 1;
488 }
489 else
490 {
491 /* Normalize. */
492
493 b = SI_TYPE_SIZE - bm;
494
495 d0 = d0 << bm;
496 n2 = n1 >> b;
497 n1 = (n1 << bm) | (n0 >> b);
498 n0 = n0 << bm;
499
500 udiv_qrnnd (q1, n1, n2, n1, d0);
501 }
502
503 /* n1 != d0... */
504
505 udiv_qrnnd (q0, n0, n1, n0, d0);
506
507 /* Remainder in n0 >> bm. */
508 }
509
510 if (rp != 0)
511 {
512 rr.s.low = n0 >> bm;
513 rr.s.high = 0;
514 *rp = rr.ll;
515 }
516 }
517#endif /* UDIV_NEEDS_NORMALIZATION */
518
519 else
520 {
521 if (d1 > n1)
522 {
523 /* 00 = nn / DD */
524
525 q0 = 0;
526 q1 = 0;
527
528 /* Remainder in n1n0. */
529 if (rp != 0)
530 {
531 rr.s.low = n0;
532 rr.s.high = n1;
533 *rp = rr.ll;
534 }
535 }
536 else
537 {
538 /* 0q = NN / dd */
539
540 count_leading_zeros (bm, d1);
541 if (bm == 0)
542 {
543 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
544 conclude (the most significant bit of n1 is set) /\ (the
545 quotient digit q0 = 0 or 1).
546
547 This special case is necessary, not an optimization. */
548
549 /* The condition on the next line takes advantage of that
550 n1 >= d1 (true due to program flow). */
551 if (n1 > d1 || n0 >= d0)
552 {
553 q0 = 1;
554 sub_ddmmss (n1, n0, n1, n0, d1, d0);
555 }
556 else
557 q0 = 0;
558
559 q1 = 0;
560
561 if (rp != 0)
562 {
563 rr.s.low = n0;
564 rr.s.high = n1;
565 *rp = rr.ll;
566 }
567 }
568 else
569 {
570 USItype m1, m0;
571 /* Normalize. */
572
573 b = SI_TYPE_SIZE - bm;
574
575 d1 = (d1 << bm) | (d0 >> b);
576 d0 = d0 << bm;
577 n2 = n1 >> b;
578 n1 = (n1 << bm) | (n0 >> b);
579 n0 = n0 << bm;
580
581 udiv_qrnnd (q0, n1, n2, n1, d1);
582 umul_ppmm (m1, m0, q0, d0);
583
584 if (m1 > n1 || (m1 == n1 && m0 > n0))
585 {
586 q0--;
587 sub_ddmmss (m1, m0, m1, m0, d1, d0);
588 }
589
590 q1 = 0;
591
592 /* Remainder in (n1n0 - m1m0) >> bm. */
593 if (rp != 0)
594 {
595 sub_ddmmss (n1, n0, n1, n0, m1, m0);
596 rr.s.low = (n1 << b) | (n0 >> bm);
597 rr.s.high = n1 >> bm;
598 *rp = rr.ll;
599 }
600 }
601 }
602 }
603
604 ww.s.low = q0;
605 ww.s.high = q1;
606 return ww.ll;
607}
608#endif
609
610#ifdef L_divdi3
611UDItype __udivmoddi4 ();
612DItype
613__divdi3 (u, v)
614 DItype u, v;
615{
616 SItype c = 0;
617 DIunion uu, vv;
618 DItype w;
619
620 uu.ll = u;
621 vv.ll = v;
622
623 if (uu.s.high < 0)
624 c = ~c,
625 uu.ll = __negdi2 (uu.ll);
626 if (vv.s.high < 0)
627 c = ~c,
628 vv.ll = __negdi2 (vv.ll);
629
630 w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
631 if (c)
632 w = __negdi2 (w);
633
634 return w;
635}
636#endif
637
638#ifdef L_moddi3
639UDItype __udivmoddi4 ();
640DItype
641__moddi3 (u, v)
642 DItype u, v;
643{
644 SItype c = 0;
645 DIunion uu, vv;
646 DItype w;
647
648 uu.ll = u;
649 vv.ll = v;
650
651 if (uu.s.high < 0)
652 c = ~c,
653 uu.ll = __negdi2 (uu.ll);
654 if (vv.s.high < 0)
655 vv.ll = __negdi2 (vv.ll);
656
657 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
658 if (c)
659 w = __negdi2 (w);
660
661 return w;
662}
663#endif
664
665#ifdef L_umoddi3
666UDItype __udivmoddi4 ();
667UDItype
668__umoddi3 (u, v)
669 UDItype u, v;
670{
671 DItype w;
672
673 (void) __udivmoddi4 (u, v, &w);
674
675 return w;
676}
677#endif
678
679#ifdef L_udivdi3
680UDItype __udivmoddi4 ();
681UDItype
682__udivdi3 (n, d)
683 UDItype n, d;
684{
685 return __udivmoddi4 (n, d, (UDItype *) 0);
686}
687#endif
688\f
689#ifdef L_cmpdi2
690SItype
691__cmpdi2 (a, b)
692 DItype a, b;
693{
694 DIunion au, bu;
695
696 au.ll = a, bu.ll = b;
697
698 if (au.s.high < bu.s.high)
699 return 0;
700 else if (au.s.high > bu.s.high)
701 return 2;
702 if ((USItype) au.s.low < (USItype) bu.s.low)
703 return 0;
704 else if ((USItype) au.s.low > (USItype) bu.s.low)
705 return 2;
706 return 1;
707}
708#endif
709
710#ifdef L_ucmpdi2
711SItype
712__ucmpdi2 (a, b)
713 DItype a, b;
714{
715 DIunion au, bu;
716
717 au.ll = a, bu.ll = b;
718
719 if ((USItype) au.s.high < (USItype) bu.s.high)
720 return 0;
721 else if ((USItype) au.s.high > (USItype) bu.s.high)
722 return 2;
723 if ((USItype) au.s.low < (USItype) bu.s.low)
724 return 0;
725 else if ((USItype) au.s.low > (USItype) bu.s.low)
726 return 2;
727 return 1;
728}
729#endif
730\f
731#if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
732#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
733#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
734
735DItype
736__fixunstfdi (a)
737 TFtype a;
738{
739 TFtype b;
740 UDItype v;
741
742 if (a < 0)
743 return 0;
744
745 /* Compute high word of result, as a flonum. */
746 b = (a / HIGH_WORD_COEFF);
747 /* Convert that to fixed (but not to DItype!),
748 and shift it into the high word. */
749 v = (USItype) b;
750 v <<= WORD_SIZE;
751 /* Remove high part from the TFtype, leaving the low part as flonum. */
752 a -= (TFtype)v;
753 /* Convert that to fixed (but not to DItype!) and add it in.
754 Sometimes A comes out negative. This is significant, since
755 A has more bits than a long int does. */
756 if (a < 0)
757 v -= (USItype) (- a);
758 else
759 v += (USItype) a;
760 return v;
761}
762#endif
763
764#if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
765DItype
766__fixtfdi (a)
767 TFtype a;
768{
769 if (a < 0)
770 return - __fixunstfdi (-a);
771 return __fixunstfdi (a);
772}
773#endif
774
775#ifdef L_fixunsdfdi
776#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
777#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
778
779DItype
780__fixunsdfdi (a)
781 DFtype a;
782{
783 DFtype b;
784 UDItype v;
785
786 if (a < 0)
787 return 0;
788
789 /* Compute high word of result, as a flonum. */
790 b = (a / HIGH_WORD_COEFF);
791 /* Convert that to fixed (but not to DItype!),
792 and shift it into the high word. */
793 v = (USItype) b;
794 v <<= WORD_SIZE;
795 /* Remove high part from the DFtype, leaving the low part as flonum. */
796 a -= (DFtype)v;
797 /* Convert that to fixed (but not to DItype!) and add it in.
798 Sometimes A comes out negative. This is significant, since
799 A has more bits than a long int does. */
800 if (a < 0)
801 v -= (USItype) (- a);
802 else
803 v += (USItype) a;
804 return v;
805}
806#endif
807
808#ifdef L_fixdfdi
809DItype
810__fixdfdi (a)
811 DFtype a;
812{
813 if (a < 0)
814 return - __fixunsdfdi (-a);
815 return __fixunsdfdi (a);
816}
817#endif
818
819#ifdef L_fixunssfdi
820#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
821#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
822
823DItype
824__fixunssfdi (SFtype original_a)
825{
826 /* Convert the SFtype to a DFtype, because that is surely not going
827 to lose any bits. Some day someone else can write a faster version
828 that avoids converting to DFtype, and verify it really works right. */
829 DFtype a = original_a;
830 DFtype b;
831 UDItype v;
832
833 if (a < 0)
834 return 0;
835
836 /* Compute high word of result, as a flonum. */
837 b = (a / HIGH_WORD_COEFF);
838 /* Convert that to fixed (but not to DItype!),
839 and shift it into the high word. */
840 v = (USItype) b;
841 v <<= WORD_SIZE;
842 /* Remove high part from the DFtype, leaving the low part as flonum. */
843 a -= (DFtype)v;
844 /* Convert that to fixed (but not to DItype!) and add it in.
845 Sometimes A comes out negative. This is significant, since
846 A has more bits than a long int does. */
847 if (a < 0)
848 v -= (USItype) (- a);
849 else
850 v += (USItype) a;
851 return v;
852}
853#endif
854
855#ifdef L_fixsfdi
856DItype
857__fixsfdi (SFtype a)
858{
859 if (a < 0)
860 return - __fixunssfdi (-a);
861 return __fixunssfdi (a);
862}
863#endif
864
865#if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
866#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
867#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
868#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
869
870TFtype
871__floatditf (u)
872 DItype u;
873{
874 TFtype d;
875 SItype negate = 0;
876
877 if (u < 0)
878 u = -u, negate = 1;
879
880 d = (USItype) (u >> WORD_SIZE);
881 d *= HIGH_HALFWORD_COEFF;
882 d *= HIGH_HALFWORD_COEFF;
883 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
884
885 return (negate ? -d : d);
886}
887#endif
888
889#ifdef L_floatdidf
890#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
891#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
892#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
893
894DFtype
895__floatdidf (u)
896 DItype u;
897{
898 DFtype d;
899 SItype negate = 0;
900
901 if (u < 0)
902 u = -u, negate = 1;
903
904 d = (USItype) (u >> WORD_SIZE);
905 d *= HIGH_HALFWORD_COEFF;
906 d *= HIGH_HALFWORD_COEFF;
907 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
908
909 return (negate ? -d : d);
910}
911#endif
912
913#ifdef L_floatdisf
914#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
915#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
916#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
917
918SFtype
919__floatdisf (u)
920 DItype u;
921{
922 SFtype f;
923 SItype negate = 0;
924
925 if (u < 0)
926 u = -u, negate = 1;
927
928 f = (USItype) (u >> WORD_SIZE);
929 f *= HIGH_HALFWORD_COEFF;
930 f *= HIGH_HALFWORD_COEFF;
931 f += (USItype) (u & (HIGH_WORD_COEFF - 1));
932
933 return (negate ? -f : f);
934}
935#endif
936
937#ifdef L_fixunsdfsi
938#include "glimits.h"
939
940USItype
941__fixunsdfsi (a)
942 DFtype a;
943{
944 if (a >= - (DFtype) LONG_MIN)
945 return (SItype) (a + LONG_MIN) - LONG_MIN;
946 return (SItype) a;
947}
948#endif
949
950#ifdef L_fixunssfsi
951#include "glimits.h"
952
953USItype
954__fixunssfsi (SFtype a)
955{
956 if (a >= - (SFtype) LONG_MIN)
957 return (SItype) (a + LONG_MIN) - LONG_MIN;
958 return (SItype) a;
959}
960#endif
961\f
962/* From here on down, the routines use normal data types. */
963
964#define SItype bogus_type
965#define USItype bogus_type
966#define DItype bogus_type
967#define UDItype bogus_type
968#define SFtype bogus_type
969#define DFtype bogus_type
970
971#undef char
972#undef short
973#undef int
974#undef long
975#undef unsigned
976#undef float
977#undef double
978\f
979#ifdef L__gcc_bcmp
980
981/* Like bcmp except the sign is meaningful.
982 Reult is negative if S1 is less than S2,
983 positive if S1 is greater, 0 if S1 and S2 are equal. */
984
985int
986__gcc_bcmp (s1, s2, size)
987 unsigned char *s1, *s2;
988 size_t size;
989{
990 while (size > 0)
991 {
992 unsigned char c1 = *s1++, c2 = *s2++;
993 if (c1 != c2)
994 return c1 - c2;
995 size--;
996 }
997 return 0;
998}
999
1000#endif
1001\f\f
1002#ifdef L_varargs
1003#ifdef __i860__
1004#if defined(__svr4__) || defined(__alliant__)
1005 asm (" .text");
1006 asm (" .align 4");
1007
1008/* The Alliant needs the added underscore. */
1009 asm (".globl __builtin_saveregs");
1010asm ("__builtin_saveregs:");
1011 asm (".globl ___builtin_saveregs");
1012asm ("___builtin_saveregs:");
1013
1014 asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
1015 asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
1016 area and also for a new va_list
1017 structure */
1018 /* Save all argument registers in the arg reg save area. The
1019 arg reg save area must have the following layout (according
1020 to the svr4 ABI):
1021
1022 struct {
1023 union {
1024 float freg[8];
1025 double dreg[4];
1026 } float_regs;
1027 long ireg[12];
1028 };
1029 */
1030
1031 asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
1032 asm (" fst.q %f12,16(%sp)");
1033
1034 asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
1035 asm (" st.l %r17,36(%sp)");
1036 asm (" st.l %r18,40(%sp)");
1037 asm (" st.l %r19,44(%sp)");
1038 asm (" st.l %r20,48(%sp)");
1039 asm (" st.l %r21,52(%sp)");
1040 asm (" st.l %r22,56(%sp)");
1041 asm (" st.l %r23,60(%sp)");
1042 asm (" st.l %r24,64(%sp)");
1043 asm (" st.l %r25,68(%sp)");
1044 asm (" st.l %r26,72(%sp)");
1045 asm (" st.l %r27,76(%sp)");
1046
1047 asm (" adds 80,%sp,%r16"); /* compute the address of the new
1048 va_list structure. Put in into
1049 r16 so that it will be returned
1050 to the caller. */
1051
1052 /* Initialize all fields of the new va_list structure. This
1053 structure looks like:
1054
1055 typedef struct {
1056 unsigned long ireg_used;
1057 unsigned long freg_used;
1058 long *reg_base;
1059 long *mem_ptr;
1060 } va_list;
1061 */
1062
1063 asm (" st.l %r0, 0(%r16)"); /* nfixed */
1064 asm (" st.l %r0, 4(%r16)"); /* nfloating */
1065 asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
1066 asm (" bri %r1"); /* delayed return */
1067 asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
1068
1069#else /* not __SVR4__ */
1070 asm (" .text");
1071 asm (" .align 4");
1072
1073 asm (".globl ___builtin_saveregs");
1074 asm ("___builtin_saveregs:");
1075 asm (" mov sp,r30");
1076 asm (" andnot 0x0f,sp,sp");
1077 asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
1078
1079/* Fill in the __va_struct. */
1080 asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
1081 asm (" st.l r17, 4(sp)"); /* int fixed[12] */
1082 asm (" st.l r18, 8(sp)");
1083 asm (" st.l r19,12(sp)");
1084 asm (" st.l r20,16(sp)");
1085 asm (" st.l r21,20(sp)");
1086 asm (" st.l r22,24(sp)");
1087 asm (" st.l r23,28(sp)");
1088 asm (" st.l r24,32(sp)");
1089 asm (" st.l r25,36(sp)");
1090 asm (" st.l r26,40(sp)");
1091 asm (" st.l r27,44(sp)");
1092
1093 asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
1094 asm (" fst.q f12,64(sp)"); /* int floating[8] */
1095
1096/* Fill in the __va_ctl. */
1097 asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
1098 asm (" st.l r28,84(sp)"); /* pointer to more args */
1099 asm (" st.l r0, 88(sp)"); /* nfixed */
1100 asm (" st.l r0, 92(sp)"); /* nfloating */
1101
1102 asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
1103 asm (" bri r1");
1104 asm (" mov r30,sp");
1105 /* recover stack and pass address to start
1106 of data. */
1107#endif /* not __SVR4__ */
1108#else /* not __i860__ */
1109#ifdef __sparc__
1110 asm (".global __builtin_saveregs");
1111 asm ("__builtin_saveregs:");
1112 asm (".global ___builtin_saveregs");
1113 asm ("___builtin_saveregs:");
1114#ifdef NEED_PROC_COMMAND
1115 asm (".proc 020");
1116#endif
1117 asm ("st %i0,[%fp+68]");
1118 asm ("st %i1,[%fp+72]");
1119 asm ("st %i2,[%fp+76]");
1120 asm ("st %i3,[%fp+80]");
1121 asm ("st %i4,[%fp+84]");
1122 asm ("retl");
1123 asm ("st %i5,[%fp+88]");
1124#ifdef NEED_TYPE_COMMAND
1125 asm (".type __builtin_saveregs,#function");
1126 asm (".size __builtin_saveregs,.-__builtin_saveregs");
1127#endif
1128#else /* not __sparc__ */
1129#if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1130
1131 asm (" .text");
1132 asm (" .ent __builtin_saveregs");
1133 asm (" .globl __builtin_saveregs");
1134 asm ("__builtin_saveregs:");
1135 asm (" sw $4,0($30)");
1136 asm (" sw $5,4($30)");
1137 asm (" sw $6,8($30)");
1138 asm (" sw $7,12($30)");
1139 asm (" j $31");
1140 asm (" .end __builtin_saveregs");
1141#else /* not __mips__, etc. */
1142__builtin_saveregs ()
1143{
1144 abort ();
1145}
1146#endif /* not __mips__ */
1147#endif /* not __sparc__ */
1148#endif /* not __i860__ */
1149#endif
1150\f
1151#ifdef L_eprintf
1152#ifndef inhibit_eprintf
1153
1154#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1155#include <stdio.h>
1156/* This is used by the `assert' macro. */
1157void
1158__eprintf (string, expression, line, filename)
1159 const char *string;
1160 const char *expression;
1161 int line;
1162 const char *filename;
1163{
1164 fprintf (stderr, string, expression, line, filename);
1165 fflush (stderr);
1166 abort ();
1167}
1168
1169#endif
1170#endif
1171
1172#ifdef L_bb
1173/* Avoid warning from ranlib about empty object file. */
1174void
1175__bb_avoid_warning ()
1176{}
1177
1178#if defined (__sun__) && defined (__mc68000__)
1179struct bb
1180{
1181 int initialized;
1182 char *filename;
1183 int *counts;
1184 int ncounts;
1185 int zero_word;
1186 int *addresses;
1187};
1188
1189extern int ___tcov_init;
1190
1191__bb_init_func (blocks)
1192 struct bb *blocks;
1193{
1194 if (! ___tcov_init)
1195 ___tcov_init_func ();
1196
1197 ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);
1198}
1199
1200#endif
1201#endif
1202\f
1203/* frills for C++ */
1204
1205#ifdef L_builtin_new
1206typedef void (*vfp)(void);
1207
1208extern vfp __new_handler;
1209
1210void *
1211__builtin_new (sz)
1212 size_t sz;
1213{
1214 void *p;
1215
1216 /* malloc (0) is unpredictable; avoid it. */
1217 if (sz == 0)
1218 sz = 1;
1219 p = (void *) malloc (sz);
1220 if (p == 0)
1221 (*__new_handler) ();
1222 return p;
1223}
1224#endif
1225
1226#ifdef L_caps_New
1227
1228/* This gets us __GNU_LIBRARY__. */
1229#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1230#include <stdio.h>
1231
1232#ifdef __GNU_LIBRARY__
1233 /* Avoid forcing the library's meaning of `write' on the user program
1234 by using the "internal" name (for use within the library) */
1235#define write(fd, buf, n) __write((fd), (buf), (n))
1236#endif
1237
1238typedef void (*vfp)(void);
1239
1240extern void *__builtin_new (size_t);
1241static void default_new_handler (void);
1242
1243vfp __new_handler = default_new_handler;
1244
1245void *
1246__builtin_vec_new (p, maxindex, size, ctor)
1247 void *p;
1248 size_t maxindex;
1249 size_t size;
1250 void (*ctor)(void *);
1251{
1252 size_t i;
1253 size_t nelts = maxindex + 1;
1254 void *rval;
1255
1256 if (p == 0)
1257 p = __builtin_new (nelts * size);
1258
1259 rval = p;
1260
1261 for (i = 0; i < nelts; i++)
1262 {
1263 (*ctor) (p);
1264 p += size;
1265 }
1266
1267 return rval;
1268}
1269
1270vfp
1271__set_new_handler (handler)
1272 vfp handler;
1273{
1274 vfp prev_handler;
1275
1276 prev_handler = __new_handler;
1277 if (handler == 0) handler = default_new_handler;
1278 __new_handler = handler;
1279 return prev_handler;
1280}
1281
1282vfp
1283set_new_handler (handler)
1284 vfp handler;
1285{
1286 return __set_new_handler (handler);
1287}
1288
1289#define MESSAGE "Virtual memory exceeded in `new'\n"
1290
1291static void
1292default_new_handler ()
1293{
1294 /* don't use fprintf (stderr, ...) because it may need to call malloc. */
1295 /* This should really print the name of the program, but that is hard to
1296 do. We need a standard, clean way to get at the name. */
1297 write (2, MESSAGE, sizeof (MESSAGE));
1298 /* don't call exit () because that may call global destructors which
1299 may cause a loop. */
1300 _exit (-1);
1301}
1302#endif
1303\f
1304#ifdef L_builtin_del
1305typedef void (*vfp)(void);
1306
1307void
1308__builtin_delete (ptr)
1309 void *ptr;
1310{
1311 if (ptr)
1312 free (ptr);
1313}
1314
1315void
1316__builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete)
1317 void *ptr;
1318 size_t maxindex;
1319 size_t size;
1320 void (*dtor)(void *, int);
1321 int auto_delete;
1322{
1323 size_t i;
1324 size_t nelts = maxindex + 1;
1325 void *p = ptr;
1326
1327 ptr += nelts * size;
1328
1329 for (i = 0; i < nelts; i++)
1330 {
1331 ptr -= size;
1332 (*dtor) (ptr, auto_delete);
1333 }
1334
1335 if (auto_delete_vec)
1336 __builtin_delete (p);
1337}
1338
1339#endif
1340
1341#ifdef L_shtab
1342unsigned int __shtab[] = {
1343 0x00000001, 0x00000002, 0x00000004, 0x00000008,
1344 0x00000010, 0x00000020, 0x00000040, 0x00000080,
1345 0x00000100, 0x00000200, 0x00000400, 0x00000800,
1346 0x00001000, 0x00002000, 0x00004000, 0x00008000,
1347 0x00010000, 0x00020000, 0x00040000, 0x00080000,
1348 0x00100000, 0x00200000, 0x00400000, 0x00800000,
1349 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1350 0x10000000, 0x20000000, 0x40000000, 0x80000000
1351 };
1352#endif
1353\f
1354#ifdef L_clear_cache
1355/* Clear part of an instruction cache. */
1356
1357#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1358
1359void
1360__clear_cache (beg, end)
1361 char *beg, *end;
1362{
1363#ifdef INSN_CACHE_SIZE
1364 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1365 static int initialized = 0;
1366 int offset;
1367 void *start_addr
1368 void *end_addr;
1369 typedef (*function_ptr) ();
1370
1371#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1372 /* It's cheaper to clear the whole cache.
1373 Put in a series of jump instructions so that calling the beginning
1374 of the cache will clear the whole thing. */
1375
1376 if (! initialized)
1377 {
1378 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1379 & -INSN_CACHE_LINE_WIDTH);
1380 int end_ptr = ptr + INSN_CACHE_SIZE;
1381
1382 while (ptr < end_ptr)
1383 {
1384 *(INSTRUCTION_TYPE *)ptr
1385 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1386 ptr += INSN_CACHE_LINE_WIDTH;
1387 }
1388 *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1389
1390 initialized = 1;
1391 }
1392
1393 /* Call the beginning of the sequence. */
1394 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1395 & -INSN_CACHE_LINE_WIDTH))
1396 ());
1397
1398#else /* Cache is large. */
1399
1400 if (! initialized)
1401 {
1402 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1403 & -INSN_CACHE_LINE_WIDTH);
1404
1405 while (ptr < (int) array + sizeof array)
1406 {
1407 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1408 ptr += INSN_CACHE_LINE_WIDTH;
1409 }
1410
1411 initialized = 1;
1412 }
1413
1414 /* Find the location in array that occupies the same cache line as BEG. */
1415
1416 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1417 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1418 & -INSN_CACHE_PLANE_SIZE)
1419 + offset);
1420
1421 /* Compute the cache alignment of the place to stop clearing. */
1422#if 0 /* This is not needed for gcc's purposes. */
1423 /* If the block to clear is bigger than a cache plane,
1424 we clear the entire cache, and OFFSET is already correct. */
1425 if (end < beg + INSN_CACHE_PLANE_SIZE)
1426#endif
1427 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1428 & -INSN_CACHE_LINE_WIDTH)
1429 & (INSN_CACHE_PLANE_SIZE - 1));
1430
1431#if INSN_CACHE_DEPTH > 1
1432 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1433 if (end_addr <= start_addr)
1434 end_addr += INSN_CACHE_PLANE_SIZE;
1435
1436 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1437 {
1438 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1439 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1440
1441 while (addr != stop)
1442 {
1443 /* Call the return instruction at ADDR. */
1444 ((function_ptr) addr) ();
1445
1446 addr += INSN_CACHE_LINE_WIDTH;
1447 }
1448 }
1449#else /* just one plane */
1450 do
1451 {
1452 /* Call the return instruction at START_ADDR. */
1453 ((function_ptr) start_addr) ();
1454
1455 start_addr += INSN_CACHE_LINE_WIDTH;
1456 }
1457 while ((start_addr % INSN_CACHE_SIZE) != offset);
1458#endif /* just one plane */
1459#endif /* Cache is large */
1460#endif /* Cache exists */
1461}
1462
1463#endif /* L_clear_cache */
1464\f
1465#ifdef L_trampoline
1466
1467/* Jump to a trampoline, loading the static chain address. */
1468
1469#ifdef TRANSFER_FROM_TRAMPOLINE
1470TRANSFER_FROM_TRAMPOLINE
1471#endif
1472
1473#ifdef __convex__
1474
1475/* Make stack executable so we can call trampolines on stack.
1476 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
1477
1478#include <sys/mman.h>
1479#include <sys/vmparam.h>
1480#include <machine/machparam.h>
1481
1482void
1483__enable_execute_stack ()
1484{
1485 int fp;
1486 static unsigned lowest = USRSTACK;
1487 unsigned current = (unsigned) &fp & -NBPG;
1488
1489 if (lowest > current)
1490 {
1491 unsigned len = lowest - current;
1492 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1493 lowest = current;
1494 }
1495
1496 /* Clear instruction cache in case an old trampoline is in it. */
1497 asm ("pich");
1498}
1499#endif /* __convex__ */
1500
1501#ifdef __pyr__
1502
1503#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1504#include <stdio.h>
1505#include <sys/mman.h>
1506#include <sys/types.h>
1507#include <sys/param.h>
1508#include <sys/vmmac.h>
1509
1510/* Modified from the convex -code above.
1511 mremap promises to clear the i-cache. */
1512
1513void
1514__enable_execute_stack ()
1515{
1516 int fp;
1517 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
1518 PROT_READ|PROT_WRITE|PROT_EXEC))
1519 {
1520 perror ("mprotect in __enable_execute_stack");
1521 fflush (stderr);
1522 abort ();
1523 }
1524}
1525#endif /* __pyr__ */
1526#endif /* L_trampoline */
1527\f
1528#ifdef L__main
1529
1530#include "gbl-ctors.h"
1531
1532/* Run all the global destructors on exit from the program. */
1533
1534void
1535__do_global_dtors ()
1536{
1537#ifdef DO_GLOBAL_DTORS_BODY
1538 DO_GLOBAL_DTORS_BODY;
1539#else
1540 unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0];
1541 unsigned i;
1542
1543 /* Some systems place the number of pointers
1544 in the first word of the table.
1545 On other systems, that word is -1.
1546 In all cases, the table is null-terminated. */
1547
1548 /* If the length is not recorded, count up to the null. */
1549 if (nptrs == -1)
1550 for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
1551
1552 /* GNU LD format. */
1553 for (i = nptrs; i >= 1; i--)
1554 __DTOR_LIST__[i] ();
1555#endif
1556}
1557
1558#ifndef INIT_SECTION_ASM_OP
1559/* Run all the global constructors on entry to the program. */
1560
1561#ifndef ON_EXIT
1562#define ON_EXIT(a, b)
1563#else
1564/* Make sure the exit routine is pulled in to define the globals as
1565 bss symbols, just in case the linker does not automatically pull
1566 bss definitions from the library. */
1567
1568extern int _exit_dummy_decl;
1569int *_exit_dummy_ref = &_exit_dummy_decl;
1570#endif /* ON_EXIT */
1571
1572void
1573__do_global_ctors ()
1574{
1575 DO_GLOBAL_CTORS_BODY;
1576 ON_EXIT (__do_global_dtors, 0);
1577}
1578#endif /* no INIT_SECTION_ASM_OP */
1579
1580#if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
1581/* Subroutine called automatically by `main'.
1582 Compiling a global function named `main'
1583 produces an automatic call to this function at the beginning.
1584
1585 For many systems, this routine calls __do_global_ctors.
1586 For systems which support a .init section we use the .init section
1587 to run __do_global_ctors, so we need not do anything here. */
1588
1589void
1590__main ()
1591{
1592 /* Support recursive calls to `main': run initializers just once. */
1593 static int initialized = 0;
1594 if (! initialized)
1595 {
1596 initialized = 1;
1597 __do_global_ctors ();
1598 }
1599}
1600#endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
1601
1602#endif /* L__main */
1603\f
1604#ifdef L_ctors
1605
1606#include "gbl-ctors.h"
1607
1608/* Provide default definitions for the lists of constructors and
1609 destructors, so that we don't get linker errors. These symbols are
1610 intentionally bss symbols, so that gld and/or collect will provide
1611 the right values. */
1612
1613/* We declare the lists here with two elements each,
1614 so that they are valid empty lists if no other definition is loaded. */
1615#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
1616#ifdef __NeXT__
1617/* After 2.3, try this definition on all systems. */
1618func_ptr __CTOR_LIST__[2] = {0, 0};
1619func_ptr __DTOR_LIST__[2] = {0, 0};
1620#else
1621func_ptr __CTOR_LIST__[2];
1622func_ptr __DTOR_LIST__[2];
1623#endif
1624#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
1625#endif /* L_ctors */
1626\f
1627#ifdef L_exit
1628
1629#include "gbl-ctors.h"
1630
1631#ifndef ON_EXIT
1632
1633/* If we have no known way of registering our own __do_global_dtors
1634 routine so that it will be invoked at program exit time, then we
1635 have to define our own exit routine which will get this to happen. */
1636
1637extern void __do_global_dtors ();
1638extern void _cleanup ();
1639extern volatile void _exit ();
1640
1641void
1642exit (status)
1643 int status;
1644{
1645 __do_global_dtors ();
1646#ifdef EXIT_BODY
1647 EXIT_BODY;
1648#else
1649 _cleanup ();
1650#endif
1651 _exit (status);
1652}
1653
1654#else
1655int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
1656#endif
1657
1658#endif /* L_exit */
1659\f
1660/* In a.out systems, we need to have these dummy constructor and destructor
1661 lists in the library.
1662
1663 When using `collect', the first link will resolve __CTOR_LIST__
1664 and __DTOR_LIST__ to these symbols. We will then run "nm" on the
1665 result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink.
1666 Since we don't do the second link if no constructors existed, these
1667 dummies must be fully functional empty lists.
1668
1669 When using `gnu ld', these symbols will be used if there are no
1670 constructors. If there are constructors, the N_SETV symbol defined
1671 by the linker from the N_SETT's in input files will define __CTOR_LIST__
1672 and __DTOR_LIST__ rather than its being allocated as common storage
1673 by the definitions below.
1674
1675 When using a linker that supports constructor and destructor segments,
1676 these definitions will not be used, since crtbegin.o and crtend.o
1677 (from crtstuff.c) will have already defined __CTOR_LIST__ and
1678 __DTOR_LIST__. The crt*.o files are passed directly to the linker
1679 on its command line, by gcc. */
1680
1681/* The list needs two elements: one is ignored (the old count); the
1682 second is the terminating zero. Since both values are zero, this
1683 declaration is not initialized, and it becomes `common'. */
1684
1685#ifdef L_ctor_list
1686#include "gbl-ctors.h"
1687func_ptr __CTOR_LIST__[2];
1688#endif
1689
1690#ifdef L_dtor_list
1691#include "gbl-ctors.h"
1692func_ptr __DTOR_LIST__[2];
1693#endif