|
|
1.1 root 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:
5: This file is part of GNU CC.
6:
7: GNU CC is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2, or (at your option)
10: any later version.
11:
12: GNU CC is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with GNU CC; see the file COPYING. If not, write to
19: the 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 "tm.h"
32: #include "gstddef.h"
33:
34: /* Don't use `fancy_abort' here even if config.h says to use it. */
35: #ifdef abort
36: #undef abort
37: #endif
38:
39: /* Need to undef this because LONG_TYPE_SIZE may rely upon GCC's
40: internal `target_flags' variable. */
41: #undef LONG_TYPE_SIZE
42:
43: #define LONG_TYPE_SIZE (sizeof (long) * BITS_PER_UNIT)
44:
45: #ifndef SItype
46: #define SItype long int
47: #endif
48:
49: /* long long ints are pairs of long ints in the order determined by
50: WORDS_BIG_ENDIAN. */
51:
52: #if WORDS_BIG_ENDIAN
53: struct longlong {long high, low;};
54: #else
55: struct longlong {long low, high;};
56: #endif
57:
58: /* We need this union to unpack/pack longlongs, since we don't have
59: any arithmetic yet. Incoming long long parameters are stored
60: into the `ll' field, and the unpacked result is read from the struct
61: longlong. */
62:
63: typedef union
64: {
65: struct longlong s;
66: long long ll;
67: } long_long;
68:
69: #if defined (L_udivmoddi4) || defined (L_muldi3)
70:
71: #include "longlong.h"
72:
73: #endif /* udiv or mul */
74:
75: extern long long __fixunssfdi (float a);
76: extern long long __fixunsdfdi (double a);
77:
78: #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
79: #if defined (L_divdi3) || defined (L_moddi3)
80: static inline
81: #endif
82: long long
83: __negdi2 (u)
84: long long u;
85: {
86: long_long w;
87: long_long uu;
88:
89: uu.ll = u;
90:
91: w.s.low = -uu.s.low;
92: w.s.high = -uu.s.high - ((unsigned long) w.s.low > 0);
93:
94: return w.ll;
95: }
96: #endif
97:
98: #ifdef L_lshldi3
99: long long
100: __lshldi3 (u, b)
101: long long u;
102: int b;
103: {
104: long_long w;
105: long bm;
106: long_long uu;
107:
108: if (b == 0)
109: return u;
110:
111: uu.ll = u;
112:
113: bm = (sizeof (long) * BITS_PER_UNIT) - b;
114: if (bm <= 0)
115: {
116: w.s.low = 0;
117: w.s.high = (unsigned long)uu.s.low << -bm;
118: }
119: else
120: {
121: unsigned long carries = (unsigned long)uu.s.low >> bm;
122: w.s.low = (unsigned long)uu.s.low << b;
123: w.s.high = ((unsigned long)uu.s.high << b) | carries;
124: }
125:
126: return w.ll;
127: }
128: #endif
129:
130: #ifdef L_lshrdi3
131: long long
132: __lshrdi3 (u, b)
133: long long u;
134: int b;
135: {
136: long_long w;
137: long bm;
138: long_long uu;
139:
140: if (b == 0)
141: return u;
142:
143: uu.ll = u;
144:
145: bm = (sizeof (long) * BITS_PER_UNIT) - b;
146: if (bm <= 0)
147: {
148: w.s.high = 0;
149: w.s.low = (unsigned long)uu.s.high >> -bm;
150: }
151: else
152: {
153: unsigned long carries = (unsigned long)uu.s.high << bm;
154: w.s.high = (unsigned long)uu.s.high >> b;
155: w.s.low = ((unsigned long)uu.s.low >> b) | carries;
156: }
157:
158: return w.ll;
159: }
160: #endif
161:
162: #ifdef L_ashldi3
163: long long
164: __ashldi3 (u, b)
165: long long u;
166: int b;
167: {
168: long_long w;
169: long bm;
170: long_long uu;
171:
172: if (b == 0)
173: return u;
174:
175: uu.ll = u;
176:
177: bm = (sizeof (long) * BITS_PER_UNIT) - b;
178: if (bm <= 0)
179: {
180: w.s.low = 0;
181: w.s.high = (unsigned long)uu.s.low << -bm;
182: }
183: else
184: {
185: unsigned long carries = (unsigned long)uu.s.low >> bm;
186: w.s.low = (unsigned long)uu.s.low << b;
187: w.s.high = ((unsigned long)uu.s.high << b) | carries;
188: }
189:
190: return w.ll;
191: }
192: #endif
193:
194: #ifdef L_ashrdi3
195: long long
196: __ashrdi3 (u, b)
197: long long u;
198: int b;
199: {
200: long_long w;
201: long bm;
202: long_long uu;
203:
204: if (b == 0)
205: return u;
206:
207: uu.ll = u;
208:
209: bm = (sizeof (long) * BITS_PER_UNIT) - b;
210: if (bm <= 0)
211: {
212: /* w.s.high = 1..1 or 0..0 */
213: w.s.high = uu.s.high >> (sizeof (long) * BITS_PER_UNIT - 1);
214: w.s.low = uu.s.high >> -bm;
215: }
216: else
217: {
218: unsigned long carries = (unsigned long)uu.s.high << bm;
219: w.s.high = uu.s.high >> b;
220: w.s.low = ((unsigned long)uu.s.low >> b) | carries;
221: }
222:
223: return w.ll;
224: }
225: #endif
226:
227: #ifdef L_muldi3
228: long long
229: __muldi3 (u, v)
230: long long u, v;
231: {
232: long_long w;
233: long_long uu, vv;
234:
235: uu.ll = u,
236: vv.ll = v;
237:
238: w.ll = __umulsidi3 (uu.s.low, vv.s.low);
239: w.s.high += ((unsigned long) uu.s.low * (unsigned long) vv.s.high
240: + (unsigned long) uu.s.high * (unsigned long) vv.s.low);
241:
242: return w.ll;
243: }
244: #endif
245:
246: #ifdef L_udivmoddi4
247: static const unsigned char __clz_tab[] =
248: {
249: 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,
250: 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,
251: 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,
252: 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,
253: 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,
254: 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,
255: 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,
256: 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,
257: };
258:
259: unsigned long long
260: __udivmoddi4 (n, d, rp)
261: unsigned long long n, d;
262: unsigned long long int *rp;
263: {
264: long_long ww;
265: long_long nn, dd;
266: long_long rr;
267: unsigned long d0, d1, n0, n1, n2;
268: unsigned long q0, q1;
269: unsigned b, bm;
270:
271: nn.ll = n;
272: dd.ll = d;
273:
274: d0 = dd.s.low;
275: d1 = dd.s.high;
276: n0 = nn.s.low;
277: n1 = nn.s.high;
278:
279: #if !UDIV_NEEDS_NORMALIZATION
280: if (d1 == 0)
281: {
282: if (d0 > n1)
283: {
284: /* 0q = nn / 0D */
285:
286: udiv_qrnnd (q0, n0, n1, n0, d0);
287: q1 = 0;
288:
289: /* Remainder in n0. */
290: }
291: else
292: {
293: /* qq = NN / 0d */
294:
295: if (d0 == 0)
296: d0 = 1 / d0; /* Divide intentionally by zero. */
297:
298: udiv_qrnnd (q1, n1, 0, n1, d0);
299: udiv_qrnnd (q0, n0, n1, n0, d0);
300:
301: /* Remainder in n0. */
302: }
303:
304: if (rp != 0)
305: {
306: rr.s.low = n0;
307: rr.s.high = 0;
308: *rp = rr.ll;
309: }
310: }
311:
312: #else /* UDIV_NEEDS_NORMALIZATION */
313:
314: if (d1 == 0)
315: {
316: if (d0 > n1)
317: {
318: /* 0q = nn / 0D */
319:
320: count_leading_zeros (bm, d0);
321:
322: if (bm != 0)
323: {
324: /* Normalize, i.e. make the most significant bit of the
325: denominator set. */
326:
327: d0 = d0 << bm;
328: n1 = (n1 << bm) | (n0 >> (LONG_TYPE_SIZE - bm));
329: n0 = n0 << bm;
330: }
331:
332: udiv_qrnnd (q0, n0, n1, n0, d0);
333: q1 = 0;
334:
335: /* Remainder in n0 >> bm. */
336: }
337: else
338: {
339: /* qq = NN / 0d */
340:
341: if (d0 == 0)
342: d0 = 1 / d0; /* Divide intentionally by zero. */
343:
344: count_leading_zeros (bm, d0);
345:
346: if (bm == 0)
347: {
348: /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
349: conclude (the most significant bit of n1 is set) /\ (the
350: leading quotient digit q1 = 1).
351:
352: This special case is necessary, not an optimization.
353: (Shifts counts of LONG_TYPE_SIZE are undefined.) */
354:
355: n1 -= d0;
356: q1 = 1;
357: }
358: else
359: {
360: /* Normalize. */
361:
362: b = LONG_TYPE_SIZE - bm;
363:
364: d0 = d0 << bm;
365: n2 = n1 >> b;
366: n1 = (n1 << bm) | (n0 >> b);
367: n0 = n0 << bm;
368:
369: udiv_qrnnd (q1, n1, n2, n1, d0);
370: }
371:
372: /* n1 != d0... */
373:
374: udiv_qrnnd (q0, n0, n1, n0, d0);
375:
376: /* Remainder in n0 >> bm. */
377: }
378:
379: if (rp != 0)
380: {
381: rr.s.low = n0 >> bm;
382: rr.s.high = 0;
383: *rp = rr.ll;
384: }
385: }
386: #endif /* UDIV_NEEDS_NORMALIZATION */
387:
388: else
389: {
390: if (d1 > n1)
391: {
392: /* 00 = nn / DD */
393:
394: q0 = 0;
395: q1 = 0;
396:
397: /* Remainder in n1n0. */
398: if (rp != 0)
399: {
400: rr.s.low = n0;
401: rr.s.high = n1;
402: *rp = rr.ll;
403: }
404: }
405: else
406: {
407: /* 0q = NN / dd */
408:
409: count_leading_zeros (bm, d1);
410: if (bm == 0)
411: {
412: /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
413: conclude (the most significant bit of n1 is set) /\ (the
414: quotient digit q0 = 0 or 1).
415:
416: This special case is necessary, not an optimization. */
417:
418: /* The condition on the next line takes advantage of that
419: n1 >= d1 (true due to program flow). */
420: if (n1 > d1 || n0 >= d0)
421: {
422: q0 = 1;
423: sub_ddmmss (n1, n0, n1, n0, d1, d0);
424: }
425: else
426: q0 = 0;
427:
428: q1 = 0;
429:
430: if (rp != 0)
431: {
432: rr.s.low = n0;
433: rr.s.high = n1;
434: *rp = rr.ll;
435: }
436: }
437: else
438: {
439: unsigned long m1, m0;
440: /* Normalize. */
441:
442: b = LONG_TYPE_SIZE - bm;
443:
444: d1 = (d1 << bm) | (d0 >> b);
445: d0 = d0 << bm;
446: n2 = n1 >> b;
447: n1 = (n1 << bm) | (n0 >> b);
448: n0 = n0 << bm;
449:
450: udiv_qrnnd (q0, n1, n2, n1, d1);
451: umul_ppmm (m1, m0, q0, d0);
452:
453: if (m1 > n1 || (m1 == n1 && m0 > n0))
454: {
455: q0--;
456: sub_ddmmss (m1, m0, m1, m0, d1, d0);
457: }
458:
459: q1 = 0;
460:
461: /* Remainder in (n1n0 - m1m0) >> bm. */
462: if (rp != 0)
463: {
464: sub_ddmmss (n1, n0, n1, n0, m1, m0);
465: rr.s.low = (n1 << b) | (n0 >> bm);
466: rr.s.high = n1 >> bm;
467: *rp = rr.ll;
468: }
469: }
470: }
471: }
472:
473: ww.s.low = q0;
474: ww.s.high = q1;
475: return ww.ll;
476: }
477: #endif
478:
479: #ifdef L_divdi3
480: unsigned long long __udivmoddi4 ();
481: long long
482: __divdi3 (u, v)
483: long long u, v;
484: {
485: int c = 0;
486: long_long uu, vv;
487: long long w;
488:
489: uu.ll = u;
490: vv.ll = v;
491:
492: if (uu.s.high < 0)
493: c = ~c,
494: uu.ll = __negdi2 (uu.ll);
495: if (vv.s.high < 0)
496: c = ~c,
497: vv.ll = __negdi2 (vv.ll);
498:
499: w = __udivmoddi4 (uu.ll, vv.ll, (unsigned long long *) 0);
500: if (c)
501: w = __negdi2 (w);
502:
503: return w;
504: }
505: #endif
506:
507: #ifdef L_moddi3
508: unsigned long long __udivmoddi4 ();
509: long long
510: __moddi3 (u, v)
511: long long u, v;
512: {
513: int c = 0;
514: long_long uu, vv;
515: long long w;
516:
517: uu.ll = u;
518: vv.ll = v;
519:
520: if (uu.s.high < 0)
521: c = ~c,
522: uu.ll = __negdi2 (uu.ll);
523: if (vv.s.high < 0)
524: vv.ll = __negdi2 (vv.ll);
525:
526: (void) __udivmoddi4 (uu.ll, vv.ll, &w);
527: if (c)
528: w = __negdi2 (w);
529:
530: return w;
531: }
532: #endif
533:
534: #ifdef L_umoddi3
535: unsigned long long __udivmoddi4 ();
536: unsigned long long
537: __umoddi3 (u, v)
538: unsigned long long u, v;
539: {
540: long long w;
541:
542: (void) __udivmoddi4 (u, v, &w);
543:
544: return w;
545: }
546: #endif
547:
548: #ifdef L_udivdi3
549: unsigned long long __udivmoddi4 ();
550: unsigned long long
551: __udivdi3 (n, d)
552: unsigned long long n, d;
553: {
554: return __udivmoddi4 (n, d, (unsigned long long *) 0);
555: }
556: #endif
557:
558: #ifdef L_cmpdi2
559: SItype
560: __cmpdi2 (a, b)
561: long long a, b;
562: {
563: long_long au, bu;
564:
565: au.ll = a, bu.ll = b;
566:
567: if (au.s.high < bu.s.high)
568: return 0;
569: else if (au.s.high > bu.s.high)
570: return 2;
571: if ((unsigned long) au.s.low < (unsigned long) bu.s.low)
572: return 0;
573: else if ((unsigned long) au.s.low > (unsigned long) bu.s.low)
574: return 2;
575: return 1;
576: }
577: #endif
578:
579: #ifdef L_ucmpdi2
580: SItype
581: __ucmpdi2 (a, b)
582: long long a, b;
583: {
584: long_long au, bu;
585:
586: au.ll = a, bu.ll = b;
587:
588: if ((unsigned long) au.s.high < (unsigned long) bu.s.high)
589: return 0;
590: else if ((unsigned long) au.s.high > (unsigned long) bu.s.high)
591: return 2;
592: if ((unsigned long) au.s.low < (unsigned long) bu.s.low)
593: return 0;
594: else if ((unsigned long) au.s.low > (unsigned long) bu.s.low)
595: return 2;
596: return 1;
597: }
598: #endif
599:
600: #ifdef L_fixunsdfdi
601: #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
602: #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
603:
604: long long
605: __fixunsdfdi (a)
606: double a;
607: {
608: double b;
609: unsigned long long v;
610:
611: if (a < 0)
612: return 0;
613:
614: /* Compute high word of result, as a flonum. */
615: b = (a / HIGH_WORD_COEFF);
616: /* Convert that to fixed (but not to long long!),
617: and shift it into the high word. */
618: v = (unsigned long int) b;
619: v <<= WORD_SIZE;
620: /* Remove high part from the double, leaving the low part as flonum. */
621: a -= (double)v;
622: /* Convert that to fixed (but not to long long!) and add it in.
623: Sometimes A comes out negative. This is significant, since
624: A has more bits than a long int does. */
625: if (a < 0)
626: v -= (unsigned long int) (- a);
627: else
628: v += (unsigned long int) a;
629: return v;
630: }
631: #endif
632:
633: #ifdef L_fixdfdi
634: long long
635: __fixdfdi (a)
636: double a;
637: {
638: if (a < 0)
639: return - __fixunsdfdi (-a);
640: return __fixunsdfdi (a);
641: }
642: #endif
643:
644: #ifdef L_fixunssfdi
645: #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
646: #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
647:
648: long long
649: __fixunssfdi (float original_a)
650: {
651: /* Convert the float to a double, because that is surely not going
652: to lose any bits. Some day someone else can write a faster version
653: that avoids converting to double, and verify it really works right. */
654: double a = original_a;
655: double b;
656: unsigned long long v;
657:
658: if (a < 0)
659: return 0;
660:
661: /* Compute high word of result, as a flonum. */
662: b = (a / HIGH_WORD_COEFF);
663: /* Convert that to fixed (but not to long long!),
664: and shift it into the high word. */
665: v = (unsigned long int) b;
666: v <<= WORD_SIZE;
667: /* Remove high part from the double, leaving the low part as flonum. */
668: a -= (double)v;
669: /* Convert that to fixed (but not to long long!) and add it in.
670: Sometimes A comes out negative. This is significant, since
671: A has more bits than a long int does. */
672: if (a < 0)
673: v -= (unsigned long int) (- a);
674: else
675: v += (unsigned long int) a;
676: return v;
677: }
678: #endif
679:
680: #ifdef L_fixsfdi
681: long long
682: __fixsfdi (float a)
683: {
684: if (a < 0)
685: return - __fixunssfdi (-a);
686: return __fixunssfdi (a);
687: }
688: #endif
689:
690: #ifdef L_floatdidf
691: #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
692: #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2))
693: #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
694:
695: double
696: __floatdidf (u)
697: long long u;
698: {
699: double d;
700: int negate = 0;
701:
702: if (u < 0)
703: u = -u, negate = 1;
704:
705: d = (unsigned int) (u >> WORD_SIZE);
706: d *= HIGH_HALFWORD_COEFF;
707: d *= HIGH_HALFWORD_COEFF;
708: d += (unsigned int) (u & (HIGH_WORD_COEFF - 1));
709:
710: return (negate ? -d : d);
711: }
712: #endif
713:
714: #ifdef L_floatdisf
715: #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
716: #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2))
717: #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
718:
719: float
720: __floatdisf (u)
721: long long u;
722: {
723: float f;
724: int negate = 0;
725:
726: if (u < 0)
727: u = -u, negate = 1;
728:
729: f = (unsigned int) (u >> WORD_SIZE);
730: f *= HIGH_HALFWORD_COEFF;
731: f *= HIGH_HALFWORD_COEFF;
732: f += (unsigned int) (u & (HIGH_WORD_COEFF - 1));
733:
734: return (negate ? -f : f);
735: }
736: #endif
737:
738: #ifdef L_fixunsdfsi
739: #include "limits.h"
740:
741: unsigned SItype
742: __fixunsdfsi (a)
743: double a;
744: {
745: if (a >= - (double) LONG_MIN)
746: return (SItype) (a + LONG_MIN) - LONG_MIN;
747: return (SItype) a;
748: }
749: #endif
750:
751: #ifdef L_fixunssfsi
752: #include "limits.h"
753:
754: unsigned SItype
755: __fixunssfsi (float a)
756: {
757: if (a >= - (float) LONG_MIN)
758: return (SItype) (a + LONG_MIN) - LONG_MIN;
759: return (SItype) a;
760: }
761: #endif
762:
763: #ifdef L_varargs
764: #ifdef __i860__
765: #ifdef SVR4
766: asm (" .text");
767: asm (" .align 4");
768:
769: asm (".globl __builtin_saveregs");
770: asm ("__builtin_saveregs:");
771: asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
772: asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
773: area and also for a new va_list
774: structure */
775: /* Save all argument registers in the arg reg save area. The
776: arg reg save area must have the following layout (according
777: to the svr4 ABI):
778:
779: struct {
780: union {
781: float freg[8];
782: double dreg[4];
783: } float_regs;
784: long ireg[12];
785: };
786: */
787:
788: asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
789: asm (" fst.q %f12,16(%sp)");
790:
791: asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
792: asm (" st.l %r17,36(%sp)");
793: asm (" st.l %r18,40(%sp)");
794: asm (" st.l %r19,44(%sp)");
795: asm (" st.l %r20,48(%sp)");
796: asm (" st.l %r21,52(%sp)");
797: asm (" st.l %r22,56(%sp)");
798: asm (" st.l %r23,60(%sp)");
799: asm (" st.l %r24,64(%sp)");
800: asm (" st.l %r25,68(%sp)");
801: asm (" st.l %r26,72(%sp)");
802: asm (" st.l %r27,76(%sp)");
803:
804: asm (" adds 80,%sp,%r16"); /* compute the address of the new
805: va_list structure. Put in into
806: r16 so that it will be returned
807: to the caller. */
808:
809: /* Initialize all fields of the new va_list structure. This
810: structure looks like:
811:
812: typedef struct {
813: unsigned long ireg_used;
814: unsigned long freg_used;
815: long *reg_base;
816: long *mem_ptr;
817: } va_list;
818: */
819:
820: asm (" st.l %r0, 0(%r16)"); /* nfixed */
821: asm (" st.l %r0, 4(%r16)"); /* nfloating */
822: asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
823: asm (" bri %r1"); /* delayed return */
824: asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
825:
826: #else /* not SVR4 */
827: asm (" .text");
828: asm (" .align 4");
829:
830: asm (".globl ___builtin_saveregs");
831: asm ("___builtin_saveregs:");
832: asm (" mov sp,r30");
833: asm (" andnot 0x0f,sp,sp");
834: asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
835:
836: /* Fill in the __va_struct. */
837: asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
838: asm (" st.l r17, 4(sp)"); /* int fixed[12] */
839: asm (" st.l r18, 8(sp)");
840: asm (" st.l r19,12(sp)");
841: asm (" st.l r20,16(sp)");
842: asm (" st.l r21,20(sp)");
843: asm (" st.l r22,24(sp)");
844: asm (" st.l r23,28(sp)");
845: asm (" st.l r24,32(sp)");
846: asm (" st.l r25,36(sp)");
847: asm (" st.l r26,40(sp)");
848: asm (" st.l r27,44(sp)");
849:
850: asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
851: asm (" fst.q f12,64(sp)"); /* int floating[8] */
852:
853: /* Fill in the __va_ctl. */
854: asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
855: asm (" st.l r28,84(sp)"); /* pointer to more args */
856: asm (" st.l r0, 88(sp)"); /* nfixed */
857: asm (" st.l r0, 92(sp)"); /* nfloating */
858:
859: asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
860: asm (" bri r1");
861: asm (" mov r30,sp");
862: /* recover stack and pass address to start
863: of data. */
864: #endif /* not SVR4 */
865: #else /* not __i860__ */
866: #ifdef __sparc__
867: asm (".global ___builtin_saveregs");
868: asm ("___builtin_saveregs:");
869: asm ("st %i0,[%fp+68]");
870: asm ("st %i1,[%fp+72]");
871: asm ("st %i2,[%fp+76]");
872: asm ("st %i3,[%fp+80]");
873: asm ("st %i4,[%fp+84]");
874: asm ("retl");
875: asm ("st %i5,[%fp+88]");
876: #else /* not __sparc__ */
877: #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
878:
879: asm (" .text");
880: asm (" .ent __builtin_saveregs");
881: asm (" .globl __builtin_saveregs");
882: asm ("__builtin_saveregs:");
883: asm (" sw $4,0($30)");
884: asm (" sw $5,4($30)");
885: asm (" sw $6,8($30)");
886: asm (" sw $7,12($30)");
887: asm (" j $31");
888: asm (" .end __builtin_saveregs");
889: #else /* not __mips__, etc. */
890: __builtin_saveregs ()
891: {
892: abort ();
893: }
894: #endif /* not __mips__ */
895: #endif /* not __sparc__ */
896: #endif /* not __i860__ */
897: #endif
898:
899: #ifdef L_eprintf
900: #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
901: #include <stdio.h>
902: /* This is used by the `assert' macro. */
903: void
904: __eprintf (string, expression, line, filename)
905: char *string;
906: char *expression;
907: int line;
908: char *filename;
909: {
910: fprintf (stderr, string, expression, line, filename);
911: fflush (stderr);
912: abort ();
913: }
914: #endif
915:
916: #ifdef L_bb
917: /* Avoid warning from ranlib about empty object file. */
918: void
919: __bb_avoid_warning ()
920: {}
921:
922: #if defined (__sun__) && defined (__mc68000__)
923: struct bb
924: {
925: int initialized;
926: char *filename;
927: int *counts;
928: int ncounts;
929: int zero_word;
930: int *addresses;
931: };
932:
933: extern int ___tcov_init;
934:
935: __bb_init_func (blocks)
936: struct bb *blocks;
937: {
938: if (! ___tcov_init)
939: ___tcov_init_func ();
940:
941: ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);
942: }
943:
944: #endif
945: #endif
946:
947: /* frills for C++ */
948:
949: #ifdef L_builtin_new
950: typedef void (*vfp)(void);
951:
952: extern vfp __new_handler;
953:
954: void *
955: __builtin_new (sz)
956: long sz;
957: {
958: void *p;
959:
960: p = (void *) malloc (sz);
961: if (p == 0)
962: (*__new_handler) ();
963: return p;
964: }
965: #endif
966:
967: #ifdef L_builtin_New
968: typedef void (*vfp)(void);
969:
970: static void default_new_handler ();
971:
972: vfp __new_handler = default_new_handler;
973:
974: void *
975: __builtin_vec_new (p, maxindex, size, ctor)
976: void *p;
977: int maxindex, size;
978: void (*ctor)(void *);
979: {
980: int i, nelts = maxindex + 1;
981: void *rval;
982:
983: if (p == 0)
984: p = (void *)__builtin_new (nelts * size);
985:
986: rval = p;
987:
988: for (i = 0; i < nelts; i++)
989: {
990: (*ctor) (p);
991: p += size;
992: }
993:
994: return rval;
995: }
996:
997: vfp
998: __set_new_handler (handler)
999: vfp handler;
1000: {
1001: vfp prev_handler;
1002:
1003: prev_handler = __new_handler;
1004: if (handler == 0) handler = default_new_handler;
1005: __new_handler = handler;
1006: return prev_handler;
1007: }
1008:
1009: vfp
1010: set_new_handler (handler)
1011: vfp handler;
1012: {
1013: return __set_new_handler (handler);
1014: }
1015:
1016: static void
1017: default_new_handler ()
1018: {
1019: /* don't use fprintf (stderr, ...) because it may need to call malloc. */
1020: /* This should really print the name of the program, but that is hard to
1021: do. We need a standard, clean way to get at the name. */
1022: write (2, "Virtual memory exceeded in `new'\n", 33);
1023: /* don't call exit () because that may call global destructors which
1024: may cause a loop. */
1025: _exit (-1);
1026: }
1027: #endif
1028:
1029: #ifdef L_builtin_del
1030: typedef void (*vfp)(void);
1031:
1032: void
1033: __builtin_delete (ptr)
1034: void *ptr;
1035: {
1036: if (ptr)
1037: free (ptr);
1038: }
1039:
1040: void
1041: __builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete)
1042: void *ptr;
1043: int maxindex, size;
1044: void (*dtor)();
1045: int auto_delete;
1046: {
1047: int i, nelts = maxindex + 1;
1048: void *p = ptr;
1049:
1050: ptr += nelts * size;
1051:
1052: for (i = 0; i < nelts; i++)
1053: {
1054: ptr -= size;
1055: (*dtor) (ptr, auto_delete);
1056: }
1057:
1058: if (auto_delete_vec)
1059: __builtin_delete (p);
1060: }
1061:
1062: #endif
1063:
1064: #ifdef L_shtab
1065: unsigned int __shtab[] = {
1066: 0x00000001, 0x00000002, 0x00000004, 0x00000008,
1067: 0x00000010, 0x00000020, 0x00000040, 0x00000080,
1068: 0x00000100, 0x00000200, 0x00000400, 0x00000800,
1069: 0x00001000, 0x00002000, 0x00004000, 0x00008000,
1070: 0x00010000, 0x00020000, 0x00040000, 0x00080000,
1071: 0x00100000, 0x00200000, 0x00400000, 0x00800000,
1072: 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1073: 0x10000000, 0x20000000, 0x40000000, 0x80000000
1074: };
1075: #endif
1076:
1077: #ifdef L_clear_cache
1078: /* Clear part of an instruction cache. */
1079:
1080: #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1081:
1082: void
1083: __clear_cache (beg, end)
1084: char *beg, *end;
1085: {
1086: #ifdef INSN_CACHE_SIZE
1087: static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1088: static int initialized = 0;
1089: int offset;
1090: unsigned int start_addr, end_addr;
1091: typedef (*function_ptr) ();
1092:
1093: #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1094: /* It's cheaper to clear the whole cache.
1095: Put in a series of jump instructions so that calling the beginning
1096: of the cache will clear the whole thing. */
1097:
1098: if (! initialized)
1099: {
1100: int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1101: & -INSN_CACHE_LINE_WIDTH);
1102: int end_ptr = ptr + INSN_CACHE_SIZE;
1103:
1104: while (ptr < end_ptr)
1105: {
1106: *(INSTRUCTION_TYPE *)ptr
1107: = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1108: ptr += INSN_CACHE_LINE_WIDTH;
1109: }
1110: *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1111:
1112: initialized = 1;
1113: }
1114:
1115: /* Call the beginning of the sequence. */
1116: (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1117: & -INSN_CACHE_LINE_WIDTH))
1118: ());
1119:
1120: #else /* Cache is large. */
1121:
1122: if (! initialized)
1123: {
1124: int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1125: & -INSN_CACHE_LINE_WIDTH);
1126:
1127: while (ptr < (int) array + sizeof array)
1128: {
1129: *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1130: ptr += INSN_CACHE_LINE_WIDTH;
1131: }
1132:
1133: initialized = 1;
1134: }
1135:
1136: /* Find the location in array that occupies the same cache line as BEG. */
1137:
1138: offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1139: start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1140: & -INSN_CACHE_PLANE_SIZE)
1141: + offset);
1142:
1143: /* Compute the cache alignment of the place to stop clearing. */
1144: #if 0 /* This is not needed for gcc's purposes. */
1145: /* If the block to clear is bigger than a cache plane,
1146: we clear the entire cache, and OFFSET is already correct. */
1147: if (end < beg + INSN_CACHE_PLANE_SIZE)
1148: #endif
1149: offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1150: & -INSN_CACHE_LINE_WIDTH)
1151: & (INSN_CACHE_PLANE_SIZE - 1));
1152:
1153: #if INSN_CACHE_DEPTH > 1
1154: end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1155: if (end_addr <= start_addr)
1156: end_addr += INSN_CACHE_PLANE_SIZE;
1157:
1158: for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1159: {
1160: int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1161: int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1162:
1163: while (addr != stop)
1164: {
1165: /* Call the return instruction at ADDR. */
1166: ((function_ptr) addr) ();
1167:
1168: addr += INSN_CACHE_LINE_WIDTH;
1169: }
1170: }
1171: #else /* just one plane */
1172: do
1173: {
1174: /* Call the return instruction at START_ADDR. */
1175: ((function_ptr) start_addr) ();
1176:
1177: start_addr += INSN_CACHE_LINE_WIDTH;
1178: }
1179: while ((start_addr % INSN_CACHE_SIZE) != offset);
1180: #endif /* just one plane */
1181: #endif /* Cache is large */
1182: #endif /* Cache exists */
1183: }
1184:
1185: #endif /* L_clear_cache */
1186:
1187: #ifdef L_trampoline
1188:
1189: /* Jump to a trampoline, loading the static chain address. */
1190:
1191: #ifdef TRANSFER_FROM_TRAMPOLINE
1192: TRANSFER_FROM_TRAMPOLINE
1193: #endif
1194:
1195: #ifdef __convex__
1196:
1197: /* Make stack executable so we can call trampolines on stack.
1198: This is called from INITIALIZE_TRAMPOLINE in convex.h. */
1199:
1200: #include <sys/mman.h>
1201: #include <sys/vmparam.h>
1202: #include <machine/machparam.h>
1203:
1204: void
1205: __enable_execute_stack ()
1206: {
1207: int fp;
1208: static unsigned lowest = USRSTACK;
1209: unsigned current = (unsigned) &fp & -NBPG;
1210:
1211: if (lowest > current)
1212: {
1213: unsigned len = lowest - current;
1214: mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1215: lowest = current;
1216: }
1217:
1218: /* Clear instruction cache in case an old trampoline is in it. */
1219: asm ("pich");
1220: }
1221: #endif /* __convex__ */
1222: #endif /* L_trampoline */
1223:
1224: #ifdef L__main
1225:
1226: #include "gbl-ctors.h"
1227:
1228: /* Run all the global destructors on exit from the program. */
1229:
1230: void
1231: __do_global_dtors ()
1232: {
1233: #ifdef DO_GLOBAL_DTORS_BODY
1234: DO_GLOBAL_DTORS_BODY;
1235: #else
1236: int nptrs = *(int *)__DTOR_LIST__;
1237: int i;
1238:
1239: /* Some systems place the number of pointers
1240: in the first word of the table.
1241: On other systems, that word is -1.
1242: In all cases, the table is null-terminated. */
1243:
1244: /* If the length is not recorded, count up to the null. */
1245: if (nptrs == -1)
1246: for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
1247:
1248: /* GNU LD format. */
1249: for (i = nptrs; i >= 1; i--)
1250: __DTOR_LIST__[i] ();
1251: #endif
1252: }
1253:
1254: #ifndef INIT_SECTION_ASM_OP
1255: /* Run all the global constructors on entry to the program. */
1256:
1257: #ifndef ON_EXIT /* DO_GLOBAL_CTORS_BODY uses ON_EXIT */
1258: #define ON_EXIT(a, b)
1259: #else
1260: /* Make sure the exit routine is pulled in to define the globals as
1261: bss symbols, just in case the linker does not automatically pull
1262: bss definitions from the library. */
1263:
1264: extern int _exit_dummy_decl;
1265: int *_exit_dummy_ref = &_exit_dummy_decl;
1266: #endif /* ON_EXIT */
1267:
1268: void
1269: __do_global_ctors ()
1270: {
1271: DO_GLOBAL_CTORS_BODY;
1272: }
1273:
1274: /* Subroutine called automatically by `main'.
1275: Compiling a global function named `main'
1276: produces an automatic call to this function at the beginning.
1277:
1278: For many systems, this routine calls __do_global_ctors.
1279: For systems which support a .init section we use the .init section
1280: to run __do_global_ctors, so we need not do anything here. */
1281:
1282: void
1283: __main ()
1284: {
1285: /* Support recursive calls to `main': run initializers just once. */
1286: static initialized = 0;
1287: if (! initialized)
1288: {
1289: initialized = 1;
1290: __do_global_ctors ();
1291: }
1292: }
1293: #endif /* no INIT_SECTION_ASM_OP */
1294:
1295: #endif /* L__main */
1296:
1297: #ifdef L_exit
1298:
1299: #include "gbl-ctors.h"
1300:
1301: /* Provide default definitions for the lists of constructors and
1302: destructors, so that we don't get linker errors. These symbols are
1303: intentionally bss symbols, so that gld and/or collect will provide
1304: the right values. */
1305:
1306: /* We declare the lists here with two elements each,
1307: so that they are valid empty lists if no other definition is loaded. */
1308: #ifndef INIT_SECTION_ASM_OP
1309: func_ptr __CTOR_LIST__[2];
1310: func_ptr __DTOR_LIST__[2];
1311: #endif /* INIT_SECTION_ASM_OP */
1312:
1313: #ifndef ON_EXIT
1314:
1315: /* If we have no known way of registering our own __do_global_dtors
1316: routine so that it will be invoked at program exit time, then we
1317: have to define our own exit routine which will get this to happen. */
1318:
1319: extern void __do_global_dtors ();
1320: extern void _cleanup ();
1321: extern void _exit ();
1322:
1323: void
1324: exit (status)
1325: int status;
1326: {
1327: __do_global_dtors ();
1328: #ifdef EXIT_BODY
1329: EXIT_BODY;
1330: #else
1331: _cleanup ();
1332: #endif
1333: _exit (status);
1334: }
1335:
1336: #else
1337: int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
1338: #endif
1339:
1340: #endif /* L_exit */
1341:
1342: /* In a.out systems, we need to have these dummy constructor and destructor
1343: lists in the library.
1344:
1345: When using `collect', the first link will resolve __CTOR_LIST__
1346: and __DTOR_LIST__ to these symbols. We will then run "nm" on the
1347: result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink.
1348: Since we don't do the second link if no constructors existed, these
1349: dummies must be fully functional empty lists.
1350:
1351: When using `gnu ld', these symbols will be used if there are no
1352: constructors. If there are constructors, the N_SETV symbol defined
1353: by the linker from the N_SETT's in input files will define __CTOR_LIST__
1354: and __DTOR_LIST__ rather than its being allocated as common storage
1355: by the definitions below.
1356:
1357: When using a linker that supports constructor and destructor segments,
1358: these definitions will not be used, since crtbegin.o and crtend.o
1359: (from crtstuff.c) will have already defined __CTOR_LIST__ and
1360: __DTOR_LIST__. The crt*.o files are passed directly to the linker
1361: on its command line, by gcc. */
1362:
1363: /* The list needs two elements: one is ignored (the old count); the
1364: second is the terminating zero. Since both values are zero, this
1365: declaration is not initialized, and it becomes `common'. */
1366:
1367: #ifdef L_ctor_list
1368: #include "gbl-ctors.h"
1369: func_ptr __CTOR_LIST__[2];
1370: #endif
1371:
1372: #ifdef L_dtor_list
1373: #include "gbl-ctors.h"
1374: func_ptr __DTOR_LIST__[2];
1375: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.