]> gcc.gnu.org Git - gcc.git/blob - gcc/libgcc2.c
*** empty log message ***
[gcc.git] / gcc / libgcc2.c
1 /* More subroutines needed by GCC output code on some machines. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 /* As a special exception, if you link this library with files
22 compiled with GCC to produce an executable, this does not cause
23 the resulting executable to be covered by the GNU General Public License.
24 This exception does not however invalidate any other reasons why
25 the executable file might be covered by the GNU General Public License. */
26
27 /* It is incorrect to include config.h here, because this file is being
28 compiled for the target, and hence definitions concerning only the host
29 do not apply. */
30
31 #include "tm.h"
32 #ifndef L_trampoline
33 #include "gstddef.h"
34 #endif
35
36 /* Don't use `fancy_abort' here even if config.h says to use it. */
37 #ifdef abort
38 #undef abort
39 #endif
40
41 /* Need to undef this because LONG_TYPE_SIZE may rely upon GCC's
42 internal `target_flags' variable. */
43 #undef LONG_TYPE_SIZE
44
45 #define LONG_TYPE_SIZE (sizeof (long) * BITS_PER_UNIT)
46
47 #ifndef SItype
48 #define SItype long int
49 #endif
50
51 /* long long ints are pairs of long ints in the order determined by
52 WORDS_BIG_ENDIAN. */
53
54 #if WORDS_BIG_ENDIAN
55 struct longlong {long high, low;};
56 #else
57 struct longlong {long low, high;};
58 #endif
59
60 /* We need this union to unpack/pack longlongs, since we don't have
61 any arithmetic yet. Incoming long long parameters are stored
62 into the `ll' field, and the unpacked result is read from the struct
63 longlong. */
64
65 typedef union
66 {
67 struct longlong s;
68 long long ll;
69 } long_long;
70
71 #if defined (L_udivmoddi4) || defined (L_muldi3)
72
73 #include "longlong.h"
74
75 #endif /* udiv or mul */
76
77 extern long long __fixunssfdi (float a);
78 extern long long __fixunsdfdi (double a);
79 \f
80 #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
81 #if defined (L_divdi3) || defined (L_moddi3)
82 static inline
83 #endif
84 long long
85 __negdi2 (u)
86 long long u;
87 {
88 long_long w;
89 long_long uu;
90
91 uu.ll = u;
92
93 w.s.low = -uu.s.low;
94 w.s.high = -uu.s.high - ((unsigned long) w.s.low > 0);
95
96 return w.ll;
97 }
98 #endif
99 \f
100 #ifdef L_lshldi3
101 long long
102 __lshldi3 (u, b)
103 long long u;
104 int b;
105 {
106 long_long w;
107 long bm;
108 long_long uu;
109
110 if (b == 0)
111 return u;
112
113 uu.ll = u;
114
115 bm = (sizeof (long) * BITS_PER_UNIT) - b;
116 if (bm <= 0)
117 {
118 w.s.low = 0;
119 w.s.high = (unsigned long)uu.s.low << -bm;
120 }
121 else
122 {
123 unsigned long carries = (unsigned long)uu.s.low >> bm;
124 w.s.low = (unsigned long)uu.s.low << b;
125 w.s.high = ((unsigned long)uu.s.high << b) | carries;
126 }
127
128 return w.ll;
129 }
130 #endif
131
132 #ifdef L_lshrdi3
133 long long
134 __lshrdi3 (u, b)
135 long long u;
136 int b;
137 {
138 long_long w;
139 long bm;
140 long_long uu;
141
142 if (b == 0)
143 return u;
144
145 uu.ll = u;
146
147 bm = (sizeof (long) * BITS_PER_UNIT) - b;
148 if (bm <= 0)
149 {
150 w.s.high = 0;
151 w.s.low = (unsigned long)uu.s.high >> -bm;
152 }
153 else
154 {
155 unsigned long carries = (unsigned long)uu.s.high << bm;
156 w.s.high = (unsigned long)uu.s.high >> b;
157 w.s.low = ((unsigned long)uu.s.low >> b) | carries;
158 }
159
160 return w.ll;
161 }
162 #endif
163
164 #ifdef L_ashldi3
165 long long
166 __ashldi3 (u, b)
167 long long u;
168 int b;
169 {
170 long_long w;
171 long bm;
172 long_long uu;
173
174 if (b == 0)
175 return u;
176
177 uu.ll = u;
178
179 bm = (sizeof (long) * BITS_PER_UNIT) - b;
180 if (bm <= 0)
181 {
182 w.s.low = 0;
183 w.s.high = (unsigned long)uu.s.low << -bm;
184 }
185 else
186 {
187 unsigned long carries = (unsigned long)uu.s.low >> bm;
188 w.s.low = (unsigned long)uu.s.low << b;
189 w.s.high = ((unsigned long)uu.s.high << b) | carries;
190 }
191
192 return w.ll;
193 }
194 #endif
195
196 #ifdef L_ashrdi3
197 long long
198 __ashrdi3 (u, b)
199 long long u;
200 int b;
201 {
202 long_long w;
203 long bm;
204 long_long uu;
205
206 if (b == 0)
207 return u;
208
209 uu.ll = u;
210
211 bm = (sizeof (long) * BITS_PER_UNIT) - b;
212 if (bm <= 0)
213 {
214 /* w.s.high = 1..1 or 0..0 */
215 w.s.high = uu.s.high >> (sizeof (long) * BITS_PER_UNIT - 1);
216 w.s.low = uu.s.high >> -bm;
217 }
218 else
219 {
220 unsigned long carries = (unsigned long)uu.s.high << bm;
221 w.s.high = uu.s.high >> b;
222 w.s.low = ((unsigned long)uu.s.low >> b) | carries;
223 }
224
225 return w.ll;
226 }
227 #endif
228 \f
229 #ifdef L_muldi3
230 long long
231 __muldi3 (u, v)
232 long long u, v;
233 {
234 long_long w;
235 long_long uu, vv;
236
237 uu.ll = u,
238 vv.ll = v;
239
240 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
241 w.s.high += ((unsigned long) uu.s.low * (unsigned long) vv.s.high
242 + (unsigned long) uu.s.high * (unsigned long) vv.s.low);
243
244 return w.ll;
245 }
246 #endif
247 \f
248 #ifdef L_udivmoddi4
249 static const unsigned char __clz_tab[] =
250 {
251 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
252 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
253 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
254 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
255 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
256 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
257 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
258 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
259 };
260
261 unsigned long long
262 __udivmoddi4 (n, d, rp)
263 unsigned long long n, d;
264 unsigned long long int *rp;
265 {
266 long_long ww;
267 long_long nn, dd;
268 long_long rr;
269 unsigned long d0, d1, n0, n1, n2;
270 unsigned long q0, q1;
271 unsigned b, bm;
272
273 nn.ll = n;
274 dd.ll = d;
275
276 d0 = dd.s.low;
277 d1 = dd.s.high;
278 n0 = nn.s.low;
279 n1 = nn.s.high;
280
281 #if !UDIV_NEEDS_NORMALIZATION
282 if (d1 == 0)
283 {
284 if (d0 > n1)
285 {
286 /* 0q = nn / 0D */
287
288 udiv_qrnnd (q0, n0, n1, n0, d0);
289 q1 = 0;
290
291 /* Remainder in n0. */
292 }
293 else
294 {
295 /* qq = NN / 0d */
296
297 if (d0 == 0)
298 d0 = 1 / d0; /* Divide intentionally by zero. */
299
300 udiv_qrnnd (q1, n1, 0, n1, d0);
301 udiv_qrnnd (q0, n0, n1, n0, d0);
302
303 /* Remainder in n0. */
304 }
305
306 if (rp != 0)
307 {
308 rr.s.low = n0;
309 rr.s.high = 0;
310 *rp = rr.ll;
311 }
312 }
313
314 #else /* UDIV_NEEDS_NORMALIZATION */
315
316 if (d1 == 0)
317 {
318 if (d0 > n1)
319 {
320 /* 0q = nn / 0D */
321
322 count_leading_zeros (bm, d0);
323
324 if (bm != 0)
325 {
326 /* Normalize, i.e. make the most significant bit of the
327 denominator set. */
328
329 d0 = d0 << bm;
330 n1 = (n1 << bm) | (n0 >> (LONG_TYPE_SIZE - bm));
331 n0 = n0 << bm;
332 }
333
334 udiv_qrnnd (q0, n0, n1, n0, d0);
335 q1 = 0;
336
337 /* Remainder in n0 >> bm. */
338 }
339 else
340 {
341 /* qq = NN / 0d */
342
343 if (d0 == 0)
344 d0 = 1 / d0; /* Divide intentionally by zero. */
345
346 count_leading_zeros (bm, d0);
347
348 if (bm == 0)
349 {
350 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
351 conclude (the most significant bit of n1 is set) /\ (the
352 leading quotient digit q1 = 1).
353
354 This special case is necessary, not an optimization.
355 (Shifts counts of LONG_TYPE_SIZE are undefined.) */
356
357 n1 -= d0;
358 q1 = 1;
359 }
360 else
361 {
362 /* Normalize. */
363
364 b = LONG_TYPE_SIZE - bm;
365
366 d0 = d0 << bm;
367 n2 = n1 >> b;
368 n1 = (n1 << bm) | (n0 >> b);
369 n0 = n0 << bm;
370
371 udiv_qrnnd (q1, n1, n2, n1, d0);
372 }
373
374 /* n1 != d0... */
375
376 udiv_qrnnd (q0, n0, n1, n0, d0);
377
378 /* Remainder in n0 >> bm. */
379 }
380
381 if (rp != 0)
382 {
383 rr.s.low = n0 >> bm;
384 rr.s.high = 0;
385 *rp = rr.ll;
386 }
387 }
388 #endif /* UDIV_NEEDS_NORMALIZATION */
389
390 else
391 {
392 if (d1 > n1)
393 {
394 /* 00 = nn / DD */
395
396 q0 = 0;
397 q1 = 0;
398
399 /* Remainder in n1n0. */
400 if (rp != 0)
401 {
402 rr.s.low = n0;
403 rr.s.high = n1;
404 *rp = rr.ll;
405 }
406 }
407 else
408 {
409 /* 0q = NN / dd */
410
411 count_leading_zeros (bm, d1);
412 if (bm == 0)
413 {
414 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
415 conclude (the most significant bit of n1 is set) /\ (the
416 quotient digit q0 = 0 or 1).
417
418 This special case is necessary, not an optimization. */
419
420 /* The condition on the next line takes advantage of that
421 n1 >= d1 (true due to program flow). */
422 if (n1 > d1 || n0 >= d0)
423 {
424 q0 = 1;
425 sub_ddmmss (n1, n0, n1, n0, d1, d0);
426 }
427 else
428 q0 = 0;
429
430 q1 = 0;
431
432 if (rp != 0)
433 {
434 rr.s.low = n0;
435 rr.s.high = n1;
436 *rp = rr.ll;
437 }
438 }
439 else
440 {
441 unsigned long m1, m0;
442 /* Normalize. */
443
444 b = LONG_TYPE_SIZE - bm;
445
446 d1 = (d1 << bm) | (d0 >> b);
447 d0 = d0 << bm;
448 n2 = n1 >> b;
449 n1 = (n1 << bm) | (n0 >> b);
450 n0 = n0 << bm;
451
452 udiv_qrnnd (q0, n1, n2, n1, d1);
453 umul_ppmm (m1, m0, q0, d0);
454
455 if (m1 > n1 || (m1 == n1 && m0 > n0))
456 {
457 q0--;
458 sub_ddmmss (m1, m0, m1, m0, d1, d0);
459 }
460
461 q1 = 0;
462
463 /* Remainder in (n1n0 - m1m0) >> bm. */
464 if (rp != 0)
465 {
466 sub_ddmmss (n1, n0, n1, n0, m1, m0);
467 rr.s.low = (n1 << b) | (n0 >> bm);
468 rr.s.high = n1 >> bm;
469 *rp = rr.ll;
470 }
471 }
472 }
473 }
474
475 ww.s.low = q0;
476 ww.s.high = q1;
477 return ww.ll;
478 }
479 #endif
480
481 #ifdef L_divdi3
482 unsigned long long __udivmoddi4 ();
483 long long
484 __divdi3 (u, v)
485 long long u, v;
486 {
487 int c = 0;
488 long_long uu, vv;
489 long long w;
490
491 uu.ll = u;
492 vv.ll = v;
493
494 if (uu.s.high < 0)
495 c = ~c,
496 uu.ll = __negdi2 (uu.ll);
497 if (vv.s.high < 0)
498 c = ~c,
499 vv.ll = __negdi2 (vv.ll);
500
501 w = __udivmoddi4 (uu.ll, vv.ll, (unsigned long long *) 0);
502 if (c)
503 w = __negdi2 (w);
504
505 return w;
506 }
507 #endif
508
509 #ifdef L_moddi3
510 unsigned long long __udivmoddi4 ();
511 long long
512 __moddi3 (u, v)
513 long long u, v;
514 {
515 int c = 0;
516 long_long uu, vv;
517 long long w;
518
519 uu.ll = u;
520 vv.ll = v;
521
522 if (uu.s.high < 0)
523 c = ~c,
524 uu.ll = __negdi2 (uu.ll);
525 if (vv.s.high < 0)
526 vv.ll = __negdi2 (vv.ll);
527
528 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
529 if (c)
530 w = __negdi2 (w);
531
532 return w;
533 }
534 #endif
535
536 #ifdef L_umoddi3
537 unsigned long long __udivmoddi4 ();
538 unsigned long long
539 __umoddi3 (u, v)
540 unsigned long long u, v;
541 {
542 long long w;
543
544 (void) __udivmoddi4 (u, v, &w);
545
546 return w;
547 }
548 #endif
549
550 #ifdef L_udivdi3
551 unsigned long long __udivmoddi4 ();
552 unsigned long long
553 __udivdi3 (n, d)
554 unsigned long long n, d;
555 {
556 return __udivmoddi4 (n, d, (unsigned long long *) 0);
557 }
558 #endif
559 \f
560 #ifdef L_cmpdi2
561 SItype
562 __cmpdi2 (a, b)
563 long long a, b;
564 {
565 long_long au, bu;
566
567 au.ll = a, bu.ll = b;
568
569 if (au.s.high < bu.s.high)
570 return 0;
571 else if (au.s.high > bu.s.high)
572 return 2;
573 if ((unsigned long) au.s.low < (unsigned long) bu.s.low)
574 return 0;
575 else if ((unsigned long) au.s.low > (unsigned long) bu.s.low)
576 return 2;
577 return 1;
578 }
579 #endif
580
581 #ifdef L_ucmpdi2
582 SItype
583 __ucmpdi2 (a, b)
584 long long a, b;
585 {
586 long_long au, bu;
587
588 au.ll = a, bu.ll = b;
589
590 if ((unsigned long) au.s.high < (unsigned long) bu.s.high)
591 return 0;
592 else if ((unsigned long) au.s.high > (unsigned long) bu.s.high)
593 return 2;
594 if ((unsigned long) au.s.low < (unsigned long) bu.s.low)
595 return 0;
596 else if ((unsigned long) au.s.low > (unsigned long) bu.s.low)
597 return 2;
598 return 1;
599 }
600 #endif
601 \f
602 #ifdef L_fixunsdfdi
603 #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
604 #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
605
606 long long
607 __fixunsdfdi (a)
608 double a;
609 {
610 double b;
611 unsigned long long v;
612
613 if (a < 0)
614 return 0;
615
616 /* Compute high word of result, as a flonum. */
617 b = (a / HIGH_WORD_COEFF);
618 /* Convert that to fixed (but not to long long!),
619 and shift it into the high word. */
620 v = (unsigned long int) b;
621 v <<= WORD_SIZE;
622 /* Remove high part from the double, leaving the low part as flonum. */
623 a -= (double)v;
624 /* Convert that to fixed (but not to long long!) and add it in.
625 Sometimes A comes out negative. This is significant, since
626 A has more bits than a long int does. */
627 if (a < 0)
628 v -= (unsigned long int) (- a);
629 else
630 v += (unsigned long int) a;
631 return v;
632 }
633 #endif
634
635 #ifdef L_fixdfdi
636 long long
637 __fixdfdi (a)
638 double a;
639 {
640 if (a < 0)
641 return - __fixunsdfdi (-a);
642 return __fixunsdfdi (a);
643 }
644 #endif
645
646 #ifdef L_fixunssfdi
647 #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
648 #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
649
650 long long
651 __fixunssfdi (float original_a)
652 {
653 /* Convert the float to a double, because that is surely not going
654 to lose any bits. Some day someone else can write a faster version
655 that avoids converting to double, and verify it really works right. */
656 double a = original_a;
657 double b;
658 unsigned long long v;
659
660 if (a < 0)
661 return 0;
662
663 /* Compute high word of result, as a flonum. */
664 b = (a / HIGH_WORD_COEFF);
665 /* Convert that to fixed (but not to long long!),
666 and shift it into the high word. */
667 v = (unsigned long int) b;
668 v <<= WORD_SIZE;
669 /* Remove high part from the double, leaving the low part as flonum. */
670 a -= (double)v;
671 /* Convert that to fixed (but not to long long!) and add it in.
672 Sometimes A comes out negative. This is significant, since
673 A has more bits than a long int does. */
674 if (a < 0)
675 v -= (unsigned long int) (- a);
676 else
677 v += (unsigned long int) a;
678 return v;
679 }
680 #endif
681
682 #ifdef L_fixsfdi
683 long long
684 __fixsfdi (float a)
685 {
686 if (a < 0)
687 return - __fixunssfdi (-a);
688 return __fixunssfdi (a);
689 }
690 #endif
691
692 #ifdef L_floatdidf
693 #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
694 #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2))
695 #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
696
697 double
698 __floatdidf (u)
699 long long u;
700 {
701 double d;
702 int negate = 0;
703
704 if (u < 0)
705 u = -u, negate = 1;
706
707 d = (unsigned int) (u >> WORD_SIZE);
708 d *= HIGH_HALFWORD_COEFF;
709 d *= HIGH_HALFWORD_COEFF;
710 d += (unsigned int) (u & (HIGH_WORD_COEFF - 1));
711
712 return (negate ? -d : d);
713 }
714 #endif
715
716 #ifdef L_floatdisf
717 #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
718 #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2))
719 #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
720
721 float
722 __floatdisf (u)
723 long long u;
724 {
725 float f;
726 int negate = 0;
727
728 if (u < 0)
729 u = -u, negate = 1;
730
731 f = (unsigned int) (u >> WORD_SIZE);
732 f *= HIGH_HALFWORD_COEFF;
733 f *= HIGH_HALFWORD_COEFF;
734 f += (unsigned int) (u & (HIGH_WORD_COEFF - 1));
735
736 return (negate ? -f : f);
737 }
738 #endif
739
740 #ifdef L_fixunsdfsi
741 #include "limits.h"
742
743 unsigned SItype
744 __fixunsdfsi (a)
745 double a;
746 {
747 if (a >= - (double) LONG_MIN)
748 return (SItype) (a + LONG_MIN) - LONG_MIN;
749 return (SItype) a;
750 }
751 #endif
752
753 #ifdef L_fixunssfsi
754 #include "limits.h"
755
756 unsigned SItype
757 __fixunssfsi (float a)
758 {
759 if (a >= - (float) LONG_MIN)
760 return (SItype) (a + LONG_MIN) - LONG_MIN;
761 return (SItype) a;
762 }
763 #endif
764 \f
765 #ifdef L_varargs
766 #ifdef __i860__
767 #ifdef SVR4
768 asm (" .text");
769 asm (" .align 4");
770
771 asm (".globl __builtin_saveregs");
772 asm ("__builtin_saveregs:");
773 asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
774 asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
775 area and also for a new va_list
776 structure */
777 /* Save all argument registers in the arg reg save area. The
778 arg reg save area must have the following layout (according
779 to the svr4 ABI):
780
781 struct {
782 union {
783 float freg[8];
784 double dreg[4];
785 } float_regs;
786 long ireg[12];
787 };
788 */
789
790 asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
791 asm (" fst.q %f12,16(%sp)");
792
793 asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
794 asm (" st.l %r17,36(%sp)");
795 asm (" st.l %r18,40(%sp)");
796 asm (" st.l %r19,44(%sp)");
797 asm (" st.l %r20,48(%sp)");
798 asm (" st.l %r21,52(%sp)");
799 asm (" st.l %r22,56(%sp)");
800 asm (" st.l %r23,60(%sp)");
801 asm (" st.l %r24,64(%sp)");
802 asm (" st.l %r25,68(%sp)");
803 asm (" st.l %r26,72(%sp)");
804 asm (" st.l %r27,76(%sp)");
805
806 asm (" adds 80,%sp,%r16"); /* compute the address of the new
807 va_list structure. Put in into
808 r16 so that it will be returned
809 to the caller. */
810
811 /* Initialize all fields of the new va_list structure. This
812 structure looks like:
813
814 typedef struct {
815 unsigned long ireg_used;
816 unsigned long freg_used;
817 long *reg_base;
818 long *mem_ptr;
819 } va_list;
820 */
821
822 asm (" st.l %r0, 0(%r16)"); /* nfixed */
823 asm (" st.l %r0, 4(%r16)"); /* nfloating */
824 asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
825 asm (" bri %r1"); /* delayed return */
826 asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
827
828 #else /* not SVR4 */
829 asm (" .text");
830 asm (" .align 4");
831
832 asm (".globl ___builtin_saveregs");
833 asm ("___builtin_saveregs:");
834 asm (" mov sp,r30");
835 asm (" andnot 0x0f,sp,sp");
836 asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
837
838 /* Fill in the __va_struct. */
839 asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
840 asm (" st.l r17, 4(sp)"); /* int fixed[12] */
841 asm (" st.l r18, 8(sp)");
842 asm (" st.l r19,12(sp)");
843 asm (" st.l r20,16(sp)");
844 asm (" st.l r21,20(sp)");
845 asm (" st.l r22,24(sp)");
846 asm (" st.l r23,28(sp)");
847 asm (" st.l r24,32(sp)");
848 asm (" st.l r25,36(sp)");
849 asm (" st.l r26,40(sp)");
850 asm (" st.l r27,44(sp)");
851
852 asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
853 asm (" fst.q f12,64(sp)"); /* int floating[8] */
854
855 /* Fill in the __va_ctl. */
856 asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
857 asm (" st.l r28,84(sp)"); /* pointer to more args */
858 asm (" st.l r0, 88(sp)"); /* nfixed */
859 asm (" st.l r0, 92(sp)"); /* nfloating */
860
861 asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
862 asm (" bri r1");
863 asm (" mov r30,sp");
864 /* recover stack and pass address to start
865 of data. */
866 #endif /* not SVR4 */
867 #else /* not __i860__ */
868 #ifdef __sparc__
869 asm (".global __builtin_saveregs");
870 asm ("__builtin_saveregs:");
871 asm (".global ___builtin_saveregs");
872 asm ("___builtin_saveregs:");
873 #ifdef NEED_PROC_COMMAND
874 asm (".proc 020");
875 #endif
876 asm ("st %i0,[%fp+68]");
877 asm ("st %i1,[%fp+72]");
878 asm ("st %i2,[%fp+76]");
879 asm ("st %i3,[%fp+80]");
880 asm ("st %i4,[%fp+84]");
881 asm ("retl");
882 asm ("st %i5,[%fp+88]");
883 #ifdef NEED_TYPE_COMMAND
884 asm (".type __builtin_saveregs,#function");
885 asm (".size __builtin_saveregs,.-__builtin_saveregs");
886 #endif
887 #else /* not __sparc__ */
888 #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
889
890 asm (" .text");
891 asm (" .ent __builtin_saveregs");
892 asm (" .globl __builtin_saveregs");
893 asm ("__builtin_saveregs:");
894 asm (" sw $4,0($30)");
895 asm (" sw $5,4($30)");
896 asm (" sw $6,8($30)");
897 asm (" sw $7,12($30)");
898 asm (" j $31");
899 asm (" .end __builtin_saveregs");
900 #else /* not __mips__, etc. */
901 __builtin_saveregs ()
902 {
903 abort ();
904 }
905 #endif /* not __mips__ */
906 #endif /* not __sparc__ */
907 #endif /* not __i860__ */
908 #endif
909 \f
910 #ifdef L_eprintf
911 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
912 #include <stdio.h>
913 /* This is used by the `assert' macro. */
914 void
915 __eprintf (string, expression, line, filename)
916 const char *string;
917 const char *expression;
918 int line;
919 const char *filename;
920 {
921 fprintf (stderr, string, expression, line, filename);
922 fflush (stderr);
923 abort ();
924 }
925 #endif
926
927 #ifdef L_bb
928 /* Avoid warning from ranlib about empty object file. */
929 void
930 __bb_avoid_warning ()
931 {}
932
933 #if defined (__sun__) && defined (__mc68000__)
934 struct bb
935 {
936 int initialized;
937 char *filename;
938 int *counts;
939 int ncounts;
940 int zero_word;
941 int *addresses;
942 };
943
944 extern int ___tcov_init;
945
946 __bb_init_func (blocks)
947 struct bb *blocks;
948 {
949 if (! ___tcov_init)
950 ___tcov_init_func ();
951
952 ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);
953 }
954
955 #endif
956 #endif
957 \f
958 /* frills for C++ */
959
960 #ifdef L_builtin_new
961 typedef void (*vfp)(void);
962
963 extern vfp __new_handler;
964 extern void *malloc ();
965
966 void *
967 __builtin_new (sz)
968 size_t sz;
969 {
970 void *p;
971
972 p = malloc (sz);
973 if (p == 0)
974 (*__new_handler) ();
975 return p;
976 }
977 #endif
978
979 #ifdef L_builtin_New
980 typedef void (*vfp)(void);
981
982 extern void *__builtin_new (size_t);
983 static void default_new_handler (void);
984
985 vfp __new_handler = default_new_handler;
986
987 void *
988 __builtin_vec_new (p, maxindex, size, ctor)
989 void *p;
990 size_t maxindex;
991 size_t size;
992 void (*ctor)(void *);
993 {
994 size_t i;
995 size_t nelts = maxindex + 1;
996 void *rval;
997
998 if (p == 0)
999 p = __builtin_new (nelts * size);
1000
1001 rval = p;
1002
1003 for (i = 0; i < nelts; i++)
1004 {
1005 (*ctor) (p);
1006 p += size;
1007 }
1008
1009 return rval;
1010 }
1011
1012 vfp
1013 __set_new_handler (handler)
1014 vfp handler;
1015 {
1016 vfp prev_handler;
1017
1018 prev_handler = __new_handler;
1019 if (handler == 0) handler = default_new_handler;
1020 __new_handler = handler;
1021 return prev_handler;
1022 }
1023
1024 vfp
1025 set_new_handler (handler)
1026 vfp handler;
1027 {
1028 return __set_new_handler (handler);
1029 }
1030
1031 #define MESSAGE "Virtual memory exceeded in `new'\n"
1032
1033 static void
1034 default_new_handler ()
1035 {
1036 /* don't use fprintf (stderr, ...) because it may need to call malloc. */
1037 /* This should really print the name of the program, but that is hard to
1038 do. We need a standard, clean way to get at the name. */
1039 write (2, MESSAGE, sizeof (MESSAGE));
1040 /* don't call exit () because that may call global destructors which
1041 may cause a loop. */
1042 _exit (-1);
1043 }
1044 #endif
1045 \f
1046 #ifdef L_builtin_del
1047 typedef void (*vfp)(void);
1048
1049 void
1050 __builtin_delete (ptr)
1051 void *ptr;
1052 {
1053 if (ptr)
1054 free (ptr);
1055 }
1056
1057 void
1058 __builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete)
1059 void *ptr;
1060 size_t maxindex;
1061 size_t size;
1062 void (*dtor)(void *, int);
1063 int auto_delete;
1064 {
1065 size_t i;
1066 size_t nelts = maxindex + 1;
1067 void *p = ptr;
1068
1069 ptr += nelts * size;
1070
1071 for (i = 0; i < nelts; i++)
1072 {
1073 ptr -= size;
1074 (*dtor) (ptr, auto_delete);
1075 }
1076
1077 if (auto_delete_vec)
1078 __builtin_delete (p);
1079 }
1080
1081 #endif
1082
1083 #ifdef L_shtab
1084 unsigned int __shtab[] = {
1085 0x00000001, 0x00000002, 0x00000004, 0x00000008,
1086 0x00000010, 0x00000020, 0x00000040, 0x00000080,
1087 0x00000100, 0x00000200, 0x00000400, 0x00000800,
1088 0x00001000, 0x00002000, 0x00004000, 0x00008000,
1089 0x00010000, 0x00020000, 0x00040000, 0x00080000,
1090 0x00100000, 0x00200000, 0x00400000, 0x00800000,
1091 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1092 0x10000000, 0x20000000, 0x40000000, 0x80000000
1093 };
1094 #endif
1095 \f
1096 #ifdef L_clear_cache
1097 /* Clear part of an instruction cache. */
1098
1099 #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1100
1101 void
1102 __clear_cache (beg, end)
1103 char *beg, *end;
1104 {
1105 #ifdef INSN_CACHE_SIZE
1106 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1107 static int initialized = 0;
1108 int offset;
1109 void *start_addr
1110 void *end_addr;
1111 typedef (*function_ptr) ();
1112
1113 #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1114 /* It's cheaper to clear the whole cache.
1115 Put in a series of jump instructions so that calling the beginning
1116 of the cache will clear the whole thing. */
1117
1118 if (! initialized)
1119 {
1120 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1121 & -INSN_CACHE_LINE_WIDTH);
1122 int end_ptr = ptr + INSN_CACHE_SIZE;
1123
1124 while (ptr < end_ptr)
1125 {
1126 *(INSTRUCTION_TYPE *)ptr
1127 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1128 ptr += INSN_CACHE_LINE_WIDTH;
1129 }
1130 *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1131
1132 initialized = 1;
1133 }
1134
1135 /* Call the beginning of the sequence. */
1136 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1137 & -INSN_CACHE_LINE_WIDTH))
1138 ());
1139
1140 #else /* Cache is large. */
1141
1142 if (! initialized)
1143 {
1144 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1145 & -INSN_CACHE_LINE_WIDTH);
1146
1147 while (ptr < (int) array + sizeof array)
1148 {
1149 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1150 ptr += INSN_CACHE_LINE_WIDTH;
1151 }
1152
1153 initialized = 1;
1154 }
1155
1156 /* Find the location in array that occupies the same cache line as BEG. */
1157
1158 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1159 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1160 & -INSN_CACHE_PLANE_SIZE)
1161 + offset);
1162
1163 /* Compute the cache alignment of the place to stop clearing. */
1164 #if 0 /* This is not needed for gcc's purposes. */
1165 /* If the block to clear is bigger than a cache plane,
1166 we clear the entire cache, and OFFSET is already correct. */
1167 if (end < beg + INSN_CACHE_PLANE_SIZE)
1168 #endif
1169 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1170 & -INSN_CACHE_LINE_WIDTH)
1171 & (INSN_CACHE_PLANE_SIZE - 1));
1172
1173 #if INSN_CACHE_DEPTH > 1
1174 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1175 if (end_addr <= start_addr)
1176 end_addr += INSN_CACHE_PLANE_SIZE;
1177
1178 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1179 {
1180 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1181 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1182
1183 while (addr != stop)
1184 {
1185 /* Call the return instruction at ADDR. */
1186 ((function_ptr) addr) ();
1187
1188 addr += INSN_CACHE_LINE_WIDTH;
1189 }
1190 }
1191 #else /* just one plane */
1192 do
1193 {
1194 /* Call the return instruction at START_ADDR. */
1195 ((function_ptr) start_addr) ();
1196
1197 start_addr += INSN_CACHE_LINE_WIDTH;
1198 }
1199 while ((start_addr % INSN_CACHE_SIZE) != offset);
1200 #endif /* just one plane */
1201 #endif /* Cache is large */
1202 #endif /* Cache exists */
1203 }
1204
1205 #endif /* L_clear_cache */
1206 \f
1207 #ifdef L_trampoline
1208
1209 /* Jump to a trampoline, loading the static chain address. */
1210
1211 #ifdef TRANSFER_FROM_TRAMPOLINE
1212 TRANSFER_FROM_TRAMPOLINE
1213 #endif
1214
1215 #ifdef __convex__
1216
1217 /* Make stack executable so we can call trampolines on stack.
1218 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
1219
1220 #include <sys/mman.h>
1221 #include <sys/vmparam.h>
1222 #include <machine/machparam.h>
1223
1224 void
1225 __enable_execute_stack ()
1226 {
1227 int fp;
1228 static unsigned lowest = USRSTACK;
1229 unsigned current = (unsigned) &fp & -NBPG;
1230
1231 if (lowest > current)
1232 {
1233 unsigned len = lowest - current;
1234 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1235 lowest = current;
1236 }
1237
1238 /* Clear instruction cache in case an old trampoline is in it. */
1239 asm ("pich");
1240 }
1241 #endif /* __convex__ */
1242
1243 #ifdef __pyr__
1244
1245 #include <stdio.h>
1246 #include <sys/mman.h>
1247 #include <sys/types.h>
1248 #include <sys/param.h>
1249 #include <sys/vmmac.h>
1250
1251 /* Modified from the convex -code above.
1252 mremap promises to clear the i-cache. */
1253
1254 void
1255 __enable_execute_stack ()
1256 {
1257 int fp;
1258 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
1259 PROT_READ|PROT_WRITE|PROT_EXEC))
1260 {
1261 perror ("mprotect in __enable_execute_stack");
1262 fflush (stderr);
1263 abort ();
1264 }
1265 }
1266 #endif /* __pyr__ */
1267 #endif /* L_trampoline */
1268 \f
1269 #ifdef L__main
1270
1271 #include "gbl-ctors.h"
1272
1273 /* Run all the global destructors on exit from the program. */
1274
1275 void
1276 __do_global_dtors ()
1277 {
1278 #ifdef DO_GLOBAL_DTORS_BODY
1279 DO_GLOBAL_DTORS_BODY;
1280 #else
1281 unsigned nptrs = (unsigned) __DTOR_LIST__[0];
1282 unsigned i;
1283
1284 /* Some systems place the number of pointers
1285 in the first word of the table.
1286 On other systems, that word is -1.
1287 In all cases, the table is null-terminated. */
1288
1289 /* If the length is not recorded, count up to the null. */
1290 if (nptrs == -1)
1291 for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
1292
1293 /* GNU LD format. */
1294 for (i = nptrs; i >= 1; i--)
1295 __DTOR_LIST__[i] ();
1296 #endif
1297 }
1298
1299 #ifndef INIT_SECTION_ASM_OP
1300 /* Run all the global constructors on entry to the program. */
1301
1302 #ifndef ON_EXIT
1303 #define ON_EXIT(a, b)
1304 #else
1305 /* Make sure the exit routine is pulled in to define the globals as
1306 bss symbols, just in case the linker does not automatically pull
1307 bss definitions from the library. */
1308
1309 extern int _exit_dummy_decl;
1310 int *_exit_dummy_ref = &_exit_dummy_decl;
1311 #endif /* ON_EXIT */
1312
1313 void
1314 __do_global_ctors ()
1315 {
1316 DO_GLOBAL_CTORS_BODY;
1317 ON_EXIT (__do_global_dtors, 0);
1318 }
1319 #endif /* no INIT_SECTION_ASM_OP */
1320
1321 #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
1322 /* Subroutine called automatically by `main'.
1323 Compiling a global function named `main'
1324 produces an automatic call to this function at the beginning.
1325
1326 For many systems, this routine calls __do_global_ctors.
1327 For systems which support a .init section we use the .init section
1328 to run __do_global_ctors, so we need not do anything here. */
1329
1330 void
1331 __main ()
1332 {
1333 /* Support recursive calls to `main': run initializers just once. */
1334 static int initialized = 0;
1335 if (! initialized)
1336 {
1337 initialized = 1;
1338 __do_global_ctors ();
1339 }
1340 }
1341 #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
1342
1343 #endif /* L__main */
1344 \f
1345 #ifdef L_exit
1346
1347 #include "gbl-ctors.h"
1348
1349 /* Provide default definitions for the lists of constructors and
1350 destructors, so that we don't get linker errors. These symbols are
1351 intentionally bss symbols, so that gld and/or collect will provide
1352 the right values. */
1353
1354 /* We declare the lists here with two elements each,
1355 so that they are valid empty lists if no other definition is loaded. */
1356 #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
1357 func_ptr __CTOR_LIST__[2];
1358 func_ptr __DTOR_LIST__[2];
1359 #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
1360
1361 #ifndef ON_EXIT
1362
1363 /* If we have no known way of registering our own __do_global_dtors
1364 routine so that it will be invoked at program exit time, then we
1365 have to define our own exit routine which will get this to happen. */
1366
1367 extern void __do_global_dtors ();
1368 extern void _cleanup ();
1369 extern void _exit ();
1370
1371 void
1372 exit (status)
1373 int status;
1374 {
1375 __do_global_dtors ();
1376 #ifdef EXIT_BODY
1377 EXIT_BODY;
1378 #else
1379 _cleanup ();
1380 #endif
1381 _exit (status);
1382 }
1383
1384 #else
1385 int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
1386 #endif
1387
1388 #endif /* L_exit */
1389 \f
1390 /* In a.out systems, we need to have these dummy constructor and destructor
1391 lists in the library.
1392
1393 When using `collect', the first link will resolve __CTOR_LIST__
1394 and __DTOR_LIST__ to these symbols. We will then run "nm" on the
1395 result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink.
1396 Since we don't do the second link if no constructors existed, these
1397 dummies must be fully functional empty lists.
1398
1399 When using `gnu ld', these symbols will be used if there are no
1400 constructors. If there are constructors, the N_SETV symbol defined
1401 by the linker from the N_SETT's in input files will define __CTOR_LIST__
1402 and __DTOR_LIST__ rather than its being allocated as common storage
1403 by the definitions below.
1404
1405 When using a linker that supports constructor and destructor segments,
1406 these definitions will not be used, since crtbegin.o and crtend.o
1407 (from crtstuff.c) will have already defined __CTOR_LIST__ and
1408 __DTOR_LIST__. The crt*.o files are passed directly to the linker
1409 on its command line, by gcc. */
1410
1411 /* The list needs two elements: one is ignored (the old count); the
1412 second is the terminating zero. Since both values are zero, this
1413 declaration is not initialized, and it becomes `common'. */
1414
1415 #ifdef L_ctor_list
1416 #include "gbl-ctors.h"
1417 func_ptr __CTOR_LIST__[2];
1418 #endif
1419
1420 #ifdef L_dtor_list
1421 #include "gbl-ctors.h"
1422 func_ptr __DTOR_LIST__[2];
1423 #endif
This page took 0.102149 seconds and 5 git commands to generate.