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