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