]> gcc.gnu.org Git - gcc.git/blame - gcc/libgcc2.c
formatting tweaks
[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. */
8b7677be 3/* Copyright (C) 1989, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
203b91b9
RS
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
a35311b0
RK
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
203b91b9 21
d5c88b0a
RK
22/* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
203b91b9
RS
26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License. */
28
29/* It is incorrect to include config.h here, because this file is being
30 compiled for the target, and hence definitions concerning only the host
31 do not apply. */
32
0dadecf6 33#include "tconfig.h"
bfe655f9 34#include "machmode.h"
daefd78b 35#include "defaults.h"
b335c2cc 36#ifndef L_trampoline
8717efce 37#include <stddef.h>
b335c2cc 38#endif
203b91b9
RS
39
40/* Don't use `fancy_abort' here even if config.h says to use it. */
41#ifdef abort
42#undef abort
43#endif
44
daefd78b
JM
45#if (SUPPORTS_WEAK == 1) && defined (ASM_OUTPUT_DEF)
46#define WEAK_ALIAS
47#endif
48
f76b9db2
ILT
49/* Permit the tm.h file to select the endianness to use just for this
50 file. This is used when the endianness is determined when the
51 compiler is run. */
52
53#ifndef LIBGCC2_WORDS_BIG_ENDIAN
54#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
55#endif
56
ab495388
RS
57/* In the first part of this file, we are interfacing to calls generated
58 by the compiler itself. These calls pass values into these routines
59 which have very specific modes (rather than very specific types), and
60 these compiler-generated calls also expect any return values to have
61 very specific modes (rather than very specific types). Thus, we need
62 to avoid using regular C language type names in this part of the file
63 because the sizes for those types can be configured to be anything.
64 Instead we use the following special type names. */
65
b2bf5aef
RK
66typedef unsigned int UQItype __attribute__ ((mode (QI)));
67typedef int SItype __attribute__ ((mode (SI)));
68typedef unsigned int USItype __attribute__ ((mode (SI)));
69typedef int DItype __attribute__ ((mode (DI)));
70typedef unsigned int UDItype __attribute__ ((mode (DI)));
a07805c0 71
b2bf5aef
RK
72typedef float SFtype __attribute__ ((mode (SF)));
73typedef float DFtype __attribute__ ((mode (DF)));
a07805c0 74
e0799b34 75#if LONG_DOUBLE_TYPE_SIZE == 96
b2bf5aef 76typedef float XFtype __attribute__ ((mode (XF)));
258d1356
CH
77#endif
78#if LONG_DOUBLE_TYPE_SIZE == 128
b2bf5aef 79typedef float TFtype __attribute__ ((mode (TF)));
258d1356 80#endif
ab495388 81
a07805c0 82typedef int word_type __attribute__ ((mode (__word__)));
4be7c28f 83
a1c37766 84/* Make sure that we don't accidentally use any normal C language built-in
ab495388
RS
85 type names in the first part of this file. Instead we want to use *only*
86 the type names defined above. The following macro definitions insure
19197caa 87 that if we *do* accidentally use some normal C language built-in type name,
ab495388
RS
88 we will get a syntax error. */
89
90#define char bogus_type
91#define short bogus_type
92#define int bogus_type
93#define long bogus_type
94#define unsigned bogus_type
95#define float bogus_type
96#define double bogus_type
97
98#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
99
100/* DIstructs are pairs of SItype values in the order determined by
f76b9db2 101 LIBGCC2_WORDS_BIG_ENDIAN. */
203b91b9 102
f76b9db2 103#if LIBGCC2_WORDS_BIG_ENDIAN
ab495388 104 struct DIstruct {SItype high, low;};
203b91b9 105#else
ab495388 106 struct DIstruct {SItype low, high;};
203b91b9
RS
107#endif
108
ab495388
RS
109/* We need this union to unpack/pack DImode values, since we don't have
110 any arithmetic yet. Incoming DImode parameters are stored into the
111 `ll' field, and the unpacked result is read from the struct `s'. */
203b91b9
RS
112
113typedef union
114{
ab495388
RS
115 struct DIstruct s;
116 DItype ll;
117} DIunion;
203b91b9 118
536bfcd0
RK
119#if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\
120 || defined (L_divdi3) || defined (L_udivdi3) \
121 || defined (L_moddi3) || defined (L_umoddi3))
203b91b9
RS
122
123#include "longlong.h"
124
125#endif /* udiv or mul */
126
ab495388
RS
127extern DItype __fixunssfdi (SFtype a);
128extern DItype __fixunsdfdi (DFtype a);
96fc2623 129#if LONG_DOUBLE_TYPE_SIZE == 96
f70ad14c 130extern DItype __fixunsxfdi (XFtype a);
96fc2623
RS
131#endif
132#if LONG_DOUBLE_TYPE_SIZE == 128
cc3cdac3 133extern DItype __fixunstfdi (TFtype a);
96fc2623 134#endif
203b91b9
RS
135\f
136#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
137#if defined (L_divdi3) || defined (L_moddi3)
138static inline
139#endif
ab495388 140DItype
203b91b9 141__negdi2 (u)
ab495388 142 DItype u;
203b91b9 143{
ab495388
RS
144 DIunion w;
145 DIunion uu;
203b91b9
RS
146
147 uu.ll = u;
148
149 w.s.low = -uu.s.low;
ab495388 150 w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
203b91b9
RS
151
152 return w.ll;
153}
154#endif
155\f
203b91b9 156#ifdef L_lshrdi3
ab495388 157DItype
203b91b9 158__lshrdi3 (u, b)
ab495388 159 DItype u;
b799cfc3 160 word_type b;
203b91b9 161{
ab495388 162 DIunion w;
b799cfc3 163 word_type bm;
ab495388 164 DIunion uu;
203b91b9
RS
165
166 if (b == 0)
167 return u;
168
169 uu.ll = u;
170
ab495388 171 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
203b91b9
RS
172 if (bm <= 0)
173 {
174 w.s.high = 0;
ab495388 175 w.s.low = (USItype)uu.s.high >> -bm;
203b91b9
RS
176 }
177 else
178 {
ab495388
RS
179 USItype carries = (USItype)uu.s.high << bm;
180 w.s.high = (USItype)uu.s.high >> b;
181 w.s.low = ((USItype)uu.s.low >> b) | carries;
203b91b9
RS
182 }
183
184 return w.ll;
185}
186#endif
187
188#ifdef L_ashldi3
ab495388 189DItype
203b91b9 190__ashldi3 (u, b)
ab495388 191 DItype u;
b799cfc3 192 word_type b;
203b91b9 193{
ab495388 194 DIunion w;
b799cfc3 195 word_type bm;
ab495388 196 DIunion uu;
203b91b9
RS
197
198 if (b == 0)
199 return u;
200
201 uu.ll = u;
202
ab495388 203 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
203b91b9
RS
204 if (bm <= 0)
205 {
206 w.s.low = 0;
ab495388 207 w.s.high = (USItype)uu.s.low << -bm;
203b91b9
RS
208 }
209 else
210 {
ab495388
RS
211 USItype carries = (USItype)uu.s.low >> bm;
212 w.s.low = (USItype)uu.s.low << b;
213 w.s.high = ((USItype)uu.s.high << b) | carries;
203b91b9
RS
214 }
215
216 return w.ll;
217}
218#endif
219
220#ifdef L_ashrdi3
ab495388 221DItype
203b91b9 222__ashrdi3 (u, b)
ab495388 223 DItype u;
b799cfc3 224 word_type b;
203b91b9 225{
ab495388 226 DIunion w;
b799cfc3 227 word_type bm;
ab495388 228 DIunion uu;
203b91b9
RS
229
230 if (b == 0)
231 return u;
232
233 uu.ll = u;
234
ab495388 235 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
203b91b9
RS
236 if (bm <= 0)
237 {
238 /* w.s.high = 1..1 or 0..0 */
ab495388 239 w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
203b91b9
RS
240 w.s.low = uu.s.high >> -bm;
241 }
242 else
243 {
ab495388 244 USItype carries = (USItype)uu.s.high << bm;
203b91b9 245 w.s.high = uu.s.high >> b;
ab495388 246 w.s.low = ((USItype)uu.s.low >> b) | carries;
203b91b9
RS
247 }
248
249 return w.ll;
250}
251#endif
252\f
aa66bd06
RS
253#ifdef L_ffsdi2
254DItype
255__ffsdi2 (u)
256 DItype u;
257{
258 DIunion uu, w;
259 uu.ll = u;
260 w.s.high = 0;
261 w.s.low = ffs (uu.s.low);
262 if (w.s.low != 0)
de6cbba6 263 return w.ll;
aa66bd06
RS
264 w.s.low = ffs (uu.s.high);
265 if (w.s.low != 0)
266 {
267 w.s.low += BITS_PER_UNIT * sizeof (SItype);
de6cbba6 268 return w.ll;
aa66bd06 269 }
de6cbba6 270 return w.ll;
aa66bd06
RS
271}
272#endif
273\f
203b91b9 274#ifdef L_muldi3
ab495388 275DItype
203b91b9 276__muldi3 (u, v)
ab495388 277 DItype u, v;
203b91b9 278{
ab495388
RS
279 DIunion w;
280 DIunion uu, vv;
203b91b9
RS
281
282 uu.ll = u,
283 vv.ll = v;
284
285 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
ab495388
RS
286 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
287 + (USItype) uu.s.high * (USItype) vv.s.low);
203b91b9
RS
288
289 return w.ll;
290}
291#endif
292\f
3904131a 293#ifdef L_udiv_w_sdiv
ce13d15f 294#if defined (sdiv_qrnnd)
431b1ee0 295USItype
3904131a 296__udiv_w_sdiv (rp, a1, a0, d)
431b1ee0
TG
297 USItype *rp, a1, a0, d;
298{
299 USItype q, r;
300 USItype c0, c1, b1;
301
302 if ((SItype) d >= 0)
303 {
7bc7d45a 304 if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
431b1ee0
TG
305 {
306 /* dividend, divisor, and quotient are nonnegative */
307 sdiv_qrnnd (q, r, a1, a0, d);
308 }
309 else
310 {
311 /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
7bc7d45a 312 sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
431b1ee0
TG
313 /* Divide (c1*2^32 + c0) by d */
314 sdiv_qrnnd (q, r, c1, c0, d);
315 /* Add 2^31 to quotient */
7bc7d45a 316 q += (USItype) 1 << (SI_TYPE_SIZE - 1);
431b1ee0
TG
317 }
318 }
319 else
320 {
321 b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
322 c1 = a1 >> 1; /* A/2 */
7bc7d45a 323 c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
431b1ee0
TG
324
325 if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
326 {
327 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
328
329 r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
330 if ((d & 1) != 0)
331 {
332 if (r >= q)
333 r = r - q;
334 else if (q - r <= d)
335 {
336 r = r - q + d;
337 q--;
338 }
339 else
340 {
341 r = r - q + 2*d;
342 q -= 2;
343 }
344 }
345 }
346 else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
347 {
348 c1 = (b1 - 1) - c1;
349 c0 = ~c0; /* logical NOT */
350
351 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
352
353 q = ~q; /* (A/2)/b1 */
354 r = (b1 - 1) - r;
355
356 r = 2*r + (a0 & 1); /* A/(2*b1) */
357
358 if ((d & 1) != 0)
359 {
360 if (r >= q)
361 r = r - q;
362 else if (q - r <= d)
363 {
364 r = r - q + d;
365 q--;
366 }
367 else
368 {
369 r = r - q + 2*d;
370 q -= 2;
371 }
372 }
373 }
374 else /* Implies c1 = b1 */
375 { /* Hence a1 = d - 1 = 2*b1 - 1 */
376 if (a0 >= -d)
377 {
378 q = -1;
379 r = a0 + d;
380 }
381 else
382 {
383 q = -2;
384 r = a0 + 2*d;
385 }
386 }
387 }
388
389 *rp = r;
390 return q;
391}
ce13d15f
RK
392#else
393/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
394USItype
395__udiv_w_sdiv (rp, a1, a0, d)
396 USItype *rp, a1, a0, d;
397{}
398#endif
431b1ee0
TG
399#endif
400\f
536bfcd0
RK
401#if (defined (L_udivdi3) || defined (L_divdi3) || \
402 defined (L_umoddi3) || defined (L_moddi3))
403#define L_udivmoddi4
404#endif
405
203b91b9 406#ifdef L_udivmoddi4
ab495388 407static const UQItype __clz_tab[] =
203b91b9
RS
408{
409 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,
410 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,
411 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,
412 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,
413 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,
414 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,
415 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,
416 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,
417};
418
536bfcd0
RK
419#if (defined (L_udivdi3) || defined (L_divdi3) || \
420 defined (L_umoddi3) || defined (L_moddi3))
421static inline
422#endif
ab495388 423UDItype
203b91b9 424__udivmoddi4 (n, d, rp)
ab495388
RS
425 UDItype n, d;
426 UDItype *rp;
203b91b9 427{
ab495388
RS
428 DIunion ww;
429 DIunion nn, dd;
430 DIunion rr;
431 USItype d0, d1, n0, n1, n2;
432 USItype q0, q1;
433 USItype b, bm;
203b91b9
RS
434
435 nn.ll = n;
436 dd.ll = d;
437
438 d0 = dd.s.low;
439 d1 = dd.s.high;
440 n0 = nn.s.low;
441 n1 = nn.s.high;
442
443#if !UDIV_NEEDS_NORMALIZATION
444 if (d1 == 0)
445 {
446 if (d0 > n1)
447 {
448 /* 0q = nn / 0D */
449
450 udiv_qrnnd (q0, n0, n1, n0, d0);
451 q1 = 0;
452
453 /* Remainder in n0. */
454 }
455 else
456 {
457 /* qq = NN / 0d */
458
459 if (d0 == 0)
460 d0 = 1 / d0; /* Divide intentionally by zero. */
461
462 udiv_qrnnd (q1, n1, 0, n1, d0);
463 udiv_qrnnd (q0, n0, n1, n0, d0);
464
465 /* Remainder in n0. */
466 }
467
468 if (rp != 0)
469 {
470 rr.s.low = n0;
471 rr.s.high = 0;
472 *rp = rr.ll;
473 }
474 }
475
476#else /* UDIV_NEEDS_NORMALIZATION */
477
478 if (d1 == 0)
479 {
480 if (d0 > n1)
481 {
482 /* 0q = nn / 0D */
483
484 count_leading_zeros (bm, d0);
485
486 if (bm != 0)
487 {
488 /* Normalize, i.e. make the most significant bit of the
489 denominator set. */
490
491 d0 = d0 << bm;
ab495388 492 n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
203b91b9
RS
493 n0 = n0 << bm;
494 }
495
496 udiv_qrnnd (q0, n0, n1, n0, d0);
497 q1 = 0;
498
499 /* Remainder in n0 >> bm. */
500 }
501 else
502 {
503 /* qq = NN / 0d */
504
505 if (d0 == 0)
506 d0 = 1 / d0; /* Divide intentionally by zero. */
507
508 count_leading_zeros (bm, d0);
509
510 if (bm == 0)
511 {
512 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
513 conclude (the most significant bit of n1 is set) /\ (the
514 leading quotient digit q1 = 1).
515
516 This special case is necessary, not an optimization.
ab495388 517 (Shifts counts of SI_TYPE_SIZE are undefined.) */
203b91b9
RS
518
519 n1 -= d0;
520 q1 = 1;
521 }
522 else
523 {
524 /* Normalize. */
525
ab495388 526 b = SI_TYPE_SIZE - bm;
203b91b9
RS
527
528 d0 = d0 << bm;
529 n2 = n1 >> b;
530 n1 = (n1 << bm) | (n0 >> b);
531 n0 = n0 << bm;
532
533 udiv_qrnnd (q1, n1, n2, n1, d0);
534 }
535
0f41302f 536 /* n1 != d0... */
203b91b9
RS
537
538 udiv_qrnnd (q0, n0, n1, n0, d0);
539
540 /* Remainder in n0 >> bm. */
541 }
542
543 if (rp != 0)
544 {
545 rr.s.low = n0 >> bm;
546 rr.s.high = 0;
547 *rp = rr.ll;
548 }
549 }
550#endif /* UDIV_NEEDS_NORMALIZATION */
551
552 else
553 {
554 if (d1 > n1)
555 {
556 /* 00 = nn / DD */
557
558 q0 = 0;
559 q1 = 0;
560
561 /* Remainder in n1n0. */
562 if (rp != 0)
563 {
564 rr.s.low = n0;
565 rr.s.high = n1;
566 *rp = rr.ll;
567 }
568 }
569 else
570 {
571 /* 0q = NN / dd */
572
573 count_leading_zeros (bm, d1);
574 if (bm == 0)
575 {
576 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
577 conclude (the most significant bit of n1 is set) /\ (the
578 quotient digit q0 = 0 or 1).
579
580 This special case is necessary, not an optimization. */
581
582 /* The condition on the next line takes advantage of that
583 n1 >= d1 (true due to program flow). */
584 if (n1 > d1 || n0 >= d0)
585 {
586 q0 = 1;
587 sub_ddmmss (n1, n0, n1, n0, d1, d0);
588 }
589 else
590 q0 = 0;
591
592 q1 = 0;
593
594 if (rp != 0)
595 {
596 rr.s.low = n0;
597 rr.s.high = n1;
598 *rp = rr.ll;
599 }
600 }
601 else
602 {
ab495388 603 USItype m1, m0;
203b91b9
RS
604 /* Normalize. */
605
ab495388 606 b = SI_TYPE_SIZE - bm;
203b91b9
RS
607
608 d1 = (d1 << bm) | (d0 >> b);
609 d0 = d0 << bm;
610 n2 = n1 >> b;
611 n1 = (n1 << bm) | (n0 >> b);
612 n0 = n0 << bm;
613
614 udiv_qrnnd (q0, n1, n2, n1, d1);
615 umul_ppmm (m1, m0, q0, d0);
616
617 if (m1 > n1 || (m1 == n1 && m0 > n0))
618 {
619 q0--;
620 sub_ddmmss (m1, m0, m1, m0, d1, d0);
621 }
622
623 q1 = 0;
624
625 /* Remainder in (n1n0 - m1m0) >> bm. */
626 if (rp != 0)
627 {
628 sub_ddmmss (n1, n0, n1, n0, m1, m0);
629 rr.s.low = (n1 << b) | (n0 >> bm);
630 rr.s.high = n1 >> bm;
631 *rp = rr.ll;
632 }
633 }
634 }
635 }
636
637 ww.s.low = q0;
638 ww.s.high = q1;
639 return ww.ll;
640}
641#endif
642
643#ifdef L_divdi3
ab495388 644UDItype __udivmoddi4 ();
f70ad14c 645
ab495388 646DItype
203b91b9 647__divdi3 (u, v)
ab495388 648 DItype u, v;
203b91b9 649{
b799cfc3 650 word_type c = 0;
ab495388
RS
651 DIunion uu, vv;
652 DItype w;
203b91b9
RS
653
654 uu.ll = u;
655 vv.ll = v;
656
657 if (uu.s.high < 0)
658 c = ~c,
659 uu.ll = __negdi2 (uu.ll);
660 if (vv.s.high < 0)
661 c = ~c,
662 vv.ll = __negdi2 (vv.ll);
663
ab495388 664 w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
203b91b9
RS
665 if (c)
666 w = __negdi2 (w);
667
668 return w;
669}
670#endif
671
672#ifdef L_moddi3
ab495388
RS
673UDItype __udivmoddi4 ();
674DItype
203b91b9 675__moddi3 (u, v)
ab495388 676 DItype u, v;
203b91b9 677{
b799cfc3 678 word_type c = 0;
ab495388
RS
679 DIunion uu, vv;
680 DItype w;
203b91b9
RS
681
682 uu.ll = u;
683 vv.ll = v;
684
685 if (uu.s.high < 0)
686 c = ~c,
687 uu.ll = __negdi2 (uu.ll);
688 if (vv.s.high < 0)
689 vv.ll = __negdi2 (vv.ll);
690
691 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
692 if (c)
693 w = __negdi2 (w);
694
695 return w;
696}
697#endif
698
699#ifdef L_umoddi3
ab495388
RS
700UDItype __udivmoddi4 ();
701UDItype
203b91b9 702__umoddi3 (u, v)
ab495388 703 UDItype u, v;
203b91b9 704{
b89a6f69 705 UDItype w;
203b91b9
RS
706
707 (void) __udivmoddi4 (u, v, &w);
708
709 return w;
710}
711#endif
712
713#ifdef L_udivdi3
ab495388
RS
714UDItype __udivmoddi4 ();
715UDItype
203b91b9 716__udivdi3 (n, d)
ab495388 717 UDItype n, d;
203b91b9 718{
ab495388 719 return __udivmoddi4 (n, d, (UDItype *) 0);
203b91b9
RS
720}
721#endif
722\f
723#ifdef L_cmpdi2
4be7c28f 724word_type
203b91b9 725__cmpdi2 (a, b)
ab495388 726 DItype a, b;
203b91b9 727{
ab495388 728 DIunion au, bu;
203b91b9
RS
729
730 au.ll = a, bu.ll = b;
731
732 if (au.s.high < bu.s.high)
733 return 0;
734 else if (au.s.high > bu.s.high)
735 return 2;
ab495388 736 if ((USItype) au.s.low < (USItype) bu.s.low)
203b91b9 737 return 0;
ab495388 738 else if ((USItype) au.s.low > (USItype) bu.s.low)
203b91b9
RS
739 return 2;
740 return 1;
741}
742#endif
743
744#ifdef L_ucmpdi2
4be7c28f 745word_type
203b91b9 746__ucmpdi2 (a, b)
ab495388 747 DItype a, b;
203b91b9 748{
ab495388 749 DIunion au, bu;
203b91b9
RS
750
751 au.ll = a, bu.ll = b;
752
ab495388 753 if ((USItype) au.s.high < (USItype) bu.s.high)
203b91b9 754 return 0;
ab495388 755 else if ((USItype) au.s.high > (USItype) bu.s.high)
203b91b9 756 return 2;
ab495388 757 if ((USItype) au.s.low < (USItype) bu.s.low)
203b91b9 758 return 0;
ab495388 759 else if ((USItype) au.s.low > (USItype) bu.s.low)
203b91b9
RS
760 return 2;
761 return 1;
762}
763#endif
764\f
ab495388
RS
765#if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
766#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
767#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
768
769DItype
770__fixunstfdi (a)
771 TFtype a;
772{
773 TFtype b;
774 UDItype v;
775
776 if (a < 0)
777 return 0;
778
779 /* Compute high word of result, as a flonum. */
780 b = (a / HIGH_WORD_COEFF);
781 /* Convert that to fixed (but not to DItype!),
782 and shift it into the high word. */
783 v = (USItype) b;
784 v <<= WORD_SIZE;
785 /* Remove high part from the TFtype, leaving the low part as flonum. */
786 a -= (TFtype)v;
787 /* Convert that to fixed (but not to DItype!) and add it in.
788 Sometimes A comes out negative. This is significant, since
789 A has more bits than a long int does. */
790 if (a < 0)
791 v -= (USItype) (- a);
792 else
793 v += (USItype) a;
794 return v;
795}
796#endif
797
798#if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
799DItype
800__fixtfdi (a)
801 TFtype a;
802{
803 if (a < 0)
804 return - __fixunstfdi (-a);
805 return __fixunstfdi (a);
806}
807#endif
808
e0799b34
RS
809#if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
810#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
811#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
812
813DItype
814__fixunsxfdi (a)
815 XFtype a;
816{
817 XFtype b;
818 UDItype v;
819
820 if (a < 0)
821 return 0;
822
823 /* Compute high word of result, as a flonum. */
824 b = (a / HIGH_WORD_COEFF);
825 /* Convert that to fixed (but not to DItype!),
826 and shift it into the high word. */
827 v = (USItype) b;
828 v <<= WORD_SIZE;
829 /* Remove high part from the XFtype, leaving the low part as flonum. */
830 a -= (XFtype)v;
831 /* Convert that to fixed (but not to DItype!) and add it in.
832 Sometimes A comes out negative. This is significant, since
833 A has more bits than a long int does. */
834 if (a < 0)
835 v -= (USItype) (- a);
836 else
837 v += (USItype) a;
838 return v;
839}
840#endif
841
842#if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
843DItype
844__fixxfdi (a)
845 XFtype a;
846{
847 if (a < 0)
848 return - __fixunsxfdi (-a);
849 return __fixunsxfdi (a);
850}
851#endif
852
203b91b9 853#ifdef L_fixunsdfdi
ab495388
RS
854#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
855#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
203b91b9 856
ab495388 857DItype
203b91b9 858__fixunsdfdi (a)
ab495388 859 DFtype a;
203b91b9 860{
ab495388
RS
861 DFtype b;
862 UDItype v;
203b91b9
RS
863
864 if (a < 0)
865 return 0;
866
867 /* Compute high word of result, as a flonum. */
868 b = (a / HIGH_WORD_COEFF);
ab495388 869 /* Convert that to fixed (but not to DItype!),
203b91b9 870 and shift it into the high word. */
ab495388 871 v = (USItype) b;
203b91b9 872 v <<= WORD_SIZE;
ab495388
RS
873 /* Remove high part from the DFtype, leaving the low part as flonum. */
874 a -= (DFtype)v;
875 /* Convert that to fixed (but not to DItype!) and add it in.
203b91b9
RS
876 Sometimes A comes out negative. This is significant, since
877 A has more bits than a long int does. */
878 if (a < 0)
ab495388 879 v -= (USItype) (- a);
203b91b9 880 else
ab495388 881 v += (USItype) a;
203b91b9
RS
882 return v;
883}
884#endif
885
886#ifdef L_fixdfdi
ab495388 887DItype
203b91b9 888__fixdfdi (a)
ab495388 889 DFtype a;
203b91b9
RS
890{
891 if (a < 0)
892 return - __fixunsdfdi (-a);
893 return __fixunsdfdi (a);
894}
895#endif
896
897#ifdef L_fixunssfdi
ab495388
RS
898#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
899#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
203b91b9 900
ab495388
RS
901DItype
902__fixunssfdi (SFtype original_a)
203b91b9 903{
ab495388 904 /* Convert the SFtype to a DFtype, because that is surely not going
203b91b9 905 to lose any bits. Some day someone else can write a faster version
ab495388
RS
906 that avoids converting to DFtype, and verify it really works right. */
907 DFtype a = original_a;
908 DFtype b;
909 UDItype v;
203b91b9
RS
910
911 if (a < 0)
912 return 0;
913
914 /* Compute high word of result, as a flonum. */
915 b = (a / HIGH_WORD_COEFF);
ab495388 916 /* Convert that to fixed (but not to DItype!),
203b91b9 917 and shift it into the high word. */
ab495388 918 v = (USItype) b;
203b91b9 919 v <<= WORD_SIZE;
ab495388
RS
920 /* Remove high part from the DFtype, leaving the low part as flonum. */
921 a -= (DFtype)v;
922 /* Convert that to fixed (but not to DItype!) and add it in.
203b91b9
RS
923 Sometimes A comes out negative. This is significant, since
924 A has more bits than a long int does. */
925 if (a < 0)
ab495388 926 v -= (USItype) (- a);
203b91b9 927 else
ab495388 928 v += (USItype) a;
203b91b9
RS
929 return v;
930}
931#endif
932
933#ifdef L_fixsfdi
ab495388
RS
934DItype
935__fixsfdi (SFtype a)
203b91b9
RS
936{
937 if (a < 0)
938 return - __fixunssfdi (-a);
939 return __fixunssfdi (a);
940}
941#endif
942
e0799b34
RS
943#if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
944#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
945#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
946#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
947
948XFtype
949__floatdixf (u)
950 DItype u;
951{
952 XFtype d;
953 SItype negate = 0;
954
955 if (u < 0)
956 u = -u, negate = 1;
957
958 d = (USItype) (u >> WORD_SIZE);
959 d *= HIGH_HALFWORD_COEFF;
960 d *= HIGH_HALFWORD_COEFF;
961 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
962
963 return (negate ? -d : d);
964}
965#endif
966
ab495388
RS
967#if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
968#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
969#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
970#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
971
972TFtype
973__floatditf (u)
974 DItype u;
975{
976 TFtype d;
977 SItype negate = 0;
978
979 if (u < 0)
980 u = -u, negate = 1;
981
982 d = (USItype) (u >> WORD_SIZE);
983 d *= HIGH_HALFWORD_COEFF;
984 d *= HIGH_HALFWORD_COEFF;
985 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
986
987 return (negate ? -d : d);
988}
989#endif
990
203b91b9 991#ifdef L_floatdidf
ab495388
RS
992#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
993#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
994#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
203b91b9 995
ab495388 996DFtype
203b91b9 997__floatdidf (u)
ab495388 998 DItype u;
203b91b9 999{
ab495388
RS
1000 DFtype d;
1001 SItype negate = 0;
203b91b9
RS
1002
1003 if (u < 0)
1004 u = -u, negate = 1;
1005
ab495388 1006 d = (USItype) (u >> WORD_SIZE);
203b91b9
RS
1007 d *= HIGH_HALFWORD_COEFF;
1008 d *= HIGH_HALFWORD_COEFF;
ab495388 1009 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
203b91b9
RS
1010
1011 return (negate ? -d : d);
1012}
1013#endif
1014
1015#ifdef L_floatdisf
ab495388
RS
1016#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
1017#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
1018#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
d9e1ab8d 1019#define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
cac896d8
RK
1020
1021/* Define codes for all the float formats that we know of. Note
1022 that this is copied from real.h. */
1023
1024#define UNKNOWN_FLOAT_FORMAT 0
1025#define IEEE_FLOAT_FORMAT 1
1026#define VAX_FLOAT_FORMAT 2
1027#define IBM_FLOAT_FORMAT 3
1028
1029/* Default to IEEE float if not specified. Nearly all machines use it. */
1030#ifndef HOST_FLOAT_FORMAT
1031#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
1032#endif
1033
1034#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
d9e1ab8d
RK
1035#define DF_SIZE 53
1036#define SF_SIZE 24
cac896d8
RK
1037#endif
1038
1039#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
d9e1ab8d
RK
1040#define DF_SIZE 56
1041#define SF_SIZE 24
cac896d8
RK
1042#endif
1043
1044#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
d9e1ab8d
RK
1045#define DF_SIZE 56
1046#define SF_SIZE 24
d9e1ab8d 1047#endif
203b91b9 1048
ab495388 1049SFtype
203b91b9 1050__floatdisf (u)
ab495388 1051 DItype u;
203b91b9 1052{
56b03d5f
RS
1053 /* Do the calculation in DFmode
1054 so that we don't lose any of the precision of the high word
1055 while multiplying it. */
1056 DFtype f;
ab495388 1057 SItype negate = 0;
203b91b9
RS
1058
1059 if (u < 0)
1060 u = -u, negate = 1;
1061
d9e1ab8d
RK
1062 /* Protect against double-rounding error.
1063 Represent any low-order bits, that might be truncated in DFmode,
1064 by a bit that won't be lost. The bit can go in anywhere below the
1065 rounding position of the SFmode. A fixed mask and bit position
1066 handles all usual configurations. It doesn't handle the case
1067 of 128-bit DImode, however. */
1068 if (DF_SIZE < DI_SIZE
1069 && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1070 {
1071#define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
1072 if (u >= ((UDItype) 1 << DF_SIZE))
1073 {
1074 if ((USItype) u & (REP_BIT - 1))
1075 u |= REP_BIT;
1076 }
1077 }
ab495388 1078 f = (USItype) (u >> WORD_SIZE);
203b91b9
RS
1079 f *= HIGH_HALFWORD_COEFF;
1080 f *= HIGH_HALFWORD_COEFF;
ab495388 1081 f += (USItype) (u & (HIGH_WORD_COEFF - 1));
203b91b9 1082
56b03d5f 1083 return (SFtype) (negate ? -f : f);
203b91b9
RS
1084}
1085#endif
1086
e0799b34 1087#if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
3f3d2ec8
JW
1088/* Reenable the normal types, in case limits.h needs them. */
1089#undef char
1090#undef short
1091#undef int
1092#undef long
1093#undef unsigned
1094#undef float
1095#undef double
c07e26bd
RK
1096#undef MIN
1097#undef MAX
a99598c9 1098#include <limits.h>
e0799b34
RS
1099
1100USItype
1101__fixunsxfsi (a)
1102 XFtype a;
1103{
1104 if (a >= - (DFtype) LONG_MIN)
1105 return (SItype) (a + LONG_MIN) - LONG_MIN;
1106 return (SItype) a;
1107}
1108#endif
1109
203b91b9 1110#ifdef L_fixunsdfsi
3f3d2ec8
JW
1111/* Reenable the normal types, in case limits.h needs them. */
1112#undef char
1113#undef short
1114#undef int
1115#undef long
1116#undef unsigned
1117#undef float
1118#undef double
c07e26bd
RK
1119#undef MIN
1120#undef MAX
a99598c9 1121#include <limits.h>
203b91b9 1122
ab495388 1123USItype
203b91b9 1124__fixunsdfsi (a)
ab495388 1125 DFtype a;
203b91b9 1126{
ab495388 1127 if (a >= - (DFtype) LONG_MIN)
203b91b9
RS
1128 return (SItype) (a + LONG_MIN) - LONG_MIN;
1129 return (SItype) a;
1130}
1131#endif
1132
1133#ifdef L_fixunssfsi
3f3d2ec8
JW
1134/* Reenable the normal types, in case limits.h needs them. */
1135#undef char
1136#undef short
1137#undef int
1138#undef long
1139#undef unsigned
1140#undef float
1141#undef double
c07e26bd
RK
1142#undef MIN
1143#undef MAX
a99598c9 1144#include <limits.h>
203b91b9 1145
ab495388
RS
1146USItype
1147__fixunssfsi (SFtype a)
203b91b9 1148{
ab495388 1149 if (a >= - (SFtype) LONG_MIN)
203b91b9
RS
1150 return (SItype) (a + LONG_MIN) - LONG_MIN;
1151 return (SItype) a;
1152}
1153#endif
1154\f
ab495388
RS
1155/* From here on down, the routines use normal data types. */
1156
1157#define SItype bogus_type
1158#define USItype bogus_type
1159#define DItype bogus_type
1160#define UDItype bogus_type
1161#define SFtype bogus_type
1162#define DFtype bogus_type
1163
1164#undef char
1165#undef short
1166#undef int
1167#undef long
1168#undef unsigned
1169#undef float
1170#undef double
9bd23d2c
RS
1171\f
1172#ifdef L__gcc_bcmp
1173
1174/* Like bcmp except the sign is meaningful.
9faa82d8 1175 Result is negative if S1 is less than S2,
9bd23d2c
RS
1176 positive if S1 is greater, 0 if S1 and S2 are equal. */
1177
1178int
1179__gcc_bcmp (s1, s2, size)
78e33213 1180 unsigned char *s1, *s2;
9bd23d2c
RS
1181 size_t size;
1182{
1183 while (size > 0)
1184 {
78e33213 1185 unsigned char c1 = *s1++, c2 = *s2++;
9bd23d2c
RS
1186 if (c1 != c2)
1187 return c1 - c2;
1188 size--;
1189 }
1190 return 0;
1191}
ab495388 1192
9bd23d2c
RS
1193#endif
1194\f\f
2e06e616
RK
1195#ifdef L__dummy
1196void
1197__dummy () {}
1198#endif
1199
203b91b9
RS
1200#ifdef L_varargs
1201#ifdef __i860__
600032fc 1202#if defined(__svr4__) || defined(__alliant__)
203b91b9
RS
1203 asm (" .text");
1204 asm (" .align 4");
1205
27d21d32 1206/* The Alliant needs the added underscore. */
203b91b9
RS
1207 asm (".globl __builtin_saveregs");
1208asm ("__builtin_saveregs:");
27d21d32
RS
1209 asm (".globl ___builtin_saveregs");
1210asm ("___builtin_saveregs:");
1211
1212 asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
203b91b9
RS
1213 asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
1214 area and also for a new va_list
1215 structure */
1216 /* Save all argument registers in the arg reg save area. The
1217 arg reg save area must have the following layout (according
1218 to the svr4 ABI):
1219
1220 struct {
1221 union {
1222 float freg[8];
1223 double dreg[4];
1224 } float_regs;
1225 long ireg[12];
1226 };
1227 */
1228
1229 asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
1230 asm (" fst.q %f12,16(%sp)");
1231
1232 asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
1233 asm (" st.l %r17,36(%sp)");
1234 asm (" st.l %r18,40(%sp)");
1235 asm (" st.l %r19,44(%sp)");
1236 asm (" st.l %r20,48(%sp)");
1237 asm (" st.l %r21,52(%sp)");
1238 asm (" st.l %r22,56(%sp)");
1239 asm (" st.l %r23,60(%sp)");
1240 asm (" st.l %r24,64(%sp)");
1241 asm (" st.l %r25,68(%sp)");
1242 asm (" st.l %r26,72(%sp)");
1243 asm (" st.l %r27,76(%sp)");
1244
1245 asm (" adds 80,%sp,%r16"); /* compute the address of the new
1246 va_list structure. Put in into
1247 r16 so that it will be returned
1248 to the caller. */
1249
1250 /* Initialize all fields of the new va_list structure. This
1251 structure looks like:
1252
1253 typedef struct {
1254 unsigned long ireg_used;
1255 unsigned long freg_used;
1256 long *reg_base;
1257 long *mem_ptr;
1258 } va_list;
1259 */
1260
1261 asm (" st.l %r0, 0(%r16)"); /* nfixed */
1262 asm (" st.l %r0, 4(%r16)"); /* nfloating */
1263 asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
1264 asm (" bri %r1"); /* delayed return */
1265 asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
1266
24e4939e 1267#else /* not __svr4__ */
6aadf9c2
RS
1268#if defined(__PARAGON__)
1269 /*
1270 * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1271 * and we stand a better chance of hooking into libraries
1272 * compiled by PGI. [andyp@ssd.intel.com]
1273 */
1274 asm (" .text");
1275 asm (" .align 4");
1276 asm (".globl __builtin_saveregs");
1277asm ("__builtin_saveregs:");
1278 asm (".globl ___builtin_saveregs");
1279asm ("___builtin_saveregs:");
1280
1281 asm (" andnot 0x0f,sp,sp"); /* round down to 16-byte boundary */
1282 asm (" adds -96,sp,sp"); /* allocate stack space for reg save
1283 area and also for a new va_list
1284 structure */
1285 /* Save all argument registers in the arg reg save area. The
1286 arg reg save area must have the following layout (according
1287 to the svr4 ABI):
1288
1289 struct {
1290 union {
1291 float freg[8];
1292 double dreg[4];
1293 } float_regs;
1294 long ireg[12];
1295 };
1296 */
1297
1298 asm (" fst.q f8, 0(sp)");
1299 asm (" fst.q f12,16(sp)");
1300 asm (" st.l r16,32(sp)");
1301 asm (" st.l r17,36(sp)");
1302 asm (" st.l r18,40(sp)");
1303 asm (" st.l r19,44(sp)");
1304 asm (" st.l r20,48(sp)");
1305 asm (" st.l r21,52(sp)");
1306 asm (" st.l r22,56(sp)");
1307 asm (" st.l r23,60(sp)");
1308 asm (" st.l r24,64(sp)");
1309 asm (" st.l r25,68(sp)");
1310 asm (" st.l r26,72(sp)");
1311 asm (" st.l r27,76(sp)");
1312
1313 asm (" adds 80,sp,r16"); /* compute the address of the new
1314 va_list structure. Put in into
1315 r16 so that it will be returned
1316 to the caller. */
1317
1318 /* Initialize all fields of the new va_list structure. This
1319 structure looks like:
1320
1321 typedef struct {
1322 unsigned long ireg_used;
1323 unsigned long freg_used;
1324 long *reg_base;
1325 long *mem_ptr;
1326 } va_list;
1327 */
1328
1329 asm (" st.l r0, 0(r16)"); /* nfixed */
1330 asm (" st.l r0, 4(r16)"); /* nfloating */
1331 asm (" st.l sp, 8(r16)"); /* __va_ctl points to __va_struct. */
1332 asm (" bri r1"); /* delayed return */
1333 asm (" st.l r28,12(r16)"); /* pointer to overflow args */
1334#else /* not __PARAGON__ */
203b91b9
RS
1335 asm (" .text");
1336 asm (" .align 4");
1337
1338 asm (".globl ___builtin_saveregs");
1339 asm ("___builtin_saveregs:");
1340 asm (" mov sp,r30");
1341 asm (" andnot 0x0f,sp,sp");
1342 asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
1343
1344/* Fill in the __va_struct. */
1345 asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
1346 asm (" st.l r17, 4(sp)"); /* int fixed[12] */
1347 asm (" st.l r18, 8(sp)");
1348 asm (" st.l r19,12(sp)");
1349 asm (" st.l r20,16(sp)");
1350 asm (" st.l r21,20(sp)");
1351 asm (" st.l r22,24(sp)");
1352 asm (" st.l r23,28(sp)");
1353 asm (" st.l r24,32(sp)");
1354 asm (" st.l r25,36(sp)");
1355 asm (" st.l r26,40(sp)");
1356 asm (" st.l r27,44(sp)");
1357
1358 asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
1359 asm (" fst.q f12,64(sp)"); /* int floating[8] */
1360
1361/* Fill in the __va_ctl. */
1362 asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
1363 asm (" st.l r28,84(sp)"); /* pointer to more args */
1364 asm (" st.l r0, 88(sp)"); /* nfixed */
1365 asm (" st.l r0, 92(sp)"); /* nfloating */
1366
1367 asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
1368 asm (" bri r1");
1369 asm (" mov r30,sp");
1370 /* recover stack and pass address to start
1371 of data. */
6aadf9c2 1372#endif /* not __PARAGON__ */
24e4939e 1373#endif /* not __svr4__ */
203b91b9
RS
1374#else /* not __i860__ */
1375#ifdef __sparc__
b335c2cc
TW
1376 asm (".global __builtin_saveregs");
1377 asm ("__builtin_saveregs:");
203b91b9
RS
1378 asm (".global ___builtin_saveregs");
1379 asm ("___builtin_saveregs:");
b1166fae
RS
1380#ifdef NEED_PROC_COMMAND
1381 asm (".proc 020");
b335c2cc 1382#endif
203b91b9
RS
1383 asm ("st %i0,[%fp+68]");
1384 asm ("st %i1,[%fp+72]");
1385 asm ("st %i2,[%fp+76]");
1386 asm ("st %i3,[%fp+80]");
1387 asm ("st %i4,[%fp+84]");
1388 asm ("retl");
1389 asm ("st %i5,[%fp+88]");
b1166fae
RS
1390#ifdef NEED_TYPE_COMMAND
1391 asm (".type __builtin_saveregs,#function");
1392 asm (".size __builtin_saveregs,.-__builtin_saveregs");
1393#endif
203b91b9
RS
1394#else /* not __sparc__ */
1395#if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1396
1397 asm (" .text");
1398 asm (" .ent __builtin_saveregs");
1399 asm (" .globl __builtin_saveregs");
1400 asm ("__builtin_saveregs:");
1401 asm (" sw $4,0($30)");
1402 asm (" sw $5,4($30)");
1403 asm (" sw $6,8($30)");
1404 asm (" sw $7,12($30)");
1405 asm (" j $31");
1406 asm (" .end __builtin_saveregs");
0f41302f 1407#else /* not __mips__, etc. */
3bd4f3b8
DE
1408
1409void *
203b91b9
RS
1410__builtin_saveregs ()
1411{
1412 abort ();
1413}
3bd4f3b8 1414
203b91b9
RS
1415#endif /* not __mips__ */
1416#endif /* not __sparc__ */
1417#endif /* not __i860__ */
1418#endif
1419\f
1420#ifdef L_eprintf
c74d5583 1421#ifndef inhibit_libc
bba2431c 1422
203b91b9
RS
1423#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1424#include <stdio.h>
1425/* This is used by the `assert' macro. */
1426void
1427__eprintf (string, expression, line, filename)
b1166fae
RS
1428 const char *string;
1429 const char *expression;
203b91b9 1430 int line;
b1166fae 1431 const char *filename;
203b91b9
RS
1432{
1433 fprintf (stderr, string, expression, line, filename);
1434 fflush (stderr);
1435 abort ();
1436}
bba2431c
RS
1437
1438#endif
203b91b9
RS
1439#endif
1440
1441#ifdef L_bb
203b91b9 1442
92832bb5 1443/* Structure emitted by -a */
203b91b9
RS
1444struct bb
1445{
92832bb5
MM
1446 long zero_word;
1447 const char *filename;
1448 long *counts;
1449 long ncounts;
1450 struct bb *next;
1451 const unsigned long *addresses;
1452
1453 /* Older GCC's did not emit these fields. */
1454 long nwords;
1455 const char **functions;
1456 const long *line_nums;
1457 const char **filenames;
90b4a764 1458 char *flags;
203b91b9
RS
1459};
1460
92832bb5
MM
1461#ifdef BLOCK_PROFILER_CODE
1462BLOCK_PROFILER_CODE
1463#else
c7544ff7 1464#ifndef inhibit_libc
92832bb5
MM
1465
1466/* Simple minded basic block profiling output dumper for
9faa82d8 1467 systems that don't provide tcov support. At present,
92832bb5
MM
1468 it requires atexit and stdio. */
1469
ebd41309 1470#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
92832bb5 1471#include <stdio.h>
b077f3ac 1472char *ctime ();
203b91b9 1473
8b7677be 1474#include "gbl-ctors.h"
92832bb5 1475
7e6f1890 1476static struct bb *bb_head;
92832bb5
MM
1477
1478/* Return the number of digits needed to print a value */
1479/* __inline__ */ static int num_digits (long value, int base)
203b91b9 1480{
92832bb5
MM
1481 int minus = (value < 0 && base != 16);
1482 unsigned long v = (minus) ? -value : value;
1483 int ret = minus;
203b91b9 1484
92832bb5
MM
1485 do
1486 {
1487 v /= base;
1488 ret++;
1489 }
1490 while (v);
1491
1492 return ret;
203b91b9
RS
1493}
1494
92832bb5
MM
1495void
1496__bb_exit_func (void)
1497{
1498 FILE *file = fopen ("bb.out", "a");
1499 long time_value;
1500
1501 if (!file)
1502 perror ("bb.out");
1503
1504 else
1505 {
1506 struct bb *ptr;
1507
1508 /* This is somewhat type incorrect, but it avoids worrying about
1509 exactly where time.h is included from. It should be ok unless
90b4a764 1510 a void * differs from other pointer formats, or if sizeof (long)
92832bb5
MM
1511 is < sizeof (time_t). It would be nice if we could assume the
1512 use of rationale standards here. */
1513
90b4a764 1514 time ((void *) &time_value);
92832bb5
MM
1515 fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1516
1517 /* We check the length field explicitly in order to allow compatibility
1518 with older GCC's which did not provide it. */
1519
0f41302f 1520 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
92832bb5
MM
1521 {
1522 int i;
1523 int func_p = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
1524 int line_p = (func_p && ptr->line_nums);
1525 int file_p = (func_p && ptr->filenames);
1526 long ncounts = ptr->ncounts;
1527 long cnt_max = 0;
1528 long line_max = 0;
1529 long addr_max = 0;
1530 int file_len = 0;
1531 int func_len = 0;
1532 int blk_len = num_digits (ncounts, 10);
1533 int cnt_len;
1534 int line_len;
1535 int addr_len;
1536
1537 fprintf (file, "File %s, %ld basic blocks \n\n",
1538 ptr->filename, ncounts);
1539
1540 /* Get max values for each field. */
1541 for (i = 0; i < ncounts; i++)
1542 {
1543 const char *p;
1544 int len;
1545
1546 if (cnt_max < ptr->counts[i])
1547 cnt_max = ptr->counts[i];
1548
1549 if (addr_max < ptr->addresses[i])
1550 addr_max = ptr->addresses[i];
1551
1552 if (line_p && line_max < ptr->line_nums[i])
1553 line_max = ptr->line_nums[i];
1554
1555 if (func_p)
1556 {
1557 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1558 len = strlen (p);
1559 if (func_len < len)
1560 func_len = len;
1561 }
1562
1563 if (file_p)
1564 {
1565 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1566 len = strlen (p);
1567 if (file_len < len)
1568 file_len = len;
1569 }
1570 }
1571
1572 addr_len = num_digits (addr_max, 16);
1573 cnt_len = num_digits (cnt_max, 10);
1574 line_len = num_digits (line_max, 10);
1575
1576 /* Now print out the basic block information. */
1577 for (i = 0; i < ncounts; i++)
1578 {
1579 fprintf (file,
3cca99e8 1580 " Block #%*d: executed %*ld time(s) address= 0x%.*lx",
92832bb5
MM
1581 blk_len, i+1,
1582 cnt_len, ptr->counts[i],
1583 addr_len, ptr->addresses[i]);
1584
1585 if (func_p)
3cca99e8 1586 fprintf (file, " function= %-*s", func_len,
92832bb5
MM
1587 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1588
1589 if (line_p)
1d42e1b7 1590 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
92832bb5
MM
1591
1592 if (file_p)
3cca99e8 1593 fprintf (file, " file= %s",
92832bb5
MM
1594 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1595
1596 fprintf (file, "\n");
1597 }
1598
1599 fprintf (file, "\n");
1600 fflush (file);
1601 }
1602
1603 fprintf (file, "\n\n");
1604 fclose (file);
1605 }
1606}
1607
1608void
1609__bb_init_func (struct bb *blocks)
1610{
1611 /* User is supposed to check whether the first word is non-0,
0f41302f 1612 but just in case.... */
92832bb5
MM
1613
1614 if (blocks->zero_word)
1615 return;
1616
1617#ifdef ON_EXIT
1618 /* Initialize destructor. */
1619 if (!bb_head)
1620 ON_EXIT (__bb_exit_func, 0);
203b91b9 1621#endif
92832bb5
MM
1622
1623 /* Set up linked list. */
1624 blocks->zero_word = 1;
1625 blocks->next = bb_head;
1626 bb_head = blocks;
1627}
1628
90b4a764
RK
1629#ifndef MACHINE_STATE_SAVE
1630#define MACHINE_STATE_SAVE(ID)
1631#endif
1632#ifndef MACHINE_STATE_RESTORE
1633#define MACHINE_STATE_RESTORE(ID)
1634#endif
1635
1636#include <string.h>
1637
0f41302f 1638/* Number of buckets in hashtable of basic block addresses. */
90b4a764
RK
1639
1640#define BB_BUCKETS 311
1641
0f41302f 1642/* Maximum length of string in file bb.in. */
90b4a764
RK
1643
1644#define BBINBUFSIZE 500
1645
1646/* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
0f41302f 1647 "BBINBUFSIZE" but want to avoid trouble with preprocessors. */
90b4a764
RK
1648
1649#define BBINBUFSIZESTR "499"
1650
1651struct bb_edge
1652{
1653 struct bb_edge *next;
1654 unsigned long src_addr;
1655 unsigned long dst_addr;
1656 unsigned long count;
1657};
1658
1659enum bb_func_mode
1660{
1661 TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1662};
1663
1664struct bb_func
1665{
1666 struct bb_func *next;
1667 char *funcname;
1668 char *filename;
1669 enum bb_func_mode mode;
1670};
1671
1672/* This is the connection to the outside world.
1673 The BLOCK_PROFILER macro must set __bb.blocks
0f41302f 1674 and __bb.blockno. */
90b4a764
RK
1675
1676struct {
1677 unsigned long blockno;
1678 struct bb *blocks;
1679} __bb;
1680
1681/* Vars to store addrs of source and destination basic blocks
0f41302f 1682 of a jump. */
90b4a764
RK
1683
1684static unsigned long bb_src = 0;
1685static unsigned long bb_dst = 0;
1686
0f41302f
MS
1687static FILE *bb_tracefile = (FILE *) 0;
1688static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1689static struct bb_func *bb_func_head = (struct bb_func *) 0;
90b4a764
RK
1690static unsigned long bb_callcount = 0;
1691static int bb_mode = 0;
1692
0f41302f 1693static unsigned long *bb_stack = (unsigned long *) 0;
90b4a764
RK
1694static size_t bb_stacksize = 0;
1695
1696static int reported = 0;
1697
1698/* Trace modes:
1699Always : Print execution frequencies of basic blocks
1700 to file bb.out.
1701bb_mode & 1 != 0 : Dump trace of basic blocks to file bbtrace[.gz]
1702bb_mode & 2 != 0 : Print jump frequencies to file bb.out.
1703bb_mode & 4 != 0 : Cut call instructions from basic block flow.
1704bb_mode & 8 != 0 : Insert return instructions in basic block flow.
1705*/
1706
1707#ifdef HAVE_POPEN
1708
1709/*#include <sys/types.h>*/
1710#include <sys/stat.h>
1711/*#include <malloc.h>*/
1712
0f41302f 1713/* Commands executed by gopen. */
90b4a764
RK
1714
1715#define GOPENDECOMPRESS "gzip -cd "
1716#define GOPENCOMPRESS "gzip -c >"
1717
1718/* Like fopen but pipes through gzip. mode may only be "r" or "w".
1719 If it does not compile, simply replace gopen by fopen and delete
0f41302f 1720 '.gz' from any first parameter to gopen. */
90b4a764
RK
1721
1722static FILE *
1723gopen (fn, mode)
1724 char *fn;
1725 char *mode;
1726{
1727 int use_gzip;
1728 char *p;
1729
1730 if (mode[1])
0f41302f 1731 return (FILE *) 0;
90b4a764
RK
1732
1733 if (mode[0] != 'r' && mode[0] != 'w')
0f41302f 1734 return (FILE *) 0;
90b4a764
RK
1735
1736 p = fn + strlen (fn)-1;
1737 use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z')) ||
1738 (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1739
1740 if (use_gzip)
1741 {
1742 if (mode[0]=='r')
1743 {
1744 FILE *f;
0f41302f
MS
1745 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1746 + sizeof (GOPENDECOMPRESS));
90b4a764
RK
1747 strcpy (s, GOPENDECOMPRESS);
1748 strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1749 f = popen (s, mode);
1750 free (s);
1751 return f;
1752 }
1753
1754 else
1755 {
1756 FILE *f;
0f41302f
MS
1757 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1758 + sizeof (GOPENCOMPRESS));
90b4a764
RK
1759 strcpy (s, GOPENCOMPRESS);
1760 strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1761 if (!(f = popen (s, mode)))
1762 f = fopen (s, mode);
1763 free (s);
1764 return f;
1765 }
1766 }
1767
1768 else
1769 return fopen (fn, mode);
1770}
1771
1772static int
1773gclose (f)
1774 FILE *f;
1775{
1776 struct stat buf;
1777
1778 if (f != NULL)
1779 {
1780 if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1781 return pclose (f);
1782
1783 return fclose (f);
1784 }
1785 return 0;
1786}
1787
1788#endif /* HAVE_POPEN */
1789
0f41302f 1790/* Called once per program. */
90b4a764
RK
1791
1792static void
1793__bb_exit_trace_func ()
1794{
1795 FILE *file = fopen ("bb.out", "a");
1796 struct bb_func *f;
1797 struct bb_edge *e;
1798 struct bb *b;
1799
1800 if (!file)
1801 perror ("bb.out");
1802
1803 if (bb_mode & 1)
1804 {
1805 if (!bb_tracefile)
1806 perror ("bbtrace");
1807 else
1808#ifdef HAVE_POPEN
1809 gclose (bb_tracefile);
1810#else
1811 fclose (bb_tracefile);
1812#endif /* HAVE_POPEN */
1813 }
1814
0f41302f 1815 /* Check functions in `bb.in'. */
90b4a764
RK
1816
1817 if (file)
1818 {
1819 long time_value;
1820 const struct bb_func *p;
1821 int printed_something = 0;
1822 struct bb *ptr;
1823 long blk;
1824
0f41302f 1825 /* This is somewhat type incorrect. */
90b4a764
RK
1826 time ((void *) &time_value);
1827
0f41302f 1828 for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
90b4a764 1829 {
0f41302f 1830 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
90b4a764 1831 {
0f41302f 1832 if (!ptr->filename || p->filename != (char *) 0 && strcmp (p->filename, ptr->filename))
90b4a764
RK
1833 continue;
1834 for (blk = 0; blk < ptr->ncounts; blk++)
1835 {
1836 if (!strcmp (p->funcname, ptr->functions[blk]))
1837 goto found;
1838 }
1839 }
1840
1841 if (!printed_something)
1842 {
1843 fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1844 printed_something = 1;
1845 }
1846
1847 fprintf (file, "\tFunction %s", p->funcname);
1848 if (p->filename)
1849 fprintf (file, " of file %s", p->filename);
1850 fprintf (file, "\n" );
1851
1852found: ;
1853 }
1854
1855 if (printed_something)
1856 fprintf (file, "\n");
1857
1858 }
1859
1860 if (bb_mode & 2)
1861 {
1862 if (!bb_hashbuckets)
1863 {
1864 if (!reported)
1865 {
1866 fprintf (stderr, "Profiler: out of memory\n");
1867 reported = 1;
1868 }
1869 return;
1870 }
1871
1872 else if (file)
1873 {
1874 long time_value;
1875 int i;
1876 unsigned long addr_max = 0;
1877 unsigned long cnt_max = 0;
1878 int cnt_len;
1879 int addr_len;
1880
1881 /* This is somewhat type incorrect, but it avoids worrying about
1882 exactly where time.h is included from. It should be ok unless
1883 a void * differs from other pointer formats, or if sizeof (long)
1884 is < sizeof (time_t). It would be nice if we could assume the
1885 use of rationale standards here. */
1886
1887 time ((void *) &time_value);
1888 fprintf (file, "Basic block jump tracing");
1889
1890 switch (bb_mode & 12)
1891 {
1892 case 0:
1893 fprintf (file, " (with call)");
1894 break;
1895
1896 case 4:
0f41302f 1897 /* Print nothing. */
90b4a764
RK
1898 break;
1899
1900 case 8:
1901 fprintf (file, " (with call & ret)");
1902 break;
1903
1904 case 12:
1905 fprintf (file, " (with ret)");
1906 break;
1907 }
1908
1909 fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1910
1911 for (i = 0; i < BB_BUCKETS; i++)
1912 {
1913 struct bb_edge *bucket = bb_hashbuckets[i];
1914 for ( ; bucket; bucket = bucket->next )
1915 {
1916 if (addr_max < bucket->src_addr)
1917 addr_max = bucket->src_addr;
1918 if (addr_max < bucket->dst_addr)
1919 addr_max = bucket->dst_addr;
1920 if (cnt_max < bucket->count)
1921 cnt_max = bucket->count;
1922 }
1923 }
1924 addr_len = num_digits (addr_max, 16);
1925 cnt_len = num_digits (cnt_max, 10);
1926
1927 for ( i = 0; i < BB_BUCKETS; i++)
1928 {
1929 struct bb_edge *bucket = bb_hashbuckets[i];
1930 for ( ; bucket; bucket = bucket->next )
1931 {
1932 fprintf (file, "Jump from block 0x%.*lx to "
1933 "block 0x%.*lx executed %*d time(s)\n",
1934 addr_len, bucket->src_addr,
1935 addr_len, bucket->dst_addr,
1936 cnt_len, bucket->count);
1937 }
1938 }
1939
1940 fprintf (file, "\n");
1941
1942 }
1943 }
1944
1945 if (file)
1946 fclose (file);
1947
0f41302f 1948 /* Free allocated memory. */
90b4a764
RK
1949
1950 f = bb_func_head;
1951 while (f)
1952 {
1953 struct bb_func *old = f;
1954
1955 f = f->next;
1956 if (old->funcname) free (old->funcname);
1957 if (old->filename) free (old->filename);
1958 free (old);
1959 }
1960
1961 if (bb_stack)
1962 free (bb_stack);
1963
1964 if (bb_hashbuckets)
1965 {
1966 int i;
1967
1968 for (i = 0; i < BB_BUCKETS; i++)
1969 {
1970 struct bb_edge *old, *bucket = bb_hashbuckets[i];
1971
1972 while (bucket)
1973 {
1974 old = bucket;
1975 bucket = bucket->next;
1976 free (old);
1977 }
1978 }
1979 free (bb_hashbuckets);
1980 }
1981
1982 for (b = bb_head; b; b = b->next)
1983 if (b->flags) free (b->flags);
1984}
1985
0f41302f 1986/* Called once per program. */
90b4a764
RK
1987
1988static void
1989__bb_init_prg ()
1990{
1991
1992 FILE *file;
1993 char buf[BBINBUFSIZE];
1994 const char *p;
1995 const char *pos;
1996 enum bb_func_mode m;
1997
1998#ifdef ON_EXIT
1999 /* Initialize destructor. */
2000 ON_EXIT (__bb_exit_func, 0);
2001#endif
2002
2003 if (!(file = fopen ("bb.in", "r")))
2004 return;
2005
2006 while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
2007 {
2008 p = buf;
2009 if (*p == '-')
2010 {
2011 m = TRACE_OFF;
2012 p++;
2013 }
2014 else
2015 {
2016 m = TRACE_ON;
2017 }
2018 if (!strcmp (p, "__bb_trace__"))
2019 bb_mode |= 1;
2020 else if (!strcmp (p, "__bb_jumps__"))
2021 bb_mode |= 2;
2022 else if (!strcmp (p, "__bb_hidecall__"))
2023 bb_mode |= 4;
2024 else if (!strcmp (p, "__bb_showret__"))
2025 bb_mode |= 8;
2026 else
2027 {
0f41302f 2028 struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
90b4a764
RK
2029 if (f)
2030 {
2031 unsigned long l;
2032 f->next = bb_func_head;
2033 if (pos = strchr (p, ':'))
2034 {
0f41302f 2035 if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
90b4a764
RK
2036 continue;
2037 strcpy (f->funcname, pos+1);
2038 l = pos-p;
0f41302f 2039 if ((f->filename = (char *) malloc (l+1)))
90b4a764
RK
2040 {
2041 strncpy (f->filename, p, l);
2042 f->filename[l] = '\0';
2043 }
2044 else
0f41302f 2045 f->filename = (char *) 0;
90b4a764
RK
2046 }
2047 else
2048 {
0f41302f 2049 if (!(f->funcname = (char *) malloc (strlen (p)+1)))
90b4a764
RK
2050 continue;
2051 strcpy (f->funcname, p);
0f41302f 2052 f->filename = (char *) 0;
90b4a764
RK
2053 }
2054 f->mode = m;
2055 bb_func_head = f;
2056 }
2057 }
2058 }
2059 fclose (file);
2060
2061#ifdef HAVE_POPEN
2062
2063 if (bb_mode & 1)
2064 bb_tracefile = gopen ("bbtrace.gz", "w");
2065
2066#else
2067
2068 if (bb_mode & 1)
2069 bb_tracefile = fopen ("bbtrace", "w");
2070
2071#endif /* HAVE_POPEN */
2072
2073 if (bb_mode & 2)
2074 {
2075 bb_hashbuckets = (struct bb_edge **)
2076 malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2077 if (bb_hashbuckets)
9bb89050 2078 bzero ((char *) bb_hashbuckets, BB_BUCKETS);
90b4a764
RK
2079 }
2080
2081 if (bb_mode & 12)
2082 {
2083 bb_stacksize = 10;
2084 bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2085 }
2086
2087#ifdef ON_EXIT
2088 /* Initialize destructor. */
2089 ON_EXIT (__bb_exit_trace_func, 0);
2090#endif
2091
2092}
2093
0f41302f 2094/* Called upon entering a basic block. */
90b4a764
RK
2095
2096void
2097__bb_trace_func ()
2098{
2099 struct bb_edge *bucket;
2100
2101 MACHINE_STATE_SAVE("1")
2102
2103 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2104 goto skip;
2105
2106 bb_dst = __bb.blocks->addresses[__bb.blockno];
2107 __bb.blocks->counts[__bb.blockno]++;
2108
2109 if (bb_tracefile)
2110 {
2111 fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2112 }
2113
2114 if (bb_hashbuckets)
2115 {
2116 struct bb_edge **startbucket, **oldnext;
2117
2118 oldnext = startbucket =
0f41302f 2119 & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
90b4a764
RK
2120 bucket = *startbucket;
2121
2122 for (bucket = *startbucket; bucket;
2123 oldnext = &(bucket->next), bucket = *oldnext)
2124 {
2125 if ( bucket->src_addr == bb_src &&
2126 bucket->dst_addr == bb_dst )
2127 {
2128 bucket->count++;
2129 *oldnext = bucket->next;
2130 bucket->next = *startbucket;
2131 *startbucket = bucket;
2132 goto ret;
2133 }
2134 }
2135
2136 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2137
2138 if (!bucket)
2139 {
2140 if (!reported)
2141 {
2142 fprintf (stderr, "Profiler: out of memory\n");
2143 reported = 1;
2144 }
2145 }
2146
2147 else
2148 {
2149 bucket->src_addr = bb_src;
2150 bucket->dst_addr = bb_dst;
2151 bucket->next = *startbucket;
2152 *startbucket = bucket;
2153 bucket->count = 1;
2154 }
2155 }
2156
2157ret:
2158 bb_src = bb_dst;
2159
2160skip:
2161 ;
2162
2163 MACHINE_STATE_RESTORE("1")
2164
2165}
2166
0f41302f 2167/* Called when returning from a function and `__bb_showret__' is set. */
90b4a764
RK
2168
2169static void
2170__bb_trace_func_ret ()
2171{
2172 struct bb_edge *bucket;
2173
2174 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2175 goto skip;
2176
2177 if (bb_hashbuckets)
2178 {
2179 struct bb_edge **startbucket, **oldnext;
2180
2181 oldnext = startbucket =
0f41302f 2182 & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
90b4a764
RK
2183 bucket = *startbucket;
2184
2185 for (bucket = *startbucket; bucket;
2186 oldnext = &(bucket->next), bucket = *oldnext)
2187 {
2188 if ( bucket->src_addr == bb_dst &&
2189 bucket->dst_addr == bb_src )
2190 {
2191 bucket->count++;
2192 *oldnext = bucket->next;
2193 bucket->next = *startbucket;
2194 *startbucket = bucket;
2195 goto ret;
2196 }
2197 }
2198
2199 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2200
2201 if (!bucket)
2202 {
2203 if (!reported)
2204 {
2205 fprintf (stderr, "Profiler: out of memory\n");
2206 reported = 1;
2207 }
2208 }
2209
2210 else
2211 {
2212 bucket->src_addr = bb_dst;
2213 bucket->dst_addr = bb_src;
2214 bucket->next = *startbucket;
2215 *startbucket = bucket;
2216 bucket->count = 1;
2217 }
2218 }
2219
2220ret:
2221 bb_dst = bb_src;
2222
2223skip:
2224 ;
2225
2226}
2227
0f41302f 2228/* Called upon entering the first function of a file. */
90b4a764
RK
2229
2230static void
2231__bb_init_file (blocks)
2232 struct bb *blocks;
2233{
2234
2235 const struct bb_func *p;
2236 long blk, ncounts = blocks->ncounts;
2237 const char **functions = blocks->functions;
2238
2239 /* Set up linked list. */
2240 blocks->zero_word = 1;
2241 blocks->next = bb_head;
2242 bb_head = blocks;
2243
2244 blocks->flags = 0;
2245 if (!bb_func_head ||
0f41302f 2246 !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
90b4a764
RK
2247 return;
2248
2249 for (blk = 0; blk < ncounts; blk++)
2250 blocks->flags[blk] = 0;
2251
2252 for (blk = 0; blk < ncounts; blk++)
2253 {
2254 for (p = bb_func_head; p; p = p->next)
2255 {
2256 if (!strcmp (p->funcname, functions[blk]) &&
2257 (!p->filename || !strcmp (p->filename, blocks->filename)))
2258 {
2259 blocks->flags[blk] |= p->mode;
2260 }
2261 }
2262 }
2263
2264}
2265
0f41302f 2266/* Called when exiting from a function. */
90b4a764
RK
2267
2268void
2269__bb_trace_ret ()
2270{
2271
2272 MACHINE_STATE_SAVE("2")
2273
2274 if (bb_callcount)
2275 {
2276 if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2277 {
2278 bb_src = bb_stack[bb_callcount];
2279 if (bb_mode & 8)
2280 __bb_trace_func_ret ();
2281 }
2282
2283 bb_callcount -= 1;
2284 }
2285
2286 MACHINE_STATE_RESTORE("2")
2287
2288}
2289
0f41302f 2290/* Called when entering a function. */
90b4a764
RK
2291
2292void
2293__bb_init_trace_func (blocks, blockno)
2294 struct bb *blocks;
2295 unsigned long blockno;
2296{
2297 static int trace_init = 0;
2298
2299 MACHINE_STATE_SAVE("3")
2300
2301 if (!blocks->zero_word)
2302 {
2303 if (!trace_init)
2304 {
2305 trace_init = 1;
2306 __bb_init_prg ();
2307 }
2308 __bb_init_file (blocks);
2309 }
2310
2311 if (bb_callcount)
2312 {
2313
2314 bb_callcount += 1;
2315
2316 if (bb_mode & 12)
2317 {
2318 if (bb_callcount >= bb_stacksize)
2319 {
2320 size_t newsize = bb_callcount + 100;
2321
2322 bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2323 if (! bb_stack)
2324 {
2325 if (!reported)
2326 {
2327 fprintf (stderr, "Profiler: out of memory\n");
2328 reported = 1;
2329 }
2330 bb_stacksize = 0;
2331 goto stack_overflow;
2332 }
2333 bb_stacksize = newsize;
2334 }
2335 bb_stack[bb_callcount] = bb_src;
2336
2337 if (bb_mode & 4)
2338 bb_src = 0;
2339
2340 }
2341
2342stack_overflow:;
2343
2344 }
2345
2346 else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2347 {
2348 bb_callcount = 1;
2349 bb_src = 0;
2350
2351 if (bb_stack)
2352 bb_stack[bb_callcount] = bb_src;
2353 }
2354
2355 MACHINE_STATE_RESTORE("3")
2356}
2357
c7544ff7
RS
2358#endif /* not inhibit_libc */
2359#endif /* not BLOCK_PROFILER_CODE */
2360#endif /* L_bb */
203b91b9 2361\f
6ffe3a32 2362/* Default free-store management functions for C++, per sections 12.5 and
0f41302f 2363 17.3.3 of the Working Paper. */
203b91b9 2364
ec06f00a 2365#ifdef L_op_new
6ffe3a32 2366/* operator new (size_t), described in 17.3.3.5. This function is used by
0f41302f 2367 C++ programs to allocate a block of memory to hold a single object. */
203b91b9 2368
6ffe3a32 2369typedef void (*vfp)(void);
203b91b9 2370extern vfp __new_handler;
8a552066 2371extern void __default_new_handler (void);
203b91b9 2372
daefd78b
JM
2373#ifdef WEAK_ALIAS
2374void * __builtin_new (size_t sz)
2375 __attribute__ ((weak, alias ("___builtin_new")));
2376void *
2377___builtin_new (size_t sz)
2378#else
203b91b9 2379void *
ec06f00a 2380__builtin_new (size_t sz)
daefd78b 2381#endif
203b91b9
RS
2382{
2383 void *p;
8a552066 2384 vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
203b91b9 2385
bcea2185
RS
2386 /* malloc (0) is unpredictable; avoid it. */
2387 if (sz == 0)
2388 sz = 1;
ecbe06a1 2389 p = (void *) malloc (sz);
442e881d
RK
2390 while (p == 0)
2391 {
8a552066 2392 (*handler) ();
442e881d
RK
2393 p = (void *) malloc (sz);
2394 }
2395
203b91b9
RS
2396 return p;
2397}
ec06f00a 2398#endif /* L_op_new */
203b91b9 2399
4c548483 2400#ifdef L_op_vnew
6ffe3a32
JM
2401/* void * operator new [] (size_t), described in 17.3.3.6. This function
2402 is used by C++ programs to allocate a block of memory for an array. */
2403
2404extern void * __builtin_new (size_t);
2405
daefd78b
JM
2406#ifdef WEAK_ALIAS
2407void * __builtin_vec_new (size_t sz)
2408 __attribute__ ((weak, alias ("___builtin_vec_new")));
2409void *
2410___builtin_vec_new (size_t sz)
2411#else
6ffe3a32
JM
2412void *
2413__builtin_vec_new (size_t sz)
daefd78b 2414#endif
6ffe3a32
JM
2415{
2416 return __builtin_new (sz);
2417}
4c548483 2418#endif /* L_op_vnew */
6ffe3a32 2419
ec06f00a 2420#ifdef L_new_handler
6ffe3a32
JM
2421/* set_new_handler (fvoid_t *) and the default new handler, described in
2422 17.3.3.2 and 17.3.3.5. These functions define the result of a failure
0f41302f 2423 to allocate the amount of memory requested from operator new or new []. */
fffa6914 2424
c74d5583 2425#ifndef inhibit_libc
fffa6914 2426/* This gets us __GNU_LIBRARY__. */
98126ed6 2427#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
fffa6914
RS
2428#include <stdio.h>
2429
2430#ifdef __GNU_LIBRARY__
2431 /* Avoid forcing the library's meaning of `write' on the user program
e45d9b98 2432 by using the "internal" name (for use within the library) */
fffa6914
RS
2433#define write(fd, buf, n) __write((fd), (buf), (n))
2434#endif
c74d5583 2435#endif /* inhibit_libc */
fffa6914 2436
203b91b9 2437typedef void (*vfp)(void);
6ffe3a32 2438void __default_new_handler (void);
203b91b9 2439
0f41302f 2440vfp __new_handler = (vfp) 0;
203b91b9 2441
203b91b9 2442vfp
6ffe3a32 2443set_new_handler (vfp handler)
203b91b9
RS
2444{
2445 vfp prev_handler;
2446
2447 prev_handler = __new_handler;
442e881d 2448 if (handler == 0) handler = __default_new_handler;
203b91b9
RS
2449 __new_handler = handler;
2450 return prev_handler;
2451}
2452
b1166fae
RS
2453#define MESSAGE "Virtual memory exceeded in `new'\n"
2454
6ffe3a32 2455void
442e881d 2456__default_new_handler ()
203b91b9 2457{
2c62c124 2458#ifndef inhibit_libc
203b91b9
RS
2459 /* don't use fprintf (stderr, ...) because it may need to call malloc. */
2460 /* This should really print the name of the program, but that is hard to
2461 do. We need a standard, clean way to get at the name. */
b1166fae 2462 write (2, MESSAGE, sizeof (MESSAGE));
2c62c124 2463#endif
203b91b9
RS
2464 /* don't call exit () because that may call global destructors which
2465 may cause a loop. */
2466 _exit (-1);
2467}
2468#endif
203b91b9 2469
ec06f00a 2470#ifdef L_op_delete
6ffe3a32
JM
2471/* operator delete (void *), described in 17.3.3.3. This function is used
2472 by C++ programs to return to the free store a block of memory allocated
0f41302f 2473 as a single object. */
6ffe3a32 2474
daefd78b
JM
2475#ifdef WEAK_ALIAS
2476void __builtin_delete (void *ptr)
2477 __attribute__ ((weak, alias ("___builtin_delete")));
2478void
2479___builtin_delete (void *ptr)
2480#else
203b91b9 2481void
ec06f00a 2482__builtin_delete (void *ptr)
daefd78b 2483#endif
203b91b9
RS
2484{
2485 if (ptr)
2486 free (ptr);
2487}
203b91b9 2488#endif
6ffe3a32 2489
4c548483 2490#ifdef L_op_vdel
6ffe3a32
JM
2491/* operator delete [] (void *), described in 17.3.3.4. This function is
2492 used by C++ programs to return to the free store a block of memory
0f41302f 2493 allocated as an array. */
6ffe3a32
JM
2494
2495extern void __builtin_delete (void *);
2496
daefd78b
JM
2497#ifdef WEAK_ALIAS
2498void __builtin_vec_delete (void *ptr)
2499 __attribute__ ((weak, alias ("___builtin_vec_delete")));
2500void
2501___builtin_vec_delete (void *ptr)
2502#else
6ffe3a32
JM
2503void
2504__builtin_vec_delete (void *ptr)
daefd78b 2505#endif
6ffe3a32
JM
2506{
2507 __builtin_delete (ptr);
2508}
2509#endif
2510
2511/* End of C++ free-store management functions */
ec06f00a 2512\f
203b91b9
RS
2513#ifdef L_shtab
2514unsigned int __shtab[] = {
2515 0x00000001, 0x00000002, 0x00000004, 0x00000008,
2516 0x00000010, 0x00000020, 0x00000040, 0x00000080,
2517 0x00000100, 0x00000200, 0x00000400, 0x00000800,
2518 0x00001000, 0x00002000, 0x00004000, 0x00008000,
2519 0x00010000, 0x00020000, 0x00040000, 0x00080000,
2520 0x00100000, 0x00200000, 0x00400000, 0x00800000,
2521 0x01000000, 0x02000000, 0x04000000, 0x08000000,
2522 0x10000000, 0x20000000, 0x40000000, 0x80000000
2523 };
2524#endif
2525\f
2526#ifdef L_clear_cache
2527/* Clear part of an instruction cache. */
2528
2529#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2530
2531void
2532__clear_cache (beg, end)
2533 char *beg, *end;
2534{
e1178973
KKT
2535#ifdef CLEAR_INSN_CACHE
2536 CLEAR_INSN_CACHE (beg, end);
2537#else
203b91b9
RS
2538#ifdef INSN_CACHE_SIZE
2539 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
7e6f1890 2540 static int initialized;
203b91b9 2541 int offset;
b6422cca
RS
2542 void *start_addr
2543 void *end_addr;
203b91b9
RS
2544 typedef (*function_ptr) ();
2545
2546#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2547 /* It's cheaper to clear the whole cache.
2548 Put in a series of jump instructions so that calling the beginning
2549 of the cache will clear the whole thing. */
2550
2551 if (! initialized)
2552 {
2553 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2554 & -INSN_CACHE_LINE_WIDTH);
2555 int end_ptr = ptr + INSN_CACHE_SIZE;
2556
2557 while (ptr < end_ptr)
2558 {
2559 *(INSTRUCTION_TYPE *)ptr
2560 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2561 ptr += INSN_CACHE_LINE_WIDTH;
2562 }
0f41302f 2563 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
203b91b9
RS
2564
2565 initialized = 1;
2566 }
2567
2568 /* Call the beginning of the sequence. */
2569 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2570 & -INSN_CACHE_LINE_WIDTH))
2571 ());
2572
2573#else /* Cache is large. */
2574
2575 if (! initialized)
2576 {
2577 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2578 & -INSN_CACHE_LINE_WIDTH);
2579
2580 while (ptr < (int) array + sizeof array)
2581 {
2582 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2583 ptr += INSN_CACHE_LINE_WIDTH;
2584 }
2585
2586 initialized = 1;
2587 }
2588
2589 /* Find the location in array that occupies the same cache line as BEG. */
2590
2591 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2592 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2593 & -INSN_CACHE_PLANE_SIZE)
2594 + offset);
2595
2596 /* Compute the cache alignment of the place to stop clearing. */
2597#if 0 /* This is not needed for gcc's purposes. */
2598 /* If the block to clear is bigger than a cache plane,
2599 we clear the entire cache, and OFFSET is already correct. */
2600 if (end < beg + INSN_CACHE_PLANE_SIZE)
2601#endif
2602 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2603 & -INSN_CACHE_LINE_WIDTH)
2604 & (INSN_CACHE_PLANE_SIZE - 1));
2605
2606#if INSN_CACHE_DEPTH > 1
2607 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2608 if (end_addr <= start_addr)
2609 end_addr += INSN_CACHE_PLANE_SIZE;
2610
2611 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2612 {
2613 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2614 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2615
2616 while (addr != stop)
2617 {
2618 /* Call the return instruction at ADDR. */
2619 ((function_ptr) addr) ();
2620
2621 addr += INSN_CACHE_LINE_WIDTH;
2622 }
2623 }
2624#else /* just one plane */
2625 do
2626 {
2627 /* Call the return instruction at START_ADDR. */
2628 ((function_ptr) start_addr) ();
2629
2630 start_addr += INSN_CACHE_LINE_WIDTH;
2631 }
2632 while ((start_addr % INSN_CACHE_SIZE) != offset);
2633#endif /* just one plane */
2634#endif /* Cache is large */
2635#endif /* Cache exists */
e1178973 2636#endif /* CLEAR_INSN_CACHE */
203b91b9
RS
2637}
2638
2639#endif /* L_clear_cache */
2640\f
2641#ifdef L_trampoline
2642
2643/* Jump to a trampoline, loading the static chain address. */
2644
f5ea9817
RK
2645#ifdef WINNT
2646
2647long getpagesize()
2648{
2649#ifdef _ALPHA_
2650 return 8192;
2651#else
2652 return 4096;
2653#endif
2654}
2655
2656int mprotect(addr, len, prot)
2657 char *addr;
2658 int len, prot;
2659{
2660 int np, op;
2661
2662 if (prot == 7) np = 0x40;
2663 else if (prot == 5) np = 0x20;
2664 else if (prot == 4) np = 0x10;
2665 else if (prot == 3) np = 0x04;
2666 else if (prot == 1) np = 0x02;
2667 else if (prot == 0) np = 0x01;
2668
2669 if (VirtualProtect (addr, len, np, &op))
2670 return 0;
2671 else
2672 return -1;
2673
2674}
2675
2676#endif
2677
203b91b9
RS
2678#ifdef TRANSFER_FROM_TRAMPOLINE
2679TRANSFER_FROM_TRAMPOLINE
2680#endif
2681
c1381fd3
KKT
2682#if defined (NeXT) && defined (__MACH__)
2683
2684/* Make stack executable so we can call trampolines on stack.
2685 This is called from INITIALIZE_TRAMPOLINE in next.h. */
c5df463e
RK
2686#ifdef NeXTStep21
2687 #include <mach.h>
2688#else
2689 #include <mach/mach.h>
2690#endif
c1381fd3
KKT
2691
2692void
2693__enable_execute_stack (addr)
2694 char *addr;
2695{
2696 kern_return_t r;
2697 char *eaddr = addr + TRAMPOLINE_SIZE;
2698 vm_address_t a = (vm_address_t) addr;
2699
2700 /* turn on execute access on stack */
2701 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2702 if (r != KERN_SUCCESS)
2703 {
2704 mach_error("vm_protect VM_PROT_ALL", r);
2705 exit(1);
2706 }
2707
2708 /* We inline the i-cache invalidation for speed */
2709
2710#ifdef CLEAR_INSN_CACHE
2711 CLEAR_INSN_CACHE (addr, eaddr);
2712#else
2713 __clear_cache ((int) addr, (int) eaddr);
2714#endif
2715}
2716
2717#endif /* defined (NeXT) && defined (__MACH__) */
2718
203b91b9
RS
2719#ifdef __convex__
2720
2721/* Make stack executable so we can call trampolines on stack.
2722 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
2723
2724#include <sys/mman.h>
2725#include <sys/vmparam.h>
2726#include <machine/machparam.h>
2727
2728void
2729__enable_execute_stack ()
2730{
2731 int fp;
2732 static unsigned lowest = USRSTACK;
2733 unsigned current = (unsigned) &fp & -NBPG;
2734
2735 if (lowest > current)
2736 {
2737 unsigned len = lowest - current;
2738 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2739 lowest = current;
2740 }
2741
0f41302f 2742 /* Clear instruction cache in case an old trampoline is in it. */
203b91b9
RS
2743 asm ("pich");
2744}
2745#endif /* __convex__ */
b335c2cc 2746
0c8ae3d3
RK
2747#ifdef __DOLPHIN__
2748
0f41302f 2749/* Modified from the convex -code above. */
0c8ae3d3
RK
2750
2751#include <sys/param.h>
2752#include <errno.h>
2753#include <sys/m88kbcs.h>
2754
2755void
2756__enable_execute_stack ()
2757{
2758 int save_errno;
2759 static unsigned long lowest = USRSTACK;
2760 unsigned long current = (unsigned long) &save_errno & -NBPC;
2761
2762 /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2763 address is seen as 'negative'. That is the case with the stack. */
2764
2765 save_errno=errno;
2766 if (lowest > current)
2767 {
2768 unsigned len=lowest-current;
2769 memctl(current,len,MCT_TEXT);
2770 lowest = current;
2771 }
2772 else
2773 memctl(current,NBPC,MCT_TEXT);
2774 errno=save_errno;
2775}
2776
2777#endif /* __DOLPHIN__ */
2778
b335c2cc
TW
2779#ifdef __pyr__
2780
98126ed6 2781#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
b335c2cc
TW
2782#include <stdio.h>
2783#include <sys/mman.h>
2784#include <sys/types.h>
2785#include <sys/param.h>
2786#include <sys/vmmac.h>
2787
2788/* Modified from the convex -code above.
0f41302f 2789 mremap promises to clear the i-cache. */
b335c2cc
TW
2790
2791void
2792__enable_execute_stack ()
2793{
2794 int fp;
2795 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2796 PROT_READ|PROT_WRITE|PROT_EXEC))
2797 {
2798 perror ("mprotect in __enable_execute_stack");
2799 fflush (stderr);
2800 abort ();
2801 }
2802}
2803#endif /* __pyr__ */
203b91b9
RS
2804#endif /* L_trampoline */
2805\f
2806#ifdef L__main
2807
2808#include "gbl-ctors.h"
c06cff95
RS
2809/* Some systems use __main in a way incompatible with its use in gcc, in these
2810 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2811 give the same symbol without quotes for an alternative entry point. You
0f41302f 2812 must define both, or neither. */
c06cff95
RS
2813#ifndef NAME__MAIN
2814#define NAME__MAIN "__main"
2815#define SYMBOL__MAIN __main
2816#endif
203b91b9 2817
68d69835 2818#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
203b91b9
RS
2819/* Run all the global destructors on exit from the program. */
2820
2821void
2822__do_global_dtors ()
2823{
89cf554b
RS
2824#ifdef DO_GLOBAL_DTORS_BODY
2825 DO_GLOBAL_DTORS_BODY;
2826#else
566b213a
JM
2827 func_ptr *p;
2828 for (p = __DTOR_LIST__ + 1; *p; )
2829 (*p++) ();
89cf554b 2830#endif
203b91b9 2831}
68d69835 2832#endif
203b91b9
RS
2833
2834#ifndef INIT_SECTION_ASM_OP
2835/* Run all the global constructors on entry to the program. */
2836
135461d9 2837#ifndef ON_EXIT
203b91b9
RS
2838#define ON_EXIT(a, b)
2839#else
2840/* Make sure the exit routine is pulled in to define the globals as
2841 bss symbols, just in case the linker does not automatically pull
2842 bss definitions from the library. */
2843
2844extern int _exit_dummy_decl;
2845int *_exit_dummy_ref = &_exit_dummy_decl;
2846#endif /* ON_EXIT */
2847
2848void
2849__do_global_ctors ()
2850{
2851 DO_GLOBAL_CTORS_BODY;
135461d9 2852 ON_EXIT (__do_global_dtors, 0);
203b91b9 2853}
b335c2cc 2854#endif /* no INIT_SECTION_ASM_OP */
203b91b9 2855
b335c2cc 2856#if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
203b91b9
RS
2857/* Subroutine called automatically by `main'.
2858 Compiling a global function named `main'
2859 produces an automatic call to this function at the beginning.
2860
2861 For many systems, this routine calls __do_global_ctors.
2862 For systems which support a .init section we use the .init section
2863 to run __do_global_ctors, so we need not do anything here. */
2864
2865void
c06cff95 2866SYMBOL__MAIN ()
203b91b9
RS
2867{
2868 /* Support recursive calls to `main': run initializers just once. */
7e6f1890 2869 static int initialized;
203b91b9
RS
2870 if (! initialized)
2871 {
2872 initialized = 1;
2873 __do_global_ctors ();
2874 }
2875}
b335c2cc 2876#endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
203b91b9
RS
2877
2878#endif /* L__main */
2879\f
ad38743d 2880#ifdef L_ctors
203b91b9
RS
2881
2882#include "gbl-ctors.h"
2883
2884/* Provide default definitions for the lists of constructors and
2885 destructors, so that we don't get linker errors. These symbols are
2886 intentionally bss symbols, so that gld and/or collect will provide
2887 the right values. */
2888
2889/* We declare the lists here with two elements each,
2890 so that they are valid empty lists if no other definition is loaded. */
b335c2cc 2891#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
b667f58f 2892#if defined(__NeXT__) || defined(_AIX)
d15d0264
RS
2893/* After 2.3, try this definition on all systems. */
2894func_ptr __CTOR_LIST__[2] = {0, 0};
2895func_ptr __DTOR_LIST__[2] = {0, 0};
2896#else
203b91b9
RS
2897func_ptr __CTOR_LIST__[2];
2898func_ptr __DTOR_LIST__[2];
d15d0264 2899#endif
b335c2cc 2900#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
ad38743d
RS
2901#endif /* L_ctors */
2902\f
2903#ifdef L_exit
2904
2905#include "gbl-ctors.h"
203b91b9 2906
8b7677be
RK
2907#ifdef NEED_ATEXIT
2908# ifdef ON_EXIT
2909# undef ON_EXIT
2910# endif
2911int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
2912#endif
2913
203b91b9
RS
2914#ifndef ON_EXIT
2915
8b7677be
RK
2916#ifdef NEED_ATEXIT
2917# include <errno.h>
2918
2919extern void *malloc ();
2920extern void *realloc ();
2921
2922static func_ptr *atexit_chain = NULL;
2923static long atexit_chain_length = 0;
2924static volatile long last_atexit_chain_slot = -1;
2925
2926int atexit (func_ptr func)
2927{
2928 if (++last_atexit_chain_slot == atexit_chain_length)
2929 {
2930 atexit_chain_length += 32;
2931 if (atexit_chain)
2932 atexit_chain = realloc (atexit_chain,
2933 atexit_chain_length * sizeof (func_ptr));
2934 else
2935 atexit_chain = malloc (atexit_chain_length * sizeof (func_ptr));
2936 if (! atexit_chain)
2937 {
2938 atexit_chain_length = 0;
2939 last_atexit_chain_slot = -1;
2940 errno = ENOMEM;
2941 return (-1);
2942 }
2943 }
2944 atexit_chain[last_atexit_chain_slot] = func;
2945 return (0);
2946}
2947#endif /* NEED_ATEXIT */
2948
203b91b9
RS
2949/* If we have no known way of registering our own __do_global_dtors
2950 routine so that it will be invoked at program exit time, then we
2951 have to define our own exit routine which will get this to happen. */
2952
2953extern void __do_global_dtors ();
2954extern void _cleanup ();
003be455 2955extern void _exit () __attribute__ ((noreturn));
203b91b9
RS
2956
2957void
2958exit (status)
2959 int status;
2960{
3a5ece65 2961#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
8b7677be
RK
2962#ifdef NEED_ATEXIT
2963 if (atexit_chain)
2964 {
2965 for ( ; last_atexit_chain_slot-- >= 0; )
2966 {
2967 (*atexit_chain[last_atexit_chain_slot + 1]) ();
2968 atexit_chain[last_atexit_chain_slot + 1] = NULL;
2969 }
2970 free (atexit_chain);
2971 atexit_chain = NULL;
2972 }
2973#else /* No NEED_ATEXIT */
203b91b9 2974 __do_global_dtors ();
8b7677be 2975#endif /* No NEED_ATEXIT */
5fd507a9 2976#endif
203b91b9
RS
2977#ifdef EXIT_BODY
2978 EXIT_BODY;
2979#else
2980 _cleanup ();
2981#endif
2982 _exit (status);
2983}
2984
2985#else
2986int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
2987#endif
2988
2989#endif /* L_exit */
2990\f
ad912eec
MS
2991#ifdef L_eh
2992typedef struct {
2993 void *start;
2994 void *end;
2995 void *exception_handler;
2996} exception_table;
2997
2998struct exception_table_node {
2999 exception_table *table;
3000 void *start;
3001 void *end;
3002 struct exception_table_node *next;
3003};
3004
7e6f1890
JM
3005static int except_table_pos;
3006static void *except_pc;
3007static struct exception_table_node *exception_table_list;
ad912eec
MS
3008
3009static exception_table *
3010find_exception_table (pc)
0f41302f 3011 void *pc;
ad912eec
MS
3012{
3013 register struct exception_table_node *table = exception_table_list;
3014 for ( ; table != 0; table = table->next)
3015 {
3016 if (table->start <= pc && table->end > pc)
3017 return table->table;
3018 }
3019 return 0;
3020}
3021
3022/* this routine takes a pc, and the address of the exception handler associated
3023 with the closest exception table handler entry associated with that PC,
3024 or 0 if there are no table entries the PC fits in. The algorithm works
3025 something like this:
3026
3027 while(current_entry exists) {
3028 if(current_entry.start < pc )
3029 current_entry = next_entry;
3030 else {
3031 if(prev_entry.start <= pc && prev_entry.end > pc) {
3032 save pointer to prev_entry;
3033 return prev_entry.exception_handler;
3034 }
3035 else return 0;
3036 }
3037 }
3038 return 0;
3039
3040 Assuming a correctly sorted table (ascending order) this routine should
abc95ed3 3041 return the tightest match...
ad912eec
MS
3042
3043 In the advent of a tie, we have to give the last entry, as it represents
0f41302f 3044 an inner block. */
ad912eec
MS
3045
3046void *
3047__find_first_exception_table_match(pc)
3048void *pc;
3049{
3050 exception_table *table = find_exception_table (pc);
3051 int pos = 0;
3052 int best = 0;
3053 if (table == 0)
0f41302f 3054 return (void *) 0;
ad912eec 3055#if 0
0f41302f 3056 printf ("find_first_exception_table_match(): pc = %x!\n", pc);
ad912eec
MS
3057#endif
3058
3059 except_pc = pc;
3060
3061#if 0
3062 /* We can't do this yet, as we don't know that the table is sorted. */
3063 do {
3064 ++pos;
3065 if (table[pos].start > except_pc)
3066 /* found the first table[pos].start > except_pc, so the previous
3067 entry better be the one we want! */
3068 break;
0f41302f 3069 } while (table[pos].exception_handler != (void *) -1);
ad912eec
MS
3070
3071 --pos;
3072 if (table[pos].start <= except_pc && table[pos].end > except_pc)
3073 {
3074 except_table_pos = pos;
3075#if 0
0f41302f 3076 printf ("find_first_eh_table_match(): found match: %x\n", table[pos].exception_handler);
ad912eec
MS
3077#endif
3078 return table[pos].exception_handler;
3079 }
3080#else
0f41302f 3081 while (table[++pos].exception_handler != (void *) -1) {
ad912eec
MS
3082 if (table[pos].start <= except_pc && table[pos].end > except_pc)
3083 {
3084 /* This can apply. Make sure it is better or as good as the previous
3085 best. */
0f41302f 3086 /* The best one ends first. */
ad912eec
MS
3087 if (best == 0 || (table[pos].end <= table[best].end
3088 /* The best one starts last. */
3089 && table[pos].start >= table[best].start))
3090 best = pos;
3091 }
3092 }
3093 if (best != 0)
3094 return table[best].exception_handler;
3095#endif
3096
3097#if 0
3098 printf("find_first_eh_table_match(): else: returning NULL!\n");
3099#endif
3100 return (void*)0;
3101}
3102
e46540c3
MS
3103void *
3104__throw_type_match (void *catch_type, void *throw_type, void* obj)
ad912eec
MS
3105{
3106#if 0
3107 printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3108 catch_type, throw_type);
3109#endif
e46540c3
MS
3110 if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3111 return obj;
3112 return 0;
ad912eec
MS
3113}
3114
3115void
3116__register_exceptions (exception_table *table)
3117{
47c0d9de 3118 struct exception_table_node *node;
ad912eec 3119 exception_table *range = table + 1;
47c0d9de 3120
0f41302f 3121 if (range->start == (void *) -1)
47c0d9de
MS
3122 return;
3123
0f41302f 3124 node = (struct exception_table_node *)
47c0d9de 3125 malloc (sizeof (struct exception_table_node));
ad912eec
MS
3126 node->table = table;
3127
3128 /* This look can be optimized away either if the table
0f41302f 3129 is sorted, or if we pass in extra parameters. */
ad912eec
MS
3130 node->start = range->start;
3131 node->end = range->end;
0f41302f 3132 for (range++ ; range->start != (void *) (-1); range++)
ad912eec
MS
3133 {
3134 if (range->start < node->start)
3135 node->start = range->start;
56031823 3136 if (range->end > node->end)
ad912eec
MS
3137 node->end = range->end;
3138 }
3139
3140 node->next = exception_table_list;
3141 exception_table_list = node;
3142}
56031823 3143
8fa6b6c9
MS
3144void
3145__empty ()
3146{
3147}
3148
1e58f107 3149#if #machine(i386)
56031823
MS
3150void
3151__unwind_function(void *ptr)
3152{
3153 asm("movl 8(%esp),%ecx");
3154 /* Undo current frame */
3155 asm("movl %ebp,%esp");
3156 asm("popl %ebp");
fd4cb6b0 3157 /* like ret, but stay here */
56031823
MS
3158 asm("addl $4,%esp");
3159
0f41302f 3160 /* Now, undo previous frame. */
56031823 3161 /* This is a test routine, as we have to dynamically probe to find out
0f41302f 3162 what to pop for certain, this is just a guess. */
56031823 3163 asm("leal -16(%ebp),%esp");
c6e84dc4
RK
3164 asm("pop %ebx");
3165 asm("pop %esi");
3166 asm("pop %edi");
56031823
MS
3167 asm("movl %ebp,%esp");
3168 asm("popl %ebp");
3169
3170 asm("movl %ecx,0(%esp)");
3171 asm("ret");
3172}
6b8149a1 3173#elif #machine(rs6000) && !defined _ARCH_PPC
71a81095
MS
3174__unwind_function(void *ptr)
3175{
3176 asm("mr 31,1");
3177 asm("l 1,0(1)");
3178 asm("l 31,-4(1)");
3179 asm("# br");
3180
3181 asm("mr 31,1");
3182 asm("l 1,0(1)");
0f41302f 3183 /* use 31 as a scratch register to restore the link register. */
71a81095
MS
3184 asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
3185 asm("l 31,-4(1)");
3186 asm("# br");
3187 asm("mtctr 3;bctr # b 3");
3188}
6b8149a1 3189#elif (#machine(rs6000) || #machine(powerpc)) && defined _ARCH_PPC
bf18d031
MM
3190__unwind_function(void *ptr)
3191{
3192 asm("mr 31,1");
3193 asm("lwz 1,0(1)");
3194 asm("lwz 31,-4(1)");
3195 asm("# br");
3196
3197 asm("mr 31,1");
3198 asm("lwz 1,0(1)");
0f41302f 3199 /* use 31 as a scratch register to restore the link register. */
bf18d031
MM
3200 asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
3201 asm("lwz 31,-4(1)");
3202 asm("# br");
3203 asm("mtctr 3;bctr # b 3");
3204}
139eda62
RK
3205#elif #machine(vax)
3206__unwind_function(void *ptr)
3207{
3208 __label__ return_again;
3209
3210 /* Replace our frame's return address with the label below.
3211 During execution, we will first return here instead of to
3212 caller, then second return takes caller's frame off the stack.
3213 Two returns matches two actual calls, so is less likely to
3214 confuse debuggers. `16' corresponds to RETURN_ADDRESS_OFFSET. */
3215 __asm ("movl %0,16(fp)" : : "p" (&& return_again));
3216 return;
3217
3218 return_again:
3219 return;
3220}
c6e84dc4
RK
3221#else
3222__unwind_function(void *ptr)
3223{
3224 abort ();
3225}
bf18d031 3226#endif /* powerpc */
ad912eec 3227#endif /* L_eh */
efc955c7
JM
3228\f
3229#ifdef L_pure
2c62c124
JM
3230#ifndef inhibit_libc
3231/* This gets us __GNU_LIBRARY__. */
3232#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
3233#include <stdio.h>
3234
3235#ifdef __GNU_LIBRARY__
3236 /* Avoid forcing the library's meaning of `write' on the user program
3237 by using the "internal" name (for use within the library) */
3238#define write(fd, buf, n) __write((fd), (buf), (n))
3239#endif
3240#endif /* inhibit_libc */
3241
efc955c7 3242#define MESSAGE "pure virtual method called\n"
2c62c124 3243
efc955c7
JM
3244void
3245__pure_virtual ()
3246{
2c62c124 3247#ifndef inhibit_libc
efc955c7 3248 write (2, MESSAGE, sizeof (MESSAGE) - 1);
2c62c124 3249#endif
efc955c7
JM
3250 _exit (-1);
3251}
3252#endif
This page took 0.722356 seconds and 5 git commands to generate.