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