]> gcc.gnu.org Git - gcc.git/blame - gcc/libgcc2.c
tweak __unwind_function for bsdi
[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
MM
1427#ifdef HAVE_ATEXIT
1428extern void atexit (void (*) (void));
1429#define ON_EXIT(FUNC,ARG) atexit ((FUNC))
1430#else
1431#ifdef sun
1432extern void on_exit (void*, void*);
1433#define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
1434#endif
1435#endif
1436
1437static struct bb *bb_head = (struct bb *)0;
1438
1439/* Return the number of digits needed to print a value */
1440/* __inline__ */ static int num_digits (long value, int base)
203b91b9 1441{
92832bb5
MM
1442 int minus = (value < 0 && base != 16);
1443 unsigned long v = (minus) ? -value : value;
1444 int ret = minus;
203b91b9 1445
92832bb5
MM
1446 do
1447 {
1448 v /= base;
1449 ret++;
1450 }
1451 while (v);
1452
1453 return ret;
203b91b9
RS
1454}
1455
92832bb5
MM
1456void
1457__bb_exit_func (void)
1458{
1459 FILE *file = fopen ("bb.out", "a");
1460 long time_value;
1461
1462 if (!file)
1463 perror ("bb.out");
1464
1465 else
1466 {
1467 struct bb *ptr;
1468
1469 /* This is somewhat type incorrect, but it avoids worrying about
1470 exactly where time.h is included from. It should be ok unless
1471 a void * differs from other pointer formats, or if sizeof(long)
1472 is < sizeof (time_t). It would be nice if we could assume the
1473 use of rationale standards here. */
1474
1475 time((void *) &time_value);
1476 fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1477
1478 /* We check the length field explicitly in order to allow compatibility
1479 with older GCC's which did not provide it. */
1480
1481 for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
1482 {
1483 int i;
1484 int func_p = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
1485 int line_p = (func_p && ptr->line_nums);
1486 int file_p = (func_p && ptr->filenames);
1487 long ncounts = ptr->ncounts;
1488 long cnt_max = 0;
1489 long line_max = 0;
1490 long addr_max = 0;
1491 int file_len = 0;
1492 int func_len = 0;
1493 int blk_len = num_digits (ncounts, 10);
1494 int cnt_len;
1495 int line_len;
1496 int addr_len;
1497
1498 fprintf (file, "File %s, %ld basic blocks \n\n",
1499 ptr->filename, ncounts);
1500
1501 /* Get max values for each field. */
1502 for (i = 0; i < ncounts; i++)
1503 {
1504 const char *p;
1505 int len;
1506
1507 if (cnt_max < ptr->counts[i])
1508 cnt_max = ptr->counts[i];
1509
1510 if (addr_max < ptr->addresses[i])
1511 addr_max = ptr->addresses[i];
1512
1513 if (line_p && line_max < ptr->line_nums[i])
1514 line_max = ptr->line_nums[i];
1515
1516 if (func_p)
1517 {
1518 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1519 len = strlen (p);
1520 if (func_len < len)
1521 func_len = len;
1522 }
1523
1524 if (file_p)
1525 {
1526 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1527 len = strlen (p);
1528 if (file_len < len)
1529 file_len = len;
1530 }
1531 }
1532
1533 addr_len = num_digits (addr_max, 16);
1534 cnt_len = num_digits (cnt_max, 10);
1535 line_len = num_digits (line_max, 10);
1536
1537 /* Now print out the basic block information. */
1538 for (i = 0; i < ncounts; i++)
1539 {
1540 fprintf (file,
3cca99e8 1541 " Block #%*d: executed %*ld time(s) address= 0x%.*lx",
92832bb5
MM
1542 blk_len, i+1,
1543 cnt_len, ptr->counts[i],
1544 addr_len, ptr->addresses[i]);
1545
1546 if (func_p)
3cca99e8 1547 fprintf (file, " function= %-*s", func_len,
92832bb5
MM
1548 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1549
1550 if (line_p)
1d42e1b7 1551 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
92832bb5
MM
1552
1553 if (file_p)
3cca99e8 1554 fprintf (file, " file= %s",
92832bb5
MM
1555 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1556
1557 fprintf (file, "\n");
1558 }
1559
1560 fprintf (file, "\n");
1561 fflush (file);
1562 }
1563
1564 fprintf (file, "\n\n");
1565 fclose (file);
1566 }
1567}
1568
1569void
1570__bb_init_func (struct bb *blocks)
1571{
1572 /* User is supposed to check whether the first word is non-0,
1573 but just in case.... */
1574
1575 if (blocks->zero_word)
1576 return;
1577
1578#ifdef ON_EXIT
1579 /* Initialize destructor. */
1580 if (!bb_head)
1581 ON_EXIT (__bb_exit_func, 0);
203b91b9 1582#endif
92832bb5
MM
1583
1584 /* Set up linked list. */
1585 blocks->zero_word = 1;
1586 blocks->next = bb_head;
1587 bb_head = blocks;
1588}
1589
c7544ff7
RS
1590#endif /* not inhibit_libc */
1591#endif /* not BLOCK_PROFILER_CODE */
1592#endif /* L_bb */
203b91b9 1593\f
6ffe3a32
JM
1594/* Default free-store management functions for C++, per sections 12.5 and
1595 17.3.3 of the Working Paper. */
203b91b9 1596
ec06f00a 1597#ifdef L_op_new
6ffe3a32
JM
1598/* operator new (size_t), described in 17.3.3.5. This function is used by
1599 C++ programs to allocate a block of memory to hold a single object. */
203b91b9 1600
6ffe3a32 1601typedef void (*vfp)(void);
203b91b9
RS
1602extern vfp __new_handler;
1603
1604void *
ec06f00a 1605__builtin_new (size_t sz)
203b91b9
RS
1606{
1607 void *p;
1608
bcea2185
RS
1609 /* malloc (0) is unpredictable; avoid it. */
1610 if (sz == 0)
1611 sz = 1;
ecbe06a1 1612 p = (void *) malloc (sz);
442e881d
RK
1613 while (p == 0)
1614 {
1615 (*__new_handler) ();
1616 p = (void *) malloc (sz);
1617 }
1618
203b91b9
RS
1619 return p;
1620}
ec06f00a 1621#endif /* L_op_new */
203b91b9 1622
4c548483 1623#ifdef L_op_vnew
6ffe3a32
JM
1624/* void * operator new [] (size_t), described in 17.3.3.6. This function
1625 is used by C++ programs to allocate a block of memory for an array. */
1626
1627extern void * __builtin_new (size_t);
1628
1629void *
1630__builtin_vec_new (size_t sz)
1631{
1632 return __builtin_new (sz);
1633}
4c548483 1634#endif /* L_op_vnew */
6ffe3a32 1635
ec06f00a 1636#ifdef L_new_handler
6ffe3a32
JM
1637/* set_new_handler (fvoid_t *) and the default new handler, described in
1638 17.3.3.2 and 17.3.3.5. These functions define the result of a failure
1639 to allocate the amount of memory requested from operator new or new []. */
fffa6914 1640
c74d5583 1641#ifndef inhibit_libc
fffa6914 1642/* This gets us __GNU_LIBRARY__. */
98126ed6 1643#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
fffa6914
RS
1644#include <stdio.h>
1645
1646#ifdef __GNU_LIBRARY__
1647 /* Avoid forcing the library's meaning of `write' on the user program
e45d9b98 1648 by using the "internal" name (for use within the library) */
fffa6914
RS
1649#define write(fd, buf, n) __write((fd), (buf), (n))
1650#endif
c74d5583 1651#endif /* inhibit_libc */
fffa6914 1652
203b91b9 1653typedef void (*vfp)(void);
6ffe3a32 1654void __default_new_handler (void);
203b91b9 1655
442e881d 1656vfp __new_handler = __default_new_handler;
203b91b9 1657
203b91b9 1658vfp
6ffe3a32 1659set_new_handler (vfp handler)
203b91b9
RS
1660{
1661 vfp prev_handler;
1662
1663 prev_handler = __new_handler;
442e881d 1664 if (handler == 0) handler = __default_new_handler;
203b91b9
RS
1665 __new_handler = handler;
1666 return prev_handler;
1667}
1668
b1166fae
RS
1669#define MESSAGE "Virtual memory exceeded in `new'\n"
1670
6ffe3a32 1671void
442e881d 1672__default_new_handler ()
203b91b9 1673{
2c62c124 1674#ifndef inhibit_libc
203b91b9
RS
1675 /* don't use fprintf (stderr, ...) because it may need to call malloc. */
1676 /* This should really print the name of the program, but that is hard to
1677 do. We need a standard, clean way to get at the name. */
b1166fae 1678 write (2, MESSAGE, sizeof (MESSAGE));
2c62c124 1679#endif
203b91b9
RS
1680 /* don't call exit () because that may call global destructors which
1681 may cause a loop. */
1682 _exit (-1);
1683}
1684#endif
203b91b9 1685
ec06f00a 1686#ifdef L_op_delete
6ffe3a32
JM
1687/* operator delete (void *), described in 17.3.3.3. This function is used
1688 by C++ programs to return to the free store a block of memory allocated
1689 as a single object. */
1690
203b91b9 1691void
ec06f00a 1692__builtin_delete (void *ptr)
203b91b9
RS
1693{
1694 if (ptr)
1695 free (ptr);
1696}
203b91b9 1697#endif
6ffe3a32 1698
4c548483 1699#ifdef L_op_vdel
6ffe3a32
JM
1700/* operator delete [] (void *), described in 17.3.3.4. This function is
1701 used by C++ programs to return to the free store a block of memory
1702 allocated as an array. */
1703
1704extern void __builtin_delete (void *);
1705
1706void
1707__builtin_vec_delete (void *ptr)
1708{
1709 __builtin_delete (ptr);
1710}
1711#endif
1712
1713/* End of C++ free-store management functions */
ec06f00a 1714\f
203b91b9
RS
1715#ifdef L_shtab
1716unsigned int __shtab[] = {
1717 0x00000001, 0x00000002, 0x00000004, 0x00000008,
1718 0x00000010, 0x00000020, 0x00000040, 0x00000080,
1719 0x00000100, 0x00000200, 0x00000400, 0x00000800,
1720 0x00001000, 0x00002000, 0x00004000, 0x00008000,
1721 0x00010000, 0x00020000, 0x00040000, 0x00080000,
1722 0x00100000, 0x00200000, 0x00400000, 0x00800000,
1723 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1724 0x10000000, 0x20000000, 0x40000000, 0x80000000
1725 };
1726#endif
1727\f
1728#ifdef L_clear_cache
1729/* Clear part of an instruction cache. */
1730
1731#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1732
1733void
1734__clear_cache (beg, end)
1735 char *beg, *end;
1736{
e1178973
KKT
1737#ifdef CLEAR_INSN_CACHE
1738 CLEAR_INSN_CACHE (beg, end);
1739#else
203b91b9
RS
1740#ifdef INSN_CACHE_SIZE
1741 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1742 static int initialized = 0;
1743 int offset;
b6422cca
RS
1744 void *start_addr
1745 void *end_addr;
203b91b9
RS
1746 typedef (*function_ptr) ();
1747
1748#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1749 /* It's cheaper to clear the whole cache.
1750 Put in a series of jump instructions so that calling the beginning
1751 of the cache will clear the whole thing. */
1752
1753 if (! initialized)
1754 {
1755 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1756 & -INSN_CACHE_LINE_WIDTH);
1757 int end_ptr = ptr + INSN_CACHE_SIZE;
1758
1759 while (ptr < end_ptr)
1760 {
1761 *(INSTRUCTION_TYPE *)ptr
1762 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1763 ptr += INSN_CACHE_LINE_WIDTH;
1764 }
1765 *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1766
1767 initialized = 1;
1768 }
1769
1770 /* Call the beginning of the sequence. */
1771 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1772 & -INSN_CACHE_LINE_WIDTH))
1773 ());
1774
1775#else /* Cache is large. */
1776
1777 if (! initialized)
1778 {
1779 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1780 & -INSN_CACHE_LINE_WIDTH);
1781
1782 while (ptr < (int) array + sizeof array)
1783 {
1784 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1785 ptr += INSN_CACHE_LINE_WIDTH;
1786 }
1787
1788 initialized = 1;
1789 }
1790
1791 /* Find the location in array that occupies the same cache line as BEG. */
1792
1793 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1794 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1795 & -INSN_CACHE_PLANE_SIZE)
1796 + offset);
1797
1798 /* Compute the cache alignment of the place to stop clearing. */
1799#if 0 /* This is not needed for gcc's purposes. */
1800 /* If the block to clear is bigger than a cache plane,
1801 we clear the entire cache, and OFFSET is already correct. */
1802 if (end < beg + INSN_CACHE_PLANE_SIZE)
1803#endif
1804 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1805 & -INSN_CACHE_LINE_WIDTH)
1806 & (INSN_CACHE_PLANE_SIZE - 1));
1807
1808#if INSN_CACHE_DEPTH > 1
1809 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1810 if (end_addr <= start_addr)
1811 end_addr += INSN_CACHE_PLANE_SIZE;
1812
1813 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1814 {
1815 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1816 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1817
1818 while (addr != stop)
1819 {
1820 /* Call the return instruction at ADDR. */
1821 ((function_ptr) addr) ();
1822
1823 addr += INSN_CACHE_LINE_WIDTH;
1824 }
1825 }
1826#else /* just one plane */
1827 do
1828 {
1829 /* Call the return instruction at START_ADDR. */
1830 ((function_ptr) start_addr) ();
1831
1832 start_addr += INSN_CACHE_LINE_WIDTH;
1833 }
1834 while ((start_addr % INSN_CACHE_SIZE) != offset);
1835#endif /* just one plane */
1836#endif /* Cache is large */
1837#endif /* Cache exists */
e1178973 1838#endif /* CLEAR_INSN_CACHE */
203b91b9
RS
1839}
1840
1841#endif /* L_clear_cache */
1842\f
1843#ifdef L_trampoline
1844
1845/* Jump to a trampoline, loading the static chain address. */
1846
1847#ifdef TRANSFER_FROM_TRAMPOLINE
1848TRANSFER_FROM_TRAMPOLINE
1849#endif
1850
c1381fd3
KKT
1851#if defined (NeXT) && defined (__MACH__)
1852
1853/* Make stack executable so we can call trampolines on stack.
1854 This is called from INITIALIZE_TRAMPOLINE in next.h. */
c5df463e
RK
1855#ifdef NeXTStep21
1856 #include <mach.h>
1857#else
1858 #include <mach/mach.h>
1859#endif
c1381fd3
KKT
1860
1861void
1862__enable_execute_stack (addr)
1863 char *addr;
1864{
1865 kern_return_t r;
1866 char *eaddr = addr + TRAMPOLINE_SIZE;
1867 vm_address_t a = (vm_address_t) addr;
1868
1869 /* turn on execute access on stack */
1870 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
1871 if (r != KERN_SUCCESS)
1872 {
1873 mach_error("vm_protect VM_PROT_ALL", r);
1874 exit(1);
1875 }
1876
1877 /* We inline the i-cache invalidation for speed */
1878
1879#ifdef CLEAR_INSN_CACHE
1880 CLEAR_INSN_CACHE (addr, eaddr);
1881#else
1882 __clear_cache ((int) addr, (int) eaddr);
1883#endif
1884}
1885
1886#endif /* defined (NeXT) && defined (__MACH__) */
1887
203b91b9
RS
1888#ifdef __convex__
1889
1890/* Make stack executable so we can call trampolines on stack.
1891 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
1892
1893#include <sys/mman.h>
1894#include <sys/vmparam.h>
1895#include <machine/machparam.h>
1896
1897void
1898__enable_execute_stack ()
1899{
1900 int fp;
1901 static unsigned lowest = USRSTACK;
1902 unsigned current = (unsigned) &fp & -NBPG;
1903
1904 if (lowest > current)
1905 {
1906 unsigned len = lowest - current;
1907 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1908 lowest = current;
1909 }
1910
1911 /* Clear instruction cache in case an old trampoline is in it. */
1912 asm ("pich");
1913}
1914#endif /* __convex__ */
b335c2cc 1915
0c8ae3d3
RK
1916#ifdef __DOLPHIN__
1917
1918/* Modified from the convex -code above. */
1919
1920#include <sys/param.h>
1921#include <errno.h>
1922#include <sys/m88kbcs.h>
1923
1924void
1925__enable_execute_stack ()
1926{
1927 int save_errno;
1928 static unsigned long lowest = USRSTACK;
1929 unsigned long current = (unsigned long) &save_errno & -NBPC;
1930
1931 /* Ignore errno being set. memctl sets errno to EINVAL whenever the
1932 address is seen as 'negative'. That is the case with the stack. */
1933
1934 save_errno=errno;
1935 if (lowest > current)
1936 {
1937 unsigned len=lowest-current;
1938 memctl(current,len,MCT_TEXT);
1939 lowest = current;
1940 }
1941 else
1942 memctl(current,NBPC,MCT_TEXT);
1943 errno=save_errno;
1944}
1945
1946#endif /* __DOLPHIN__ */
1947
b335c2cc
TW
1948#ifdef __pyr__
1949
98126ed6 1950#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
b335c2cc
TW
1951#include <stdio.h>
1952#include <sys/mman.h>
1953#include <sys/types.h>
1954#include <sys/param.h>
1955#include <sys/vmmac.h>
1956
1957/* Modified from the convex -code above.
1958 mremap promises to clear the i-cache. */
1959
1960void
1961__enable_execute_stack ()
1962{
1963 int fp;
1964 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
1965 PROT_READ|PROT_WRITE|PROT_EXEC))
1966 {
1967 perror ("mprotect in __enable_execute_stack");
1968 fflush (stderr);
1969 abort ();
1970 }
1971}
1972#endif /* __pyr__ */
203b91b9
RS
1973#endif /* L_trampoline */
1974\f
1975#ifdef L__main
1976
1977#include "gbl-ctors.h"
c06cff95
RS
1978/* Some systems use __main in a way incompatible with its use in gcc, in these
1979 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
1980 give the same symbol without quotes for an alternative entry point. You
1981 must define both, or niether. */
1982#ifndef NAME__MAIN
1983#define NAME__MAIN "__main"
1984#define SYMBOL__MAIN __main
1985#endif
203b91b9 1986
68d69835 1987#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
203b91b9
RS
1988/* Run all the global destructors on exit from the program. */
1989
1990void
1991__do_global_dtors ()
1992{
89cf554b
RS
1993#ifdef DO_GLOBAL_DTORS_BODY
1994 DO_GLOBAL_DTORS_BODY;
1995#else
566b213a
JM
1996 func_ptr *p;
1997 for (p = __DTOR_LIST__ + 1; *p; )
1998 (*p++) ();
89cf554b 1999#endif
203b91b9 2000}
68d69835 2001#endif
203b91b9
RS
2002
2003#ifndef INIT_SECTION_ASM_OP
2004/* Run all the global constructors on entry to the program. */
2005
135461d9 2006#ifndef ON_EXIT
203b91b9
RS
2007#define ON_EXIT(a, b)
2008#else
2009/* Make sure the exit routine is pulled in to define the globals as
2010 bss symbols, just in case the linker does not automatically pull
2011 bss definitions from the library. */
2012
2013extern int _exit_dummy_decl;
2014int *_exit_dummy_ref = &_exit_dummy_decl;
2015#endif /* ON_EXIT */
2016
2017void
2018__do_global_ctors ()
2019{
2020 DO_GLOBAL_CTORS_BODY;
135461d9 2021 ON_EXIT (__do_global_dtors, 0);
203b91b9 2022}
b335c2cc 2023#endif /* no INIT_SECTION_ASM_OP */
203b91b9 2024
b335c2cc 2025#if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
203b91b9
RS
2026/* Subroutine called automatically by `main'.
2027 Compiling a global function named `main'
2028 produces an automatic call to this function at the beginning.
2029
2030 For many systems, this routine calls __do_global_ctors.
2031 For systems which support a .init section we use the .init section
2032 to run __do_global_ctors, so we need not do anything here. */
2033
2034void
c06cff95 2035SYMBOL__MAIN ()
203b91b9
RS
2036{
2037 /* Support recursive calls to `main': run initializers just once. */
b6422cca 2038 static int initialized = 0;
203b91b9
RS
2039 if (! initialized)
2040 {
2041 initialized = 1;
2042 __do_global_ctors ();
2043 }
2044}
b335c2cc 2045#endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
203b91b9
RS
2046
2047#endif /* L__main */
2048\f
ad38743d 2049#ifdef L_ctors
203b91b9
RS
2050
2051#include "gbl-ctors.h"
2052
2053/* Provide default definitions for the lists of constructors and
2054 destructors, so that we don't get linker errors. These symbols are
2055 intentionally bss symbols, so that gld and/or collect will provide
2056 the right values. */
2057
2058/* We declare the lists here with two elements each,
2059 so that they are valid empty lists if no other definition is loaded. */
b335c2cc 2060#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
d15d0264
RS
2061#ifdef __NeXT__
2062/* After 2.3, try this definition on all systems. */
2063func_ptr __CTOR_LIST__[2] = {0, 0};
2064func_ptr __DTOR_LIST__[2] = {0, 0};
2065#else
203b91b9
RS
2066func_ptr __CTOR_LIST__[2];
2067func_ptr __DTOR_LIST__[2];
d15d0264 2068#endif
b335c2cc 2069#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
ad38743d
RS
2070#endif /* L_ctors */
2071\f
2072#ifdef L_exit
2073
2074#include "gbl-ctors.h"
203b91b9
RS
2075
2076#ifndef ON_EXIT
2077
2078/* If we have no known way of registering our own __do_global_dtors
2079 routine so that it will be invoked at program exit time, then we
2080 have to define our own exit routine which will get this to happen. */
2081
2082extern void __do_global_dtors ();
2083extern void _cleanup ();
003be455 2084extern void _exit () __attribute__ ((noreturn));
203b91b9
RS
2085
2086void
2087exit (status)
2088 int status;
2089{
3a5ece65 2090#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
203b91b9 2091 __do_global_dtors ();
5fd507a9 2092#endif
203b91b9
RS
2093#ifdef EXIT_BODY
2094 EXIT_BODY;
2095#else
2096 _cleanup ();
2097#endif
2098 _exit (status);
2099}
2100
2101#else
2102int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
2103#endif
2104
2105#endif /* L_exit */
2106\f
ad912eec
MS
2107#ifdef L_eh
2108typedef struct {
2109 void *start;
2110 void *end;
2111 void *exception_handler;
2112} exception_table;
2113
2114struct exception_table_node {
2115 exception_table *table;
2116 void *start;
2117 void *end;
2118 struct exception_table_node *next;
2119};
2120
2121static int except_table_pos = 0;
2122static void *except_pc = (void *)0;
2123static struct exception_table_node *exception_table_list = 0;
2124
2125static exception_table *
2126find_exception_table (pc)
2127 void* pc;
2128{
2129 register struct exception_table_node *table = exception_table_list;
2130 for ( ; table != 0; table = table->next)
2131 {
2132 if (table->start <= pc && table->end > pc)
2133 return table->table;
2134 }
2135 return 0;
2136}
2137
2138/* this routine takes a pc, and the address of the exception handler associated
2139 with the closest exception table handler entry associated with that PC,
2140 or 0 if there are no table entries the PC fits in. The algorithm works
2141 something like this:
2142
2143 while(current_entry exists) {
2144 if(current_entry.start < pc )
2145 current_entry = next_entry;
2146 else {
2147 if(prev_entry.start <= pc && prev_entry.end > pc) {
2148 save pointer to prev_entry;
2149 return prev_entry.exception_handler;
2150 }
2151 else return 0;
2152 }
2153 }
2154 return 0;
2155
2156 Assuming a correctly sorted table (ascending order) this routine should
2157 return the tighest match...
2158
2159 In the advent of a tie, we have to give the last entry, as it represents
2160 an inner block.
2161 */
2162
2163
2164void *
2165__find_first_exception_table_match(pc)
2166void *pc;
2167{
2168 exception_table *table = find_exception_table (pc);
2169 int pos = 0;
2170 int best = 0;
2171 if (table == 0)
2172 return (void*)0;
2173#if 0
2174 printf("find_first_exception_table_match(): pc = %x!\n",pc);
2175#endif
2176
2177 except_pc = pc;
2178
2179#if 0
2180 /* We can't do this yet, as we don't know that the table is sorted. */
2181 do {
2182 ++pos;
2183 if (table[pos].start > except_pc)
2184 /* found the first table[pos].start > except_pc, so the previous
2185 entry better be the one we want! */
2186 break;
2187 } while(table[pos].exception_handler != (void*)-1);
2188
2189 --pos;
2190 if (table[pos].start <= except_pc && table[pos].end > except_pc)
2191 {
2192 except_table_pos = pos;
2193#if 0
2194 printf("find_first_eh_table_match(): found match: %x\n",table[pos].exception_handler);
2195#endif
2196 return table[pos].exception_handler;
2197 }
2198#else
2199 while (table[++pos].exception_handler != (void*)-1) {
2200 if (table[pos].start <= except_pc && table[pos].end > except_pc)
2201 {
2202 /* This can apply. Make sure it is better or as good as the previous
2203 best. */
2204 /* The best one ends first. */
2205 if (best == 0 || (table[pos].end <= table[best].end
2206 /* The best one starts last. */
2207 && table[pos].start >= table[best].start))
2208 best = pos;
2209 }
2210 }
2211 if (best != 0)
2212 return table[best].exception_handler;
2213#endif
2214
2215#if 0
2216 printf("find_first_eh_table_match(): else: returning NULL!\n");
2217#endif
2218 return (void*)0;
2219}
2220
2221int
2222__throw_type_match (const char *catch_type, const char *throw_type)
2223{
2224#if 0
2225 printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
2226 catch_type, throw_type);
2227#endif
2228 return strcmp (catch_type, throw_type);
2229}
2230
2231void
2232__register_exceptions (exception_table *table)
2233{
2234 struct exception_table_node *node = (struct exception_table_node*)
2235 malloc (sizeof (struct exception_table_node));
2236 exception_table *range = table + 1;
2237 node->table = table;
2238
2239 /* This look can be optimized away either if the table
2240 is sorted, or if we pass in extra parameters. */
2241 node->start = range->start;
2242 node->end = range->end;
2243 for (range++ ; range->start != (void*)(-1); range++)
2244 {
2245 if (range->start < node->start)
2246 node->start = range->start;
56031823 2247 if (range->end > node->end)
ad912eec
MS
2248 node->end = range->end;
2249 }
2250
2251 node->next = exception_table_list;
2252 exception_table_list = node;
2253}
56031823 2254
1e58f107 2255#if #machine(i386)
56031823
MS
2256void
2257__unwind_function(void *ptr)
2258{
2259 asm("movl 8(%esp),%ecx");
2260 /* Undo current frame */
2261 asm("movl %ebp,%esp");
2262 asm("popl %ebp");
2263 asm("# like ret, but stay here");
2264 asm("addl $4,%esp");
2265
2266 /* Now, undo previous frame. */
2267 /* This is a test routine, as we have to dynamically probe to find out
2268 what to pop for certain, this is just a guess. */
2269 asm("leal -16(%ebp),%esp");
2270 asm("pop %eax # really for popl %ebx");
2271 asm("pop %eax # really for popl %esi");
2272 asm("pop %eax # really for popl %edi");
2273 asm("movl %ebp,%esp");
2274 asm("popl %ebp");
2275
2276 asm("movl %ecx,0(%esp)");
2277 asm("ret");
2278}
2279#endif
ad912eec 2280#endif /* L_eh */
efc955c7
JM
2281\f
2282#ifdef L_pure
2c62c124
JM
2283#ifndef inhibit_libc
2284/* This gets us __GNU_LIBRARY__. */
2285#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
2286#include <stdio.h>
2287
2288#ifdef __GNU_LIBRARY__
2289 /* Avoid forcing the library's meaning of `write' on the user program
2290 by using the "internal" name (for use within the library) */
2291#define write(fd, buf, n) __write((fd), (buf), (n))
2292#endif
2293#endif /* inhibit_libc */
2294
efc955c7 2295#define MESSAGE "pure virtual method called\n"
2c62c124 2296
efc955c7
JM
2297void
2298__pure_virtual ()
2299{
2c62c124 2300#ifndef inhibit_libc
efc955c7 2301 write (2, MESSAGE, sizeof (MESSAGE) - 1);
2c62c124 2302#endif
efc955c7
JM
2303 _exit (-1);
2304}
2305#endif
This page took 0.693835 seconds and 5 git commands to generate.