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