|
|
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: #ifdef NO_UNDERSCORES
! 870: asm (".global __builtin_saveregs");
! 871: asm ("__builtin_saveregs:");
! 872: #else
1.1 root 873: asm (".global ___builtin_saveregs");
874: asm ("___builtin_saveregs:");
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]");
883: #else /* not __sparc__ */
884: #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
885:
886: asm (" .text");
887: asm (" .ent __builtin_saveregs");
888: asm (" .globl __builtin_saveregs");
889: asm ("__builtin_saveregs:");
890: asm (" sw $4,0($30)");
891: asm (" sw $5,4($30)");
892: asm (" sw $6,8($30)");
893: asm (" sw $7,12($30)");
894: asm (" j $31");
895: asm (" .end __builtin_saveregs");
896: #else /* not __mips__, etc. */
897: __builtin_saveregs ()
898: {
899: abort ();
900: }
901: #endif /* not __mips__ */
902: #endif /* not __sparc__ */
903: #endif /* not __i860__ */
904: #endif
905:
906: #ifdef L_eprintf
907: #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
908: #include <stdio.h>
909: /* This is used by the `assert' macro. */
910: void
911: __eprintf (string, expression, line, filename)
912: char *string;
913: char *expression;
914: int line;
915: char *filename;
916: {
917: fprintf (stderr, string, expression, line, filename);
918: fflush (stderr);
919: abort ();
920: }
921: #endif
922:
923: #ifdef L_bb
924: /* Avoid warning from ranlib about empty object file. */
925: void
926: __bb_avoid_warning ()
927: {}
928:
929: #if defined (__sun__) && defined (__mc68000__)
930: struct bb
931: {
932: int initialized;
933: char *filename;
934: int *counts;
935: int ncounts;
936: int zero_word;
937: int *addresses;
938: };
939:
940: extern int ___tcov_init;
941:
942: __bb_init_func (blocks)
943: struct bb *blocks;
944: {
945: if (! ___tcov_init)
946: ___tcov_init_func ();
947:
948: ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);
949: }
950:
951: #endif
952: #endif
953:
954: /* frills for C++ */
955:
956: #ifdef L_builtin_new
957: typedef void (*vfp)(void);
958:
959: extern vfp __new_handler;
960:
961: void *
962: __builtin_new (sz)
963: long sz;
964: {
965: void *p;
966:
967: p = (void *) malloc (sz);
968: if (p == 0)
969: (*__new_handler) ();
970: return p;
971: }
972: #endif
973:
974: #ifdef L_builtin_New
975: typedef void (*vfp)(void);
976:
977: static void default_new_handler ();
978:
979: vfp __new_handler = default_new_handler;
980:
981: void *
982: __builtin_vec_new (p, maxindex, size, ctor)
983: void *p;
984: int maxindex, size;
985: void (*ctor)(void *);
986: {
987: int i, nelts = maxindex + 1;
988: void *rval;
989:
990: if (p == 0)
991: p = (void *)__builtin_new (nelts * size);
992:
993: rval = p;
994:
995: for (i = 0; i < nelts; i++)
996: {
997: (*ctor) (p);
998: p += size;
999: }
1000:
1001: return rval;
1002: }
1003:
1004: vfp
1005: __set_new_handler (handler)
1006: vfp handler;
1007: {
1008: vfp prev_handler;
1009:
1010: prev_handler = __new_handler;
1011: if (handler == 0) handler = default_new_handler;
1012: __new_handler = handler;
1013: return prev_handler;
1014: }
1015:
1016: vfp
1017: set_new_handler (handler)
1018: vfp handler;
1019: {
1020: return __set_new_handler (handler);
1021: }
1022:
1023: static void
1024: default_new_handler ()
1025: {
1026: /* don't use fprintf (stderr, ...) because it may need to call malloc. */
1027: /* This should really print the name of the program, but that is hard to
1028: do. We need a standard, clean way to get at the name. */
1029: write (2, "Virtual memory exceeded in `new'\n", 33);
1030: /* don't call exit () because that may call global destructors which
1031: may cause a loop. */
1032: _exit (-1);
1033: }
1034: #endif
1035:
1036: #ifdef L_builtin_del
1037: typedef void (*vfp)(void);
1038:
1039: void
1040: __builtin_delete (ptr)
1041: void *ptr;
1042: {
1043: if (ptr)
1044: free (ptr);
1045: }
1046:
1047: void
1048: __builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete)
1049: void *ptr;
1050: int maxindex, size;
1051: void (*dtor)();
1052: int auto_delete;
1053: {
1054: int i, nelts = maxindex + 1;
1055: void *p = ptr;
1056:
1057: ptr += nelts * size;
1058:
1059: for (i = 0; i < nelts; i++)
1060: {
1061: ptr -= size;
1062: (*dtor) (ptr, auto_delete);
1063: }
1064:
1065: if (auto_delete_vec)
1066: __builtin_delete (p);
1067: }
1068:
1069: #endif
1070:
1071: #ifdef L_shtab
1072: unsigned int __shtab[] = {
1073: 0x00000001, 0x00000002, 0x00000004, 0x00000008,
1074: 0x00000010, 0x00000020, 0x00000040, 0x00000080,
1075: 0x00000100, 0x00000200, 0x00000400, 0x00000800,
1076: 0x00001000, 0x00002000, 0x00004000, 0x00008000,
1077: 0x00010000, 0x00020000, 0x00040000, 0x00080000,
1078: 0x00100000, 0x00200000, 0x00400000, 0x00800000,
1079: 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1080: 0x10000000, 0x20000000, 0x40000000, 0x80000000
1081: };
1082: #endif
1083:
1084: #ifdef L_clear_cache
1085: /* Clear part of an instruction cache. */
1086:
1087: #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1088:
1089: void
1090: __clear_cache (beg, end)
1091: char *beg, *end;
1092: {
1093: #ifdef INSN_CACHE_SIZE
1094: static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1095: static int initialized = 0;
1096: int offset;
1097: unsigned int start_addr, end_addr;
1098: typedef (*function_ptr) ();
1099:
1100: #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1101: /* It's cheaper to clear the whole cache.
1102: Put in a series of jump instructions so that calling the beginning
1103: of the cache will clear the whole thing. */
1104:
1105: if (! initialized)
1106: {
1107: int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1108: & -INSN_CACHE_LINE_WIDTH);
1109: int end_ptr = ptr + INSN_CACHE_SIZE;
1110:
1111: while (ptr < end_ptr)
1112: {
1113: *(INSTRUCTION_TYPE *)ptr
1114: = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1115: ptr += INSN_CACHE_LINE_WIDTH;
1116: }
1117: *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1118:
1119: initialized = 1;
1120: }
1121:
1122: /* Call the beginning of the sequence. */
1123: (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1124: & -INSN_CACHE_LINE_WIDTH))
1125: ());
1126:
1127: #else /* Cache is large. */
1128:
1129: if (! initialized)
1130: {
1131: int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1132: & -INSN_CACHE_LINE_WIDTH);
1133:
1134: while (ptr < (int) array + sizeof array)
1135: {
1136: *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1137: ptr += INSN_CACHE_LINE_WIDTH;
1138: }
1139:
1140: initialized = 1;
1141: }
1142:
1143: /* Find the location in array that occupies the same cache line as BEG. */
1144:
1145: offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1146: start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1147: & -INSN_CACHE_PLANE_SIZE)
1148: + offset);
1149:
1150: /* Compute the cache alignment of the place to stop clearing. */
1151: #if 0 /* This is not needed for gcc's purposes. */
1152: /* If the block to clear is bigger than a cache plane,
1153: we clear the entire cache, and OFFSET is already correct. */
1154: if (end < beg + INSN_CACHE_PLANE_SIZE)
1155: #endif
1156: offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1157: & -INSN_CACHE_LINE_WIDTH)
1158: & (INSN_CACHE_PLANE_SIZE - 1));
1159:
1160: #if INSN_CACHE_DEPTH > 1
1161: end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1162: if (end_addr <= start_addr)
1163: end_addr += INSN_CACHE_PLANE_SIZE;
1164:
1165: for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1166: {
1167: int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1168: int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1169:
1170: while (addr != stop)
1171: {
1172: /* Call the return instruction at ADDR. */
1173: ((function_ptr) addr) ();
1174:
1175: addr += INSN_CACHE_LINE_WIDTH;
1176: }
1177: }
1178: #else /* just one plane */
1179: do
1180: {
1181: /* Call the return instruction at START_ADDR. */
1182: ((function_ptr) start_addr) ();
1183:
1184: start_addr += INSN_CACHE_LINE_WIDTH;
1185: }
1186: while ((start_addr % INSN_CACHE_SIZE) != offset);
1187: #endif /* just one plane */
1188: #endif /* Cache is large */
1189: #endif /* Cache exists */
1190: }
1191:
1192: #endif /* L_clear_cache */
1193:
1194: #ifdef L_trampoline
1195:
1196: /* Jump to a trampoline, loading the static chain address. */
1197:
1198: #ifdef TRANSFER_FROM_TRAMPOLINE
1199: TRANSFER_FROM_TRAMPOLINE
1200: #endif
1201:
1202: #ifdef __convex__
1203:
1204: /* Make stack executable so we can call trampolines on stack.
1205: This is called from INITIALIZE_TRAMPOLINE in convex.h. */
1206:
1207: #include <sys/mman.h>
1208: #include <sys/vmparam.h>
1209: #include <machine/machparam.h>
1210:
1211: void
1212: __enable_execute_stack ()
1213: {
1214: int fp;
1215: static unsigned lowest = USRSTACK;
1216: unsigned current = (unsigned) &fp & -NBPG;
1217:
1218: if (lowest > current)
1219: {
1220: unsigned len = lowest - current;
1221: mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1222: lowest = current;
1223: }
1224:
1225: /* Clear instruction cache in case an old trampoline is in it. */
1226: asm ("pich");
1227: }
1228: #endif /* __convex__ */
1.1.1.2 ! root 1229:
! 1230: #ifdef __pyr__
! 1231:
! 1232: #include <stdio.h>
! 1233: #include <sys/mman.h>
! 1234: #include <sys/types.h>
! 1235: #include <sys/param.h>
! 1236: #include <sys/vmmac.h>
! 1237:
! 1238: /* Modified from the convex -code above.
! 1239: mremap promises to clear the i-cache. */
! 1240:
! 1241: void
! 1242: __enable_execute_stack ()
! 1243: {
! 1244: int fp;
! 1245: if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
! 1246: PROT_READ|PROT_WRITE|PROT_EXEC))
! 1247: {
! 1248: perror ("mprotect in __enable_execute_stack");
! 1249: fflush (stderr);
! 1250: abort ();
! 1251: }
! 1252: }
! 1253: #endif /* __pyr__ */
1.1 root 1254: #endif /* L_trampoline */
1255:
1256: #ifdef L__main
1257:
1258: #include "gbl-ctors.h"
1259:
1260: /* Run all the global destructors on exit from the program. */
1261:
1262: void
1263: __do_global_dtors ()
1264: {
1265: #ifdef DO_GLOBAL_DTORS_BODY
1266: DO_GLOBAL_DTORS_BODY;
1267: #else
1268: int nptrs = *(int *)__DTOR_LIST__;
1269: int i;
1270:
1271: /* Some systems place the number of pointers
1272: in the first word of the table.
1273: On other systems, that word is -1.
1274: In all cases, the table is null-terminated. */
1275:
1276: /* If the length is not recorded, count up to the null. */
1277: if (nptrs == -1)
1278: for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
1279:
1280: /* GNU LD format. */
1281: for (i = nptrs; i >= 1; i--)
1282: __DTOR_LIST__[i] ();
1283: #endif
1284: }
1285:
1286: #ifndef INIT_SECTION_ASM_OP
1287: /* Run all the global constructors on entry to the program. */
1288:
1.1.1.2 ! root 1289: #ifndef ON_EXIT
1.1 root 1290: #define ON_EXIT(a, b)
1291: #else
1292: /* Make sure the exit routine is pulled in to define the globals as
1293: bss symbols, just in case the linker does not automatically pull
1294: bss definitions from the library. */
1295:
1296: extern int _exit_dummy_decl;
1297: int *_exit_dummy_ref = &_exit_dummy_decl;
1298: #endif /* ON_EXIT */
1299:
1300: void
1301: __do_global_ctors ()
1302: {
1303: DO_GLOBAL_CTORS_BODY;
1.1.1.2 ! root 1304: ON_EXIT (__do_global_dtors, 0);
1.1 root 1305: }
1.1.1.2 ! root 1306: #endif /* no INIT_SECTION_ASM_OP */
1.1 root 1307:
1.1.1.2 ! root 1308: #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
1.1 root 1309: /* Subroutine called automatically by `main'.
1310: Compiling a global function named `main'
1311: produces an automatic call to this function at the beginning.
1312:
1313: For many systems, this routine calls __do_global_ctors.
1314: For systems which support a .init section we use the .init section
1315: to run __do_global_ctors, so we need not do anything here. */
1316:
1317: void
1318: __main ()
1319: {
1320: /* Support recursive calls to `main': run initializers just once. */
1321: static initialized = 0;
1322: if (! initialized)
1323: {
1324: initialized = 1;
1325: __do_global_ctors ();
1326: }
1327: }
1.1.1.2 ! root 1328: #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
1.1 root 1329:
1330: #endif /* L__main */
1331:
1332: #ifdef L_exit
1333:
1334: #include "gbl-ctors.h"
1335:
1336: /* Provide default definitions for the lists of constructors and
1337: destructors, so that we don't get linker errors. These symbols are
1338: intentionally bss symbols, so that gld and/or collect will provide
1339: the right values. */
1340:
1341: /* We declare the lists here with two elements each,
1342: so that they are valid empty lists if no other definition is loaded. */
1.1.1.2 ! root 1343: #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
1.1 root 1344: func_ptr __CTOR_LIST__[2];
1345: func_ptr __DTOR_LIST__[2];
1.1.1.2 ! root 1346: #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
1.1 root 1347:
1348: #ifndef ON_EXIT
1349:
1350: /* If we have no known way of registering our own __do_global_dtors
1351: routine so that it will be invoked at program exit time, then we
1352: have to define our own exit routine which will get this to happen. */
1353:
1354: extern void __do_global_dtors ();
1355: extern void _cleanup ();
1356: extern void _exit ();
1357:
1358: void
1359: exit (status)
1360: int status;
1361: {
1362: __do_global_dtors ();
1363: #ifdef EXIT_BODY
1364: EXIT_BODY;
1365: #else
1366: _cleanup ();
1367: #endif
1368: _exit (status);
1369: }
1370:
1371: #else
1372: int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
1373: #endif
1374:
1375: #endif /* L_exit */
1376:
1377: /* In a.out systems, we need to have these dummy constructor and destructor
1378: lists in the library.
1379:
1380: When using `collect', the first link will resolve __CTOR_LIST__
1381: and __DTOR_LIST__ to these symbols. We will then run "nm" on the
1382: result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink.
1383: Since we don't do the second link if no constructors existed, these
1384: dummies must be fully functional empty lists.
1385:
1386: When using `gnu ld', these symbols will be used if there are no
1387: constructors. If there are constructors, the N_SETV symbol defined
1388: by the linker from the N_SETT's in input files will define __CTOR_LIST__
1389: and __DTOR_LIST__ rather than its being allocated as common storage
1390: by the definitions below.
1391:
1392: When using a linker that supports constructor and destructor segments,
1393: these definitions will not be used, since crtbegin.o and crtend.o
1394: (from crtstuff.c) will have already defined __CTOR_LIST__ and
1395: __DTOR_LIST__. The crt*.o files are passed directly to the linker
1396: on its command line, by gcc. */
1397:
1398: /* The list needs two elements: one is ignored (the old count); the
1399: second is the terminating zero. Since both values are zero, this
1400: declaration is not initialized, and it becomes `common'. */
1401:
1402: #ifdef L_ctor_list
1403: #include "gbl-ctors.h"
1404: func_ptr __CTOR_LIST__[2];
1405: #endif
1406:
1407: #ifdef L_dtor_list
1408: #include "gbl-ctors.h"
1409: func_ptr __DTOR_LIST__[2];
1410: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.