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