]> gcc.gnu.org Git - gcc.git/blame - gcc/libgcc2.c
Bring in final gcc-2.8.0 changes.
[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. */
37ef1054 3/* Copyright (C) 1989, 92, 93, 94, 95, 96, 1997 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;
1500 unsigned char tmp;
1501 int i;
1502 int ret = 0;
1503
1504
1505 if (__read_long (&n_counts, da_file, 8) != 0)
1506 {
1507 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1508 ptr->filename);
1509 continue;
1510 }
1511
1512 if (n_counts == ptr->ncounts)
1513 {
1514 int i;
1515
1516 for (i = 0; i < n_counts; i++)
1517 {
1518 long v = 0;
1519 unsigned char tmp;
1520 int j;
1521 int ret = 0;
1522
1523 if (__read_long (&v, da_file, 8) != 0)
1524 {
1525 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1526 ptr->filename);
1527 break;
1528 }
1529 ptr->counts[i] += v;
1530 }
1531 }
1532
1533 if (fclose (da_file) == EOF)
1534 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1535 ptr->filename);
1536 }
b472527b 1537 if ((da_file = fopen (ptr->filename, "w")) == 0)
65f7a653
DE
1538 {
1539 fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1540 ptr->filename);
1541 continue;
1542 }
1543
956d6950 1544 /* ??? Should first write a header to the file. Preferably, a 4 byte
65f7a653
DE
1545 magic number, 4 bytes containing the time the program was
1546 compiled, 4 bytes containing the last modification time of the
1547 source file, and 4 bytes indicating the compiler options used.
1548
1549 That way we can easily verify that the proper source/executable/
1550 data file combination is being used from gcov. */
1551
1552 if (__write_long (ptr->ncounts, da_file, 8) != 0)
1553 {
1554
1555 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1556 ptr->filename);
1557 }
1558 else
1559 {
1560 int j;
1561 long *count_ptr = ptr->counts;
1562 int ret = 0;
1563 for (j = ptr->ncounts; j > 0; j--)
1564 {
1565 if (__write_long (*count_ptr, da_file, 8) != 0)
1566 {
1567 ret=1;
1568 break;
1569 }
1570 count_ptr++;
1571 }
1572 if (ret)
1573 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1574 ptr->filename);
1575 }
1576
1577 if (fclose (da_file) == EOF)
1578 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1579 ptr->filename);
1580 }
1581
1582 return;
1583 }
1584
1585 /* Must be basic block profiling. Emit a human readable output file. */
1586
1587 file = fopen ("bb.out", "a");
92832bb5
MM
1588
1589 if (!file)
1590 perror ("bb.out");
1591
1592 else
1593 {
1594 struct bb *ptr;
1595
1596 /* This is somewhat type incorrect, but it avoids worrying about
1597 exactly where time.h is included from. It should be ok unless
90b4a764 1598 a void * differs from other pointer formats, or if sizeof (long)
92832bb5
MM
1599 is < sizeof (time_t). It would be nice if we could assume the
1600 use of rationale standards here. */
1601
90b4a764 1602 time ((void *) &time_value);
92832bb5
MM
1603 fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1604
1605 /* We check the length field explicitly in order to allow compatibility
1606 with older GCC's which did not provide it. */
1607
0f41302f 1608 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
92832bb5
MM
1609 {
1610 int i;
65f7a653
DE
1611 int func_p = (ptr->nwords >= sizeof (struct bb)
1612 && ptr->nwords <= 1000
1613 && ptr->functions);
92832bb5
MM
1614 int line_p = (func_p && ptr->line_nums);
1615 int file_p = (func_p && ptr->filenames);
65f7a653 1616 int addr_p = (ptr->addresses != 0);
92832bb5
MM
1617 long ncounts = ptr->ncounts;
1618 long cnt_max = 0;
1619 long line_max = 0;
1620 long addr_max = 0;
1621 int file_len = 0;
1622 int func_len = 0;
1623 int blk_len = num_digits (ncounts, 10);
1624 int cnt_len;
1625 int line_len;
1626 int addr_len;
1627
1628 fprintf (file, "File %s, %ld basic blocks \n\n",
1629 ptr->filename, ncounts);
1630
1631 /* Get max values for each field. */
1632 for (i = 0; i < ncounts; i++)
1633 {
1634 const char *p;
1635 int len;
1636
1637 if (cnt_max < ptr->counts[i])
1638 cnt_max = ptr->counts[i];
1639
65f7a653 1640 if (addr_p && addr_max < ptr->addresses[i])
92832bb5
MM
1641 addr_max = ptr->addresses[i];
1642
1643 if (line_p && line_max < ptr->line_nums[i])
1644 line_max = ptr->line_nums[i];
1645
1646 if (func_p)
1647 {
1648 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1649 len = strlen (p);
1650 if (func_len < len)
1651 func_len = len;
1652 }
1653
1654 if (file_p)
1655 {
1656 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1657 len = strlen (p);
1658 if (file_len < len)
1659 file_len = len;
1660 }
1661 }
1662
1663 addr_len = num_digits (addr_max, 16);
1664 cnt_len = num_digits (cnt_max, 10);
1665 line_len = num_digits (line_max, 10);
1666
1667 /* Now print out the basic block information. */
1668 for (i = 0; i < ncounts; i++)
1669 {
1670 fprintf (file,
65f7a653 1671 " Block #%*d: executed %*ld time(s)",
92832bb5 1672 blk_len, i+1,
65f7a653
DE
1673 cnt_len, ptr->counts[i]);
1674
1675 if (addr_p)
1676 fprintf (file, " address= 0x%.*lx", addr_len,
1677 ptr->addresses[i]);
92832bb5
MM
1678
1679 if (func_p)
3cca99e8 1680 fprintf (file, " function= %-*s", func_len,
92832bb5
MM
1681 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1682
1683 if (line_p)
1d42e1b7 1684 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
92832bb5
MM
1685
1686 if (file_p)
3cca99e8 1687 fprintf (file, " file= %s",
92832bb5
MM
1688 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1689
1690 fprintf (file, "\n");
1691 }
1692
1693 fprintf (file, "\n");
1694 fflush (file);
1695 }
1696
1697 fprintf (file, "\n\n");
1698 fclose (file);
1699 }
1700}
1701
1702void
1703__bb_init_func (struct bb *blocks)
1704{
1705 /* User is supposed to check whether the first word is non-0,
0f41302f 1706 but just in case.... */
92832bb5
MM
1707
1708 if (blocks->zero_word)
1709 return;
1710
1711#ifdef ON_EXIT
1712 /* Initialize destructor. */
1713 if (!bb_head)
1714 ON_EXIT (__bb_exit_func, 0);
203b91b9 1715#endif
92832bb5
MM
1716
1717 /* Set up linked list. */
1718 blocks->zero_word = 1;
1719 blocks->next = bb_head;
1720 bb_head = blocks;
1721}
1722
90b4a764
RK
1723#ifndef MACHINE_STATE_SAVE
1724#define MACHINE_STATE_SAVE(ID)
1725#endif
1726#ifndef MACHINE_STATE_RESTORE
1727#define MACHINE_STATE_RESTORE(ID)
1728#endif
1729
0f41302f 1730/* Number of buckets in hashtable of basic block addresses. */
90b4a764
RK
1731
1732#define BB_BUCKETS 311
1733
0f41302f 1734/* Maximum length of string in file bb.in. */
90b4a764
RK
1735
1736#define BBINBUFSIZE 500
1737
1738/* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
0f41302f 1739 "BBINBUFSIZE" but want to avoid trouble with preprocessors. */
90b4a764
RK
1740
1741#define BBINBUFSIZESTR "499"
1742
1743struct bb_edge
1744{
1745 struct bb_edge *next;
1746 unsigned long src_addr;
1747 unsigned long dst_addr;
1748 unsigned long count;
1749};
1750
1751enum bb_func_mode
1752{
1753 TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1754};
1755
1756struct bb_func
1757{
1758 struct bb_func *next;
1759 char *funcname;
1760 char *filename;
1761 enum bb_func_mode mode;
1762};
1763
1764/* This is the connection to the outside world.
1765 The BLOCK_PROFILER macro must set __bb.blocks
0f41302f 1766 and __bb.blockno. */
90b4a764
RK
1767
1768struct {
1769 unsigned long blockno;
1770 struct bb *blocks;
1771} __bb;
1772
1773/* Vars to store addrs of source and destination basic blocks
0f41302f 1774 of a jump. */
90b4a764
RK
1775
1776static unsigned long bb_src = 0;
1777static unsigned long bb_dst = 0;
1778
0f41302f
MS
1779static FILE *bb_tracefile = (FILE *) 0;
1780static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1781static struct bb_func *bb_func_head = (struct bb_func *) 0;
90b4a764
RK
1782static unsigned long bb_callcount = 0;
1783static int bb_mode = 0;
1784
0f41302f 1785static unsigned long *bb_stack = (unsigned long *) 0;
90b4a764
RK
1786static size_t bb_stacksize = 0;
1787
1788static int reported = 0;
1789
1790/* Trace modes:
1791Always : Print execution frequencies of basic blocks
1792 to file bb.out.
1793bb_mode & 1 != 0 : Dump trace of basic blocks to file bbtrace[.gz]
1794bb_mode & 2 != 0 : Print jump frequencies to file bb.out.
1795bb_mode & 4 != 0 : Cut call instructions from basic block flow.
1796bb_mode & 8 != 0 : Insert return instructions in basic block flow.
1797*/
1798
1799#ifdef HAVE_POPEN
1800
1801/*#include <sys/types.h>*/
1802#include <sys/stat.h>
1803/*#include <malloc.h>*/
1804
0f41302f 1805/* Commands executed by gopen. */
90b4a764
RK
1806
1807#define GOPENDECOMPRESS "gzip -cd "
1808#define GOPENCOMPRESS "gzip -c >"
1809
1810/* Like fopen but pipes through gzip. mode may only be "r" or "w".
1811 If it does not compile, simply replace gopen by fopen and delete
0f41302f 1812 '.gz' from any first parameter to gopen. */
90b4a764
RK
1813
1814static FILE *
37ef1054 1815gopen (char *fn, char *mode)
90b4a764
RK
1816{
1817 int use_gzip;
1818 char *p;
1819
1820 if (mode[1])
0f41302f 1821 return (FILE *) 0;
90b4a764
RK
1822
1823 if (mode[0] != 'r' && mode[0] != 'w')
0f41302f 1824 return (FILE *) 0;
90b4a764
RK
1825
1826 p = fn + strlen (fn)-1;
db3cf6fb
MS
1827 use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
1828 || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
90b4a764
RK
1829
1830 if (use_gzip)
1831 {
1832 if (mode[0]=='r')
1833 {
1834 FILE *f;
0f41302f
MS
1835 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1836 + sizeof (GOPENDECOMPRESS));
90b4a764
RK
1837 strcpy (s, GOPENDECOMPRESS);
1838 strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1839 f = popen (s, mode);
1840 free (s);
1841 return f;
1842 }
1843
1844 else
1845 {
1846 FILE *f;
0f41302f
MS
1847 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1848 + sizeof (GOPENCOMPRESS));
90b4a764
RK
1849 strcpy (s, GOPENCOMPRESS);
1850 strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1851 if (!(f = popen (s, mode)))
1852 f = fopen (s, mode);
1853 free (s);
1854 return f;
1855 }
1856 }
1857
1858 else
1859 return fopen (fn, mode);
1860}
1861
1862static int
37ef1054 1863gclose (FILE *f)
90b4a764
RK
1864{
1865 struct stat buf;
1866
920b13cc 1867 if (f != 0)
90b4a764
RK
1868 {
1869 if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1870 return pclose (f);
1871
1872 return fclose (f);
1873 }
1874 return 0;
1875}
1876
1877#endif /* HAVE_POPEN */
1878
0f41302f 1879/* Called once per program. */
90b4a764
RK
1880
1881static void
1882__bb_exit_trace_func ()
1883{
1884 FILE *file = fopen ("bb.out", "a");
1885 struct bb_func *f;
1886 struct bb_edge *e;
1887 struct bb *b;
1888
1889 if (!file)
1890 perror ("bb.out");
1891
1892 if (bb_mode & 1)
1893 {
1894 if (!bb_tracefile)
1895 perror ("bbtrace");
1896 else
1897#ifdef HAVE_POPEN
1898 gclose (bb_tracefile);
1899#else
1900 fclose (bb_tracefile);
1901#endif /* HAVE_POPEN */
1902 }
1903
0f41302f 1904 /* Check functions in `bb.in'. */
90b4a764
RK
1905
1906 if (file)
1907 {
1908 long time_value;
1909 const struct bb_func *p;
1910 int printed_something = 0;
1911 struct bb *ptr;
1912 long blk;
1913
0f41302f 1914 /* This is somewhat type incorrect. */
90b4a764
RK
1915 time ((void *) &time_value);
1916
0f41302f 1917 for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
90b4a764 1918 {
0f41302f 1919 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
90b4a764 1920 {
0f41302f 1921 if (!ptr->filename || p->filename != (char *) 0 && strcmp (p->filename, ptr->filename))
90b4a764
RK
1922 continue;
1923 for (blk = 0; blk < ptr->ncounts; blk++)
1924 {
1925 if (!strcmp (p->funcname, ptr->functions[blk]))
1926 goto found;
1927 }
1928 }
1929
1930 if (!printed_something)
1931 {
1932 fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1933 printed_something = 1;
1934 }
1935
1936 fprintf (file, "\tFunction %s", p->funcname);
1937 if (p->filename)
1938 fprintf (file, " of file %s", p->filename);
1939 fprintf (file, "\n" );
1940
1941found: ;
1942 }
1943
1944 if (printed_something)
1945 fprintf (file, "\n");
1946
1947 }
1948
1949 if (bb_mode & 2)
1950 {
1951 if (!bb_hashbuckets)
1952 {
1953 if (!reported)
1954 {
1955 fprintf (stderr, "Profiler: out of memory\n");
1956 reported = 1;
1957 }
1958 return;
1959 }
1960
1961 else if (file)
1962 {
1963 long time_value;
1964 int i;
1965 unsigned long addr_max = 0;
1966 unsigned long cnt_max = 0;
1967 int cnt_len;
1968 int addr_len;
1969
1970 /* This is somewhat type incorrect, but it avoids worrying about
1971 exactly where time.h is included from. It should be ok unless
1972 a void * differs from other pointer formats, or if sizeof (long)
1973 is < sizeof (time_t). It would be nice if we could assume the
1974 use of rationale standards here. */
1975
1976 time ((void *) &time_value);
1977 fprintf (file, "Basic block jump tracing");
1978
1979 switch (bb_mode & 12)
1980 {
1981 case 0:
1982 fprintf (file, " (with call)");
1983 break;
1984
1985 case 4:
0f41302f 1986 /* Print nothing. */
90b4a764
RK
1987 break;
1988
1989 case 8:
1990 fprintf (file, " (with call & ret)");
1991 break;
1992
1993 case 12:
1994 fprintf (file, " (with ret)");
1995 break;
1996 }
1997
1998 fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1999
2000 for (i = 0; i < BB_BUCKETS; i++)
2001 {
2002 struct bb_edge *bucket = bb_hashbuckets[i];
2003 for ( ; bucket; bucket = bucket->next )
2004 {
2005 if (addr_max < bucket->src_addr)
2006 addr_max = bucket->src_addr;
2007 if (addr_max < bucket->dst_addr)
2008 addr_max = bucket->dst_addr;
2009 if (cnt_max < bucket->count)
2010 cnt_max = bucket->count;
2011 }
2012 }
2013 addr_len = num_digits (addr_max, 16);
2014 cnt_len = num_digits (cnt_max, 10);
2015
2016 for ( i = 0; i < BB_BUCKETS; i++)
2017 {
2018 struct bb_edge *bucket = bb_hashbuckets[i];
2019 for ( ; bucket; bucket = bucket->next )
2020 {
2021 fprintf (file, "Jump from block 0x%.*lx to "
2022 "block 0x%.*lx executed %*d time(s)\n",
2023 addr_len, bucket->src_addr,
2024 addr_len, bucket->dst_addr,
2025 cnt_len, bucket->count);
2026 }
2027 }
2028
2029 fprintf (file, "\n");
2030
2031 }
2032 }
2033
2034 if (file)
2035 fclose (file);
2036
0f41302f 2037 /* Free allocated memory. */
90b4a764
RK
2038
2039 f = bb_func_head;
2040 while (f)
2041 {
2042 struct bb_func *old = f;
2043
2044 f = f->next;
2045 if (old->funcname) free (old->funcname);
2046 if (old->filename) free (old->filename);
2047 free (old);
2048 }
2049
2050 if (bb_stack)
2051 free (bb_stack);
2052
2053 if (bb_hashbuckets)
2054 {
2055 int i;
2056
2057 for (i = 0; i < BB_BUCKETS; i++)
2058 {
2059 struct bb_edge *old, *bucket = bb_hashbuckets[i];
2060
2061 while (bucket)
2062 {
2063 old = bucket;
2064 bucket = bucket->next;
2065 free (old);
2066 }
2067 }
2068 free (bb_hashbuckets);
2069 }
2070
2071 for (b = bb_head; b; b = b->next)
2072 if (b->flags) free (b->flags);
2073}
2074
0f41302f 2075/* Called once per program. */
90b4a764
RK
2076
2077static void
2078__bb_init_prg ()
2079{
2080
2081 FILE *file;
2082 char buf[BBINBUFSIZE];
2083 const char *p;
2084 const char *pos;
2085 enum bb_func_mode m;
2086
2087#ifdef ON_EXIT
2088 /* Initialize destructor. */
2089 ON_EXIT (__bb_exit_func, 0);
2090#endif
2091
2092 if (!(file = fopen ("bb.in", "r")))
2093 return;
2094
2095 while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
2096 {
2097 p = buf;
2098 if (*p == '-')
2099 {
2100 m = TRACE_OFF;
2101 p++;
2102 }
2103 else
2104 {
2105 m = TRACE_ON;
2106 }
2107 if (!strcmp (p, "__bb_trace__"))
2108 bb_mode |= 1;
2109 else if (!strcmp (p, "__bb_jumps__"))
2110 bb_mode |= 2;
2111 else if (!strcmp (p, "__bb_hidecall__"))
2112 bb_mode |= 4;
2113 else if (!strcmp (p, "__bb_showret__"))
2114 bb_mode |= 8;
2115 else
2116 {
0f41302f 2117 struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
90b4a764
RK
2118 if (f)
2119 {
2120 unsigned long l;
2121 f->next = bb_func_head;
2122 if (pos = strchr (p, ':'))
2123 {
0f41302f 2124 if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
90b4a764
RK
2125 continue;
2126 strcpy (f->funcname, pos+1);
2127 l = pos-p;
0f41302f 2128 if ((f->filename = (char *) malloc (l+1)))
90b4a764
RK
2129 {
2130 strncpy (f->filename, p, l);
2131 f->filename[l] = '\0';
2132 }
2133 else
0f41302f 2134 f->filename = (char *) 0;
90b4a764
RK
2135 }
2136 else
2137 {
0f41302f 2138 if (!(f->funcname = (char *) malloc (strlen (p)+1)))
90b4a764
RK
2139 continue;
2140 strcpy (f->funcname, p);
0f41302f 2141 f->filename = (char *) 0;
90b4a764
RK
2142 }
2143 f->mode = m;
2144 bb_func_head = f;
2145 }
2146 }
2147 }
2148 fclose (file);
2149
2150#ifdef HAVE_POPEN
2151
2152 if (bb_mode & 1)
2153 bb_tracefile = gopen ("bbtrace.gz", "w");
2154
2155#else
2156
2157 if (bb_mode & 1)
2158 bb_tracefile = fopen ("bbtrace", "w");
2159
2160#endif /* HAVE_POPEN */
2161
2162 if (bb_mode & 2)
2163 {
2164 bb_hashbuckets = (struct bb_edge **)
2165 malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2166 if (bb_hashbuckets)
9bb89050 2167 bzero ((char *) bb_hashbuckets, BB_BUCKETS);
90b4a764
RK
2168 }
2169
2170 if (bb_mode & 12)
2171 {
2172 bb_stacksize = 10;
2173 bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2174 }
2175
2176#ifdef ON_EXIT
2177 /* Initialize destructor. */
2178 ON_EXIT (__bb_exit_trace_func, 0);
2179#endif
2180
2181}
2182
0f41302f 2183/* Called upon entering a basic block. */
90b4a764
RK
2184
2185void
2186__bb_trace_func ()
2187{
2188 struct bb_edge *bucket;
2189
2190 MACHINE_STATE_SAVE("1")
2191
2192 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2193 goto skip;
2194
2195 bb_dst = __bb.blocks->addresses[__bb.blockno];
2196 __bb.blocks->counts[__bb.blockno]++;
2197
2198 if (bb_tracefile)
2199 {
2200 fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2201 }
2202
2203 if (bb_hashbuckets)
2204 {
2205 struct bb_edge **startbucket, **oldnext;
2206
db3cf6fb
MS
2207 oldnext = startbucket
2208 = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
90b4a764
RK
2209 bucket = *startbucket;
2210
2211 for (bucket = *startbucket; bucket;
2212 oldnext = &(bucket->next), bucket = *oldnext)
2213 {
db3cf6fb
MS
2214 if (bucket->src_addr == bb_src
2215 && bucket->dst_addr == bb_dst)
90b4a764
RK
2216 {
2217 bucket->count++;
2218 *oldnext = bucket->next;
2219 bucket->next = *startbucket;
2220 *startbucket = bucket;
2221 goto ret;
2222 }
2223 }
2224
2225 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2226
2227 if (!bucket)
2228 {
2229 if (!reported)
2230 {
2231 fprintf (stderr, "Profiler: out of memory\n");
2232 reported = 1;
2233 }
2234 }
2235
2236 else
2237 {
2238 bucket->src_addr = bb_src;
2239 bucket->dst_addr = bb_dst;
2240 bucket->next = *startbucket;
2241 *startbucket = bucket;
2242 bucket->count = 1;
2243 }
2244 }
2245
2246ret:
2247 bb_src = bb_dst;
2248
2249skip:
2250 ;
2251
2252 MACHINE_STATE_RESTORE("1")
2253
2254}
2255
0f41302f 2256/* Called when returning from a function and `__bb_showret__' is set. */
90b4a764
RK
2257
2258static void
2259__bb_trace_func_ret ()
2260{
2261 struct bb_edge *bucket;
2262
2263 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2264 goto skip;
2265
2266 if (bb_hashbuckets)
2267 {
2268 struct bb_edge **startbucket, **oldnext;
2269
db3cf6fb
MS
2270 oldnext = startbucket
2271 = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
90b4a764
RK
2272 bucket = *startbucket;
2273
2274 for (bucket = *startbucket; bucket;
2275 oldnext = &(bucket->next), bucket = *oldnext)
2276 {
db3cf6fb
MS
2277 if (bucket->src_addr == bb_dst
2278 && bucket->dst_addr == bb_src)
90b4a764
RK
2279 {
2280 bucket->count++;
2281 *oldnext = bucket->next;
2282 bucket->next = *startbucket;
2283 *startbucket = bucket;
2284 goto ret;
2285 }
2286 }
2287
2288 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2289
2290 if (!bucket)
2291 {
2292 if (!reported)
2293 {
2294 fprintf (stderr, "Profiler: out of memory\n");
2295 reported = 1;
2296 }
2297 }
2298
2299 else
2300 {
2301 bucket->src_addr = bb_dst;
2302 bucket->dst_addr = bb_src;
2303 bucket->next = *startbucket;
2304 *startbucket = bucket;
2305 bucket->count = 1;
2306 }
2307 }
2308
2309ret:
2310 bb_dst = bb_src;
2311
2312skip:
2313 ;
2314
2315}
2316
0f41302f 2317/* Called upon entering the first function of a file. */
90b4a764
RK
2318
2319static void
37ef1054 2320__bb_init_file (struct bb *blocks)
90b4a764
RK
2321{
2322
2323 const struct bb_func *p;
2324 long blk, ncounts = blocks->ncounts;
2325 const char **functions = blocks->functions;
2326
2327 /* Set up linked list. */
2328 blocks->zero_word = 1;
2329 blocks->next = bb_head;
2330 bb_head = blocks;
2331
2332 blocks->flags = 0;
db3cf6fb
MS
2333 if (!bb_func_head
2334 || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
90b4a764
RK
2335 return;
2336
2337 for (blk = 0; blk < ncounts; blk++)
2338 blocks->flags[blk] = 0;
2339
2340 for (blk = 0; blk < ncounts; blk++)
2341 {
2342 for (p = bb_func_head; p; p = p->next)
2343 {
db3cf6fb
MS
2344 if (!strcmp (p->funcname, functions[blk])
2345 && (!p->filename || !strcmp (p->filename, blocks->filename)))
90b4a764
RK
2346 {
2347 blocks->flags[blk] |= p->mode;
2348 }
2349 }
2350 }
2351
2352}
2353
0f41302f 2354/* Called when exiting from a function. */
90b4a764
RK
2355
2356void
2357__bb_trace_ret ()
2358{
2359
2360 MACHINE_STATE_SAVE("2")
2361
2362 if (bb_callcount)
2363 {
2364 if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2365 {
2366 bb_src = bb_stack[bb_callcount];
2367 if (bb_mode & 8)
2368 __bb_trace_func_ret ();
2369 }
2370
2371 bb_callcount -= 1;
2372 }
2373
2374 MACHINE_STATE_RESTORE("2")
2375
2376}
2377
0f41302f 2378/* Called when entering a function. */
90b4a764
RK
2379
2380void
37ef1054 2381__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
90b4a764
RK
2382{
2383 static int trace_init = 0;
2384
2385 MACHINE_STATE_SAVE("3")
2386
2387 if (!blocks->zero_word)
2388 {
2389 if (!trace_init)
2390 {
2391 trace_init = 1;
2392 __bb_init_prg ();
2393 }
2394 __bb_init_file (blocks);
2395 }
2396
2397 if (bb_callcount)
2398 {
2399
2400 bb_callcount += 1;
2401
2402 if (bb_mode & 12)
2403 {
2404 if (bb_callcount >= bb_stacksize)
2405 {
2406 size_t newsize = bb_callcount + 100;
2407
2408 bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2409 if (! bb_stack)
2410 {
2411 if (!reported)
2412 {
2413 fprintf (stderr, "Profiler: out of memory\n");
2414 reported = 1;
2415 }
2416 bb_stacksize = 0;
2417 goto stack_overflow;
2418 }
2419 bb_stacksize = newsize;
2420 }
2421 bb_stack[bb_callcount] = bb_src;
2422
2423 if (bb_mode & 4)
2424 bb_src = 0;
2425
2426 }
2427
2428stack_overflow:;
2429
2430 }
2431
2432 else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2433 {
2434 bb_callcount = 1;
2435 bb_src = 0;
2436
2437 if (bb_stack)
2438 bb_stack[bb_callcount] = bb_src;
2439 }
2440
2441 MACHINE_STATE_RESTORE("3")
2442}
2443
c7544ff7
RS
2444#endif /* not inhibit_libc */
2445#endif /* not BLOCK_PROFILER_CODE */
2446#endif /* L_bb */
203b91b9 2447\f
203b91b9
RS
2448#ifdef L_shtab
2449unsigned int __shtab[] = {
2450 0x00000001, 0x00000002, 0x00000004, 0x00000008,
2451 0x00000010, 0x00000020, 0x00000040, 0x00000080,
2452 0x00000100, 0x00000200, 0x00000400, 0x00000800,
2453 0x00001000, 0x00002000, 0x00004000, 0x00008000,
2454 0x00010000, 0x00020000, 0x00040000, 0x00080000,
2455 0x00100000, 0x00200000, 0x00400000, 0x00800000,
2456 0x01000000, 0x02000000, 0x04000000, 0x08000000,
2457 0x10000000, 0x20000000, 0x40000000, 0x80000000
2458 };
2459#endif
2460\f
2461#ifdef L_clear_cache
2462/* Clear part of an instruction cache. */
2463
2464#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2465
2466void
37ef1054 2467__clear_cache (char *beg, char *end)
203b91b9 2468{
e1178973
KKT
2469#ifdef CLEAR_INSN_CACHE
2470 CLEAR_INSN_CACHE (beg, end);
2471#else
203b91b9
RS
2472#ifdef INSN_CACHE_SIZE
2473 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
7e6f1890 2474 static int initialized;
203b91b9 2475 int offset;
b6422cca
RS
2476 void *start_addr
2477 void *end_addr;
203b91b9
RS
2478 typedef (*function_ptr) ();
2479
2480#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2481 /* It's cheaper to clear the whole cache.
2482 Put in a series of jump instructions so that calling the beginning
2483 of the cache will clear the whole thing. */
2484
2485 if (! initialized)
2486 {
2487 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2488 & -INSN_CACHE_LINE_WIDTH);
2489 int end_ptr = ptr + INSN_CACHE_SIZE;
2490
2491 while (ptr < end_ptr)
2492 {
2493 *(INSTRUCTION_TYPE *)ptr
2494 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2495 ptr += INSN_CACHE_LINE_WIDTH;
2496 }
0f41302f 2497 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
203b91b9
RS
2498
2499 initialized = 1;
2500 }
2501
2502 /* Call the beginning of the sequence. */
2503 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2504 & -INSN_CACHE_LINE_WIDTH))
2505 ());
2506
2507#else /* Cache is large. */
2508
2509 if (! initialized)
2510 {
2511 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2512 & -INSN_CACHE_LINE_WIDTH);
2513
2514 while (ptr < (int) array + sizeof array)
2515 {
2516 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2517 ptr += INSN_CACHE_LINE_WIDTH;
2518 }
2519
2520 initialized = 1;
2521 }
2522
2523 /* Find the location in array that occupies the same cache line as BEG. */
2524
2525 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2526 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2527 & -INSN_CACHE_PLANE_SIZE)
2528 + offset);
2529
2530 /* Compute the cache alignment of the place to stop clearing. */
2531#if 0 /* This is not needed for gcc's purposes. */
2532 /* If the block to clear is bigger than a cache plane,
2533 we clear the entire cache, and OFFSET is already correct. */
2534 if (end < beg + INSN_CACHE_PLANE_SIZE)
2535#endif
2536 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2537 & -INSN_CACHE_LINE_WIDTH)
2538 & (INSN_CACHE_PLANE_SIZE - 1));
2539
2540#if INSN_CACHE_DEPTH > 1
2541 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2542 if (end_addr <= start_addr)
2543 end_addr += INSN_CACHE_PLANE_SIZE;
2544
2545 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2546 {
2547 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2548 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2549
2550 while (addr != stop)
2551 {
2552 /* Call the return instruction at ADDR. */
2553 ((function_ptr) addr) ();
2554
2555 addr += INSN_CACHE_LINE_WIDTH;
2556 }
2557 }
2558#else /* just one plane */
2559 do
2560 {
2561 /* Call the return instruction at START_ADDR. */
2562 ((function_ptr) start_addr) ();
2563
2564 start_addr += INSN_CACHE_LINE_WIDTH;
2565 }
2566 while ((start_addr % INSN_CACHE_SIZE) != offset);
2567#endif /* just one plane */
2568#endif /* Cache is large */
2569#endif /* Cache exists */
e1178973 2570#endif /* CLEAR_INSN_CACHE */
203b91b9
RS
2571}
2572
2573#endif /* L_clear_cache */
2574\f
2575#ifdef L_trampoline
2576
2577/* Jump to a trampoline, loading the static chain address. */
2578
272e2587 2579#if defined(WINNT) && ! defined(__CYGWIN32__)
e3367a77 2580
f5ea9817
RK
2581long getpagesize()
2582{
2583#ifdef _ALPHA_
2584 return 8192;
2585#else
2586 return 4096;
2587#endif
2588}
2589
e4b15106
RK
2590#ifdef i386
2591extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
2592#endif
2593
272e2587
RK
2594int
2595mprotect (char *addr, int len, int prot)
f5ea9817
RK
2596{
2597 int np, op;
2598
272e2587
RK
2599 if (prot == 7)
2600 np = 0x40;
2601 else if (prot == 5)
2602 np = 0x20;
2603 else if (prot == 4)
2604 np = 0x10;
2605 else if (prot == 3)
2606 np = 0x04;
2607 else if (prot == 1)
2608 np = 0x02;
2609 else if (prot == 0)
2610 np = 0x01;
f5ea9817
RK
2611
2612 if (VirtualProtect (addr, len, np, &op))
2613 return 0;
2614 else
2615 return -1;
f5ea9817
RK
2616}
2617
2618#endif
2619
203b91b9
RS
2620#ifdef TRANSFER_FROM_TRAMPOLINE
2621TRANSFER_FROM_TRAMPOLINE
2622#endif
2623
c1381fd3
KKT
2624#if defined (NeXT) && defined (__MACH__)
2625
2626/* Make stack executable so we can call trampolines on stack.
2627 This is called from INITIALIZE_TRAMPOLINE in next.h. */
c5df463e
RK
2628#ifdef NeXTStep21
2629 #include <mach.h>
2630#else
2631 #include <mach/mach.h>
2632#endif
c1381fd3
KKT
2633
2634void
37ef1054 2635__enable_execute_stack (char *addr)
c1381fd3
KKT
2636{
2637 kern_return_t r;
2638 char *eaddr = addr + TRAMPOLINE_SIZE;
2639 vm_address_t a = (vm_address_t) addr;
2640
2641 /* turn on execute access on stack */
2642 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2643 if (r != KERN_SUCCESS)
2644 {
2645 mach_error("vm_protect VM_PROT_ALL", r);
2646 exit(1);
2647 }
2648
2649 /* We inline the i-cache invalidation for speed */
2650
2651#ifdef CLEAR_INSN_CACHE
2652 CLEAR_INSN_CACHE (addr, eaddr);
2653#else
2654 __clear_cache ((int) addr, (int) eaddr);
2655#endif
2656}
2657
2658#endif /* defined (NeXT) && defined (__MACH__) */
2659
203b91b9
RS
2660#ifdef __convex__
2661
2662/* Make stack executable so we can call trampolines on stack.
2663 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
2664
2665#include <sys/mman.h>
2666#include <sys/vmparam.h>
2667#include <machine/machparam.h>
2668
2669void
2670__enable_execute_stack ()
2671{
2672 int fp;
2673 static unsigned lowest = USRSTACK;
2674 unsigned current = (unsigned) &fp & -NBPG;
2675
2676 if (lowest > current)
2677 {
2678 unsigned len = lowest - current;
2679 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2680 lowest = current;
2681 }
2682
0f41302f 2683 /* Clear instruction cache in case an old trampoline is in it. */
203b91b9
RS
2684 asm ("pich");
2685}
2686#endif /* __convex__ */
b335c2cc 2687
db87ec0b 2688#ifdef __sysV88__
0c8ae3d3 2689
0f41302f 2690/* Modified from the convex -code above. */
0c8ae3d3
RK
2691
2692#include <sys/param.h>
2693#include <errno.h>
2694#include <sys/m88kbcs.h>
2695
2696void
2697__enable_execute_stack ()
2698{
2699 int save_errno;
2700 static unsigned long lowest = USRSTACK;
2701 unsigned long current = (unsigned long) &save_errno & -NBPC;
2702
2703 /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2704 address is seen as 'negative'. That is the case with the stack. */
2705
2706 save_errno=errno;
2707 if (lowest > current)
2708 {
2709 unsigned len=lowest-current;
2710 memctl(current,len,MCT_TEXT);
2711 lowest = current;
2712 }
2713 else
2714 memctl(current,NBPC,MCT_TEXT);
2715 errno=save_errno;
2716}
2717
db87ec0b 2718#endif /* __sysV88__ */
0c8ae3d3 2719
c85f7c16
JL
2720#ifdef __sysV68__
2721
2722#include <sys/signal.h>
2723#include <errno.h>
2724
2725/* Motorola forgot to put memctl.o in the libp version of libc881.a,
2726 so define it here, because we need it in __clear_insn_cache below */
2727
2728asm("\n\
2729 global memctl\n\
2730memctl:\n\
2731 movq &75,%d0\n\
2732 trap &0\n\
2733 bcc.b noerror\n\
2734 jmp cerror%\n\
2735noerror:\n\
2736 movq &0,%d0\n\
2737 rts");
2738
2739/* Clear instruction cache so we can call trampolines on stack.
2740 This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
2741
2742void
2743__clear_insn_cache ()
2744{
2745 int save_errno;
2746
2747 /* Preserve errno, because users would be surprised to have
2748 errno changing without explicitly calling any system-call. */
2749 save_errno = errno;
2750
2751 /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
2752 No need to use an address derived from _start or %sp, as 0 works also. */
2753 memctl(0, 4096, MCT_TEXT);
2754 errno = save_errno;
2755}
2756
2757#endif /* __sysV68__ */
2758
b335c2cc
TW
2759#ifdef __pyr__
2760
98126ed6 2761#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
b335c2cc
TW
2762#include <stdio.h>
2763#include <sys/mman.h>
2764#include <sys/types.h>
2765#include <sys/param.h>
2766#include <sys/vmmac.h>
2767
2768/* Modified from the convex -code above.
0f41302f 2769 mremap promises to clear the i-cache. */
b335c2cc
TW
2770
2771void
2772__enable_execute_stack ()
2773{
2774 int fp;
2775 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2776 PROT_READ|PROT_WRITE|PROT_EXEC))
2777 {
2778 perror ("mprotect in __enable_execute_stack");
2779 fflush (stderr);
2780 abort ();
2781 }
2782}
2783#endif /* __pyr__ */
7d41c411
RK
2784
2785#if defined (sony_news) && defined (SYSTYPE_BSD)
2786
2787#include <stdio.h>
2788#include <sys/types.h>
2789#include <sys/param.h>
2790#include <syscall.h>
2791#include <machine/sysnews.h>
2792
2793/* cacheflush function for NEWS-OS 4.2.
2794 This function is called from trampoline-initialize code
2795 defined in config/mips/mips.h. */
2796
2797void
37ef1054 2798cacheflush (char *beg, int size, int flag)
7d41c411
RK
2799{
2800 if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
2801 {
2802 perror ("cache_flush");
2803 fflush (stderr);
2804 abort ();
2805 }
2806}
2807
2808#endif /* sony_news */
203b91b9
RS
2809#endif /* L_trampoline */
2810\f
2811#ifdef L__main
2812
2813#include "gbl-ctors.h"
c06cff95
RS
2814/* Some systems use __main in a way incompatible with its use in gcc, in these
2815 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2816 give the same symbol without quotes for an alternative entry point. You
0f41302f 2817 must define both, or neither. */
c06cff95
RS
2818#ifndef NAME__MAIN
2819#define NAME__MAIN "__main"
2820#define SYMBOL__MAIN __main
2821#endif
203b91b9 2822
fe1fd353
JM
2823#ifdef INIT_SECTION_ASM_OP
2824#undef HAS_INIT_SECTION
2825#define HAS_INIT_SECTION
2826#endif
2827
2828#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
203b91b9
RS
2829/* Run all the global destructors on exit from the program. */
2830
2831void
2832__do_global_dtors ()
2833{
89cf554b
RS
2834#ifdef DO_GLOBAL_DTORS_BODY
2835 DO_GLOBAL_DTORS_BODY;
2836#else
b40b9d93
MS
2837 static func_ptr *p = __DTOR_LIST__ + 1;
2838 while (*p)
2839 {
2840 p++;
2841 (*(p-1)) ();
2842 }
89cf554b 2843#endif
203b91b9 2844}
68d69835 2845#endif
203b91b9 2846
fe1fd353 2847#ifndef HAS_INIT_SECTION
203b91b9
RS
2848/* Run all the global constructors on entry to the program. */
2849
135461d9 2850#ifndef ON_EXIT
203b91b9
RS
2851#define ON_EXIT(a, b)
2852#else
2853/* Make sure the exit routine is pulled in to define the globals as
2854 bss symbols, just in case the linker does not automatically pull
2855 bss definitions from the library. */
2856
2857extern int _exit_dummy_decl;
2858int *_exit_dummy_ref = &_exit_dummy_decl;
2859#endif /* ON_EXIT */
2860
2861void
2862__do_global_ctors ()
2863{
2864 DO_GLOBAL_CTORS_BODY;
135461d9 2865 ON_EXIT (__do_global_dtors, 0);
203b91b9 2866}
fe1fd353 2867#endif /* no HAS_INIT_SECTION */
203b91b9 2868
fe1fd353 2869#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
203b91b9
RS
2870/* Subroutine called automatically by `main'.
2871 Compiling a global function named `main'
2872 produces an automatic call to this function at the beginning.
2873
2874 For many systems, this routine calls __do_global_ctors.
2875 For systems which support a .init section we use the .init section
2876 to run __do_global_ctors, so we need not do anything here. */
2877
2878void
c06cff95 2879SYMBOL__MAIN ()
203b91b9
RS
2880{
2881 /* Support recursive calls to `main': run initializers just once. */
7e6f1890 2882 static int initialized;
203b91b9
RS
2883 if (! initialized)
2884 {
2885 initialized = 1;
2886 __do_global_ctors ();
2887 }
2888}
fe1fd353 2889#endif /* no HAS_INIT_SECTION or INVOKE__main */
203b91b9
RS
2890
2891#endif /* L__main */
2892\f
ad38743d 2893#ifdef L_ctors
203b91b9
RS
2894
2895#include "gbl-ctors.h"
2896
2897/* Provide default definitions for the lists of constructors and
2898 destructors, so that we don't get linker errors. These symbols are
2899 intentionally bss symbols, so that gld and/or collect will provide
2900 the right values. */
2901
2902/* We declare the lists here with two elements each,
2903 so that they are valid empty lists if no other definition is loaded. */
b335c2cc 2904#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
b667f58f 2905#if defined(__NeXT__) || defined(_AIX)
d15d0264
RS
2906/* After 2.3, try this definition on all systems. */
2907func_ptr __CTOR_LIST__[2] = {0, 0};
2908func_ptr __DTOR_LIST__[2] = {0, 0};
2909#else
203b91b9
RS
2910func_ptr __CTOR_LIST__[2];
2911func_ptr __DTOR_LIST__[2];
d15d0264 2912#endif
b335c2cc 2913#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
ad38743d
RS
2914#endif /* L_ctors */
2915\f
2916#ifdef L_exit
2917
2918#include "gbl-ctors.h"
203b91b9 2919
8b7677be
RK
2920#ifdef NEED_ATEXIT
2921# ifdef ON_EXIT
2922# undef ON_EXIT
2923# endif
2924int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
2925#endif
2926
203b91b9
RS
2927#ifndef ON_EXIT
2928
8b7677be
RK
2929#ifdef NEED_ATEXIT
2930# include <errno.h>
2931
920b13cc 2932static func_ptr *atexit_chain = 0;
8b7677be
RK
2933static long atexit_chain_length = 0;
2934static volatile long last_atexit_chain_slot = -1;
2935
2936int atexit (func_ptr func)
2937{
2938 if (++last_atexit_chain_slot == atexit_chain_length)
2939 {
2940 atexit_chain_length += 32;
2941 if (atexit_chain)
a25cea96
RK
2942 atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2943 * sizeof (func_ptr));
8b7677be 2944 else
a25cea96
RK
2945 atexit_chain = (func_ptr *) malloc (atexit_chain_length
2946 * sizeof (func_ptr));
8b7677be
RK
2947 if (! atexit_chain)
2948 {
2949 atexit_chain_length = 0;
2950 last_atexit_chain_slot = -1;
2951 errno = ENOMEM;
2952 return (-1);
2953 }
2954 }
2955 atexit_chain[last_atexit_chain_slot] = func;
2956 return (0);
2957}
2958#endif /* NEED_ATEXIT */
2959
203b91b9
RS
2960/* If we have no known way of registering our own __do_global_dtors
2961 routine so that it will be invoked at program exit time, then we
2962 have to define our own exit routine which will get this to happen. */
2963
2964extern void __do_global_dtors ();
65f7a653 2965extern void __bb_exit_func ();
203b91b9 2966extern void _cleanup ();
003be455 2967extern void _exit () __attribute__ ((noreturn));
203b91b9
RS
2968
2969void
37ef1054 2970exit (int status)
203b91b9 2971{
3a5ece65 2972#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
8b7677be
RK
2973#ifdef NEED_ATEXIT
2974 if (atexit_chain)
2975 {
2976 for ( ; last_atexit_chain_slot-- >= 0; )
2977 {
2978 (*atexit_chain[last_atexit_chain_slot + 1]) ();
920b13cc 2979 atexit_chain[last_atexit_chain_slot + 1] = 0;
8b7677be
RK
2980 }
2981 free (atexit_chain);
920b13cc 2982 atexit_chain = 0;
8b7677be
RK
2983 }
2984#else /* No NEED_ATEXIT */
203b91b9 2985 __do_global_dtors ();
8b7677be 2986#endif /* No NEED_ATEXIT */
5fd507a9 2987#endif
65f7a653
DE
2988#ifndef inhibit_libc
2989 __bb_exit_func ();
2990#endif
203b91b9
RS
2991#ifdef EXIT_BODY
2992 EXIT_BODY;
2993#else
2994 _cleanup ();
2995#endif
2996 _exit (status);
2997}
2998
2999#else
3000int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
3001#endif
3002
3003#endif /* L_exit */
3004\f
ad912eec 3005#ifdef L_eh
6adb4e3a 3006
f24af81b 3007#include "gthr.h"
6adb4e3a 3008
154bba13 3009/* Shared exception handling support routines. */
6adb4e3a 3010
e976b8b2
MS
3011void
3012__default_terminate ()
3013{
3014 abort ();
3015}
3016
3017void (*__terminate_func)() = __default_terminate;
3018
3019void
3020__terminate ()
3021{
3022 (*__terminate_func)();
3023}
3024
ca55abae
JM
3025void *
3026__throw_type_match (void *catch_type, void *throw_type, void *obj)
3027{
3028#if 0
3029 printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3030 catch_type, throw_type);
3031#endif
3032 if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3033 return obj;
3034 return 0;
3035}
3036
3037void
3038__empty ()
3039{
3040}
3041\f
154bba13
TT
3042/* EH context structure. */
3043
3044struct eh_context
3045{
3046 void **dynamic_handler_chain;
154bba13
TT
3047 /* This is language dependent part of the eh context. */
3048 void *info;
3049};
3050
3051/* This is a safeguard for dynamic handler chain. */
3052
3053static void *top_elt[2];
3054
3055/* Allocate and return a new EH context structure. */
3056
3057extern void __throw ();
3058
3059static void *
3060new_eh_context ()
3061{
3062 struct eh_context *eh = (struct eh_context *) malloc (sizeof *eh);
3063 if (! eh)
3064 __terminate ();
3065
3066 memset (eh, 0, sizeof *eh);
3067
3068 eh->dynamic_handler_chain = top_elt;
154bba13
TT
3069
3070 return eh;
3071}
3072
3073#if __GTHREADS
3074static __gthread_key_t eh_context_key;
3075
3076/* Destructor for struct eh_context. */
3077static void
3078eh_context_free (void *ptr)
3079{
f24af81b 3080 __gthread_key_dtor (eh_context_key, ptr);
154bba13
TT
3081 if (ptr)
3082 free (ptr);
3083}
3084#endif
3085
3086/* Pointer to function to return EH context. */
3087
3088static struct eh_context *eh_context_initialize ();
3089static struct eh_context *eh_context_static ();
3090#if __GTHREADS
3091static struct eh_context *eh_context_specific ();
3092#endif
3093
3094static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
3095
3096/* Routine to get EH context.
3097 This one will simply call the function pointer. */
3098
3099void *
3100__get_eh_context ()
3101{
3102 return (void *) (*get_eh_context) ();
3103}
3104
3105/* Get and set the language specific info pointer. */
3106
3107void **
3108__get_eh_info ()
3109{
3110 struct eh_context *eh = (*get_eh_context) ();
0776059e 3111 return &eh->info;
154bba13
TT
3112}
3113\f
3114#if __GTHREADS
3115static void
3116eh_threads_initialize ()
3117{
3118 /* Try to create the key. If it fails, revert to static method,
3119 otherwise start using thread specific EH contexts. */
3120 if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
3121 get_eh_context = &eh_context_specific;
3122 else
3123 get_eh_context = &eh_context_static;
3124}
3125#endif /* no __GTHREADS */
3126
3127/* Initialize EH context.
3128 This will be called only once, since we change GET_EH_CONTEXT
3129 pointer to another routine. */
3130
3131static struct eh_context *
3132eh_context_initialize ()
3133{
3134#if __GTHREADS
3135
3136 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
f24af81b
TT
3137 if (__gthread_once (&once, eh_threads_initialize) == -1)
3138 {
3139 /* Use static version of EH context. */
3140 get_eh_context = &eh_context_static;
3141 }
154bba13
TT
3142
3143#else /* no __GTHREADS */
3144
3145 /* Use static version of EH context. */
3146 get_eh_context = &eh_context_static;
3147
3148#endif /* no __GTHREADS */
3149
3150 return (*get_eh_context) ();
3151}
3152
3153/* Return a static EH context. */
3154
3155static struct eh_context *
3156eh_context_static ()
3157{
3158 static struct eh_context *eh;
3159 if (! eh)
3160 eh = new_eh_context ();
3161 return eh;
3162}
3163
3164#if __GTHREADS
3165/* Return a thread specific EH context. */
3166
3167static struct eh_context *
3168eh_context_specific ()
3169{
3170 struct eh_context *eh;
3171 eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
3172 if (! eh)
3173 {
3174 eh = new_eh_context ();
3175 if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
3176 __terminate ();
3177 }
3178
3179 return eh;
3180}
3181#endif __GTHREADS
3182\f
ca55abae
JM
3183/* Support routines for setjmp/longjmp exception handling. */
3184
e976b8b2
MS
3185/* Calls to __sjthrow are generated by the compiler when an exception
3186 is raised when using the setjmp/longjmp exception handling codegen
3187 method. */
3188
154bba13 3189#ifdef DONT_USE_BUILTIN_SETJMP
6e6a07d2 3190extern void longjmp (void *, int);
154bba13 3191#endif
e976b8b2
MS
3192
3193/* Routine to get the head of the current thread's dynamic handler chain
154bba13 3194 use for exception handling. */
e976b8b2
MS
3195
3196void ***
3197__get_dynamic_handler_chain ()
3198{
154bba13 3199 struct eh_context *eh = (*get_eh_context) ();
0776059e 3200 return &eh->dynamic_handler_chain;
e976b8b2
MS
3201}
3202
3203/* This is used to throw an exception when the setjmp/longjmp codegen
3204 method is used for exception handling.
3205
154bba13
TT
3206 We call __terminate if there are no handlers left. Otherwise we run the
3207 cleanup actions off the dynamic cleanup stack, and pop the top of the
3208 dynamic handler chain, and use longjmp to transfer back to the associated
3209 handler. */
e976b8b2
MS
3210
3211void
3212__sjthrow ()
3213{
154bba13
TT
3214 struct eh_context *eh = (*get_eh_context) ();
3215 void ***dhc = &eh->dynamic_handler_chain;
e976b8b2
MS
3216 void *jmpbuf;
3217 void (*func)(void *, int);
3218 void *arg;
3219 void ***cleanup;
3220
3221 /* The cleanup chain is one word into the buffer. Get the cleanup
3222 chain. */
3223 cleanup = (void***)&(*dhc)[1];
3224
3225 /* If there are any cleanups in the chain, run them now. */
3226 if (cleanup[0])
3227 {
3228 double store[200];
3229 void **buf = (void**)store;
3230 buf[1] = 0;
3231 buf[0] = (*dhc);
3232
3233 /* try { */
6e6a07d2 3234#ifdef DONT_USE_BUILTIN_SETJMP
e976b8b2 3235 if (! setjmp (&buf[2]))
6e6a07d2
MS
3236#else
3237 if (! __builtin_setjmp (&buf[2]))
3238#endif
e976b8b2
MS
3239 {
3240 *dhc = buf;
3241 while (cleanup[0])
3242 {
3243 func = (void(*)(void*, int))cleanup[0][1];
3244 arg = (void*)cleanup[0][2];
3245
3246 /* Update this before running the cleanup. */
3247 cleanup[0] = (void **)cleanup[0][0];
3248
3249 (*func)(arg, 2);
3250 }
3251 *dhc = buf[0];
3252 }
3253 /* catch (...) */
3254 else
3255 {
3256 __terminate ();
3257 }
3258 }
3259
3260 /* We must call terminate if we try and rethrow an exception, when
3261 there is no exception currently active and when there are no
3262 handlers left. */
154bba13 3263 if (! eh->info || (*dhc) == top_elt)
e976b8b2
MS
3264 __terminate ();
3265
3266 /* Find the jmpbuf associated with the top element of the dynamic
3267 handler chain. The jumpbuf starts two words into the buffer. */
3268 jmpbuf = &(*dhc)[2];
3269
3270 /* Then we pop the top element off the dynamic handler chain. */
3271 *dhc = (void**)(*dhc)[0];
3272
3273 /* And then we jump to the handler. */
3274
6e6a07d2 3275#ifdef DONT_USE_BUILTIN_SETJMP
e976b8b2 3276 longjmp (jmpbuf, 1);
6e6a07d2
MS
3277#else
3278 __builtin_longjmp (jmpbuf, 1);
e976b8b2
MS
3279#endif
3280}
3281
3282/* Run cleanups on the dynamic cleanup stack for the current dynamic
3283 handler, then pop the handler off the dynamic handler stack, and
3284 then throw. This is used to skip the first handler, and transfer
3285 control to the next handler in the dynamic handler stack. */
3286
3287void
3288__sjpopnthrow ()
3289{
154bba13
TT
3290 struct eh_context *eh = (*get_eh_context) ();
3291 void ***dhc = &eh->dynamic_handler_chain;
e976b8b2
MS
3292 void *jmpbuf;
3293 void (*func)(void *, int);
3294 void *arg;
3295 void ***cleanup;
3296
3297 /* The cleanup chain is one word into the buffer. Get the cleanup
3298 chain. */
3299 cleanup = (void***)&(*dhc)[1];
3300
3301 /* If there are any cleanups in the chain, run them now. */
3302 if (cleanup[0])
3303 {
3304 double store[200];
3305 void **buf = (void**)store;
3306 buf[1] = 0;
3307 buf[0] = (*dhc);
3308
3309 /* try { */
6e6a07d2 3310#ifdef DONT_USE_BUILTIN_SETJMP
e976b8b2 3311 if (! setjmp (&buf[2]))
6e6a07d2
MS
3312#else
3313 if (! __builtin_setjmp (&buf[2]))
3314#endif
e976b8b2
MS
3315 {
3316 *dhc = buf;
3317 while (cleanup[0])
3318 {
3319 func = (void(*)(void*, int))cleanup[0][1];
3320 arg = (void*)cleanup[0][2];
3321
3322 /* Update this before running the cleanup. */
3323 cleanup[0] = (void **)cleanup[0][0];
3324
3325 (*func)(arg, 2);
3326 }
3327 *dhc = buf[0];
3328 }
3329 /* catch (...) */
3330 else
3331 {
3332 __terminate ();
3333 }
3334 }
3335
3336 /* Then we pop the top element off the dynamic handler chain. */
3337 *dhc = (void**)(*dhc)[0];
3338
3339 __sjthrow ();
3340}
ca55abae
JM
3341\f
3342/* Support code for all exception region-based exception handling. */
3343
3344/* This value identifies the place from which an exception is being
3345 thrown. */
3346
ca55abae
JM
3347#ifdef EH_TABLE_LOOKUP
3348
3349EH_TABLE_LOOKUP
e976b8b2 3350
ca55abae
JM
3351#else
3352
3353typedef struct exception_table {
ad912eec
MS
3354 void *start;
3355 void *end;
3356 void *exception_handler;
3357} exception_table;
3358
ca55abae
JM
3359/* This routine takes a PC and a pointer to the exception region TABLE for
3360 its translation unit, and returns the address of the exception handler
3361 associated with the closest exception table handler entry associated
3362 with that PC, or 0 if there are no table entries the PC fits in.
3363
3364 In the advent of a tie, we have to give the last entry, as it represents
3365 an inner block. */
3366
3367static void *
3368find_exception_handler (void *pc, exception_table *table)
3369{
3370 if (table)
3371 {
3372 int pos;
c0727e2a 3373 int best = -1;
ca55abae
JM
3374
3375 /* We can't do a binary search because the table isn't guaranteed
3376 to be sorted from function to function. */
3377 for (pos = 0; table[pos].exception_handler != (void *) -1; ++pos)
3378 {
6020d360 3379 if (table[pos].start <= pc && table[pos].end > pc)
ca55abae
JM
3380 {
3381 /* This can apply. Make sure it is at least as small as
3382 the previous best. */
c0727e2a
JM
3383 if (best == -1 || (table[pos].end <= table[best].end
3384 && table[pos].start >= table[best].start))
ca55abae
JM
3385 best = pos;
3386 }
3387 /* But it is sorted by starting PC within a function. */
6020d360 3388 else if (best >= 0 && table[pos].start > pc)
ca55abae
JM
3389 break;
3390 }
c0727e2a 3391 if (best != -1)
ca55abae
JM
3392 return table[best].exception_handler;
3393 }
3394
3395 return (void *) 0;
3396}
3397#endif /* EH_TABLE_LOOKUP */
3398\f
0776059e 3399#ifdef DWARF2_UNWIND_INFO
ca55abae
JM
3400/* Support code for exception handling using static unwind information. */
3401
3402#include "frame.h"
3403
3404/* This type is used in get_reg and put_reg to deal with ABIs where a void*
3405 is smaller than a word, such as the Irix 6 n32 ABI. We cast twice to
3406 avoid a warning about casting between int and pointer of different
3407 sizes. */
3408
3409typedef int ptr_type __attribute__ ((mode (pointer)));
3410
3411/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
3412 frame called by UDATA or 0. */
3413
3414static void*
3415get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
3416{
3417 if (udata->saved[reg] == REG_SAVED_OFFSET)
3418 return (void *)(ptr_type)
3419 *(word_type *)(udata->cfa + udata->reg_or_offset[reg]);
3420 else if (udata->saved[reg] == REG_SAVED_REG && sub_udata)
3421 return get_reg (udata->reg_or_offset[reg], sub_udata, 0);
3422 else
3423 abort ();
3424}
3425
3426/* Overwrite the saved value for register REG in frame UDATA with VAL. */
3427
3428static void
3429put_reg (unsigned reg, void *val, frame_state *udata)
3430{
3431 if (udata->saved[reg] == REG_SAVED_OFFSET)
3432 *(word_type *)(udata->cfa + udata->reg_or_offset[reg])
3433 = (word_type)(ptr_type) val;
3434 else
3435 abort ();
3436}
3437
2f3ca9e7
JM
3438/* Copy the saved value for register REG from frame UDATA to frame
3439 TARGET_UDATA. Unlike the previous two functions, this can handle
3440 registers that are not one word large. */
3441
3442static void
3443copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
3444{
3445 if (udata->saved[reg] == REG_SAVED_OFFSET
3446 && target_udata->saved[reg] == REG_SAVED_OFFSET)
3447 memcpy (target_udata->cfa + target_udata->reg_or_offset[reg],
3448 udata->cfa + udata->reg_or_offset[reg],
3449 __builtin_dwarf_reg_size (reg));
3450 else
3451 abort ();
3452}
3453
ca55abae
JM
3454/* Retrieve the return address for frame UDATA, where SUB_UDATA is a
3455 frame called by UDATA or 0. */
3456
3457static inline void *
3458get_return_addr (frame_state *udata, frame_state *sub_udata)
3459{
3460 return __builtin_extract_return_addr
3461 (get_reg (udata->retaddr_column, udata, sub_udata));
3462}
3463
3464/* Overwrite the return address for frame UDATA with VAL. */
3465
3466static inline void
3467put_return_addr (void *val, frame_state *udata)
3468{
3469 val = __builtin_frob_return_addr (val);
3470 put_reg (udata->retaddr_column, val, udata);
3471}
3472
3473/* Given the current frame UDATA and its return address PC, return the
3474 information about the calling frame in CALLER_UDATA. */
3475
3476static void *
3477next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
3478{
3479 caller_udata = __frame_state_for (pc, caller_udata);
3480 if (! caller_udata)
3481 return 0;
3482
3483 /* Now go back to our caller's stack frame. If our caller's CFA register
3484 was saved in our stack frame, restore it; otherwise, assume the CFA
3485 register is SP and restore it to our CFA value. */
3486 if (udata->saved[caller_udata->cfa_reg])
3487 caller_udata->cfa = get_reg (caller_udata->cfa_reg, udata, 0);
3488 else
3489 caller_udata->cfa = udata->cfa;
3490 caller_udata->cfa += caller_udata->cfa_offset;
3491
3492 return caller_udata;
3493}
3494
3495#ifdef INCOMING_REGNO
3496/* Is the saved value for register REG in frame UDATA stored in a register
3497 window in the previous frame? */
3498
3499static int
3500in_reg_window (int reg, frame_state *udata)
3501{
3502 if (udata->saved[reg] != REG_SAVED_OFFSET)
3503 return 0;
3504
3505#ifdef STACK_GROWS_DOWNWARD
3506 return udata->reg_or_offset[reg] > 0;
3507#else
3508 return udata->reg_or_offset[reg] < 0;
3509#endif
3510}
3511#endif /* INCOMING_REGNO */
3512
3513/* We first search for an exception handler, and if we don't find
3514 it, we call __terminate on the current stack frame so that we may
3515 use the debugger to walk the stack and understand why no handler
3516 was found.
3517
3518 If we find one, then we unwind the frames down to the one that
3519 has the handler and transfer control into the handler. */
3520
3521void
3522__throw ()
3523{
154bba13
TT
3524 struct eh_context *eh = (*get_eh_context) ();
3525 void *saved_pc, *pc, *handler, *retaddr;
ca55abae
JM
3526 frame_state ustruct, ustruct2;
3527 frame_state *udata = &ustruct;
3528 frame_state *sub_udata = &ustruct2;
3529 frame_state my_ustruct, *my_udata = &my_ustruct;
3530 long args_size;
3531
3532 /* This is required for C++ semantics. We must call terminate if we
3533 try and rethrow an exception, when there is no exception currently
3534 active. */
154bba13 3535 if (! eh->info)
ca55abae
JM
3536 __terminate ();
3537
3538 /* Start at our stack frame. */
3539label:
3540 udata = __frame_state_for (&&label, udata);
3541 if (! udata)
3542 __terminate ();
3543
3544 /* We need to get the value from the CFA register. At this point in
3545 compiling __throw we don't know whether or not we will use the frame
3546 pointer register for the CFA, so we check our unwind info. */
3547 if (udata->cfa_reg == __builtin_dwarf_fp_regnum ())
3548 udata->cfa = __builtin_fp ();
3549 else
3550 udata->cfa = __builtin_sp ();
3551 udata->cfa += udata->cfa_offset;
3552
3553 memcpy (my_udata, udata, sizeof (*udata));
3554
3555 /* Do any necessary initialization to access arbitrary stack frames.
3556 On the SPARC, this means flushing the register windows. */
3557 __builtin_unwind_init ();
3558
3559 /* Now reset pc to the right throw point. */
154bba13
TT
3560 pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
3561 saved_pc = pc;
ca55abae 3562
f4744807 3563 handler = 0;
ca55abae
JM
3564 for (;;)
3565 {
3566 frame_state *p = udata;
3567 udata = next_stack_level (pc, udata, sub_udata);
3568 sub_udata = p;
3569
3570 /* If we couldn't find the next frame, we lose. */
3571 if (! udata)
3572 break;
3573
3574 handler = find_exception_handler (pc, udata->eh_ptr);
3575
3576 /* If we found one, we can stop searching. */
3577 if (handler)
3578 {
3579 args_size = udata->args_size;
3580 break;
3581 }
3582
6020d360
JM
3583 /* Otherwise, we continue searching. We subtract 1 from PC to avoid
3584 hitting the beginning of the next region. */
3585 pc = get_return_addr (udata, sub_udata) - 1;
ca55abae
JM
3586 }
3587
3588 /* If we haven't found a handler by now, this is an unhandled
3589 exception. */
3590 if (! handler)
3591 __terminate ();
3592
154bba13 3593 if (pc == saved_pc)
ca55abae
JM
3594 /* We found a handler in the throw context, no need to unwind. */
3595 udata = my_udata;
3596 else
3597 {
3598 int i;
3599 void *val;
3600
3601 /* Unwind all the frames between this one and the handler by copying
3602 their saved register values into our register save slots. */
3603
3604 /* Remember the PC where we found the handler. */
3605 void *handler_pc = pc;
3606
3607 /* Start from the throw context again. */
154bba13 3608 pc = saved_pc;
ca55abae
JM
3609 memcpy (udata, my_udata, sizeof (*udata));
3610
3611 while (pc != handler_pc)
3612 {
3613 frame_state *p = udata;
3614 udata = next_stack_level (pc, udata, sub_udata);
3615 sub_udata = p;
3616
3617 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
d1485032 3618 if (i != udata->retaddr_column && udata->saved[i])
ca55abae
JM
3619 {
3620#ifdef INCOMING_REGNO
3621 /* If you modify the saved value of the return address
3622 register on the SPARC, you modify the return address for
3623 your caller's frame. Don't do that here, as it will
3624 confuse get_return_addr. */
3625 if (in_reg_window (i, udata)
3626 && udata->saved[udata->retaddr_column] == REG_SAVED_REG
3627 && udata->reg_or_offset[udata->retaddr_column] == i)
3628 continue;
3629#endif
2f3ca9e7 3630 copy_reg (i, udata, my_udata);
ca55abae
JM
3631 }
3632
6020d360 3633 pc = get_return_addr (udata, sub_udata) - 1;
ca55abae
JM
3634 }
3635
3636#ifdef INCOMING_REGNO
3637 /* But we do need to update the saved return address register from
3638 the last frame we unwind, or the handler frame will have the wrong
3639 return address. */
3640 if (udata->saved[udata->retaddr_column] == REG_SAVED_REG)
3641 {
3642 i = udata->reg_or_offset[udata->retaddr_column];
3643 if (in_reg_window (i, udata))
f3447109 3644 copy_reg (i, udata, my_udata);
ca55abae
JM
3645 }
3646#endif
3647 }
3648 /* udata now refers to the frame called by the handler frame. */
3649
3650 /* Emit the stub to adjust sp and jump to the handler. */
3651 retaddr = __builtin_eh_stub ();
3652
3653 /* And then set our return address to point to the stub. */
3654 if (my_udata->saved[my_udata->retaddr_column] == REG_SAVED_OFFSET)
3655 put_return_addr (retaddr, my_udata);
3656 else
3657 __builtin_set_return_addr_reg (retaddr);
3658
3659 /* Set up the registers we use to communicate with the stub.
3660 We check STACK_GROWS_DOWNWARD so the stub can use adjust_stack. */
3661 __builtin_set_eh_regs (handler,
3662#ifdef STACK_GROWS_DOWNWARD
3663 udata->cfa - my_udata->cfa
3664#else
3665 my_udata->cfa - udata->cfa
3666#endif
3667 + args_size
3668 );
3669
3670 /* Epilogue: restore the handler frame's register values and return
3671 to the stub. */
3672}
0776059e 3673#endif /* DWARF2_UNWIND_INFO */
ca55abae 3674
ad912eec 3675#endif /* L_eh */
c85f7c16 3676
efc955c7
JM
3677\f
3678#ifdef L_pure
2c62c124
JM
3679#ifndef inhibit_libc
3680/* This gets us __GNU_LIBRARY__. */
3681#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
3682#include <stdio.h>
3683
3684#ifdef __GNU_LIBRARY__
3685 /* Avoid forcing the library's meaning of `write' on the user program
3686 by using the "internal" name (for use within the library) */
3687#define write(fd, buf, n) __write((fd), (buf), (n))
3688#endif
3689#endif /* inhibit_libc */
3690
efc955c7 3691#define MESSAGE "pure virtual method called\n"
2c62c124 3692
efc955c7
JM
3693void
3694__pure_virtual ()
3695{
2c62c124 3696#ifndef inhibit_libc
efc955c7 3697 write (2, MESSAGE, sizeof (MESSAGE) - 1);
2c62c124 3698#endif
efc955c7
JM
3699 _exit (-1);
3700}
3701#endif
This page took 0.945441 seconds and 5 git commands to generate.