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