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