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