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