|
|
1.1 root 1: /* More subroutines needed by GCC output code on some machines. */
2: /* Compile this one with gcc. */
1.1.1.8 ! root 3: /* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
1.1 root 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
1.1.1.8 ! root 19: the Free Software Foundation, 59 Temple Place - Suite 330,
! 20: Boston, MA 02111-1307, USA. */
1.1 root 21:
1.1.1.7 root 22: /* As a special exception, if you link this library with other files,
23: some of which are compiled with GCC, to produce an executable,
24: this library does not by itself cause the resulting executable
25: to be covered by the GNU General Public License.
1.1 root 26: This exception does not however invalidate any other reasons why
27: the executable file might be covered by the GNU General Public License. */
28:
29: /* It is incorrect to include config.h here, because this file is being
30: compiled for the target, and hence definitions concerning only the host
31: do not apply. */
32:
1.1.1.4 root 33: #include "tconfig.h"
34: #include "machmode.h"
1.1.1.8 ! root 35: #include "defaults.h"
1.1.1.2 root 36: #ifndef L_trampoline
1.1.1.7 root 37: #include <stddef.h>
1.1.1.2 root 38: #endif
1.1 root 39:
40: /* Don't use `fancy_abort' here even if config.h says to use it. */
41: #ifdef abort
42: #undef abort
43: #endif
44:
1.1.1.8 ! root 45: #if (SUPPORTS_WEAK == 1) && defined (ASM_OUTPUT_DEF)
! 46: #define WEAK_ALIAS
! 47: #endif
! 48:
! 49: /* Permit the tm.h file to select the endianness to use just for this
! 50: file. This is used when the endianness is determined when the
! 51: compiler is run. */
! 52:
! 53: #ifndef LIBGCC2_WORDS_BIG_ENDIAN
! 54: #define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
! 55: #endif
! 56:
1.1.1.4 root 57: /* In the first part of this file, we are interfacing to calls generated
58: by the compiler itself. These calls pass values into these routines
59: which have very specific modes (rather than very specific types), and
60: these compiler-generated calls also expect any return values to have
61: very specific modes (rather than very specific types). Thus, we need
62: to avoid using regular C language type names in this part of the file
63: because the sizes for those types can be configured to be anything.
64: Instead we use the following special type names. */
65:
66: typedef unsigned int UQItype __attribute__ ((mode (QI)));
67: typedef int SItype __attribute__ ((mode (SI)));
68: typedef unsigned int USItype __attribute__ ((mode (SI)));
69: typedef int DItype __attribute__ ((mode (DI)));
70: typedef unsigned int UDItype __attribute__ ((mode (DI)));
1.1.1.8 ! root 71:
1.1.1.4 root 72: typedef float SFtype __attribute__ ((mode (SF)));
73: typedef float DFtype __attribute__ ((mode (DF)));
1.1.1.8 ! root 74:
1.1.1.5 root 75: #if LONG_DOUBLE_TYPE_SIZE == 96
1.1.1.4 root 76: typedef float XFtype __attribute__ ((mode (XF)));
77: #endif
78: #if LONG_DOUBLE_TYPE_SIZE == 128
79: typedef float TFtype __attribute__ ((mode (TF)));
80: #endif
81:
1.1.1.8 ! root 82: typedef int word_type __attribute__ ((mode (__word__)));
1.1.1.5 root 83:
84: /* Make sure that we don't accidentally use any normal C language built-in
1.1.1.4 root 85: type names in the first part of this file. Instead we want to use *only*
86: the type names defined above. The following macro definitions insure
1.1.1.5 root 87: that if we *do* accidentally use some normal C language built-in type name,
1.1.1.4 root 88: we will get a syntax error. */
89:
90: #define char bogus_type
91: #define short bogus_type
92: #define int bogus_type
93: #define long bogus_type
94: #define unsigned bogus_type
95: #define float bogus_type
96: #define double bogus_type
1.1 root 97:
1.1.1.4 root 98: #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
1.1 root 99:
1.1.1.4 root 100: /* DIstructs are pairs of SItype values in the order determined by
1.1.1.8 ! root 101: LIBGCC2_WORDS_BIG_ENDIAN. */
1.1 root 102:
1.1.1.8 ! root 103: #if LIBGCC2_WORDS_BIG_ENDIAN
1.1.1.4 root 104: struct DIstruct {SItype high, low;};
1.1 root 105: #else
1.1.1.4 root 106: struct DIstruct {SItype low, high;};
1.1 root 107: #endif
108:
1.1.1.4 root 109: /* We need this union to unpack/pack DImode values, since we don't have
110: any arithmetic yet. Incoming DImode parameters are stored into the
111: `ll' field, and the unpacked result is read from the struct `s'. */
1.1 root 112:
113: typedef union
114: {
1.1.1.4 root 115: struct DIstruct s;
116: DItype ll;
117: } DIunion;
1.1 root 118:
1.1.1.8 ! root 119: #if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\
! 120: || defined (L_divdi3) || defined (L_udivdi3) \
! 121: || defined (L_moddi3) || defined (L_umoddi3))
1.1 root 122:
123: #include "longlong.h"
124:
125: #endif /* udiv or mul */
126:
1.1.1.4 root 127: extern DItype __fixunssfdi (SFtype a);
128: extern DItype __fixunsdfdi (DFtype a);
1.1.1.6 root 129: #if LONG_DOUBLE_TYPE_SIZE == 96
130: extern DItype __fixunsxfdi (XFtype a);
131: #endif
132: #if LONG_DOUBLE_TYPE_SIZE == 128
133: extern DItype __fixunstfdi (TFtype a);
134: #endif
1.1 root 135:
136: #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
137: #if defined (L_divdi3) || defined (L_moddi3)
138: static inline
139: #endif
1.1.1.4 root 140: DItype
1.1 root 141: __negdi2 (u)
1.1.1.4 root 142: DItype u;
1.1 root 143: {
1.1.1.4 root 144: DIunion w;
145: DIunion uu;
1.1 root 146:
147: uu.ll = u;
148:
149: w.s.low = -uu.s.low;
1.1.1.4 root 150: w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
1.1 root 151:
152: return w.ll;
153: }
154: #endif
155:
156: #ifdef L_lshrdi3
1.1.1.4 root 157: DItype
1.1 root 158: __lshrdi3 (u, b)
1.1.1.4 root 159: DItype u;
1.1.1.8 ! root 160: word_type b;
1.1 root 161: {
1.1.1.4 root 162: DIunion w;
1.1.1.8 ! root 163: word_type bm;
1.1.1.4 root 164: DIunion uu;
1.1 root 165:
166: if (b == 0)
167: return u;
168:
169: uu.ll = u;
170:
1.1.1.4 root 171: bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
1.1 root 172: if (bm <= 0)
173: {
174: w.s.high = 0;
1.1.1.4 root 175: w.s.low = (USItype)uu.s.high >> -bm;
1.1 root 176: }
177: else
178: {
1.1.1.4 root 179: USItype carries = (USItype)uu.s.high << bm;
180: w.s.high = (USItype)uu.s.high >> b;
181: w.s.low = ((USItype)uu.s.low >> b) | carries;
1.1 root 182: }
183:
184: return w.ll;
185: }
186: #endif
187:
188: #ifdef L_ashldi3
1.1.1.4 root 189: DItype
1.1 root 190: __ashldi3 (u, b)
1.1.1.4 root 191: DItype u;
1.1.1.8 ! root 192: word_type b;
1.1 root 193: {
1.1.1.4 root 194: DIunion w;
1.1.1.8 ! root 195: word_type bm;
1.1.1.4 root 196: DIunion uu;
1.1 root 197:
198: if (b == 0)
199: return u;
200:
201: uu.ll = u;
202:
1.1.1.4 root 203: bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
1.1 root 204: if (bm <= 0)
205: {
206: w.s.low = 0;
1.1.1.4 root 207: w.s.high = (USItype)uu.s.low << -bm;
1.1 root 208: }
209: else
210: {
1.1.1.4 root 211: USItype carries = (USItype)uu.s.low >> bm;
212: w.s.low = (USItype)uu.s.low << b;
213: w.s.high = ((USItype)uu.s.high << b) | carries;
1.1 root 214: }
215:
216: return w.ll;
217: }
218: #endif
219:
220: #ifdef L_ashrdi3
1.1.1.4 root 221: DItype
1.1 root 222: __ashrdi3 (u, b)
1.1.1.4 root 223: DItype u;
1.1.1.8 ! root 224: word_type b;
1.1 root 225: {
1.1.1.4 root 226: DIunion w;
1.1.1.8 ! root 227: word_type bm;
1.1.1.4 root 228: DIunion uu;
1.1 root 229:
230: if (b == 0)
231: return u;
232:
233: uu.ll = u;
234:
1.1.1.4 root 235: bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
1.1 root 236: if (bm <= 0)
237: {
238: /* w.s.high = 1..1 or 0..0 */
1.1.1.4 root 239: w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
1.1 root 240: w.s.low = uu.s.high >> -bm;
241: }
242: else
243: {
1.1.1.4 root 244: USItype carries = (USItype)uu.s.high << bm;
1.1 root 245: w.s.high = uu.s.high >> b;
1.1.1.4 root 246: w.s.low = ((USItype)uu.s.low >> b) | carries;
1.1 root 247: }
248:
249: return w.ll;
250: }
251: #endif
252:
1.1.1.5 root 253: #ifdef L_ffsdi2
254: DItype
255: __ffsdi2 (u)
256: DItype u;
257: {
258: DIunion uu, w;
259: uu.ll = u;
260: w.s.high = 0;
261: w.s.low = ffs (uu.s.low);
262: if (w.s.low != 0)
263: return w.ll;
264: w.s.low = ffs (uu.s.high);
265: if (w.s.low != 0)
266: {
267: w.s.low += BITS_PER_UNIT * sizeof (SItype);
268: return w.ll;
269: }
270: return w.ll;
271: }
272: #endif
273:
1.1 root 274: #ifdef L_muldi3
1.1.1.4 root 275: DItype
1.1 root 276: __muldi3 (u, v)
1.1.1.4 root 277: DItype u, v;
1.1 root 278: {
1.1.1.4 root 279: DIunion w;
280: DIunion uu, vv;
1.1 root 281:
282: uu.ll = u,
283: vv.ll = v;
284:
285: w.ll = __umulsidi3 (uu.s.low, vv.s.low);
1.1.1.4 root 286: w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
287: + (USItype) uu.s.high * (USItype) vv.s.low);
1.1 root 288:
289: return w.ll;
290: }
291: #endif
292:
1.1.1.4 root 293: #ifdef L_udiv_w_sdiv
1.1.1.8 ! root 294: #if defined (sdiv_qrnnd)
1.1.1.4 root 295: USItype
296: __udiv_w_sdiv (rp, a1, a0, d)
297: USItype *rp, a1, a0, d;
298: {
299: USItype q, r;
300: USItype c0, c1, b1;
301:
302: if ((SItype) d >= 0)
303: {
1.1.1.5 root 304: if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
1.1.1.4 root 305: {
306: /* dividend, divisor, and quotient are nonnegative */
307: sdiv_qrnnd (q, r, a1, a0, d);
308: }
309: else
310: {
311: /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
1.1.1.5 root 312: sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
1.1.1.4 root 313: /* Divide (c1*2^32 + c0) by d */
314: sdiv_qrnnd (q, r, c1, c0, d);
315: /* Add 2^31 to quotient */
1.1.1.5 root 316: q += (USItype) 1 << (SI_TYPE_SIZE - 1);
1.1.1.4 root 317: }
318: }
319: else
320: {
321: b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
322: c1 = a1 >> 1; /* A/2 */
1.1.1.5 root 323: c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
1.1.1.4 root 324:
325: if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
326: {
327: sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
328:
329: r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
330: if ((d & 1) != 0)
331: {
332: if (r >= q)
333: r = r - q;
334: else if (q - r <= d)
335: {
336: r = r - q + d;
337: q--;
338: }
339: else
340: {
341: r = r - q + 2*d;
342: q -= 2;
343: }
344: }
345: }
346: else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
347: {
348: c1 = (b1 - 1) - c1;
349: c0 = ~c0; /* logical NOT */
350:
351: sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
352:
353: q = ~q; /* (A/2)/b1 */
354: r = (b1 - 1) - r;
355:
356: r = 2*r + (a0 & 1); /* A/(2*b1) */
357:
358: if ((d & 1) != 0)
359: {
360: if (r >= q)
361: r = r - q;
362: else if (q - r <= d)
363: {
364: r = r - q + d;
365: q--;
366: }
367: else
368: {
369: r = r - q + 2*d;
370: q -= 2;
371: }
372: }
373: }
374: else /* Implies c1 = b1 */
375: { /* Hence a1 = d - 1 = 2*b1 - 1 */
376: if (a0 >= -d)
377: {
378: q = -1;
379: r = a0 + d;
380: }
381: else
382: {
383: q = -2;
384: r = a0 + 2*d;
385: }
386: }
387: }
388:
389: *rp = r;
390: return q;
391: }
1.1.1.8 ! root 392: #else
! 393: /* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
! 394: USItype
! 395: __udiv_w_sdiv (rp, a1, a0, d)
! 396: USItype *rp, a1, a0, d;
! 397: {}
! 398: #endif
1.1.1.4 root 399: #endif
400:
1.1.1.8 ! root 401: #if (defined (L_udivdi3) || defined (L_divdi3) || \
! 402: defined (L_umoddi3) || defined (L_moddi3))
! 403: #define L_udivmoddi4
! 404: #endif
! 405:
1.1 root 406: #ifdef L_udivmoddi4
1.1.1.4 root 407: static const UQItype __clz_tab[] =
1.1 root 408: {
409: 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,
410: 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,
411: 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,
412: 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,
413: 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,
414: 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,
415: 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,
416: 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,
417: };
418:
1.1.1.8 ! root 419: #if (defined (L_udivdi3) || defined (L_divdi3) || \
! 420: defined (L_umoddi3) || defined (L_moddi3))
! 421: static inline
! 422: #endif
1.1.1.4 root 423: UDItype
1.1 root 424: __udivmoddi4 (n, d, rp)
1.1.1.4 root 425: UDItype n, d;
426: UDItype *rp;
1.1 root 427: {
1.1.1.4 root 428: DIunion ww;
429: DIunion nn, dd;
430: DIunion rr;
431: USItype d0, d1, n0, n1, n2;
432: USItype q0, q1;
433: USItype b, bm;
1.1 root 434:
435: nn.ll = n;
436: dd.ll = d;
437:
438: d0 = dd.s.low;
439: d1 = dd.s.high;
440: n0 = nn.s.low;
441: n1 = nn.s.high;
442:
443: #if !UDIV_NEEDS_NORMALIZATION
444: if (d1 == 0)
445: {
446: if (d0 > n1)
447: {
448: /* 0q = nn / 0D */
449:
450: udiv_qrnnd (q0, n0, n1, n0, d0);
451: q1 = 0;
452:
453: /* Remainder in n0. */
454: }
455: else
456: {
457: /* qq = NN / 0d */
458:
459: if (d0 == 0)
460: d0 = 1 / d0; /* Divide intentionally by zero. */
461:
462: udiv_qrnnd (q1, n1, 0, n1, d0);
463: udiv_qrnnd (q0, n0, n1, n0, d0);
464:
465: /* Remainder in n0. */
466: }
467:
468: if (rp != 0)
469: {
470: rr.s.low = n0;
471: rr.s.high = 0;
472: *rp = rr.ll;
473: }
474: }
475:
476: #else /* UDIV_NEEDS_NORMALIZATION */
477:
478: if (d1 == 0)
479: {
480: if (d0 > n1)
481: {
482: /* 0q = nn / 0D */
483:
484: count_leading_zeros (bm, d0);
485:
486: if (bm != 0)
487: {
488: /* Normalize, i.e. make the most significant bit of the
489: denominator set. */
490:
491: d0 = d0 << bm;
1.1.1.4 root 492: n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
1.1 root 493: n0 = n0 << bm;
494: }
495:
496: udiv_qrnnd (q0, n0, n1, n0, d0);
497: q1 = 0;
498:
499: /* Remainder in n0 >> bm. */
500: }
501: else
502: {
503: /* qq = NN / 0d */
504:
505: if (d0 == 0)
506: d0 = 1 / d0; /* Divide intentionally by zero. */
507:
508: count_leading_zeros (bm, d0);
509:
510: if (bm == 0)
511: {
512: /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
513: conclude (the most significant bit of n1 is set) /\ (the
514: leading quotient digit q1 = 1).
515:
516: This special case is necessary, not an optimization.
1.1.1.4 root 517: (Shifts counts of SI_TYPE_SIZE are undefined.) */
1.1 root 518:
519: n1 -= d0;
520: q1 = 1;
521: }
522: else
523: {
524: /* Normalize. */
525:
1.1.1.4 root 526: b = SI_TYPE_SIZE - bm;
1.1 root 527:
528: d0 = d0 << bm;
529: n2 = n1 >> b;
530: n1 = (n1 << bm) | (n0 >> b);
531: n0 = n0 << bm;
532:
533: udiv_qrnnd (q1, n1, n2, n1, d0);
534: }
535:
536: /* n1 != d0... */
537:
538: udiv_qrnnd (q0, n0, n1, n0, d0);
539:
540: /* Remainder in n0 >> bm. */
541: }
542:
543: if (rp != 0)
544: {
545: rr.s.low = n0 >> bm;
546: rr.s.high = 0;
547: *rp = rr.ll;
548: }
549: }
550: #endif /* UDIV_NEEDS_NORMALIZATION */
551:
552: else
553: {
554: if (d1 > n1)
555: {
556: /* 00 = nn / DD */
557:
558: q0 = 0;
559: q1 = 0;
560:
561: /* Remainder in n1n0. */
562: if (rp != 0)
563: {
564: rr.s.low = n0;
565: rr.s.high = n1;
566: *rp = rr.ll;
567: }
568: }
569: else
570: {
571: /* 0q = NN / dd */
572:
573: count_leading_zeros (bm, d1);
574: if (bm == 0)
575: {
576: /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
577: conclude (the most significant bit of n1 is set) /\ (the
578: quotient digit q0 = 0 or 1).
579:
580: This special case is necessary, not an optimization. */
581:
582: /* The condition on the next line takes advantage of that
583: n1 >= d1 (true due to program flow). */
584: if (n1 > d1 || n0 >= d0)
585: {
586: q0 = 1;
587: sub_ddmmss (n1, n0, n1, n0, d1, d0);
588: }
589: else
590: q0 = 0;
591:
592: q1 = 0;
593:
594: if (rp != 0)
595: {
596: rr.s.low = n0;
597: rr.s.high = n1;
598: *rp = rr.ll;
599: }
600: }
601: else
602: {
1.1.1.4 root 603: USItype m1, m0;
1.1 root 604: /* Normalize. */
605:
1.1.1.4 root 606: b = SI_TYPE_SIZE - bm;
1.1 root 607:
608: d1 = (d1 << bm) | (d0 >> b);
609: d0 = d0 << bm;
610: n2 = n1 >> b;
611: n1 = (n1 << bm) | (n0 >> b);
612: n0 = n0 << bm;
613:
614: udiv_qrnnd (q0, n1, n2, n1, d1);
615: umul_ppmm (m1, m0, q0, d0);
616:
617: if (m1 > n1 || (m1 == n1 && m0 > n0))
618: {
619: q0--;
620: sub_ddmmss (m1, m0, m1, m0, d1, d0);
621: }
622:
623: q1 = 0;
624:
625: /* Remainder in (n1n0 - m1m0) >> bm. */
626: if (rp != 0)
627: {
628: sub_ddmmss (n1, n0, n1, n0, m1, m0);
629: rr.s.low = (n1 << b) | (n0 >> bm);
630: rr.s.high = n1 >> bm;
631: *rp = rr.ll;
632: }
633: }
634: }
635: }
636:
637: ww.s.low = q0;
638: ww.s.high = q1;
639: return ww.ll;
640: }
641: #endif
642:
643: #ifdef L_divdi3
1.1.1.4 root 644: UDItype __udivmoddi4 ();
1.1.1.6 root 645:
1.1.1.4 root 646: DItype
1.1 root 647: __divdi3 (u, v)
1.1.1.4 root 648: DItype u, v;
1.1 root 649: {
1.1.1.8 ! root 650: word_type c = 0;
1.1.1.4 root 651: DIunion uu, vv;
652: DItype w;
1.1 root 653:
654: uu.ll = u;
655: vv.ll = v;
656:
657: if (uu.s.high < 0)
658: c = ~c,
659: uu.ll = __negdi2 (uu.ll);
660: if (vv.s.high < 0)
661: c = ~c,
662: vv.ll = __negdi2 (vv.ll);
663:
1.1.1.4 root 664: w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
1.1 root 665: if (c)
666: w = __negdi2 (w);
667:
668: return w;
669: }
670: #endif
671:
672: #ifdef L_moddi3
1.1.1.4 root 673: UDItype __udivmoddi4 ();
674: DItype
1.1 root 675: __moddi3 (u, v)
1.1.1.4 root 676: DItype u, v;
1.1 root 677: {
1.1.1.8 ! root 678: word_type c = 0;
1.1.1.4 root 679: DIunion uu, vv;
680: DItype w;
1.1 root 681:
682: uu.ll = u;
683: vv.ll = v;
684:
685: if (uu.s.high < 0)
686: c = ~c,
687: uu.ll = __negdi2 (uu.ll);
688: if (vv.s.high < 0)
689: vv.ll = __negdi2 (vv.ll);
690:
691: (void) __udivmoddi4 (uu.ll, vv.ll, &w);
692: if (c)
693: w = __negdi2 (w);
694:
695: return w;
696: }
697: #endif
698:
699: #ifdef L_umoddi3
1.1.1.4 root 700: UDItype __udivmoddi4 ();
701: UDItype
1.1 root 702: __umoddi3 (u, v)
1.1.1.4 root 703: UDItype u, v;
1.1 root 704: {
1.1.1.7 root 705: UDItype w;
1.1 root 706:
707: (void) __udivmoddi4 (u, v, &w);
708:
709: return w;
710: }
711: #endif
712:
713: #ifdef L_udivdi3
1.1.1.4 root 714: UDItype __udivmoddi4 ();
715: UDItype
1.1 root 716: __udivdi3 (n, d)
1.1.1.4 root 717: UDItype n, d;
1.1 root 718: {
1.1.1.4 root 719: return __udivmoddi4 (n, d, (UDItype *) 0);
1.1 root 720: }
721: #endif
722:
723: #ifdef L_cmpdi2
1.1.1.5 root 724: word_type
1.1 root 725: __cmpdi2 (a, b)
1.1.1.4 root 726: DItype a, b;
1.1 root 727: {
1.1.1.4 root 728: DIunion au, bu;
1.1 root 729:
730: au.ll = a, bu.ll = b;
731:
732: if (au.s.high < bu.s.high)
733: return 0;
734: else if (au.s.high > bu.s.high)
735: return 2;
1.1.1.4 root 736: if ((USItype) au.s.low < (USItype) bu.s.low)
1.1 root 737: return 0;
1.1.1.4 root 738: else if ((USItype) au.s.low > (USItype) bu.s.low)
1.1 root 739: return 2;
740: return 1;
741: }
742: #endif
743:
744: #ifdef L_ucmpdi2
1.1.1.5 root 745: word_type
1.1 root 746: __ucmpdi2 (a, b)
1.1.1.4 root 747: DItype a, b;
1.1 root 748: {
1.1.1.4 root 749: DIunion au, bu;
1.1 root 750:
751: au.ll = a, bu.ll = b;
752:
1.1.1.4 root 753: if ((USItype) au.s.high < (USItype) bu.s.high)
1.1 root 754: return 0;
1.1.1.4 root 755: else if ((USItype) au.s.high > (USItype) bu.s.high)
1.1 root 756: return 2;
1.1.1.4 root 757: if ((USItype) au.s.low < (USItype) bu.s.low)
1.1 root 758: return 0;
1.1.1.4 root 759: else if ((USItype) au.s.low > (USItype) bu.s.low)
1.1 root 760: return 2;
761: return 1;
762: }
763: #endif
764:
1.1.1.4 root 765: #if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
766: #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
767: #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
768:
769: DItype
770: __fixunstfdi (a)
771: TFtype a;
772: {
773: TFtype b;
774: UDItype v;
775:
776: if (a < 0)
777: return 0;
778:
779: /* Compute high word of result, as a flonum. */
780: b = (a / HIGH_WORD_COEFF);
781: /* Convert that to fixed (but not to DItype!),
782: and shift it into the high word. */
783: v = (USItype) b;
784: v <<= WORD_SIZE;
785: /* Remove high part from the TFtype, leaving the low part as flonum. */
786: a -= (TFtype)v;
787: /* Convert that to fixed (but not to DItype!) and add it in.
788: Sometimes A comes out negative. This is significant, since
789: A has more bits than a long int does. */
790: if (a < 0)
791: v -= (USItype) (- a);
792: else
793: v += (USItype) a;
794: return v;
795: }
796: #endif
797:
798: #if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
799: DItype
800: __fixtfdi (a)
801: TFtype a;
802: {
803: if (a < 0)
804: return - __fixunstfdi (-a);
805: return __fixunstfdi (a);
806: }
807: #endif
808:
1.1.1.5 root 809: #if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
810: #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
811: #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
812:
813: DItype
814: __fixunsxfdi (a)
815: XFtype a;
816: {
817: XFtype b;
818: UDItype v;
819:
820: if (a < 0)
821: return 0;
822:
823: /* Compute high word of result, as a flonum. */
824: b = (a / HIGH_WORD_COEFF);
825: /* Convert that to fixed (but not to DItype!),
826: and shift it into the high word. */
827: v = (USItype) b;
828: v <<= WORD_SIZE;
829: /* Remove high part from the XFtype, leaving the low part as flonum. */
830: a -= (XFtype)v;
831: /* Convert that to fixed (but not to DItype!) and add it in.
832: Sometimes A comes out negative. This is significant, since
833: A has more bits than a long int does. */
834: if (a < 0)
835: v -= (USItype) (- a);
836: else
837: v += (USItype) a;
838: return v;
839: }
840: #endif
841:
842: #if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
843: DItype
844: __fixxfdi (a)
845: XFtype a;
846: {
847: if (a < 0)
848: return - __fixunsxfdi (-a);
849: return __fixunsxfdi (a);
850: }
851: #endif
852:
1.1 root 853: #ifdef L_fixunsdfdi
1.1.1.4 root 854: #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
855: #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
1.1 root 856:
1.1.1.4 root 857: DItype
1.1 root 858: __fixunsdfdi (a)
1.1.1.4 root 859: DFtype a;
1.1 root 860: {
1.1.1.4 root 861: DFtype b;
862: UDItype v;
1.1 root 863:
864: if (a < 0)
865: return 0;
866:
867: /* Compute high word of result, as a flonum. */
868: b = (a / HIGH_WORD_COEFF);
1.1.1.4 root 869: /* Convert that to fixed (but not to DItype!),
1.1 root 870: and shift it into the high word. */
1.1.1.4 root 871: v = (USItype) b;
1.1 root 872: v <<= WORD_SIZE;
1.1.1.4 root 873: /* Remove high part from the DFtype, leaving the low part as flonum. */
874: a -= (DFtype)v;
875: /* Convert that to fixed (but not to DItype!) and add it in.
1.1 root 876: Sometimes A comes out negative. This is significant, since
877: A has more bits than a long int does. */
878: if (a < 0)
1.1.1.4 root 879: v -= (USItype) (- a);
1.1 root 880: else
1.1.1.4 root 881: v += (USItype) a;
1.1 root 882: return v;
883: }
884: #endif
885:
886: #ifdef L_fixdfdi
1.1.1.4 root 887: DItype
1.1 root 888: __fixdfdi (a)
1.1.1.4 root 889: DFtype a;
1.1 root 890: {
891: if (a < 0)
892: return - __fixunsdfdi (-a);
893: return __fixunsdfdi (a);
894: }
895: #endif
896:
897: #ifdef L_fixunssfdi
1.1.1.4 root 898: #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
899: #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
1.1 root 900:
1.1.1.4 root 901: DItype
902: __fixunssfdi (SFtype original_a)
1.1 root 903: {
1.1.1.4 root 904: /* Convert the SFtype to a DFtype, because that is surely not going
1.1 root 905: to lose any bits. Some day someone else can write a faster version
1.1.1.4 root 906: that avoids converting to DFtype, and verify it really works right. */
907: DFtype a = original_a;
908: DFtype b;
909: UDItype v;
1.1 root 910:
911: if (a < 0)
912: return 0;
913:
914: /* Compute high word of result, as a flonum. */
915: b = (a / HIGH_WORD_COEFF);
1.1.1.4 root 916: /* Convert that to fixed (but not to DItype!),
1.1 root 917: and shift it into the high word. */
1.1.1.4 root 918: v = (USItype) b;
1.1 root 919: v <<= WORD_SIZE;
1.1.1.4 root 920: /* Remove high part from the DFtype, leaving the low part as flonum. */
921: a -= (DFtype)v;
922: /* Convert that to fixed (but not to DItype!) and add it in.
1.1 root 923: Sometimes A comes out negative. This is significant, since
924: A has more bits than a long int does. */
925: if (a < 0)
1.1.1.4 root 926: v -= (USItype) (- a);
1.1 root 927: else
1.1.1.4 root 928: v += (USItype) a;
1.1 root 929: return v;
930: }
931: #endif
932:
933: #ifdef L_fixsfdi
1.1.1.4 root 934: DItype
935: __fixsfdi (SFtype a)
1.1 root 936: {
937: if (a < 0)
938: return - __fixunssfdi (-a);
939: return __fixunssfdi (a);
940: }
941: #endif
942:
1.1.1.5 root 943: #if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
944: #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
945: #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
946: #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
947:
948: XFtype
949: __floatdixf (u)
950: DItype u;
951: {
952: XFtype d;
953: SItype negate = 0;
954:
955: if (u < 0)
956: u = -u, negate = 1;
957:
958: d = (USItype) (u >> WORD_SIZE);
959: d *= HIGH_HALFWORD_COEFF;
960: d *= HIGH_HALFWORD_COEFF;
961: d += (USItype) (u & (HIGH_WORD_COEFF - 1));
962:
963: return (negate ? -d : d);
964: }
965: #endif
966:
1.1.1.4 root 967: #if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
968: #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
969: #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
970: #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
971:
972: TFtype
973: __floatditf (u)
974: DItype u;
975: {
976: TFtype d;
977: SItype negate = 0;
978:
979: if (u < 0)
980: u = -u, negate = 1;
981:
982: d = (USItype) (u >> WORD_SIZE);
983: d *= HIGH_HALFWORD_COEFF;
984: d *= HIGH_HALFWORD_COEFF;
985: d += (USItype) (u & (HIGH_WORD_COEFF - 1));
986:
987: return (negate ? -d : d);
988: }
989: #endif
990:
1.1 root 991: #ifdef L_floatdidf
1.1.1.4 root 992: #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
993: #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
994: #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
1.1 root 995:
1.1.1.4 root 996: DFtype
1.1 root 997: __floatdidf (u)
1.1.1.4 root 998: DItype u;
1.1 root 999: {
1.1.1.4 root 1000: DFtype d;
1001: SItype negate = 0;
1.1 root 1002:
1003: if (u < 0)
1004: u = -u, negate = 1;
1005:
1.1.1.4 root 1006: d = (USItype) (u >> WORD_SIZE);
1.1 root 1007: d *= HIGH_HALFWORD_COEFF;
1008: d *= HIGH_HALFWORD_COEFF;
1.1.1.4 root 1009: d += (USItype) (u & (HIGH_WORD_COEFF - 1));
1.1 root 1010:
1011: return (negate ? -d : d);
1012: }
1013: #endif
1014:
1015: #ifdef L_floatdisf
1.1.1.4 root 1016: #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
1017: #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
1018: #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
1.1.1.7 root 1019: #define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
1.1.1.8 ! root 1020:
! 1021: /* Define codes for all the float formats that we know of. Note
! 1022: that this is copied from real.h. */
! 1023:
! 1024: #define UNKNOWN_FLOAT_FORMAT 0
! 1025: #define IEEE_FLOAT_FORMAT 1
! 1026: #define VAX_FLOAT_FORMAT 2
! 1027: #define IBM_FLOAT_FORMAT 3
! 1028:
! 1029: /* Default to IEEE float if not specified. Nearly all machines use it. */
! 1030: #ifndef HOST_FLOAT_FORMAT
! 1031: #define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
! 1032: #endif
! 1033:
! 1034: #if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
1.1.1.7 root 1035: #define DF_SIZE 53
1036: #define SF_SIZE 24
1.1.1.8 ! root 1037: #endif
! 1038:
! 1039: #if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
1.1.1.7 root 1040: #define DF_SIZE 56
1041: #define SF_SIZE 24
1.1.1.8 ! root 1042: #endif
! 1043:
! 1044: #if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
1.1.1.7 root 1045: #define DF_SIZE 56
1046: #define SF_SIZE 24
1047: #endif
1.1 root 1048:
1.1.1.4 root 1049: SFtype
1.1 root 1050: __floatdisf (u)
1.1.1.4 root 1051: DItype u;
1.1 root 1052: {
1.1.1.5 root 1053: /* Do the calculation in DFmode
1054: so that we don't lose any of the precision of the high word
1055: while multiplying it. */
1056: DFtype f;
1.1.1.4 root 1057: SItype negate = 0;
1.1 root 1058:
1059: if (u < 0)
1060: u = -u, negate = 1;
1061:
1.1.1.7 root 1062: /* Protect against double-rounding error.
1063: Represent any low-order bits, that might be truncated in DFmode,
1064: by a bit that won't be lost. The bit can go in anywhere below the
1065: rounding position of the SFmode. A fixed mask and bit position
1066: handles all usual configurations. It doesn't handle the case
1067: of 128-bit DImode, however. */
1068: if (DF_SIZE < DI_SIZE
1069: && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1070: {
1071: #define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
1072: if (u >= ((UDItype) 1 << DF_SIZE))
1073: {
1074: if ((USItype) u & (REP_BIT - 1))
1075: u |= REP_BIT;
1076: }
1077: }
1.1.1.4 root 1078: f = (USItype) (u >> WORD_SIZE);
1.1 root 1079: f *= HIGH_HALFWORD_COEFF;
1080: f *= HIGH_HALFWORD_COEFF;
1.1.1.4 root 1081: f += (USItype) (u & (HIGH_WORD_COEFF - 1));
1.1 root 1082:
1.1.1.5 root 1083: return (SFtype) (negate ? -f : f);
1084: }
1085: #endif
1086:
1087: #if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
1.1.1.8 ! root 1088: /* Reenable the normal types, in case limits.h needs them. */
! 1089: #undef char
! 1090: #undef short
! 1091: #undef int
! 1092: #undef long
! 1093: #undef unsigned
! 1094: #undef float
! 1095: #undef double
! 1096: #undef MIN
! 1097: #undef MAX
! 1098: #include <limits.h>
1.1.1.5 root 1099:
1100: USItype
1101: __fixunsxfsi (a)
1102: XFtype a;
1103: {
1104: if (a >= - (DFtype) LONG_MIN)
1105: return (SItype) (a + LONG_MIN) - LONG_MIN;
1106: return (SItype) a;
1.1 root 1107: }
1108: #endif
1109:
1110: #ifdef L_fixunsdfsi
1.1.1.8 ! root 1111: /* Reenable the normal types, in case limits.h needs them. */
! 1112: #undef char
! 1113: #undef short
! 1114: #undef int
! 1115: #undef long
! 1116: #undef unsigned
! 1117: #undef float
! 1118: #undef double
! 1119: #undef MIN
! 1120: #undef MAX
! 1121: #include <limits.h>
1.1 root 1122:
1.1.1.4 root 1123: USItype
1.1 root 1124: __fixunsdfsi (a)
1.1.1.4 root 1125: DFtype a;
1.1 root 1126: {
1.1.1.4 root 1127: if (a >= - (DFtype) LONG_MIN)
1.1 root 1128: return (SItype) (a + LONG_MIN) - LONG_MIN;
1129: return (SItype) a;
1130: }
1131: #endif
1132:
1133: #ifdef L_fixunssfsi
1.1.1.8 ! root 1134: /* Reenable the normal types, in case limits.h needs them. */
! 1135: #undef char
! 1136: #undef short
! 1137: #undef int
! 1138: #undef long
! 1139: #undef unsigned
! 1140: #undef float
! 1141: #undef double
! 1142: #undef MIN
! 1143: #undef MAX
! 1144: #include <limits.h>
1.1 root 1145:
1.1.1.4 root 1146: USItype
1147: __fixunssfsi (SFtype a)
1.1 root 1148: {
1.1.1.4 root 1149: if (a >= - (SFtype) LONG_MIN)
1.1 root 1150: return (SItype) (a + LONG_MIN) - LONG_MIN;
1151: return (SItype) a;
1152: }
1153: #endif
1154:
1.1.1.4 root 1155: /* From here on down, the routines use normal data types. */
1156:
1157: #define SItype bogus_type
1158: #define USItype bogus_type
1159: #define DItype bogus_type
1160: #define UDItype bogus_type
1161: #define SFtype bogus_type
1162: #define DFtype bogus_type
1163:
1164: #undef char
1165: #undef short
1166: #undef int
1167: #undef long
1168: #undef unsigned
1169: #undef float
1170: #undef double
1171:
1172: #ifdef L__gcc_bcmp
1173:
1174: /* Like bcmp except the sign is meaningful.
1.1.1.8 ! root 1175: Result is negative if S1 is less than S2,
1.1.1.4 root 1176: positive if S1 is greater, 0 if S1 and S2 are equal. */
1177:
1178: int
1179: __gcc_bcmp (s1, s2, size)
1180: unsigned char *s1, *s2;
1181: size_t size;
1182: {
1183: while (size > 0)
1184: {
1185: unsigned char c1 = *s1++, c2 = *s2++;
1186: if (c1 != c2)
1187: return c1 - c2;
1188: size--;
1189: }
1190: return 0;
1191: }
1192:
1193: #endif
1194:
1.1 root 1195: #ifdef L_varargs
1196: #ifdef __i860__
1.1.1.4 root 1197: #if defined(__svr4__) || defined(__alliant__)
1.1 root 1198: asm (" .text");
1199: asm (" .align 4");
1200:
1.1.1.4 root 1201: /* The Alliant needs the added underscore. */
1.1 root 1202: asm (".globl __builtin_saveregs");
1203: asm ("__builtin_saveregs:");
1.1.1.4 root 1204: asm (".globl ___builtin_saveregs");
1205: asm ("___builtin_saveregs:");
1206:
1207: asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
1.1 root 1208: asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
1209: area and also for a new va_list
1210: structure */
1211: /* Save all argument registers in the arg reg save area. The
1212: arg reg save area must have the following layout (according
1213: to the svr4 ABI):
1214:
1215: struct {
1216: union {
1217: float freg[8];
1218: double dreg[4];
1219: } float_regs;
1220: long ireg[12];
1221: };
1222: */
1223:
1224: asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
1225: asm (" fst.q %f12,16(%sp)");
1226:
1227: asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
1228: asm (" st.l %r17,36(%sp)");
1229: asm (" st.l %r18,40(%sp)");
1230: asm (" st.l %r19,44(%sp)");
1231: asm (" st.l %r20,48(%sp)");
1232: asm (" st.l %r21,52(%sp)");
1233: asm (" st.l %r22,56(%sp)");
1234: asm (" st.l %r23,60(%sp)");
1235: asm (" st.l %r24,64(%sp)");
1236: asm (" st.l %r25,68(%sp)");
1237: asm (" st.l %r26,72(%sp)");
1238: asm (" st.l %r27,76(%sp)");
1239:
1240: asm (" adds 80,%sp,%r16"); /* compute the address of the new
1241: va_list structure. Put in into
1242: r16 so that it will be returned
1243: to the caller. */
1244:
1245: /* Initialize all fields of the new va_list structure. This
1246: structure looks like:
1247:
1248: typedef struct {
1249: unsigned long ireg_used;
1250: unsigned long freg_used;
1251: long *reg_base;
1252: long *mem_ptr;
1253: } va_list;
1254: */
1255:
1256: asm (" st.l %r0, 0(%r16)"); /* nfixed */
1257: asm (" st.l %r0, 4(%r16)"); /* nfloating */
1258: asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
1259: asm (" bri %r1"); /* delayed return */
1260: asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
1261:
1.1.1.5 root 1262: #else /* not __svr4__ */
1.1.1.6 root 1263: #if defined(__PARAGON__)
1264: /*
1265: * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1266: * and we stand a better chance of hooking into libraries
1267: * compiled by PGI. [[email protected]]
1268: */
1269: asm (" .text");
1270: asm (" .align 4");
1271: asm (".globl __builtin_saveregs");
1272: asm ("__builtin_saveregs:");
1273: asm (".globl ___builtin_saveregs");
1274: asm ("___builtin_saveregs:");
1275:
1276: asm (" andnot 0x0f,sp,sp"); /* round down to 16-byte boundary */
1277: asm (" adds -96,sp,sp"); /* allocate stack space for reg save
1278: area and also for a new va_list
1279: structure */
1280: /* Save all argument registers in the arg reg save area. The
1281: arg reg save area must have the following layout (according
1282: to the svr4 ABI):
1283:
1284: struct {
1285: union {
1286: float freg[8];
1287: double dreg[4];
1288: } float_regs;
1289: long ireg[12];
1290: };
1291: */
1292:
1293: asm (" fst.q f8, 0(sp)");
1294: asm (" fst.q f12,16(sp)");
1295: asm (" st.l r16,32(sp)");
1296: asm (" st.l r17,36(sp)");
1297: asm (" st.l r18,40(sp)");
1298: asm (" st.l r19,44(sp)");
1299: asm (" st.l r20,48(sp)");
1300: asm (" st.l r21,52(sp)");
1301: asm (" st.l r22,56(sp)");
1302: asm (" st.l r23,60(sp)");
1303: asm (" st.l r24,64(sp)");
1304: asm (" st.l r25,68(sp)");
1305: asm (" st.l r26,72(sp)");
1306: asm (" st.l r27,76(sp)");
1307:
1308: asm (" adds 80,sp,r16"); /* compute the address of the new
1309: va_list structure. Put in into
1310: r16 so that it will be returned
1311: to the caller. */
1312:
1313: /* Initialize all fields of the new va_list structure. This
1314: structure looks like:
1315:
1316: typedef struct {
1317: unsigned long ireg_used;
1318: unsigned long freg_used;
1319: long *reg_base;
1320: long *mem_ptr;
1321: } va_list;
1322: */
1323:
1324: asm (" st.l r0, 0(r16)"); /* nfixed */
1325: asm (" st.l r0, 4(r16)"); /* nfloating */
1326: asm (" st.l sp, 8(r16)"); /* __va_ctl points to __va_struct. */
1327: asm (" bri r1"); /* delayed return */
1328: asm (" st.l r28,12(r16)"); /* pointer to overflow args */
1329: #else /* not __PARAGON__ */
1.1 root 1330: asm (" .text");
1331: asm (" .align 4");
1332:
1333: asm (".globl ___builtin_saveregs");
1334: asm ("___builtin_saveregs:");
1335: asm (" mov sp,r30");
1336: asm (" andnot 0x0f,sp,sp");
1337: asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
1338:
1339: /* Fill in the __va_struct. */
1340: asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
1341: asm (" st.l r17, 4(sp)"); /* int fixed[12] */
1342: asm (" st.l r18, 8(sp)");
1343: asm (" st.l r19,12(sp)");
1344: asm (" st.l r20,16(sp)");
1345: asm (" st.l r21,20(sp)");
1346: asm (" st.l r22,24(sp)");
1347: asm (" st.l r23,28(sp)");
1348: asm (" st.l r24,32(sp)");
1349: asm (" st.l r25,36(sp)");
1350: asm (" st.l r26,40(sp)");
1351: asm (" st.l r27,44(sp)");
1352:
1353: asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
1354: asm (" fst.q f12,64(sp)"); /* int floating[8] */
1355:
1356: /* Fill in the __va_ctl. */
1357: asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
1358: asm (" st.l r28,84(sp)"); /* pointer to more args */
1359: asm (" st.l r0, 88(sp)"); /* nfixed */
1360: asm (" st.l r0, 92(sp)"); /* nfloating */
1361:
1362: asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
1363: asm (" bri r1");
1364: asm (" mov r30,sp");
1365: /* recover stack and pass address to start
1366: of data. */
1.1.1.6 root 1367: #endif /* not __PARAGON__ */
1.1.1.5 root 1368: #endif /* not __svr4__ */
1.1 root 1369: #else /* not __i860__ */
1370: #ifdef __sparc__
1.1.1.2 root 1371: asm (".global __builtin_saveregs");
1372: asm ("__builtin_saveregs:");
1.1 root 1373: asm (".global ___builtin_saveregs");
1374: asm ("___builtin_saveregs:");
1.1.1.3 root 1375: #ifdef NEED_PROC_COMMAND
1376: asm (".proc 020");
1.1.1.2 root 1377: #endif
1.1 root 1378: asm ("st %i0,[%fp+68]");
1379: asm ("st %i1,[%fp+72]");
1380: asm ("st %i2,[%fp+76]");
1381: asm ("st %i3,[%fp+80]");
1382: asm ("st %i4,[%fp+84]");
1383: asm ("retl");
1384: asm ("st %i5,[%fp+88]");
1.1.1.3 root 1385: #ifdef NEED_TYPE_COMMAND
1386: asm (".type __builtin_saveregs,#function");
1387: asm (".size __builtin_saveregs,.-__builtin_saveregs");
1388: #endif
1.1 root 1389: #else /* not __sparc__ */
1390: #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1391:
1392: asm (" .text");
1393: asm (" .ent __builtin_saveregs");
1394: asm (" .globl __builtin_saveregs");
1395: asm ("__builtin_saveregs:");
1396: asm (" sw $4,0($30)");
1397: asm (" sw $5,4($30)");
1398: asm (" sw $6,8($30)");
1399: asm (" sw $7,12($30)");
1400: asm (" j $31");
1401: asm (" .end __builtin_saveregs");
1402: #else /* not __mips__, etc. */
1.1.1.7 root 1403:
1404: void *
1.1 root 1405: __builtin_saveregs ()
1406: {
1407: abort ();
1408: }
1.1.1.7 root 1409:
1.1 root 1410: #endif /* not __mips__ */
1411: #endif /* not __sparc__ */
1412: #endif /* not __i860__ */
1413: #endif
1414:
1415: #ifdef L_eprintf
1.1.1.5 root 1416: #ifndef inhibit_libc
1.1.1.4 root 1417:
1.1 root 1418: #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1419: #include <stdio.h>
1420: /* This is used by the `assert' macro. */
1421: void
1422: __eprintf (string, expression, line, filename)
1.1.1.3 root 1423: const char *string;
1424: const char *expression;
1.1 root 1425: int line;
1.1.1.3 root 1426: const char *filename;
1.1 root 1427: {
1428: fprintf (stderr, string, expression, line, filename);
1429: fflush (stderr);
1430: abort ();
1431: }
1.1.1.4 root 1432:
1433: #endif
1.1 root 1434: #endif
1435:
1436: #ifdef L_bb
1437:
1.1.1.6 root 1438: /* Structure emitted by -a */
1.1 root 1439: struct bb
1440: {
1.1.1.6 root 1441: long zero_word;
1442: const char *filename;
1443: long *counts;
1444: long ncounts;
1445: struct bb *next;
1446: const unsigned long *addresses;
1447:
1448: /* Older GCC's did not emit these fields. */
1449: long nwords;
1450: const char **functions;
1451: const long *line_nums;
1452: const char **filenames;
1.1 root 1453: };
1454:
1.1.1.6 root 1455: #ifdef BLOCK_PROFILER_CODE
1456: BLOCK_PROFILER_CODE
1457: #else
1458: #ifndef inhibit_libc
1459:
1460: /* Simple minded basic block profiling output dumper for
1.1.1.8 ! root 1461: systems that don't provide tcov support. At present,
1.1.1.6 root 1462: it requires atexit and stdio. */
1463:
1464: #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1465: #include <stdio.h>
1.1.1.7 root 1466: char *ctime ();
1.1.1.6 root 1467:
1468: #ifdef HAVE_ATEXIT
1.1.1.8 ! root 1469: #ifdef WINNT
! 1470: extern int atexit (void (*) (void));
! 1471: #else
1.1.1.6 root 1472: extern void atexit (void (*) (void));
1.1.1.8 ! root 1473: #endif
1.1.1.6 root 1474: #define ON_EXIT(FUNC,ARG) atexit ((FUNC))
1475: #else
1476: #ifdef sun
1477: extern void on_exit (void*, void*);
1478: #define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
1479: #endif
1480: #endif
1.1 root 1481:
1.1.1.8 ! root 1482: static struct bb *bb_head;
1.1.1.6 root 1483:
1484: /* Return the number of digits needed to print a value */
1485: /* __inline__ */ static int num_digits (long value, int base)
1.1 root 1486: {
1.1.1.6 root 1487: int minus = (value < 0 && base != 16);
1488: unsigned long v = (minus) ? -value : value;
1489: int ret = minus;
1.1 root 1490:
1.1.1.6 root 1491: do
1492: {
1493: v /= base;
1494: ret++;
1495: }
1496: while (v);
1497:
1498: return ret;
1.1 root 1499: }
1500:
1.1.1.6 root 1501: void
1502: __bb_exit_func (void)
1503: {
1504: FILE *file = fopen ("bb.out", "a");
1505: long time_value;
1506:
1507: if (!file)
1508: perror ("bb.out");
1509:
1510: else
1511: {
1512: struct bb *ptr;
1513:
1514: /* This is somewhat type incorrect, but it avoids worrying about
1515: exactly where time.h is included from. It should be ok unless
1516: a void * differs from other pointer formats, or if sizeof(long)
1517: is < sizeof (time_t). It would be nice if we could assume the
1518: use of rationale standards here. */
1519:
1520: time((void *) &time_value);
1521: fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1522:
1523: /* We check the length field explicitly in order to allow compatibility
1524: with older GCC's which did not provide it. */
1525:
1526: for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
1527: {
1528: int i;
1529: int func_p = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
1530: int line_p = (func_p && ptr->line_nums);
1531: int file_p = (func_p && ptr->filenames);
1532: long ncounts = ptr->ncounts;
1533: long cnt_max = 0;
1534: long line_max = 0;
1535: long addr_max = 0;
1536: int file_len = 0;
1537: int func_len = 0;
1538: int blk_len = num_digits (ncounts, 10);
1539: int cnt_len;
1540: int line_len;
1541: int addr_len;
1542:
1543: fprintf (file, "File %s, %ld basic blocks \n\n",
1544: ptr->filename, ncounts);
1545:
1546: /* Get max values for each field. */
1547: for (i = 0; i < ncounts; i++)
1548: {
1549: const char *p;
1550: int len;
1551:
1552: if (cnt_max < ptr->counts[i])
1553: cnt_max = ptr->counts[i];
1554:
1555: if (addr_max < ptr->addresses[i])
1556: addr_max = ptr->addresses[i];
1557:
1558: if (line_p && line_max < ptr->line_nums[i])
1559: line_max = ptr->line_nums[i];
1560:
1561: if (func_p)
1562: {
1563: p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1564: len = strlen (p);
1565: if (func_len < len)
1566: func_len = len;
1567: }
1568:
1569: if (file_p)
1570: {
1571: p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1572: len = strlen (p);
1573: if (file_len < len)
1574: file_len = len;
1575: }
1576: }
1577:
1578: addr_len = num_digits (addr_max, 16);
1579: cnt_len = num_digits (cnt_max, 10);
1580: line_len = num_digits (line_max, 10);
1581:
1582: /* Now print out the basic block information. */
1583: for (i = 0; i < ncounts; i++)
1584: {
1585: fprintf (file,
1586: " Block #%*d: executed %*ld time(s) address= 0x%.*lx",
1587: blk_len, i+1,
1588: cnt_len, ptr->counts[i],
1589: addr_len, ptr->addresses[i]);
1590:
1591: if (func_p)
1592: fprintf (file, " function= %-*s", func_len,
1593: (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1594:
1595: if (line_p)
1596: fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1597:
1598: if (file_p)
1599: fprintf (file, " file= %s",
1600: (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1601:
1602: fprintf (file, "\n");
1603: }
1604:
1605: fprintf (file, "\n");
1606: fflush (file);
1607: }
1608:
1609: fprintf (file, "\n\n");
1610: fclose (file);
1611: }
1612: }
1613:
1614: void
1615: __bb_init_func (struct bb *blocks)
1616: {
1617: /* User is supposed to check whether the first word is non-0,
1618: but just in case.... */
1619:
1620: if (blocks->zero_word)
1621: return;
1622:
1623: #ifdef ON_EXIT
1624: /* Initialize destructor. */
1625: if (!bb_head)
1626: ON_EXIT (__bb_exit_func, 0);
1.1 root 1627: #endif
1.1.1.6 root 1628:
1629: /* Set up linked list. */
1630: blocks->zero_word = 1;
1631: blocks->next = bb_head;
1632: bb_head = blocks;
1633: }
1634:
1635: #endif /* not inhibit_libc */
1636: #endif /* not BLOCK_PROFILER_CODE */
1637: #endif /* L_bb */
1.1 root 1638:
1.1.1.7 root 1639: /* Default free-store management functions for C++, per sections 12.5 and
1640: 17.3.3 of the Working Paper. */
1.1 root 1641:
1.1.1.5 root 1642: #ifdef L_op_new
1.1.1.7 root 1643: /* operator new (size_t), described in 17.3.3.5. This function is used by
1644: C++ programs to allocate a block of memory to hold a single object. */
1.1 root 1645:
1.1.1.7 root 1646: typedef void (*vfp)(void);
1.1 root 1647: extern vfp __new_handler;
1.1.1.8 ! root 1648: extern void __default_new_handler (void);
1.1 root 1649:
1.1.1.8 ! root 1650: #ifdef WEAK_ALIAS
! 1651: void * __builtin_new (size_t sz)
! 1652: __attribute__ ((weak, alias ("___builtin_new")));
! 1653: void *
! 1654: ___builtin_new (size_t sz)
! 1655: #else
1.1 root 1656: void *
1.1.1.5 root 1657: __builtin_new (size_t sz)
1.1.1.8 ! root 1658: #endif
1.1 root 1659: {
1660: void *p;
1.1.1.8 ! root 1661: vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
1.1 root 1662:
1.1.1.4 root 1663: /* malloc (0) is unpredictable; avoid it. */
1664: if (sz == 0)
1665: sz = 1;
1666: p = (void *) malloc (sz);
1.1.1.7 root 1667: while (p == 0)
1668: {
1.1.1.8 ! root 1669: (*handler) ();
1.1.1.7 root 1670: p = (void *) malloc (sz);
1671: }
1672:
1.1 root 1673: return p;
1674: }
1.1.1.5 root 1675: #endif /* L_op_new */
1.1 root 1676:
1.1.1.7 root 1677: #ifdef L_op_vnew
1678: /* void * operator new [] (size_t), described in 17.3.3.6. This function
1679: is used by C++ programs to allocate a block of memory for an array. */
1680:
1681: extern void * __builtin_new (size_t);
1682:
1.1.1.8 ! root 1683: #ifdef WEAK_ALIAS
! 1684: void * __builtin_vec_new (size_t sz)
! 1685: __attribute__ ((weak, alias ("___builtin_vec_new")));
! 1686: void *
! 1687: ___builtin_vec_new (size_t sz)
! 1688: #else
1.1.1.7 root 1689: void *
1690: __builtin_vec_new (size_t sz)
1.1.1.8 ! root 1691: #endif
1.1.1.7 root 1692: {
1693: return __builtin_new (sz);
1694: }
1695: #endif /* L_op_vnew */
1696:
1.1.1.5 root 1697: #ifdef L_new_handler
1.1.1.7 root 1698: /* set_new_handler (fvoid_t *) and the default new handler, described in
1699: 17.3.3.2 and 17.3.3.5. These functions define the result of a failure
1700: to allocate the amount of memory requested from operator new or new []. */
1.1.1.4 root 1701:
1.1.1.5 root 1702: #ifndef inhibit_libc
1.1.1.4 root 1703: /* This gets us __GNU_LIBRARY__. */
1704: #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1705: #include <stdio.h>
1706:
1707: #ifdef __GNU_LIBRARY__
1708: /* Avoid forcing the library's meaning of `write' on the user program
1709: by using the "internal" name (for use within the library) */
1710: #define write(fd, buf, n) __write((fd), (buf), (n))
1711: #endif
1.1.1.5 root 1712: #endif /* inhibit_libc */
1.1.1.4 root 1713:
1.1 root 1714: typedef void (*vfp)(void);
1.1.1.7 root 1715: void __default_new_handler (void);
1.1 root 1716:
1.1.1.8 ! root 1717: vfp __new_handler = (vfp)0;
1.1 root 1718:
1719: vfp
1.1.1.7 root 1720: set_new_handler (vfp handler)
1.1 root 1721: {
1722: vfp prev_handler;
1723:
1724: prev_handler = __new_handler;
1.1.1.7 root 1725: if (handler == 0) handler = __default_new_handler;
1.1 root 1726: __new_handler = handler;
1727: return prev_handler;
1728: }
1729:
1.1.1.3 root 1730: #define MESSAGE "Virtual memory exceeded in `new'\n"
1731:
1.1.1.7 root 1732: void
1733: __default_new_handler ()
1.1 root 1734: {
1.1.1.8 ! root 1735: #ifndef inhibit_libc
1.1 root 1736: /* don't use fprintf (stderr, ...) because it may need to call malloc. */
1737: /* This should really print the name of the program, but that is hard to
1738: do. We need a standard, clean way to get at the name. */
1.1.1.3 root 1739: write (2, MESSAGE, sizeof (MESSAGE));
1.1.1.8 ! root 1740: #endif
1.1 root 1741: /* don't call exit () because that may call global destructors which
1742: may cause a loop. */
1743: _exit (-1);
1744: }
1745: #endif
1746:
1.1.1.5 root 1747: #ifdef L_op_delete
1.1.1.7 root 1748: /* operator delete (void *), described in 17.3.3.3. This function is used
1749: by C++ programs to return to the free store a block of memory allocated
1750: as a single object. */
1751:
1.1.1.8 ! root 1752: #ifdef WEAK_ALIAS
! 1753: void __builtin_delete (void *ptr)
! 1754: __attribute__ ((weak, alias ("___builtin_delete")));
! 1755: void
! 1756: ___builtin_delete (void *ptr)
! 1757: #else
1.1 root 1758: void
1.1.1.5 root 1759: __builtin_delete (void *ptr)
1.1.1.8 ! root 1760: #endif
1.1 root 1761: {
1762: if (ptr)
1763: free (ptr);
1764: }
1765: #endif
1.1.1.7 root 1766:
1767: #ifdef L_op_vdel
1768: /* operator delete [] (void *), described in 17.3.3.4. This function is
1769: used by C++ programs to return to the free store a block of memory
1770: allocated as an array. */
1771:
1772: extern void __builtin_delete (void *);
1773:
1.1.1.8 ! root 1774: #ifdef WEAK_ALIAS
! 1775: void __builtin_vec_delete (void *ptr)
! 1776: __attribute__ ((weak, alias ("___builtin_vec_delete")));
! 1777: void
! 1778: ___builtin_vec_delete (void *ptr)
! 1779: #else
1.1.1.7 root 1780: void
1781: __builtin_vec_delete (void *ptr)
1.1.1.8 ! root 1782: #endif
1.1.1.7 root 1783: {
1784: __builtin_delete (ptr);
1785: }
1786: #endif
1787:
1788: /* End of C++ free-store management functions */
1.1.1.5 root 1789:
1.1 root 1790: #ifdef L_shtab
1791: unsigned int __shtab[] = {
1792: 0x00000001, 0x00000002, 0x00000004, 0x00000008,
1793: 0x00000010, 0x00000020, 0x00000040, 0x00000080,
1794: 0x00000100, 0x00000200, 0x00000400, 0x00000800,
1795: 0x00001000, 0x00002000, 0x00004000, 0x00008000,
1796: 0x00010000, 0x00020000, 0x00040000, 0x00080000,
1797: 0x00100000, 0x00200000, 0x00400000, 0x00800000,
1798: 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1799: 0x10000000, 0x20000000, 0x40000000, 0x80000000
1800: };
1801: #endif
1802:
1803: #ifdef L_clear_cache
1804: /* Clear part of an instruction cache. */
1805:
1806: #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1807:
1808: void
1809: __clear_cache (beg, end)
1810: char *beg, *end;
1811: {
1.1.1.6 root 1812: #ifdef CLEAR_INSN_CACHE
1813: CLEAR_INSN_CACHE (beg, end);
1814: #else
1.1 root 1815: #ifdef INSN_CACHE_SIZE
1816: static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1.1.1.8 ! root 1817: static int initialized;
1.1 root 1818: int offset;
1.1.1.3 root 1819: void *start_addr
1820: void *end_addr;
1.1 root 1821: typedef (*function_ptr) ();
1822:
1823: #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1824: /* It's cheaper to clear the whole cache.
1825: Put in a series of jump instructions so that calling the beginning
1826: of the cache will clear the whole thing. */
1827:
1828: if (! initialized)
1829: {
1830: int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1831: & -INSN_CACHE_LINE_WIDTH);
1832: int end_ptr = ptr + INSN_CACHE_SIZE;
1833:
1834: while (ptr < end_ptr)
1835: {
1836: *(INSTRUCTION_TYPE *)ptr
1837: = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1838: ptr += INSN_CACHE_LINE_WIDTH;
1839: }
1840: *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1841:
1842: initialized = 1;
1843: }
1844:
1845: /* Call the beginning of the sequence. */
1846: (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1847: & -INSN_CACHE_LINE_WIDTH))
1848: ());
1849:
1850: #else /* Cache is large. */
1851:
1852: if (! initialized)
1853: {
1854: int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1855: & -INSN_CACHE_LINE_WIDTH);
1856:
1857: while (ptr < (int) array + sizeof array)
1858: {
1859: *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1860: ptr += INSN_CACHE_LINE_WIDTH;
1861: }
1862:
1863: initialized = 1;
1864: }
1865:
1866: /* Find the location in array that occupies the same cache line as BEG. */
1867:
1868: offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1869: start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1870: & -INSN_CACHE_PLANE_SIZE)
1871: + offset);
1872:
1873: /* Compute the cache alignment of the place to stop clearing. */
1874: #if 0 /* This is not needed for gcc's purposes. */
1875: /* If the block to clear is bigger than a cache plane,
1876: we clear the entire cache, and OFFSET is already correct. */
1877: if (end < beg + INSN_CACHE_PLANE_SIZE)
1878: #endif
1879: offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1880: & -INSN_CACHE_LINE_WIDTH)
1881: & (INSN_CACHE_PLANE_SIZE - 1));
1882:
1883: #if INSN_CACHE_DEPTH > 1
1884: end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1885: if (end_addr <= start_addr)
1886: end_addr += INSN_CACHE_PLANE_SIZE;
1887:
1888: for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1889: {
1890: int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1891: int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1892:
1893: while (addr != stop)
1894: {
1895: /* Call the return instruction at ADDR. */
1896: ((function_ptr) addr) ();
1897:
1898: addr += INSN_CACHE_LINE_WIDTH;
1899: }
1900: }
1901: #else /* just one plane */
1902: do
1903: {
1904: /* Call the return instruction at START_ADDR. */
1905: ((function_ptr) start_addr) ();
1906:
1907: start_addr += INSN_CACHE_LINE_WIDTH;
1908: }
1909: while ((start_addr % INSN_CACHE_SIZE) != offset);
1910: #endif /* just one plane */
1911: #endif /* Cache is large */
1912: #endif /* Cache exists */
1.1.1.6 root 1913: #endif /* CLEAR_INSN_CACHE */
1.1 root 1914: }
1915:
1916: #endif /* L_clear_cache */
1917:
1918: #ifdef L_trampoline
1919:
1920: /* Jump to a trampoline, loading the static chain address. */
1921:
1.1.1.8 ! root 1922: #ifdef WINNT
! 1923:
! 1924: long getpagesize()
! 1925: {
! 1926: #ifdef _ALPHA_
! 1927: return 8192;
! 1928: #else
! 1929: return 4096;
! 1930: #endif
! 1931: }
! 1932:
! 1933: int mprotect(addr, len, prot)
! 1934: char *addr;
! 1935: int len, prot;
! 1936: {
! 1937: int np, op;
! 1938:
! 1939: if (prot == 7) np = 0x40;
! 1940: else if (prot == 5) np = 0x20;
! 1941: else if (prot == 4) np = 0x10;
! 1942: else if (prot == 3) np = 0x04;
! 1943: else if (prot == 1) np = 0x02;
! 1944: else if (prot == 0) np = 0x01;
! 1945:
! 1946: if (VirtualProtect (addr, len, np, &op))
! 1947: return 0;
! 1948: else
! 1949: return -1;
! 1950:
! 1951: }
! 1952:
! 1953: #endif
! 1954:
1.1 root 1955: #ifdef TRANSFER_FROM_TRAMPOLINE
1956: TRANSFER_FROM_TRAMPOLINE
1957: #endif
1958:
1.1.1.6 root 1959: #if defined (NeXT) && defined (__MACH__)
1960:
1961: /* Make stack executable so we can call trampolines on stack.
1962: This is called from INITIALIZE_TRAMPOLINE in next.h. */
1.1.1.7 root 1963: #ifdef NeXTStep21
1964: #include <mach.h>
1965: #else
1966: #include <mach/mach.h>
1967: #endif
1.1.1.6 root 1968:
1969: void
1970: __enable_execute_stack (addr)
1971: char *addr;
1972: {
1973: kern_return_t r;
1974: char *eaddr = addr + TRAMPOLINE_SIZE;
1975: vm_address_t a = (vm_address_t) addr;
1976:
1977: /* turn on execute access on stack */
1978: r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
1979: if (r != KERN_SUCCESS)
1980: {
1981: mach_error("vm_protect VM_PROT_ALL", r);
1982: exit(1);
1983: }
1984:
1985: /* We inline the i-cache invalidation for speed */
1986:
1987: #ifdef CLEAR_INSN_CACHE
1988: CLEAR_INSN_CACHE (addr, eaddr);
1989: #else
1990: __clear_cache ((int) addr, (int) eaddr);
1991: #endif
1992: }
1993:
1994: #endif /* defined (NeXT) && defined (__MACH__) */
1995:
1.1 root 1996: #ifdef __convex__
1997:
1998: /* Make stack executable so we can call trampolines on stack.
1999: This is called from INITIALIZE_TRAMPOLINE in convex.h. */
2000:
2001: #include <sys/mman.h>
2002: #include <sys/vmparam.h>
2003: #include <machine/machparam.h>
2004:
2005: void
2006: __enable_execute_stack ()
2007: {
2008: int fp;
2009: static unsigned lowest = USRSTACK;
2010: unsigned current = (unsigned) &fp & -NBPG;
2011:
2012: if (lowest > current)
2013: {
2014: unsigned len = lowest - current;
2015: mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2016: lowest = current;
2017: }
2018:
2019: /* Clear instruction cache in case an old trampoline is in it. */
2020: asm ("pich");
2021: }
2022: #endif /* __convex__ */
1.1.1.2 root 2023:
1.1.1.6 root 2024: #ifdef __DOLPHIN__
2025:
2026: /* Modified from the convex -code above. */
2027:
2028: #include <sys/param.h>
2029: #include <errno.h>
2030: #include <sys/m88kbcs.h>
2031:
2032: void
2033: __enable_execute_stack ()
2034: {
2035: int save_errno;
2036: static unsigned long lowest = USRSTACK;
2037: unsigned long current = (unsigned long) &save_errno & -NBPC;
2038:
2039: /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2040: address is seen as 'negative'. That is the case with the stack. */
2041:
2042: save_errno=errno;
2043: if (lowest > current)
2044: {
2045: unsigned len=lowest-current;
2046: memctl(current,len,MCT_TEXT);
2047: lowest = current;
2048: }
2049: else
2050: memctl(current,NBPC,MCT_TEXT);
2051: errno=save_errno;
2052: }
2053:
2054: #endif /* __DOLPHIN__ */
2055:
1.1.1.2 root 2056: #ifdef __pyr__
2057:
1.1.1.4 root 2058: #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1.1.1.2 root 2059: #include <stdio.h>
2060: #include <sys/mman.h>
2061: #include <sys/types.h>
2062: #include <sys/param.h>
2063: #include <sys/vmmac.h>
2064:
2065: /* Modified from the convex -code above.
2066: mremap promises to clear the i-cache. */
2067:
2068: void
2069: __enable_execute_stack ()
2070: {
2071: int fp;
2072: if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2073: PROT_READ|PROT_WRITE|PROT_EXEC))
2074: {
2075: perror ("mprotect in __enable_execute_stack");
2076: fflush (stderr);
2077: abort ();
2078: }
2079: }
2080: #endif /* __pyr__ */
1.1 root 2081: #endif /* L_trampoline */
2082:
2083: #ifdef L__main
2084:
2085: #include "gbl-ctors.h"
1.1.1.6 root 2086: /* Some systems use __main in a way incompatible with its use in gcc, in these
2087: cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2088: give the same symbol without quotes for an alternative entry point. You
1.1.1.8 ! root 2089: must define both, or neither. */
1.1.1.6 root 2090: #ifndef NAME__MAIN
2091: #define NAME__MAIN "__main"
2092: #define SYMBOL__MAIN __main
2093: #endif
1.1 root 2094:
1.1.1.8 ! root 2095: #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
1.1 root 2096: /* Run all the global destructors on exit from the program. */
2097:
2098: void
2099: __do_global_dtors ()
2100: {
2101: #ifdef DO_GLOBAL_DTORS_BODY
2102: DO_GLOBAL_DTORS_BODY;
2103: #else
1.1.1.7 root 2104: func_ptr *p;
2105: for (p = __DTOR_LIST__ + 1; *p; )
2106: (*p++) ();
1.1 root 2107: #endif
2108: }
1.1.1.8 ! root 2109: #endif
1.1 root 2110:
2111: #ifndef INIT_SECTION_ASM_OP
2112: /* Run all the global constructors on entry to the program. */
2113:
1.1.1.2 root 2114: #ifndef ON_EXIT
1.1 root 2115: #define ON_EXIT(a, b)
2116: #else
2117: /* Make sure the exit routine is pulled in to define the globals as
2118: bss symbols, just in case the linker does not automatically pull
2119: bss definitions from the library. */
2120:
2121: extern int _exit_dummy_decl;
2122: int *_exit_dummy_ref = &_exit_dummy_decl;
2123: #endif /* ON_EXIT */
2124:
2125: void
2126: __do_global_ctors ()
2127: {
2128: DO_GLOBAL_CTORS_BODY;
1.1.1.2 root 2129: ON_EXIT (__do_global_dtors, 0);
1.1 root 2130: }
1.1.1.2 root 2131: #endif /* no INIT_SECTION_ASM_OP */
1.1 root 2132:
1.1.1.2 root 2133: #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
1.1 root 2134: /* Subroutine called automatically by `main'.
2135: Compiling a global function named `main'
2136: produces an automatic call to this function at the beginning.
2137:
2138: For many systems, this routine calls __do_global_ctors.
2139: For systems which support a .init section we use the .init section
2140: to run __do_global_ctors, so we need not do anything here. */
2141:
2142: void
1.1.1.6 root 2143: SYMBOL__MAIN ()
1.1 root 2144: {
2145: /* Support recursive calls to `main': run initializers just once. */
1.1.1.8 ! root 2146: static int initialized;
1.1 root 2147: if (! initialized)
2148: {
2149: initialized = 1;
2150: __do_global_ctors ();
2151: }
2152: }
1.1.1.2 root 2153: #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
1.1 root 2154:
2155: #endif /* L__main */
2156:
1.1.1.4 root 2157: #ifdef L_ctors
1.1 root 2158:
2159: #include "gbl-ctors.h"
2160:
2161: /* Provide default definitions for the lists of constructors and
2162: destructors, so that we don't get linker errors. These symbols are
2163: intentionally bss symbols, so that gld and/or collect will provide
2164: the right values. */
2165:
2166: /* We declare the lists here with two elements each,
2167: so that they are valid empty lists if no other definition is loaded. */
1.1.1.2 root 2168: #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
1.1.1.8 ! root 2169: #if defined(__NeXT__) || defined(_AIX)
1.1.1.4 root 2170: /* After 2.3, try this definition on all systems. */
2171: func_ptr __CTOR_LIST__[2] = {0, 0};
2172: func_ptr __DTOR_LIST__[2] = {0, 0};
2173: #else
1.1 root 2174: func_ptr __CTOR_LIST__[2];
2175: func_ptr __DTOR_LIST__[2];
1.1.1.4 root 2176: #endif
1.1.1.2 root 2177: #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
1.1.1.4 root 2178: #endif /* L_ctors */
2179:
2180: #ifdef L_exit
2181:
2182: #include "gbl-ctors.h"
1.1 root 2183:
2184: #ifndef ON_EXIT
2185:
2186: /* If we have no known way of registering our own __do_global_dtors
2187: routine so that it will be invoked at program exit time, then we
2188: have to define our own exit routine which will get this to happen. */
2189:
2190: extern void __do_global_dtors ();
2191: extern void _cleanup ();
1.1.1.6 root 2192: extern void _exit () __attribute__ ((noreturn));
1.1 root 2193:
2194: void
2195: exit (status)
2196: int status;
2197: {
1.1.1.8 ! root 2198: #if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
1.1 root 2199: __do_global_dtors ();
1.1.1.8 ! root 2200: #endif
1.1 root 2201: #ifdef EXIT_BODY
2202: EXIT_BODY;
2203: #else
2204: _cleanup ();
2205: #endif
2206: _exit (status);
2207: }
2208:
2209: #else
2210: int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
2211: #endif
2212:
2213: #endif /* L_exit */
2214:
1.1.1.7 root 2215: #ifdef L_eh
2216: typedef struct {
2217: void *start;
2218: void *end;
2219: void *exception_handler;
2220: } exception_table;
2221:
2222: struct exception_table_node {
2223: exception_table *table;
2224: void *start;
2225: void *end;
2226: struct exception_table_node *next;
2227: };
2228:
1.1.1.8 ! root 2229: static int except_table_pos;
! 2230: static void *except_pc;
! 2231: static struct exception_table_node *exception_table_list;
1.1.1.7 root 2232:
2233: static exception_table *
2234: find_exception_table (pc)
2235: void* pc;
2236: {
2237: register struct exception_table_node *table = exception_table_list;
2238: for ( ; table != 0; table = table->next)
2239: {
2240: if (table->start <= pc && table->end > pc)
2241: return table->table;
2242: }
2243: return 0;
2244: }
2245:
2246: /* this routine takes a pc, and the address of the exception handler associated
2247: with the closest exception table handler entry associated with that PC,
2248: or 0 if there are no table entries the PC fits in. The algorithm works
2249: something like this:
2250:
2251: while(current_entry exists) {
2252: if(current_entry.start < pc )
2253: current_entry = next_entry;
2254: else {
2255: if(prev_entry.start <= pc && prev_entry.end > pc) {
2256: save pointer to prev_entry;
2257: return prev_entry.exception_handler;
2258: }
2259: else return 0;
2260: }
2261: }
2262: return 0;
2263:
2264: Assuming a correctly sorted table (ascending order) this routine should
1.1.1.8 ! root 2265: return the tightest match...
1.1.1.7 root 2266:
2267: In the advent of a tie, we have to give the last entry, as it represents
2268: an inner block.
2269: */
2270:
2271:
2272: void *
2273: __find_first_exception_table_match(pc)
2274: void *pc;
2275: {
2276: exception_table *table = find_exception_table (pc);
2277: int pos = 0;
2278: int best = 0;
2279: if (table == 0)
2280: return (void*)0;
2281: #if 0
2282: printf("find_first_exception_table_match(): pc = %x!\n",pc);
2283: #endif
2284:
2285: except_pc = pc;
2286:
2287: #if 0
2288: /* We can't do this yet, as we don't know that the table is sorted. */
2289: do {
2290: ++pos;
2291: if (table[pos].start > except_pc)
2292: /* found the first table[pos].start > except_pc, so the previous
2293: entry better be the one we want! */
2294: break;
2295: } while(table[pos].exception_handler != (void*)-1);
2296:
2297: --pos;
2298: if (table[pos].start <= except_pc && table[pos].end > except_pc)
2299: {
2300: except_table_pos = pos;
2301: #if 0
2302: printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
2303: #endif
2304: return table[pos].exception_handler;
2305: }
2306: #else
2307: while (table[++pos].exception_handler != (void*)-1) {
2308: if (table[pos].start <= except_pc && table[pos].end > except_pc)
2309: {
2310: /* This can apply. Make sure it is better or as good as the previous
2311: best. */
2312: /* The best one ends first. */
2313: if (best == 0 || (table[pos].end <= table[best].end
2314: /* The best one starts last. */
2315: && table[pos].start >= table[best].start))
2316: best = pos;
2317: }
2318: }
2319: if (best != 0)
2320: return table[best].exception_handler;
2321: #endif
2322:
2323: #if 0
2324: printf("find_first_eh_table_match(): else: returning NULL!\n");
2325: #endif
2326: return (void*)0;
2327: }
2328:
1.1.1.8 ! root 2329: void *
! 2330: __throw_type_match (void *catch_type, void *throw_type, void* obj)
1.1.1.7 root 2331: {
2332: #if 0
2333: printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
2334: catch_type, throw_type);
2335: #endif
1.1.1.8 ! root 2336: if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
! 2337: return obj;
! 2338: return 0;
1.1.1.7 root 2339: }
2340:
2341: void
2342: __register_exceptions (exception_table *table)
2343: {
1.1.1.8 ! root 2344: struct exception_table_node *node;
1.1.1.7 root 2345: exception_table *range = table + 1;
1.1.1.8 ! root 2346:
! 2347: if (range->start == (void*)-1)
! 2348: return;
! 2349:
! 2350: node = (struct exception_table_node*)
! 2351: malloc (sizeof (struct exception_table_node));
1.1.1.7 root 2352: node->table = table;
2353:
2354: /* This look can be optimized away either if the table
2355: is sorted, or if we pass in extra parameters. */
2356: node->start = range->start;
2357: node->end = range->end;
2358: for (range++ ; range->start != (void*)(-1); range++)
2359: {
2360: if (range->start < node->start)
2361: node->start = range->start;
1.1.1.8 ! root 2362: if (range->end > node->end)
1.1.1.7 root 2363: node->end = range->end;
2364: }
2365:
2366: node->next = exception_table_list;
2367: exception_table_list = node;
2368: }
1.1.1.8 ! root 2369:
! 2370: #if #machine(i386)
! 2371: void
! 2372: __unwind_function(void *ptr)
! 2373: {
! 2374: asm("movl 8(%esp),%ecx");
! 2375: /* Undo current frame */
! 2376: asm("movl %ebp,%esp");
! 2377: asm("popl %ebp");
! 2378: /* like ret, but stay here */
! 2379: asm("addl $4,%esp");
! 2380:
! 2381: /* Now, undo previous frame. */
! 2382: /* This is a test routine, as we have to dynamically probe to find out
! 2383: what to pop for certain, this is just a guess. */
! 2384: asm("leal -16(%ebp),%esp");
! 2385: asm("pop %ebx");
! 2386: asm("pop %esi");
! 2387: asm("pop %edi");
! 2388: asm("movl %ebp,%esp");
! 2389: asm("popl %ebp");
! 2390:
! 2391: asm("movl %ecx,0(%esp)");
! 2392: asm("ret");
! 2393: }
! 2394: #elif #machine(rs6000)
! 2395: __unwind_function(void *ptr)
! 2396: {
! 2397: asm("mr 31,1");
! 2398: asm("l 1,0(1)");
! 2399: asm("l 31,-4(1)");
! 2400: asm("# br");
! 2401:
! 2402: asm("mr 31,1");
! 2403: asm("l 1,0(1)");
! 2404: /* use 31 as a scratch register to restore the link register. */
! 2405: asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
! 2406: asm("l 31,-4(1)");
! 2407: asm("# br");
! 2408: asm("mtctr 3;bctr # b 3");
! 2409: }
! 2410: #elif #machine(powerpc)
! 2411: __unwind_function(void *ptr)
! 2412: {
! 2413: asm("mr 31,1");
! 2414: asm("lwz 1,0(1)");
! 2415: asm("lwz 31,-4(1)");
! 2416: asm("# br");
! 2417:
! 2418: asm("mr 31,1");
! 2419: asm("lwz 1,0(1)");
! 2420: /* use 31 as a scratch register to restore the link register. */
! 2421: asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
! 2422: asm("lwz 31,-4(1)");
! 2423: asm("# br");
! 2424: asm("mtctr 3;bctr # b 3");
! 2425: }
! 2426: #elif #machine(vax)
! 2427: __unwind_function(void *ptr)
! 2428: {
! 2429: __label__ return_again;
! 2430:
! 2431: /* Replace our frame's return address with the label below.
! 2432: During execution, we will first return here instead of to
! 2433: caller, then second return takes caller's frame off the stack.
! 2434: Two returns matches two actual calls, so is less likely to
! 2435: confuse debuggers. `16' corresponds to RETURN_ADDRESS_OFFSET. */
! 2436: __asm ("movl %0,16(fp)" : : "p" (&& return_again));
! 2437: return;
! 2438:
! 2439: return_again:
! 2440: return;
! 2441: }
! 2442: #else
! 2443: __unwind_function(void *ptr)
! 2444: {
! 2445: abort ();
! 2446: }
! 2447: #endif /* powerpc */
1.1.1.7 root 2448: #endif /* L_eh */
2449:
2450: #ifdef L_pure
1.1.1.8 ! root 2451: #ifndef inhibit_libc
! 2452: /* This gets us __GNU_LIBRARY__. */
! 2453: #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
! 2454: #include <stdio.h>
! 2455:
! 2456: #ifdef __GNU_LIBRARY__
! 2457: /* Avoid forcing the library's meaning of `write' on the user program
! 2458: by using the "internal" name (for use within the library) */
! 2459: #define write(fd, buf, n) __write((fd), (buf), (n))
! 2460: #endif
! 2461: #endif /* inhibit_libc */
! 2462:
1.1.1.7 root 2463: #define MESSAGE "pure virtual method called\n"
1.1.1.8 ! root 2464:
1.1.1.7 root 2465: void
2466: __pure_virtual ()
2467: {
1.1.1.8 ! root 2468: #ifndef inhibit_libc
1.1.1.7 root 2469: write (2, MESSAGE, sizeof (MESSAGE) - 1);
1.1.1.8 ! root 2470: #endif
1.1.1.7 root 2471: _exit (-1);
2472: }
2473: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.