]> gcc.gnu.org Git - gcc.git/blame - gcc/libgcc2.c
lex.c (init_cpp_parse): Call xcalloc, not malloc/bzero.
[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. */
1b528097 3/* Copyright (C) 1989, 92-98, 1999 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/* In a cross-compilation situation, default to inhibiting compilation
57 of routines that use libc. */
58
eff0f7ac 59#if defined(CROSS_COMPILE) && !defined(inhibit_libc)
956d6950
JL
60#define inhibit_libc
61#endif
62
f76b9db2
ILT
63/* Permit the tm.h file to select the endianness to use just for this
64 file. This is used when the endianness is determined when the
65 compiler is run. */
66
67#ifndef LIBGCC2_WORDS_BIG_ENDIAN
68#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
69#endif
70
eaa4b44c
VM
71#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
72#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
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
eaa4b44c 93#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
b2bf5aef 94typedef float XFtype __attribute__ ((mode (XF)));
258d1356 95#endif
eaa4b44c 96#if LIBGCC2_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);
eaa4b44c 147#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
f70ad14c 148extern DItype __fixunsxfdi (XFtype a);
96fc2623 149#endif
eaa4b44c 150#if LIBGCC2_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
eaa4b44c 771#if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
ab495388
RS
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
eaa4b44c 803#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
ab495388 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
eaa4b44c 813#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
e0799b34
RS
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
eaa4b44c 845#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
e0799b34 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
eaa4b44c 943#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
e0799b34
RS
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
eaa4b44c 962#if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
ab495388
RS
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
eaa4b44c 1068#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
3f3d2ec8
JW
1069/* Reenable the normal types, in case limits.h needs them. */
1070#undef char
1071#undef short
1072#undef int
1073#undef long
1074#undef unsigned
1075#undef float
1076#undef double
c07e26bd
RK
1077#undef MIN
1078#undef MAX
a99598c9 1079#include <limits.h>
e0799b34
RS
1080
1081USItype
37ef1054 1082__fixunsxfsi (XFtype a)
e0799b34
RS
1083{
1084 if (a >= - (DFtype) LONG_MIN)
1085 return (SItype) (a + LONG_MIN) - LONG_MIN;
1086 return (SItype) a;
1087}
1088#endif
1089
203b91b9 1090#ifdef L_fixunsdfsi
3f3d2ec8
JW
1091/* Reenable the normal types, in case limits.h needs them. */
1092#undef char
1093#undef short
1094#undef int
1095#undef long
1096#undef unsigned
1097#undef float
1098#undef double
c07e26bd
RK
1099#undef MIN
1100#undef MAX
a99598c9 1101#include <limits.h>
203b91b9 1102
ab495388 1103USItype
37ef1054 1104__fixunsdfsi (DFtype a)
203b91b9 1105{
ab495388 1106 if (a >= - (DFtype) LONG_MIN)
203b91b9
RS
1107 return (SItype) (a + LONG_MIN) - LONG_MIN;
1108 return (SItype) a;
1109}
1110#endif
1111
1112#ifdef L_fixunssfsi
3f3d2ec8
JW
1113/* Reenable the normal types, in case limits.h needs them. */
1114#undef char
1115#undef short
1116#undef int
1117#undef long
1118#undef unsigned
1119#undef float
1120#undef double
c07e26bd
RK
1121#undef MIN
1122#undef MAX
a99598c9 1123#include <limits.h>
203b91b9 1124
ab495388
RS
1125USItype
1126__fixunssfsi (SFtype a)
203b91b9 1127{
ab495388 1128 if (a >= - (SFtype) LONG_MIN)
203b91b9
RS
1129 return (SItype) (a + LONG_MIN) - LONG_MIN;
1130 return (SItype) a;
1131}
1132#endif
1133\f
ab495388
RS
1134/* From here on down, the routines use normal data types. */
1135
1136#define SItype bogus_type
1137#define USItype bogus_type
1138#define DItype bogus_type
1139#define UDItype bogus_type
1140#define SFtype bogus_type
1141#define DFtype bogus_type
1142
1143#undef char
1144#undef short
1145#undef int
1146#undef long
1147#undef unsigned
1148#undef float
1149#undef double
9bd23d2c
RS
1150\f
1151#ifdef L__gcc_bcmp
1152
1153/* Like bcmp except the sign is meaningful.
9faa82d8 1154 Result is negative if S1 is less than S2,
9bd23d2c
RS
1155 positive if S1 is greater, 0 if S1 and S2 are equal. */
1156
1157int
37ef1054 1158__gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size)
9bd23d2c
RS
1159{
1160 while (size > 0)
1161 {
78e33213 1162 unsigned char c1 = *s1++, c2 = *s2++;
9bd23d2c
RS
1163 if (c1 != c2)
1164 return c1 - c2;
1165 size--;
1166 }
1167 return 0;
1168}
ab495388 1169
9bd23d2c
RS
1170#endif
1171\f\f
2e06e616
RK
1172#ifdef L__dummy
1173void
1174__dummy () {}
1175#endif
1176
203b91b9
RS
1177#ifdef L_varargs
1178#ifdef __i860__
600032fc 1179#if defined(__svr4__) || defined(__alliant__)
203b91b9
RS
1180 asm (" .text");
1181 asm (" .align 4");
1182
27d21d32 1183/* The Alliant needs the added underscore. */
203b91b9
RS
1184 asm (".globl __builtin_saveregs");
1185asm ("__builtin_saveregs:");
27d21d32
RS
1186 asm (".globl ___builtin_saveregs");
1187asm ("___builtin_saveregs:");
1188
1189 asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
203b91b9
RS
1190 asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
1191 area and also for a new va_list
1192 structure */
1193 /* Save all argument registers in the arg reg save area. The
1194 arg reg save area must have the following layout (according
1195 to the svr4 ABI):
1196
1197 struct {
1198 union {
1199 float freg[8];
1200 double dreg[4];
1201 } float_regs;
1202 long ireg[12];
1203 };
1204 */
1205
1206 asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
1207 asm (" fst.q %f12,16(%sp)");
1208
1209 asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
1210 asm (" st.l %r17,36(%sp)");
1211 asm (" st.l %r18,40(%sp)");
1212 asm (" st.l %r19,44(%sp)");
1213 asm (" st.l %r20,48(%sp)");
1214 asm (" st.l %r21,52(%sp)");
1215 asm (" st.l %r22,56(%sp)");
1216 asm (" st.l %r23,60(%sp)");
1217 asm (" st.l %r24,64(%sp)");
1218 asm (" st.l %r25,68(%sp)");
1219 asm (" st.l %r26,72(%sp)");
1220 asm (" st.l %r27,76(%sp)");
1221
1222 asm (" adds 80,%sp,%r16"); /* compute the address of the new
1223 va_list structure. Put in into
1224 r16 so that it will be returned
1225 to the caller. */
1226
1227 /* Initialize all fields of the new va_list structure. This
1228 structure looks like:
1229
1230 typedef struct {
1231 unsigned long ireg_used;
1232 unsigned long freg_used;
1233 long *reg_base;
1234 long *mem_ptr;
1235 } va_list;
1236 */
1237
1238 asm (" st.l %r0, 0(%r16)"); /* nfixed */
1239 asm (" st.l %r0, 4(%r16)"); /* nfloating */
1240 asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
1241 asm (" bri %r1"); /* delayed return */
1242 asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
1243
24e4939e 1244#else /* not __svr4__ */
6aadf9c2
RS
1245#if defined(__PARAGON__)
1246 /*
1247 * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1248 * and we stand a better chance of hooking into libraries
1249 * compiled by PGI. [andyp@ssd.intel.com]
1250 */
1251 asm (" .text");
1252 asm (" .align 4");
1253 asm (".globl __builtin_saveregs");
1254asm ("__builtin_saveregs:");
1255 asm (".globl ___builtin_saveregs");
1256asm ("___builtin_saveregs:");
1257
1258 asm (" andnot 0x0f,sp,sp"); /* round down to 16-byte boundary */
1259 asm (" adds -96,sp,sp"); /* allocate stack space for reg save
1260 area and also for a new va_list
1261 structure */
1262 /* Save all argument registers in the arg reg save area. The
1263 arg reg save area must have the following layout (according
1264 to the svr4 ABI):
1265
1266 struct {
1267 union {
1268 float freg[8];
1269 double dreg[4];
1270 } float_regs;
1271 long ireg[12];
1272 };
1273 */
1274
1275 asm (" fst.q f8, 0(sp)");
1276 asm (" fst.q f12,16(sp)");
1277 asm (" st.l r16,32(sp)");
1278 asm (" st.l r17,36(sp)");
1279 asm (" st.l r18,40(sp)");
1280 asm (" st.l r19,44(sp)");
1281 asm (" st.l r20,48(sp)");
1282 asm (" st.l r21,52(sp)");
1283 asm (" st.l r22,56(sp)");
1284 asm (" st.l r23,60(sp)");
1285 asm (" st.l r24,64(sp)");
1286 asm (" st.l r25,68(sp)");
1287 asm (" st.l r26,72(sp)");
1288 asm (" st.l r27,76(sp)");
1289
1290 asm (" adds 80,sp,r16"); /* compute the address of the new
1291 va_list structure. Put in into
1292 r16 so that it will be returned
1293 to the caller. */
1294
1295 /* Initialize all fields of the new va_list structure. This
1296 structure looks like:
1297
1298 typedef struct {
1299 unsigned long ireg_used;
1300 unsigned long freg_used;
1301 long *reg_base;
1302 long *mem_ptr;
1303 } va_list;
1304 */
1305
1306 asm (" st.l r0, 0(r16)"); /* nfixed */
1307 asm (" st.l r0, 4(r16)"); /* nfloating */
1308 asm (" st.l sp, 8(r16)"); /* __va_ctl points to __va_struct. */
1309 asm (" bri r1"); /* delayed return */
1310 asm (" st.l r28,12(r16)"); /* pointer to overflow args */
1311#else /* not __PARAGON__ */
203b91b9
RS
1312 asm (" .text");
1313 asm (" .align 4");
1314
1315 asm (".globl ___builtin_saveregs");
1316 asm ("___builtin_saveregs:");
1317 asm (" mov sp,r30");
1318 asm (" andnot 0x0f,sp,sp");
1319 asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
1320
1321/* Fill in the __va_struct. */
1322 asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
1323 asm (" st.l r17, 4(sp)"); /* int fixed[12] */
1324 asm (" st.l r18, 8(sp)");
1325 asm (" st.l r19,12(sp)");
1326 asm (" st.l r20,16(sp)");
1327 asm (" st.l r21,20(sp)");
1328 asm (" st.l r22,24(sp)");
1329 asm (" st.l r23,28(sp)");
1330 asm (" st.l r24,32(sp)");
1331 asm (" st.l r25,36(sp)");
1332 asm (" st.l r26,40(sp)");
1333 asm (" st.l r27,44(sp)");
1334
1335 asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
1336 asm (" fst.q f12,64(sp)"); /* int floating[8] */
1337
1338/* Fill in the __va_ctl. */
1339 asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
1340 asm (" st.l r28,84(sp)"); /* pointer to more args */
1341 asm (" st.l r0, 88(sp)"); /* nfixed */
1342 asm (" st.l r0, 92(sp)"); /* nfloating */
1343
1344 asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
1345 asm (" bri r1");
1346 asm (" mov r30,sp");
1347 /* recover stack and pass address to start
1348 of data. */
6aadf9c2 1349#endif /* not __PARAGON__ */
24e4939e 1350#endif /* not __svr4__ */
203b91b9
RS
1351#else /* not __i860__ */
1352#ifdef __sparc__
b335c2cc
TW
1353 asm (".global __builtin_saveregs");
1354 asm ("__builtin_saveregs:");
203b91b9
RS
1355 asm (".global ___builtin_saveregs");
1356 asm ("___builtin_saveregs:");
b1166fae
RS
1357#ifdef NEED_PROC_COMMAND
1358 asm (".proc 020");
b335c2cc 1359#endif
203b91b9
RS
1360 asm ("st %i0,[%fp+68]");
1361 asm ("st %i1,[%fp+72]");
1362 asm ("st %i2,[%fp+76]");
1363 asm ("st %i3,[%fp+80]");
1364 asm ("st %i4,[%fp+84]");
1365 asm ("retl");
1366 asm ("st %i5,[%fp+88]");
b1166fae
RS
1367#ifdef NEED_TYPE_COMMAND
1368 asm (".type __builtin_saveregs,#function");
1369 asm (".size __builtin_saveregs,.-__builtin_saveregs");
1370#endif
203b91b9
RS
1371#else /* not __sparc__ */
1372#if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1373
1374 asm (" .text");
6003a6bf
JL
1375#ifdef __mips16
1376 asm (" .set nomips16");
1377#endif
203b91b9
RS
1378 asm (" .ent __builtin_saveregs");
1379 asm (" .globl __builtin_saveregs");
1380 asm ("__builtin_saveregs:");
1381 asm (" sw $4,0($30)");
1382 asm (" sw $5,4($30)");
1383 asm (" sw $6,8($30)");
1384 asm (" sw $7,12($30)");
1385 asm (" j $31");
1386 asm (" .end __builtin_saveregs");
0f41302f 1387#else /* not __mips__, etc. */
3bd4f3b8
DE
1388
1389void *
203b91b9
RS
1390__builtin_saveregs ()
1391{
1392 abort ();
1393}
3bd4f3b8 1394
203b91b9
RS
1395#endif /* not __mips__ */
1396#endif /* not __sparc__ */
1397#endif /* not __i860__ */
1398#endif
1399\f
1400#ifdef L_eprintf
c74d5583 1401#ifndef inhibit_libc
bba2431c 1402
203b91b9
RS
1403#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1404#include <stdio.h>
1405/* This is used by the `assert' macro. */
bf94d1ec
KG
1406extern void __eprintf (const char *, const char *, unsigned int, const char *)
1407 __attribute__ ((__noreturn__));
1408
203b91b9 1409void
37ef1054 1410__eprintf (const char *string, const char *expression,
10c301ac 1411 unsigned int line, const char *filename)
203b91b9
RS
1412{
1413 fprintf (stderr, string, expression, line, filename);
1414 fflush (stderr);
1415 abort ();
1416}
bba2431c
RS
1417
1418#endif
203b91b9
RS
1419#endif
1420
1421#ifdef L_bb
203b91b9 1422
92832bb5 1423/* Structure emitted by -a */
203b91b9
RS
1424struct bb
1425{
92832bb5
MM
1426 long zero_word;
1427 const char *filename;
1428 long *counts;
1429 long ncounts;
1430 struct bb *next;
1431 const unsigned long *addresses;
1432
1433 /* Older GCC's did not emit these fields. */
1434 long nwords;
1435 const char **functions;
1436 const long *line_nums;
1437 const char **filenames;
90b4a764 1438 char *flags;
203b91b9
RS
1439};
1440
92832bb5
MM
1441#ifdef BLOCK_PROFILER_CODE
1442BLOCK_PROFILER_CODE
1443#else
c7544ff7 1444#ifndef inhibit_libc
92832bb5
MM
1445
1446/* Simple minded basic block profiling output dumper for
9faa82d8 1447 systems that don't provide tcov support. At present,
92832bb5
MM
1448 it requires atexit and stdio. */
1449
ebd41309 1450#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
92832bb5 1451#include <stdio.h>
b077f3ac 1452char *ctime ();
203b91b9 1453
8b7677be 1454#include "gbl-ctors.h"
65f7a653 1455#include "gcov-io.h"
ac957f13 1456#include <string.h>
92832bb5 1457
7e6f1890 1458static struct bb *bb_head;
92832bb5
MM
1459
1460/* Return the number of digits needed to print a value */
1461/* __inline__ */ static int num_digits (long value, int base)
203b91b9 1462{
92832bb5
MM
1463 int minus = (value < 0 && base != 16);
1464 unsigned long v = (minus) ? -value : value;
1465 int ret = minus;
203b91b9 1466
92832bb5
MM
1467 do
1468 {
1469 v /= base;
1470 ret++;
1471 }
1472 while (v);
1473
1474 return ret;
203b91b9
RS
1475}
1476
92832bb5
MM
1477void
1478__bb_exit_func (void)
1479{
65f7a653 1480 FILE *da_file, *file;
92832bb5 1481 long time_value;
65f7a653
DE
1482 int i;
1483
1484 if (bb_head == 0)
1485 return;
1486
1487 i = strlen (bb_head->filename) - 3;
1488
1489 if (!strcmp (bb_head->filename+i, ".da"))
1490 {
1491 /* Must be -fprofile-arcs not -a.
1492 Dump data in a form that gcov expects. */
1493
1494 struct bb *ptr;
1495
1496 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1497 {
1498 /* If the file exists, and the number of counts in it is the same,
1499 then merge them in. */
1500
920b13cc 1501 if ((da_file = fopen (ptr->filename, "r")) != 0)
65f7a653
DE
1502 {
1503 long n_counts = 0;
65f7a653
DE
1504
1505 if (__read_long (&n_counts, da_file, 8) != 0)
1506 {
1507 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1508 ptr->filename);
1509 continue;
1510 }
1511
1512 if (n_counts == ptr->ncounts)
1513 {
1514 int i;
1515
1516 for (i = 0; i < n_counts; i++)
1517 {
1518 long v = 0;
65f7a653
DE
1519
1520 if (__read_long (&v, da_file, 8) != 0)
1521 {
1522 fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1523 ptr->filename);
1524 break;
1525 }
1526 ptr->counts[i] += v;
1527 }
1528 }
1529
1530 if (fclose (da_file) == EOF)
1531 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1532 ptr->filename);
1533 }
b472527b 1534 if ((da_file = fopen (ptr->filename, "w")) == 0)
65f7a653
DE
1535 {
1536 fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1537 ptr->filename);
1538 continue;
1539 }
1540
956d6950 1541 /* ??? Should first write a header to the file. Preferably, a 4 byte
65f7a653
DE
1542 magic number, 4 bytes containing the time the program was
1543 compiled, 4 bytes containing the last modification time of the
1544 source file, and 4 bytes indicating the compiler options used.
1545
1546 That way we can easily verify that the proper source/executable/
1547 data file combination is being used from gcov. */
1548
1549 if (__write_long (ptr->ncounts, da_file, 8) != 0)
1550 {
1551
1552 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1553 ptr->filename);
1554 }
1555 else
1556 {
1557 int j;
1558 long *count_ptr = ptr->counts;
1559 int ret = 0;
1560 for (j = ptr->ncounts; j > 0; j--)
1561 {
1562 if (__write_long (*count_ptr, da_file, 8) != 0)
1563 {
1564 ret=1;
1565 break;
1566 }
1567 count_ptr++;
1568 }
1569 if (ret)
1570 fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1571 ptr->filename);
1572 }
1573
1574 if (fclose (da_file) == EOF)
1575 fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1576 ptr->filename);
1577 }
1578
1579 return;
1580 }
1581
1582 /* Must be basic block profiling. Emit a human readable output file. */
1583
1584 file = fopen ("bb.out", "a");
92832bb5
MM
1585
1586 if (!file)
1587 perror ("bb.out");
1588
1589 else
1590 {
1591 struct bb *ptr;
1592
1593 /* This is somewhat type incorrect, but it avoids worrying about
1594 exactly where time.h is included from. It should be ok unless
90b4a764 1595 a void * differs from other pointer formats, or if sizeof (long)
92832bb5
MM
1596 is < sizeof (time_t). It would be nice if we could assume the
1597 use of rationale standards here. */
1598
90b4a764 1599 time ((void *) &time_value);
92832bb5
MM
1600 fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1601
1602 /* We check the length field explicitly in order to allow compatibility
1603 with older GCC's which did not provide it. */
1604
0f41302f 1605 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
92832bb5
MM
1606 {
1607 int i;
65f7a653
DE
1608 int func_p = (ptr->nwords >= sizeof (struct bb)
1609 && ptr->nwords <= 1000
1610 && ptr->functions);
92832bb5
MM
1611 int line_p = (func_p && ptr->line_nums);
1612 int file_p = (func_p && ptr->filenames);
65f7a653 1613 int addr_p = (ptr->addresses != 0);
92832bb5
MM
1614 long ncounts = ptr->ncounts;
1615 long cnt_max = 0;
1616 long line_max = 0;
1617 long addr_max = 0;
1618 int file_len = 0;
1619 int func_len = 0;
1620 int blk_len = num_digits (ncounts, 10);
1621 int cnt_len;
1622 int line_len;
1623 int addr_len;
1624
1625 fprintf (file, "File %s, %ld basic blocks \n\n",
1626 ptr->filename, ncounts);
1627
1628 /* Get max values for each field. */
1629 for (i = 0; i < ncounts; i++)
1630 {
1631 const char *p;
1632 int len;
1633
1634 if (cnt_max < ptr->counts[i])
1635 cnt_max = ptr->counts[i];
1636
65f7a653 1637 if (addr_p && addr_max < ptr->addresses[i])
92832bb5
MM
1638 addr_max = ptr->addresses[i];
1639
1640 if (line_p && line_max < ptr->line_nums[i])
1641 line_max = ptr->line_nums[i];
1642
1643 if (func_p)
1644 {
1645 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1646 len = strlen (p);
1647 if (func_len < len)
1648 func_len = len;
1649 }
1650
1651 if (file_p)
1652 {
1653 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1654 len = strlen (p);
1655 if (file_len < len)
1656 file_len = len;
1657 }
1658 }
1659
1660 addr_len = num_digits (addr_max, 16);
1661 cnt_len = num_digits (cnt_max, 10);
1662 line_len = num_digits (line_max, 10);
1663
1664 /* Now print out the basic block information. */
1665 for (i = 0; i < ncounts; i++)
1666 {
1667 fprintf (file,
65f7a653 1668 " Block #%*d: executed %*ld time(s)",
92832bb5 1669 blk_len, i+1,
65f7a653
DE
1670 cnt_len, ptr->counts[i]);
1671
1672 if (addr_p)
1673 fprintf (file, " address= 0x%.*lx", addr_len,
1674 ptr->addresses[i]);
92832bb5
MM
1675
1676 if (func_p)
3cca99e8 1677 fprintf (file, " function= %-*s", func_len,
92832bb5
MM
1678 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1679
1680 if (line_p)
1d42e1b7 1681 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
92832bb5
MM
1682
1683 if (file_p)
3cca99e8 1684 fprintf (file, " file= %s",
92832bb5
MM
1685 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1686
1687 fprintf (file, "\n");
1688 }
1689
1690 fprintf (file, "\n");
1691 fflush (file);
1692 }
1693
1694 fprintf (file, "\n\n");
1695 fclose (file);
1696 }
1697}
1698
1699void
1700__bb_init_func (struct bb *blocks)
1701{
1702 /* User is supposed to check whether the first word is non-0,
0f41302f 1703 but just in case.... */
92832bb5
MM
1704
1705 if (blocks->zero_word)
1706 return;
1707
92832bb5
MM
1708 /* Initialize destructor. */
1709 if (!bb_head)
c063dc98 1710 atexit (__bb_exit_func);
92832bb5
MM
1711
1712 /* Set up linked list. */
1713 blocks->zero_word = 1;
1714 blocks->next = bb_head;
1715 bb_head = blocks;
1716}
1717
90b4a764
RK
1718#ifndef MACHINE_STATE_SAVE
1719#define MACHINE_STATE_SAVE(ID)
1720#endif
1721#ifndef MACHINE_STATE_RESTORE
1722#define MACHINE_STATE_RESTORE(ID)
1723#endif
1724
0f41302f 1725/* Number of buckets in hashtable of basic block addresses. */
90b4a764
RK
1726
1727#define BB_BUCKETS 311
1728
0f41302f 1729/* Maximum length of string in file bb.in. */
90b4a764
RK
1730
1731#define BBINBUFSIZE 500
1732
1733/* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
0f41302f 1734 "BBINBUFSIZE" but want to avoid trouble with preprocessors. */
90b4a764
RK
1735
1736#define BBINBUFSIZESTR "499"
1737
1738struct bb_edge
1739{
1740 struct bb_edge *next;
1741 unsigned long src_addr;
1742 unsigned long dst_addr;
1743 unsigned long count;
1744};
1745
1746enum bb_func_mode
1747{
1748 TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1749};
1750
1751struct bb_func
1752{
1753 struct bb_func *next;
1754 char *funcname;
1755 char *filename;
1756 enum bb_func_mode mode;
1757};
1758
1759/* This is the connection to the outside world.
1760 The BLOCK_PROFILER macro must set __bb.blocks
0f41302f 1761 and __bb.blockno. */
90b4a764
RK
1762
1763struct {
1764 unsigned long blockno;
1765 struct bb *blocks;
1766} __bb;
1767
1768/* Vars to store addrs of source and destination basic blocks
0f41302f 1769 of a jump. */
90b4a764
RK
1770
1771static unsigned long bb_src = 0;
1772static unsigned long bb_dst = 0;
1773
0f41302f
MS
1774static FILE *bb_tracefile = (FILE *) 0;
1775static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1776static struct bb_func *bb_func_head = (struct bb_func *) 0;
90b4a764
RK
1777static unsigned long bb_callcount = 0;
1778static int bb_mode = 0;
1779
0f41302f 1780static unsigned long *bb_stack = (unsigned long *) 0;
90b4a764
RK
1781static size_t bb_stacksize = 0;
1782
1783static int reported = 0;
1784
1785/* Trace modes:
1786Always : Print execution frequencies of basic blocks
1787 to file bb.out.
1788bb_mode & 1 != 0 : Dump trace of basic blocks to file bbtrace[.gz]
1789bb_mode & 2 != 0 : Print jump frequencies to file bb.out.
1790bb_mode & 4 != 0 : Cut call instructions from basic block flow.
1791bb_mode & 8 != 0 : Insert return instructions in basic block flow.
1792*/
1793
1794#ifdef HAVE_POPEN
1795
1796/*#include <sys/types.h>*/
1797#include <sys/stat.h>
1798/*#include <malloc.h>*/
1799
0f41302f 1800/* Commands executed by gopen. */
90b4a764
RK
1801
1802#define GOPENDECOMPRESS "gzip -cd "
1803#define GOPENCOMPRESS "gzip -c >"
1804
1805/* Like fopen but pipes through gzip. mode may only be "r" or "w".
1806 If it does not compile, simply replace gopen by fopen and delete
0f41302f 1807 '.gz' from any first parameter to gopen. */
90b4a764
RK
1808
1809static FILE *
37ef1054 1810gopen (char *fn, char *mode)
90b4a764
RK
1811{
1812 int use_gzip;
1813 char *p;
1814
1815 if (mode[1])
0f41302f 1816 return (FILE *) 0;
90b4a764
RK
1817
1818 if (mode[0] != 'r' && mode[0] != 'w')
0f41302f 1819 return (FILE *) 0;
90b4a764
RK
1820
1821 p = fn + strlen (fn)-1;
db3cf6fb
MS
1822 use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
1823 || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
90b4a764
RK
1824
1825 if (use_gzip)
1826 {
1827 if (mode[0]=='r')
1828 {
1829 FILE *f;
0f41302f
MS
1830 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1831 + sizeof (GOPENDECOMPRESS));
90b4a764
RK
1832 strcpy (s, GOPENDECOMPRESS);
1833 strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1834 f = popen (s, mode);
1835 free (s);
1836 return f;
1837 }
1838
1839 else
1840 {
1841 FILE *f;
0f41302f
MS
1842 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1843 + sizeof (GOPENCOMPRESS));
90b4a764
RK
1844 strcpy (s, GOPENCOMPRESS);
1845 strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1846 if (!(f = popen (s, mode)))
1847 f = fopen (s, mode);
1848 free (s);
1849 return f;
1850 }
1851 }
1852
1853 else
1854 return fopen (fn, mode);
1855}
1856
1857static int
37ef1054 1858gclose (FILE *f)
90b4a764
RK
1859{
1860 struct stat buf;
1861
920b13cc 1862 if (f != 0)
90b4a764
RK
1863 {
1864 if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1865 return pclose (f);
1866
1867 return fclose (f);
1868 }
1869 return 0;
1870}
1871
1872#endif /* HAVE_POPEN */
1873
0f41302f 1874/* Called once per program. */
90b4a764
RK
1875
1876static void
1877__bb_exit_trace_func ()
1878{
1879 FILE *file = fopen ("bb.out", "a");
1880 struct bb_func *f;
90b4a764
RK
1881 struct bb *b;
1882
1883 if (!file)
1884 perror ("bb.out");
1885
1886 if (bb_mode & 1)
1887 {
1888 if (!bb_tracefile)
1889 perror ("bbtrace");
1890 else
1891#ifdef HAVE_POPEN
1892 gclose (bb_tracefile);
1893#else
1894 fclose (bb_tracefile);
1895#endif /* HAVE_POPEN */
1896 }
1897
0f41302f 1898 /* Check functions in `bb.in'. */
90b4a764
RK
1899
1900 if (file)
1901 {
1902 long time_value;
1903 const struct bb_func *p;
1904 int printed_something = 0;
1905 struct bb *ptr;
1906 long blk;
1907
0f41302f 1908 /* This is somewhat type incorrect. */
90b4a764
RK
1909 time ((void *) &time_value);
1910
0f41302f 1911 for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
90b4a764 1912 {
0f41302f 1913 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
90b4a764 1914 {
51723711 1915 if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
90b4a764
RK
1916 continue;
1917 for (blk = 0; blk < ptr->ncounts; blk++)
1918 {
1919 if (!strcmp (p->funcname, ptr->functions[blk]))
1920 goto found;
1921 }
1922 }
1923
1924 if (!printed_something)
1925 {
1926 fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1927 printed_something = 1;
1928 }
1929
1930 fprintf (file, "\tFunction %s", p->funcname);
1931 if (p->filename)
1932 fprintf (file, " of file %s", p->filename);
1933 fprintf (file, "\n" );
1934
1935found: ;
1936 }
1937
1938 if (printed_something)
1939 fprintf (file, "\n");
1940
1941 }
1942
1943 if (bb_mode & 2)
1944 {
1945 if (!bb_hashbuckets)
1946 {
1947 if (!reported)
1948 {
1949 fprintf (stderr, "Profiler: out of memory\n");
1950 reported = 1;
1951 }
1952 return;
1953 }
1954
1955 else if (file)
1956 {
1957 long time_value;
1958 int i;
1959 unsigned long addr_max = 0;
1960 unsigned long cnt_max = 0;
1961 int cnt_len;
1962 int addr_len;
1963
1964 /* This is somewhat type incorrect, but it avoids worrying about
1965 exactly where time.h is included from. It should be ok unless
1966 a void * differs from other pointer formats, or if sizeof (long)
1967 is < sizeof (time_t). It would be nice if we could assume the
1968 use of rationale standards here. */
1969
1970 time ((void *) &time_value);
1971 fprintf (file, "Basic block jump tracing");
1972
1973 switch (bb_mode & 12)
1974 {
1975 case 0:
1976 fprintf (file, " (with call)");
1977 break;
1978
1979 case 4:
0f41302f 1980 /* Print nothing. */
90b4a764
RK
1981 break;
1982
1983 case 8:
1984 fprintf (file, " (with call & ret)");
1985 break;
1986
1987 case 12:
1988 fprintf (file, " (with ret)");
1989 break;
1990 }
1991
1992 fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1993
1994 for (i = 0; i < BB_BUCKETS; i++)
1995 {
1996 struct bb_edge *bucket = bb_hashbuckets[i];
1997 for ( ; bucket; bucket = bucket->next )
1998 {
1999 if (addr_max < bucket->src_addr)
2000 addr_max = bucket->src_addr;
2001 if (addr_max < bucket->dst_addr)
2002 addr_max = bucket->dst_addr;
2003 if (cnt_max < bucket->count)
2004 cnt_max = bucket->count;
2005 }
2006 }
2007 addr_len = num_digits (addr_max, 16);
2008 cnt_len = num_digits (cnt_max, 10);
2009
2010 for ( i = 0; i < BB_BUCKETS; i++)
2011 {
2012 struct bb_edge *bucket = bb_hashbuckets[i];
2013 for ( ; bucket; bucket = bucket->next )
2014 {
2015 fprintf (file, "Jump from block 0x%.*lx to "
51723711 2016 "block 0x%.*lx executed %*lu time(s)\n",
90b4a764
RK
2017 addr_len, bucket->src_addr,
2018 addr_len, bucket->dst_addr,
2019 cnt_len, bucket->count);
2020 }
2021 }
2022
2023 fprintf (file, "\n");
2024
2025 }
2026 }
2027
2028 if (file)
2029 fclose (file);
2030
0f41302f 2031 /* Free allocated memory. */
90b4a764
RK
2032
2033 f = bb_func_head;
2034 while (f)
2035 {
2036 struct bb_func *old = f;
2037
2038 f = f->next;
2039 if (old->funcname) free (old->funcname);
2040 if (old->filename) free (old->filename);
2041 free (old);
2042 }
2043
2044 if (bb_stack)
2045 free (bb_stack);
2046
2047 if (bb_hashbuckets)
2048 {
2049 int i;
2050
2051 for (i = 0; i < BB_BUCKETS; i++)
2052 {
2053 struct bb_edge *old, *bucket = bb_hashbuckets[i];
2054
2055 while (bucket)
2056 {
2057 old = bucket;
2058 bucket = bucket->next;
2059 free (old);
2060 }
2061 }
2062 free (bb_hashbuckets);
2063 }
2064
2065 for (b = bb_head; b; b = b->next)
2066 if (b->flags) free (b->flags);
2067}
2068
0f41302f 2069/* Called once per program. */
90b4a764
RK
2070
2071static void
2072__bb_init_prg ()
2073{
90b4a764
RK
2074 FILE *file;
2075 char buf[BBINBUFSIZE];
2076 const char *p;
2077 const char *pos;
2078 enum bb_func_mode m;
c5c76735 2079 int i;
90b4a764 2080
90b4a764 2081 /* Initialize destructor. */
c063dc98 2082 atexit (__bb_exit_func);
90b4a764
RK
2083
2084 if (!(file = fopen ("bb.in", "r")))
2085 return;
2086
2087 while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
2088 {
2089 p = buf;
2090 if (*p == '-')
2091 {
2092 m = TRACE_OFF;
2093 p++;
2094 }
2095 else
2096 {
2097 m = TRACE_ON;
2098 }
2099 if (!strcmp (p, "__bb_trace__"))
2100 bb_mode |= 1;
2101 else if (!strcmp (p, "__bb_jumps__"))
2102 bb_mode |= 2;
2103 else if (!strcmp (p, "__bb_hidecall__"))
2104 bb_mode |= 4;
2105 else if (!strcmp (p, "__bb_showret__"))
2106 bb_mode |= 8;
2107 else
2108 {
0f41302f 2109 struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
90b4a764
RK
2110 if (f)
2111 {
2112 unsigned long l;
2113 f->next = bb_func_head;
51723711 2114 if ((pos = strchr (p, ':')))
90b4a764 2115 {
0f41302f 2116 if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
90b4a764
RK
2117 continue;
2118 strcpy (f->funcname, pos+1);
2119 l = pos-p;
0f41302f 2120 if ((f->filename = (char *) malloc (l+1)))
90b4a764
RK
2121 {
2122 strncpy (f->filename, p, l);
2123 f->filename[l] = '\0';
2124 }
2125 else
0f41302f 2126 f->filename = (char *) 0;
90b4a764
RK
2127 }
2128 else
2129 {
0f41302f 2130 if (!(f->funcname = (char *) malloc (strlen (p)+1)))
90b4a764
RK
2131 continue;
2132 strcpy (f->funcname, p);
0f41302f 2133 f->filename = (char *) 0;
90b4a764
RK
2134 }
2135 f->mode = m;
2136 bb_func_head = f;
2137 }
2138 }
2139 }
2140 fclose (file);
2141
2142#ifdef HAVE_POPEN
2143
2144 if (bb_mode & 1)
2145 bb_tracefile = gopen ("bbtrace.gz", "w");
2146
2147#else
2148
2149 if (bb_mode & 1)
2150 bb_tracefile = fopen ("bbtrace", "w");
2151
2152#endif /* HAVE_POPEN */
2153
2154 if (bb_mode & 2)
2155 {
2156 bb_hashbuckets = (struct bb_edge **)
2157 malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2158 if (bb_hashbuckets)
c5c76735
JL
2159 /* Use a loop here rather than calling bzero to avoid having to
2160 conditionalize its existance. */
2161 for (i = 0; i < BB_BUCKETS; i++)
2162 bb_hashbuckets[i] = 0;
90b4a764
RK
2163 }
2164
2165 if (bb_mode & 12)
2166 {
2167 bb_stacksize = 10;
2168 bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2169 }
2170
c063dc98
JM
2171 /* Initialize destructor. */
2172 atexit (__bb_exit_trace_func);
90b4a764
RK
2173}
2174
0f41302f 2175/* Called upon entering a basic block. */
90b4a764
RK
2176
2177void
2178__bb_trace_func ()
2179{
2180 struct bb_edge *bucket;
2181
2182 MACHINE_STATE_SAVE("1")
2183
2184 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2185 goto skip;
2186
2187 bb_dst = __bb.blocks->addresses[__bb.blockno];
2188 __bb.blocks->counts[__bb.blockno]++;
2189
2190 if (bb_tracefile)
2191 {
2192 fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2193 }
2194
2195 if (bb_hashbuckets)
2196 {
2197 struct bb_edge **startbucket, **oldnext;
2198
db3cf6fb
MS
2199 oldnext = startbucket
2200 = & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
90b4a764
RK
2201 bucket = *startbucket;
2202
2203 for (bucket = *startbucket; bucket;
2204 oldnext = &(bucket->next), bucket = *oldnext)
2205 {
db3cf6fb
MS
2206 if (bucket->src_addr == bb_src
2207 && bucket->dst_addr == bb_dst)
90b4a764
RK
2208 {
2209 bucket->count++;
2210 *oldnext = bucket->next;
2211 bucket->next = *startbucket;
2212 *startbucket = bucket;
2213 goto ret;
2214 }
2215 }
2216
2217 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2218
2219 if (!bucket)
2220 {
2221 if (!reported)
2222 {
2223 fprintf (stderr, "Profiler: out of memory\n");
2224 reported = 1;
2225 }
2226 }
2227
2228 else
2229 {
2230 bucket->src_addr = bb_src;
2231 bucket->dst_addr = bb_dst;
2232 bucket->next = *startbucket;
2233 *startbucket = bucket;
2234 bucket->count = 1;
2235 }
2236 }
2237
2238ret:
2239 bb_src = bb_dst;
2240
2241skip:
2242 ;
2243
2244 MACHINE_STATE_RESTORE("1")
2245
2246}
2247
0f41302f 2248/* Called when returning from a function and `__bb_showret__' is set. */
90b4a764
RK
2249
2250static void
2251__bb_trace_func_ret ()
2252{
2253 struct bb_edge *bucket;
2254
2255 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2256 goto skip;
2257
2258 if (bb_hashbuckets)
2259 {
2260 struct bb_edge **startbucket, **oldnext;
2261
db3cf6fb
MS
2262 oldnext = startbucket
2263 = & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
90b4a764
RK
2264 bucket = *startbucket;
2265
2266 for (bucket = *startbucket; bucket;
2267 oldnext = &(bucket->next), bucket = *oldnext)
2268 {
db3cf6fb
MS
2269 if (bucket->src_addr == bb_dst
2270 && bucket->dst_addr == bb_src)
90b4a764
RK
2271 {
2272 bucket->count++;
2273 *oldnext = bucket->next;
2274 bucket->next = *startbucket;
2275 *startbucket = bucket;
2276 goto ret;
2277 }
2278 }
2279
2280 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2281
2282 if (!bucket)
2283 {
2284 if (!reported)
2285 {
2286 fprintf (stderr, "Profiler: out of memory\n");
2287 reported = 1;
2288 }
2289 }
2290
2291 else
2292 {
2293 bucket->src_addr = bb_dst;
2294 bucket->dst_addr = bb_src;
2295 bucket->next = *startbucket;
2296 *startbucket = bucket;
2297 bucket->count = 1;
2298 }
2299 }
2300
2301ret:
2302 bb_dst = bb_src;
2303
2304skip:
2305 ;
2306
2307}
2308
0f41302f 2309/* Called upon entering the first function of a file. */
90b4a764
RK
2310
2311static void
37ef1054 2312__bb_init_file (struct bb *blocks)
90b4a764
RK
2313{
2314
2315 const struct bb_func *p;
2316 long blk, ncounts = blocks->ncounts;
2317 const char **functions = blocks->functions;
2318
2319 /* Set up linked list. */
2320 blocks->zero_word = 1;
2321 blocks->next = bb_head;
2322 bb_head = blocks;
2323
2324 blocks->flags = 0;
db3cf6fb
MS
2325 if (!bb_func_head
2326 || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
90b4a764
RK
2327 return;
2328
2329 for (blk = 0; blk < ncounts; blk++)
2330 blocks->flags[blk] = 0;
2331
2332 for (blk = 0; blk < ncounts; blk++)
2333 {
2334 for (p = bb_func_head; p; p = p->next)
2335 {
db3cf6fb
MS
2336 if (!strcmp (p->funcname, functions[blk])
2337 && (!p->filename || !strcmp (p->filename, blocks->filename)))
90b4a764
RK
2338 {
2339 blocks->flags[blk] |= p->mode;
2340 }
2341 }
2342 }
2343
2344}
2345
0f41302f 2346/* Called when exiting from a function. */
90b4a764
RK
2347
2348void
2349__bb_trace_ret ()
2350{
2351
2352 MACHINE_STATE_SAVE("2")
2353
2354 if (bb_callcount)
2355 {
2356 if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2357 {
2358 bb_src = bb_stack[bb_callcount];
2359 if (bb_mode & 8)
2360 __bb_trace_func_ret ();
2361 }
2362
2363 bb_callcount -= 1;
2364 }
2365
2366 MACHINE_STATE_RESTORE("2")
2367
2368}
2369
0f41302f 2370/* Called when entering a function. */
90b4a764
RK
2371
2372void
37ef1054 2373__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
90b4a764
RK
2374{
2375 static int trace_init = 0;
2376
2377 MACHINE_STATE_SAVE("3")
2378
2379 if (!blocks->zero_word)
2380 {
2381 if (!trace_init)
2382 {
2383 trace_init = 1;
2384 __bb_init_prg ();
2385 }
2386 __bb_init_file (blocks);
2387 }
2388
2389 if (bb_callcount)
2390 {
2391
2392 bb_callcount += 1;
2393
2394 if (bb_mode & 12)
2395 {
2396 if (bb_callcount >= bb_stacksize)
2397 {
2398 size_t newsize = bb_callcount + 100;
2399
2400 bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2401 if (! bb_stack)
2402 {
2403 if (!reported)
2404 {
2405 fprintf (stderr, "Profiler: out of memory\n");
2406 reported = 1;
2407 }
2408 bb_stacksize = 0;
2409 goto stack_overflow;
2410 }
2411 bb_stacksize = newsize;
2412 }
2413 bb_stack[bb_callcount] = bb_src;
2414
2415 if (bb_mode & 4)
2416 bb_src = 0;
2417
2418 }
2419
2420stack_overflow:;
2421
2422 }
2423
2424 else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2425 {
2426 bb_callcount = 1;
2427 bb_src = 0;
2428
2429 if (bb_stack)
2430 bb_stack[bb_callcount] = bb_src;
2431 }
2432
2433 MACHINE_STATE_RESTORE("3")
2434}
2435
c7544ff7
RS
2436#endif /* not inhibit_libc */
2437#endif /* not BLOCK_PROFILER_CODE */
2438#endif /* L_bb */
203b91b9 2439\f
203b91b9
RS
2440#ifdef L_shtab
2441unsigned int __shtab[] = {
2442 0x00000001, 0x00000002, 0x00000004, 0x00000008,
2443 0x00000010, 0x00000020, 0x00000040, 0x00000080,
2444 0x00000100, 0x00000200, 0x00000400, 0x00000800,
2445 0x00001000, 0x00002000, 0x00004000, 0x00008000,
2446 0x00010000, 0x00020000, 0x00040000, 0x00080000,
2447 0x00100000, 0x00200000, 0x00400000, 0x00800000,
2448 0x01000000, 0x02000000, 0x04000000, 0x08000000,
2449 0x10000000, 0x20000000, 0x40000000, 0x80000000
2450 };
2451#endif
2452\f
2453#ifdef L_clear_cache
2454/* Clear part of an instruction cache. */
2455
2456#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2457
2458void
37ef1054 2459__clear_cache (char *beg, char *end)
203b91b9 2460{
e1178973
KKT
2461#ifdef CLEAR_INSN_CACHE
2462 CLEAR_INSN_CACHE (beg, end);
2463#else
203b91b9
RS
2464#ifdef INSN_CACHE_SIZE
2465 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
7e6f1890 2466 static int initialized;
203b91b9 2467 int offset;
b6422cca
RS
2468 void *start_addr
2469 void *end_addr;
203b91b9
RS
2470 typedef (*function_ptr) ();
2471
2472#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2473 /* It's cheaper to clear the whole cache.
2474 Put in a series of jump instructions so that calling the beginning
2475 of the cache will clear the whole thing. */
2476
2477 if (! initialized)
2478 {
2479 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2480 & -INSN_CACHE_LINE_WIDTH);
2481 int end_ptr = ptr + INSN_CACHE_SIZE;
2482
2483 while (ptr < end_ptr)
2484 {
2485 *(INSTRUCTION_TYPE *)ptr
2486 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2487 ptr += INSN_CACHE_LINE_WIDTH;
2488 }
0f41302f 2489 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
203b91b9
RS
2490
2491 initialized = 1;
2492 }
2493
2494 /* Call the beginning of the sequence. */
2495 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2496 & -INSN_CACHE_LINE_WIDTH))
2497 ());
2498
2499#else /* Cache is large. */
2500
2501 if (! initialized)
2502 {
2503 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2504 & -INSN_CACHE_LINE_WIDTH);
2505
2506 while (ptr < (int) array + sizeof array)
2507 {
2508 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2509 ptr += INSN_CACHE_LINE_WIDTH;
2510 }
2511
2512 initialized = 1;
2513 }
2514
2515 /* Find the location in array that occupies the same cache line as BEG. */
2516
2517 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2518 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2519 & -INSN_CACHE_PLANE_SIZE)
2520 + offset);
2521
2522 /* Compute the cache alignment of the place to stop clearing. */
2523#if 0 /* This is not needed for gcc's purposes. */
2524 /* If the block to clear is bigger than a cache plane,
2525 we clear the entire cache, and OFFSET is already correct. */
2526 if (end < beg + INSN_CACHE_PLANE_SIZE)
2527#endif
2528 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2529 & -INSN_CACHE_LINE_WIDTH)
2530 & (INSN_CACHE_PLANE_SIZE - 1));
2531
2532#if INSN_CACHE_DEPTH > 1
2533 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2534 if (end_addr <= start_addr)
2535 end_addr += INSN_CACHE_PLANE_SIZE;
2536
2537 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2538 {
2539 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2540 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2541
2542 while (addr != stop)
2543 {
2544 /* Call the return instruction at ADDR. */
2545 ((function_ptr) addr) ();
2546
2547 addr += INSN_CACHE_LINE_WIDTH;
2548 }
2549 }
2550#else /* just one plane */
2551 do
2552 {
2553 /* Call the return instruction at START_ADDR. */
2554 ((function_ptr) start_addr) ();
2555
2556 start_addr += INSN_CACHE_LINE_WIDTH;
2557 }
2558 while ((start_addr % INSN_CACHE_SIZE) != offset);
2559#endif /* just one plane */
2560#endif /* Cache is large */
2561#endif /* Cache exists */
e1178973 2562#endif /* CLEAR_INSN_CACHE */
203b91b9
RS
2563}
2564
2565#endif /* L_clear_cache */
2566\f
2567#ifdef L_trampoline
2568
2569/* Jump to a trampoline, loading the static chain address. */
2570
b27d2bd5 2571#if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
e3367a77 2572
f5ea9817
RK
2573long getpagesize()
2574{
2575#ifdef _ALPHA_
2576 return 8192;
2577#else
2578 return 4096;
2579#endif
2580}
2581
e4b15106
RK
2582#ifdef i386
2583extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
2584#endif
2585
272e2587
RK
2586int
2587mprotect (char *addr, int len, int prot)
f5ea9817
RK
2588{
2589 int np, op;
2590
272e2587
RK
2591 if (prot == 7)
2592 np = 0x40;
2593 else if (prot == 5)
2594 np = 0x20;
2595 else if (prot == 4)
2596 np = 0x10;
2597 else if (prot == 3)
2598 np = 0x04;
2599 else if (prot == 1)
2600 np = 0x02;
2601 else if (prot == 0)
2602 np = 0x01;
f5ea9817
RK
2603
2604 if (VirtualProtect (addr, len, np, &op))
2605 return 0;
2606 else
2607 return -1;
f5ea9817
RK
2608}
2609
b27d2bd5 2610#endif /* WINNT && ! __CYGWIN__ && ! _UWIN */
f5ea9817 2611
203b91b9
RS
2612#ifdef TRANSFER_FROM_TRAMPOLINE
2613TRANSFER_FROM_TRAMPOLINE
2614#endif
2615
c1381fd3
KKT
2616#if defined (NeXT) && defined (__MACH__)
2617
2618/* Make stack executable so we can call trampolines on stack.
2619 This is called from INITIALIZE_TRAMPOLINE in next.h. */
c5df463e
RK
2620#ifdef NeXTStep21
2621 #include <mach.h>
2622#else
2623 #include <mach/mach.h>
2624#endif
c1381fd3
KKT
2625
2626void
37ef1054 2627__enable_execute_stack (char *addr)
c1381fd3
KKT
2628{
2629 kern_return_t r;
2630 char *eaddr = addr + TRAMPOLINE_SIZE;
2631 vm_address_t a = (vm_address_t) addr;
2632
2633 /* turn on execute access on stack */
2634 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2635 if (r != KERN_SUCCESS)
2636 {
2637 mach_error("vm_protect VM_PROT_ALL", r);
2638 exit(1);
2639 }
2640
2641 /* We inline the i-cache invalidation for speed */
2642
2643#ifdef CLEAR_INSN_CACHE
2644 CLEAR_INSN_CACHE (addr, eaddr);
2645#else
2646 __clear_cache ((int) addr, (int) eaddr);
2647#endif
2648}
2649
2650#endif /* defined (NeXT) && defined (__MACH__) */
2651
203b91b9
RS
2652#ifdef __convex__
2653
2654/* Make stack executable so we can call trampolines on stack.
2655 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
2656
2657#include <sys/mman.h>
2658#include <sys/vmparam.h>
2659#include <machine/machparam.h>
2660
2661void
2662__enable_execute_stack ()
2663{
2664 int fp;
2665 static unsigned lowest = USRSTACK;
2666 unsigned current = (unsigned) &fp & -NBPG;
2667
2668 if (lowest > current)
2669 {
2670 unsigned len = lowest - current;
2671 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2672 lowest = current;
2673 }
2674
0f41302f 2675 /* Clear instruction cache in case an old trampoline is in it. */
203b91b9
RS
2676 asm ("pich");
2677}
2678#endif /* __convex__ */
b335c2cc 2679
db87ec0b 2680#ifdef __sysV88__
0c8ae3d3 2681
0f41302f 2682/* Modified from the convex -code above. */
0c8ae3d3
RK
2683
2684#include <sys/param.h>
2685#include <errno.h>
2686#include <sys/m88kbcs.h>
2687
2688void
2689__enable_execute_stack ()
2690{
2691 int save_errno;
2692 static unsigned long lowest = USRSTACK;
2693 unsigned long current = (unsigned long) &save_errno & -NBPC;
2694
2695 /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2696 address is seen as 'negative'. That is the case with the stack. */
2697
2698 save_errno=errno;
2699 if (lowest > current)
2700 {
2701 unsigned len=lowest-current;
2702 memctl(current,len,MCT_TEXT);
2703 lowest = current;
2704 }
2705 else
2706 memctl(current,NBPC,MCT_TEXT);
2707 errno=save_errno;
2708}
2709
db87ec0b 2710#endif /* __sysV88__ */
0c8ae3d3 2711
c85f7c16
JL
2712#ifdef __sysV68__
2713
2714#include <sys/signal.h>
2715#include <errno.h>
2716
2717/* Motorola forgot to put memctl.o in the libp version of libc881.a,
2718 so define it here, because we need it in __clear_insn_cache below */
3698f44e
MH
2719/* On older versions of this OS, no memctl or MCT_TEXT are defined;
2720 hence we enable this stuff only if MCT_TEXT is #define'd. */
c85f7c16 2721
3698f44e 2722#ifdef MCT_TEXT
c85f7c16
JL
2723asm("\n\
2724 global memctl\n\
2725memctl:\n\
2726 movq &75,%d0\n\
2727 trap &0\n\
2728 bcc.b noerror\n\
2729 jmp cerror%\n\
2730noerror:\n\
2731 movq &0,%d0\n\
2732 rts");
3698f44e 2733#endif
c85f7c16
JL
2734
2735/* Clear instruction cache so we can call trampolines on stack.
2736 This is called from FINALIZE_TRAMPOLINE in mot3300.h. */
2737
2738void
2739__clear_insn_cache ()
2740{
3698f44e 2741#ifdef MCT_TEXT
c85f7c16
JL
2742 int save_errno;
2743
2744 /* Preserve errno, because users would be surprised to have
2745 errno changing without explicitly calling any system-call. */
2746 save_errno = errno;
2747
2748 /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
2749 No need to use an address derived from _start or %sp, as 0 works also. */
2750 memctl(0, 4096, MCT_TEXT);
2751 errno = save_errno;
3698f44e 2752#endif
c85f7c16
JL
2753}
2754
2755#endif /* __sysV68__ */
2756
b335c2cc
TW
2757#ifdef __pyr__
2758
98126ed6 2759#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
b335c2cc
TW
2760#include <stdio.h>
2761#include <sys/mman.h>
2762#include <sys/types.h>
2763#include <sys/param.h>
2764#include <sys/vmmac.h>
2765
2766/* Modified from the convex -code above.
0f41302f 2767 mremap promises to clear the i-cache. */
b335c2cc
TW
2768
2769void
2770__enable_execute_stack ()
2771{
2772 int fp;
2773 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2774 PROT_READ|PROT_WRITE|PROT_EXEC))
2775 {
2776 perror ("mprotect in __enable_execute_stack");
2777 fflush (stderr);
2778 abort ();
2779 }
2780}
2781#endif /* __pyr__ */
7d41c411
RK
2782
2783#if defined (sony_news) && defined (SYSTYPE_BSD)
2784
2785#include <stdio.h>
2786#include <sys/types.h>
2787#include <sys/param.h>
2788#include <syscall.h>
2789#include <machine/sysnews.h>
2790
2791/* cacheflush function for NEWS-OS 4.2.
2792 This function is called from trampoline-initialize code
2793 defined in config/mips/mips.h. */
2794
2795void
37ef1054 2796cacheflush (char *beg, int size, int flag)
7d41c411
RK
2797{
2798 if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
2799 {
2800 perror ("cache_flush");
2801 fflush (stderr);
2802 abort ();
2803 }
2804}
2805
2806#endif /* sony_news */
203b91b9
RS
2807#endif /* L_trampoline */
2808\f
cae21ae8 2809#ifndef __CYGWIN__
203b91b9
RS
2810#ifdef L__main
2811
2812#include "gbl-ctors.h"
c06cff95
RS
2813/* Some systems use __main in a way incompatible with its use in gcc, in these
2814 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2815 give the same symbol without quotes for an alternative entry point. You
0f41302f 2816 must define both, or neither. */
c06cff95
RS
2817#ifndef NAME__MAIN
2818#define NAME__MAIN "__main"
2819#define SYMBOL__MAIN __main
2820#endif
203b91b9 2821
fe1fd353
JM
2822#ifdef INIT_SECTION_ASM_OP
2823#undef HAS_INIT_SECTION
2824#define HAS_INIT_SECTION
2825#endif
2826
2827#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
31cf0144
JM
2828
2829/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this
2830 code to run constructors. In that case, we need to handle EH here, too. */
2831
2832#ifdef EH_FRAME_SECTION
2833#include "frame.h"
2834extern unsigned char __EH_FRAME_BEGIN__[];
2835#endif
2836
203b91b9
RS
2837/* Run all the global destructors on exit from the program. */
2838
2839void
2840__do_global_dtors ()
2841{
89cf554b
RS
2842#ifdef DO_GLOBAL_DTORS_BODY
2843 DO_GLOBAL_DTORS_BODY;
2844#else
b40b9d93
MS
2845 static func_ptr *p = __DTOR_LIST__ + 1;
2846 while (*p)
2847 {
2848 p++;
2849 (*(p-1)) ();
2850 }
89cf554b 2851#endif
31cf0144
JM
2852#ifdef EH_FRAME_SECTION
2853 __deregister_frame_info (__EH_FRAME_BEGIN__);
2854#endif
203b91b9 2855}
68d69835 2856#endif
203b91b9 2857
fe1fd353 2858#ifndef HAS_INIT_SECTION
203b91b9
RS
2859/* Run all the global constructors on entry to the program. */
2860
203b91b9
RS
2861void
2862__do_global_ctors ()
2863{
31cf0144
JM
2864#ifdef EH_FRAME_SECTION
2865 {
2866 static struct object object;
2867 __register_frame_info (__EH_FRAME_BEGIN__, &object);
2868 }
2869#endif
203b91b9 2870 DO_GLOBAL_CTORS_BODY;
c063dc98 2871 atexit (__do_global_dtors, 0);
203b91b9 2872}
fe1fd353 2873#endif /* no HAS_INIT_SECTION */
203b91b9 2874
fe1fd353 2875#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
203b91b9
RS
2876/* Subroutine called automatically by `main'.
2877 Compiling a global function named `main'
2878 produces an automatic call to this function at the beginning.
2879
2880 For many systems, this routine calls __do_global_ctors.
2881 For systems which support a .init section we use the .init section
2882 to run __do_global_ctors, so we need not do anything here. */
2883
2884void
c06cff95 2885SYMBOL__MAIN ()
203b91b9
RS
2886{
2887 /* Support recursive calls to `main': run initializers just once. */
7e6f1890 2888 static int initialized;
203b91b9
RS
2889 if (! initialized)
2890 {
2891 initialized = 1;
2892 __do_global_ctors ();
2893 }
2894}
fe1fd353 2895#endif /* no HAS_INIT_SECTION or INVOKE__main */
203b91b9
RS
2896
2897#endif /* L__main */
cae21ae8 2898#endif /* __CYGWIN__ */
203b91b9 2899\f
ad38743d 2900#ifdef L_ctors
203b91b9
RS
2901
2902#include "gbl-ctors.h"
2903
2904/* Provide default definitions for the lists of constructors and
657be7af
JL
2905 destructors, so that we don't get linker errors. These symbols are
2906 intentionally bss symbols, so that gld and/or collect will provide
2907 the right values. */
203b91b9
RS
2908
2909/* We declare the lists here with two elements each,
657be7af
JL
2910 so that they are valid empty lists if no other definition is loaded.
2911
2912 If we are using the old "set" extensions to have the gnu linker
2913 collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__
2914 must be in the bss/common section.
2915
2916 Long term no port should use those extensions. But many still do. */
b335c2cc 2917#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
657be7af 2918#if defined (ASM_OUTPUT_CONSTRUCTOR) || defined (USE_COLLECT2)
d15d0264
RS
2919func_ptr __CTOR_LIST__[2] = {0, 0};
2920func_ptr __DTOR_LIST__[2] = {0, 0};
657be7af
JL
2921#else
2922func_ptr __CTOR_LIST__[2];
2923func_ptr __DTOR_LIST__[2];
2924#endif
b335c2cc 2925#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
ad38743d
RS
2926#endif /* L_ctors */
2927\f
2928#ifdef L_exit
2929
2930#include "gbl-ctors.h"
203b91b9 2931
8b7677be 2932#ifdef NEED_ATEXIT
8b7677be 2933
c063dc98 2934#ifndef HAVE_ON_EXIT
203b91b9 2935
8b7677be
RK
2936# include <errno.h>
2937
920b13cc 2938static func_ptr *atexit_chain = 0;
8b7677be
RK
2939static long atexit_chain_length = 0;
2940static volatile long last_atexit_chain_slot = -1;
2941
c063dc98
JM
2942int
2943atexit (func_ptr func)
8b7677be
RK
2944{
2945 if (++last_atexit_chain_slot == atexit_chain_length)
2946 {
2947 atexit_chain_length += 32;
2948 if (atexit_chain)
a25cea96
RK
2949 atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2950 * sizeof (func_ptr));
8b7677be 2951 else
a25cea96
RK
2952 atexit_chain = (func_ptr *) malloc (atexit_chain_length
2953 * sizeof (func_ptr));
8b7677be
RK
2954 if (! atexit_chain)
2955 {
2956 atexit_chain_length = 0;
2957 last_atexit_chain_slot = -1;
2958 errno = ENOMEM;
2959 return (-1);
2960 }
2961 }
2962 atexit_chain[last_atexit_chain_slot] = func;
2963 return (0);
2964}
8b7677be 2965
203b91b9 2966extern void _cleanup ();
003be455 2967extern void _exit () __attribute__ ((noreturn));
203b91b9
RS
2968
2969void
37ef1054 2970exit (int status)
203b91b9 2971{
8b7677be
RK
2972 if (atexit_chain)
2973 {
2974 for ( ; last_atexit_chain_slot-- >= 0; )
2975 {
2976 (*atexit_chain[last_atexit_chain_slot + 1]) ();
920b13cc 2977 atexit_chain[last_atexit_chain_slot + 1] = 0;
8b7677be
RK
2978 }
2979 free (atexit_chain);
920b13cc 2980 atexit_chain = 0;
8b7677be 2981 }
203b91b9
RS
2982#ifdef EXIT_BODY
2983 EXIT_BODY;
2984#else
2985 _cleanup ();
2986#endif
2987 _exit (status);
2988}
2989
c063dc98 2990#else /* HAVE_ON_EXIT */
bceb30e7 2991
c063dc98
JM
2992/* Simple; we just need a wrapper for ON_EXIT. */
2993int
2994atexit (func_ptr func)
bceb30e7 2995{
c063dc98 2996 return ON_EXIT (func);
bceb30e7 2997}
c063dc98
JM
2998
2999#endif /* HAVE_ON_EXIT */
3000#endif /* NEED_ATEXIT */
203b91b9
RS
3001
3002#endif /* L_exit */
3003\f
ad912eec 3004#ifdef L_eh
6adb4e3a 3005
f24af81b 3006#include "gthr.h"
6adb4e3a 3007
154bba13 3008/* Shared exception handling support routines. */
6adb4e3a 3009
bf94d1ec
KG
3010extern void __default_terminate (void) __attribute__ ((__noreturn__));
3011
e976b8b2
MS
3012void
3013__default_terminate ()
3014{
3015 abort ();
3016}
3017
3018void (*__terminate_func)() = __default_terminate;
3019
3020void
3021__terminate ()
3022{
3023 (*__terminate_func)();
3024}
3025
ca55abae
JM
3026void *
3027__throw_type_match (void *catch_type, void *throw_type, void *obj)
3028{
3029#if 0
3030 printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3031 catch_type, throw_type);
3032#endif
3033 if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3034 return obj;
3035 return 0;
3036}
3037
3038void
3039__empty ()
3040{
3041}
3042\f
154bba13 3043
9a0d1e1b
AM
3044/* Include definitions of EH context and table layout */
3045
3046#include "eh-common.h"
43566944 3047#ifndef inhibit_libc
7ac2148b 3048#include <stdio.h>
43566944 3049#endif
154bba13 3050
154bba13
TT
3051/* Allocate and return a new EH context structure. */
3052
3053extern void __throw ();
3054
3055static void *
3056new_eh_context ()
3057{
d0b9a143
MS
3058 struct eh_full_context {
3059 struct eh_context c;
3060 void *top_elt[2];
3061 } *ehfc = (struct eh_full_context *) malloc (sizeof *ehfc);
3062
3063 if (! ehfc)
154bba13
TT
3064 __terminate ();
3065
d0b9a143 3066 memset (ehfc, 0, sizeof *ehfc);
154bba13 3067
d0b9a143 3068 ehfc->c.dynamic_handler_chain = (void **) ehfc->top_elt;
154bba13 3069
d0b9a143
MS
3070 /* This should optimize out entirely. This should always be true,
3071 but just in case it ever isn't, don't allow bogus code to be
3072 generated. */
3073
3074 if ((void*)(&ehfc->c) != (void*)ehfc)
3075 __terminate ();
3076
3077 return &ehfc->c;
154bba13
TT
3078}
3079
3080#if __GTHREADS
3081static __gthread_key_t eh_context_key;
3082
3083/* Destructor for struct eh_context. */
3084static void
3085eh_context_free (void *ptr)
3086{
f24af81b 3087 __gthread_key_dtor (eh_context_key, ptr);
154bba13
TT
3088 if (ptr)
3089 free (ptr);
3090}
3091#endif
3092
3093/* Pointer to function to return EH context. */
3094
3095static struct eh_context *eh_context_initialize ();
3096static struct eh_context *eh_context_static ();
3097#if __GTHREADS
3098static struct eh_context *eh_context_specific ();
3099#endif
3100
3101static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
3102
3103/* Routine to get EH context.
3104 This one will simply call the function pointer. */
3105
3106void *
3107__get_eh_context ()
3108{
3109 return (void *) (*get_eh_context) ();
3110}
3111
3112/* Get and set the language specific info pointer. */
3113
3114void **
3115__get_eh_info ()
3116{
3117 struct eh_context *eh = (*get_eh_context) ();
0776059e 3118 return &eh->info;
154bba13
TT
3119}
3120\f
3121#if __GTHREADS
3122static void
3123eh_threads_initialize ()
3124{
3125 /* Try to create the key. If it fails, revert to static method,
3126 otherwise start using thread specific EH contexts. */
3127 if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
3128 get_eh_context = &eh_context_specific;
3129 else
3130 get_eh_context = &eh_context_static;
3131}
3132#endif /* no __GTHREADS */
3133
3134/* Initialize EH context.
3135 This will be called only once, since we change GET_EH_CONTEXT
3136 pointer to another routine. */
3137
3138static struct eh_context *
3139eh_context_initialize ()
3140{
3141#if __GTHREADS
3142
3143 static __gthread_once_t once = __GTHREAD_ONCE_INIT;
754d1a92
TT
3144 /* Make sure that get_eh_context does not point to us anymore.
3145 Some systems have dummy thread routines in their libc that
3146 return a success (Solaris 2.6 for example). */
3147 if (__gthread_once (&once, eh_threads_initialize) != 0
3148 || get_eh_context == &eh_context_initialize)
f24af81b
TT
3149 {
3150 /* Use static version of EH context. */
3151 get_eh_context = &eh_context_static;
3152 }
154bba13
TT
3153
3154#else /* no __GTHREADS */
3155
3156 /* Use static version of EH context. */
3157 get_eh_context = &eh_context_static;
3158
3159#endif /* no __GTHREADS */
3160
3161 return (*get_eh_context) ();
3162}
3163
3164/* Return a static EH context. */
3165
3166static struct eh_context *
3167eh_context_static ()
3168{
c3cad221
JL
3169 static struct eh_context eh;
3170 static int initialized;
d0b9a143
MS
3171 static void *top_elt[2];
3172
c3cad221
JL
3173 if (! initialized)
3174 {
3175 initialized = 1;
3176 memset (&eh, 0, sizeof eh);
3177 eh.dynamic_handler_chain = top_elt;
3178 }
3179 return &eh;
154bba13
TT
3180}
3181
3182#if __GTHREADS
3183/* Return a thread specific EH context. */
3184
3185static struct eh_context *
3186eh_context_specific ()
3187{
3188 struct eh_context *eh;
3189 eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
3190 if (! eh)
3191 {
3192 eh = new_eh_context ();
3193 if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
3194 __terminate ();
3195 }
3196
3197 return eh;
3198}
3199#endif __GTHREADS
3200\f
ca55abae
JM
3201/* Support routines for setjmp/longjmp exception handling. */
3202
e976b8b2
MS
3203/* Calls to __sjthrow are generated by the compiler when an exception
3204 is raised when using the setjmp/longjmp exception handling codegen
3205 method. */
3206
154bba13 3207#ifdef DONT_USE_BUILTIN_SETJMP
6e6a07d2 3208extern void longjmp (void *, int);
154bba13 3209#endif
e976b8b2
MS
3210
3211/* Routine to get the head of the current thread's dynamic handler chain
154bba13 3212 use for exception handling. */
e976b8b2
MS
3213
3214void ***
3215__get_dynamic_handler_chain ()
3216{
154bba13 3217 struct eh_context *eh = (*get_eh_context) ();
0776059e 3218 return &eh->dynamic_handler_chain;
e976b8b2
MS
3219}
3220
3221/* This is used to throw an exception when the setjmp/longjmp codegen
3222 method is used for exception handling.
3223
154bba13
TT
3224 We call __terminate if there are no handlers left. Otherwise we run the
3225 cleanup actions off the dynamic cleanup stack, and pop the top of the
3226 dynamic handler chain, and use longjmp to transfer back to the associated
3227 handler. */
e976b8b2 3228
bf94d1ec
KG
3229extern void __sjthrow (void) __attribute__ ((__noreturn__));
3230
e976b8b2
MS
3231void
3232__sjthrow ()
3233{
154bba13
TT
3234 struct eh_context *eh = (*get_eh_context) ();
3235 void ***dhc = &eh->dynamic_handler_chain;
e976b8b2
MS
3236 void *jmpbuf;
3237 void (*func)(void *, int);
3238 void *arg;
3239 void ***cleanup;
3240
3241 /* The cleanup chain is one word into the buffer. Get the cleanup
3242 chain. */
3243 cleanup = (void***)&(*dhc)[1];
3244
3245 /* If there are any cleanups in the chain, run them now. */
3246 if (cleanup[0])
3247 {
3248 double store[200];
3249 void **buf = (void**)store;
3250 buf[1] = 0;
3251 buf[0] = (*dhc);
3252
3253 /* try { */
6e6a07d2 3254#ifdef DONT_USE_BUILTIN_SETJMP
e976b8b2 3255 if (! setjmp (&buf[2]))
6e6a07d2
MS
3256#else
3257 if (! __builtin_setjmp (&buf[2]))
3258#endif
e976b8b2
MS
3259 {
3260 *dhc = buf;
3261 while (cleanup[0])
3262 {
3263 func = (void(*)(void*, int))cleanup[0][1];
3264 arg = (void*)cleanup[0][2];
3265
3266 /* Update this before running the cleanup. */
3267 cleanup[0] = (void **)cleanup[0][0];
3268
3269 (*func)(arg, 2);
3270 }
3271 *dhc = buf[0];
3272 }
3273 /* catch (...) */
3274 else
3275 {
3276 __terminate ();
3277 }
3278 }
3279
3280 /* We must call terminate if we try and rethrow an exception, when
3281 there is no exception currently active and when there are no
3282 handlers left. */
d0b9a143 3283 if (! eh->info || (*dhc)[0] == 0)
e976b8b2
MS
3284 __terminate ();
3285
3286 /* Find the jmpbuf associated with the top element of the dynamic
3287 handler chain. The jumpbuf starts two words into the buffer. */
3288 jmpbuf = &(*dhc)[2];
3289
3290 /* Then we pop the top element off the dynamic handler chain. */
3291 *dhc = (void**)(*dhc)[0];
3292
3293 /* And then we jump to the handler. */
3294
6e6a07d2 3295#ifdef DONT_USE_BUILTIN_SETJMP
e976b8b2 3296 longjmp (jmpbuf, 1);
6e6a07d2
MS
3297#else
3298 __builtin_longjmp (jmpbuf, 1);
e976b8b2
MS
3299#endif
3300}
3301
3302/* Run cleanups on the dynamic cleanup stack for the current dynamic
3303 handler, then pop the handler off the dynamic handler stack, and
3304 then throw. This is used to skip the first handler, and transfer
3305 control to the next handler in the dynamic handler stack. */
3306
bf94d1ec
KG
3307extern void __sjpopnthrow (void) __attribute__ ((__noreturn__));
3308
e976b8b2
MS
3309void
3310__sjpopnthrow ()
3311{
154bba13
TT
3312 struct eh_context *eh = (*get_eh_context) ();
3313 void ***dhc = &eh->dynamic_handler_chain;
e976b8b2
MS
3314 void (*func)(void *, int);
3315 void *arg;
3316 void ***cleanup;
3317
3318 /* The cleanup chain is one word into the buffer. Get the cleanup
3319 chain. */
3320 cleanup = (void***)&(*dhc)[1];
3321
3322 /* If there are any cleanups in the chain, run them now. */
3323 if (cleanup[0])
3324 {
3325 double store[200];
3326 void **buf = (void**)store;
3327 buf[1] = 0;
3328 buf[0] = (*dhc);
3329
3330 /* try { */
6e6a07d2 3331#ifdef DONT_USE_BUILTIN_SETJMP
e976b8b2 3332 if (! setjmp (&buf[2]))
6e6a07d2
MS
3333#else
3334 if (! __builtin_setjmp (&buf[2]))
3335#endif
e976b8b2
MS
3336 {
3337 *dhc = buf;
3338 while (cleanup[0])
3339 {
3340 func = (void(*)(void*, int))cleanup[0][1];
3341 arg = (void*)cleanup[0][2];
3342
3343 /* Update this before running the cleanup. */
3344 cleanup[0] = (void **)cleanup[0][0];
3345
3346 (*func)(arg, 2);
3347 }
3348 *dhc = buf[0];
3349 }
3350 /* catch (...) */
3351 else
3352 {
3353 __terminate ();
3354 }
3355 }
3356
3357 /* Then we pop the top element off the dynamic handler chain. */
3358 *dhc = (void**)(*dhc)[0];
3359
3360 __sjthrow ();
3361}
ca55abae
JM
3362\f
3363/* Support code for all exception region-based exception handling. */
3364
bf71cd2e
AM
3365int
3366__eh_rtime_match (void *rtime)
3367{
3368 void *info;
3369 __eh_matcher matcher;
3370 void *ret;
3371
3372 info = *(__get_eh_info ());
3373 matcher = ((__eh_info *)info)->match_function;
7ac2148b
AM
3374 if (! matcher)
3375 {
43566944 3376#ifndef inhibit_libc
7ac2148b 3377 fprintf (stderr, "Internal Compiler Bug: No runtime type matcher.");
43566944 3378#endif
7ac2148b
AM
3379 return 0;
3380 }
bf71cd2e 3381 ret = (*matcher) (info, rtime, (void *)0);
7ac2148b 3382 return (ret != NULL);
bf71cd2e
AM
3383}
3384
ca55abae
JM
3385/* This value identifies the place from which an exception is being
3386 thrown. */
3387
ca55abae
JM
3388#ifdef EH_TABLE_LOOKUP
3389
3390EH_TABLE_LOOKUP
e976b8b2 3391
ca55abae
JM
3392#else
3393
d6f4ec51 3394#ifdef DWARF2_UNWIND_INFO
ad912eec 3395
48b24bcd
AM
3396
3397/* Return the table version of an exception descriptor */
3398
3399short
3400__get_eh_table_version (exception_descriptor *table)
3401{
3402 return table->lang.version;
3403}
3404
3405/* Return the originating table language of an exception descriptor */
3406
3407short
3408__get_eh_table_language (exception_descriptor *table)
3409{
3410 return table->lang.language;
3411}
3412
ca55abae
JM
3413/* This routine takes a PC and a pointer to the exception region TABLE for
3414 its translation unit, and returns the address of the exception handler
3415 associated with the closest exception table handler entry associated
3416 with that PC, or 0 if there are no table entries the PC fits in.
3417
3418 In the advent of a tie, we have to give the last entry, as it represents
3419 an inner block. */
3420
a1622f83
AM
3421static void *
3422old_find_exception_handler (void *pc, old_exception_table *table)
3423{
3424 if (table)
3425 {
3426 int pos;
3427 int best = -1;
3428
3429 /* We can't do a binary search because the table isn't guaranteed
3430 to be sorted from function to function. */
3431 for (pos = 0; table[pos].start_region != (void *) -1; ++pos)
3432 {
3433 if (table[pos].start_region <= pc && table[pos].end_region > pc)
3434 {
3435 /* This can apply. Make sure it is at least as small as
3436 the previous best. */
3437 if (best == -1 || (table[pos].end_region <= table[best].end_region
3438 && table[pos].start_region >= table[best].start_region))
3439 best = pos;
3440 }
3441 /* But it is sorted by starting PC within a function. */
3442 else if (best >= 0 && table[pos].start_region > pc)
3443 break;
3444 }
3445 if (best != -1)
3446 return table[best].exception_handler;
3447 }
3448
3449 return (void *) 0;
3450}
3451
e6cfb550
AM
3452/* find_exception_handler finds the correct handler, if there is one, to
3453 handle an exception.
3454 returns a pointer to the handler which controlled should be transferred
3455 to, or NULL if there is nothing left.
3456 Parameters:
3457 PC - pc where the exception originates. If this is a rethrow,
3458 then this starts out as a pointer to the exception table
3459 entry we wish to rethrow out of.
3460 TABLE - exception table for the current module.
3461 EH_INFO - eh info pointer for this exception.
3462 RETHROW - 1 if this is a rethrow. (see incoming value of PC).
3463 CLEANUP - returned flag indicating whether this is a cleanup handler.
3464*/
ca55abae 3465static void *
e6cfb550
AM
3466find_exception_handler (void *pc, exception_descriptor *table,
3467 __eh_info *eh_info, int rethrow, int *cleanup)
ca55abae 3468{
e6cfb550
AM
3469
3470 void *retval = NULL;
3471 *cleanup = 1;
ca55abae
JM
3472 if (table)
3473 {
e6cfb550 3474 int pos = 0;
9a0d1e1b
AM
3475 /* The new model assumed the table is sorted inner-most out so the
3476 first region we find which matches is the correct one */
3477
9a0d1e1b
AM
3478 exception_table *tab = &(table->table[0]);
3479
3480 /* Subtract 1 from the PC to avoid hitting the next region */
e6cfb550
AM
3481 if (rethrow)
3482 {
3483 /* pc is actually the region table entry to rethrow out of */
3484 pos = ((exception_table *) pc) - tab;
3485 pc = ((exception_table *) pc)->end_region - 1;
3486
3487 /* The label is always on the LAST handler entry for a region,
3488 so we know the next entry is a different region, even if the
3489 addresses are the same. Make sure its not end of table tho. */
3490 if (tab[pos].start_region != (void *) -1)
3491 pos++;
3492 }
3493 else
3494 pc--;
9a0d1e1b
AM
3495
3496 /* We can't do a binary search because the table is in inner-most
3497 to outermost address ranges within functions */
e6cfb550 3498 for ( ; tab[pos].start_region != (void *) -1; pos++)
9a0d1e1b
AM
3499 {
3500 if (tab[pos].start_region <= pc && tab[pos].end_region > pc)
3501 {
3502 if (tab[pos].match_info)
3503 {
e6cfb550 3504 __eh_matcher matcher = eh_info->match_function;
9a0d1e1b
AM
3505 /* match info but no matcher is NOT a match */
3506 if (matcher)
3507 {
e6cfb550
AM
3508 void *ret = (*matcher)((void *) eh_info,
3509 tab[pos].match_info, table);
3510 if (ret)
3511 {
3512 if (retval == NULL)
3513 retval = tab[pos].exception_handler;
3514 *cleanup = 0;
3515 break;
3516 }
9a0d1e1b
AM
3517 }
3518 }
3519 else
e6cfb550
AM
3520 {
3521 if (retval == NULL)
3522 retval = tab[pos].exception_handler;
3523 }
9a0d1e1b
AM
3524 }
3525 }
ca55abae 3526 }
e6cfb550 3527 return retval;
ca55abae 3528}
d6f4ec51 3529#endif /* DWARF2_UNWIND_INFO */
ca55abae
JM
3530#endif /* EH_TABLE_LOOKUP */
3531\f
0776059e 3532#ifdef DWARF2_UNWIND_INFO
ca55abae
JM
3533/* Support code for exception handling using static unwind information. */
3534
3535#include "frame.h"
3536
3537/* This type is used in get_reg and put_reg to deal with ABIs where a void*
3538 is smaller than a word, such as the Irix 6 n32 ABI. We cast twice to
3539 avoid a warning about casting between int and pointer of different
3540 sizes. */
3541
3542typedef int ptr_type __attribute__ ((mode (pointer)));
3543
71038426
RH
3544#ifdef INCOMING_REGNO
3545/* Is the saved value for register REG in frame UDATA stored in a register
3546 window in the previous frame? */
3547
3548/* ??? The Sparc INCOMING_REGNO references TARGET_FLAT. This allows us
3549 to use the macro here. One wonders, though, that perhaps TARGET_FLAT
3550 compiled functions won't work with the frame-unwind stuff here.
3551 Perhaps the entireity of in_reg_window should be conditional on having
3552 seen a DW_CFA_GNU_window_save? */
3553#define target_flags 0
3554
3555static int
3556in_reg_window (int reg, frame_state *udata)
3557{
3558 if (udata->saved[reg] == REG_SAVED_REG)
3559 return INCOMING_REGNO (reg) == reg;
3560 if (udata->saved[reg] != REG_SAVED_OFFSET)
3561 return 0;
3562
3563#ifdef STACK_GROWS_DOWNWARD
3564 return udata->reg_or_offset[reg] > 0;
3565#else
3566 return udata->reg_or_offset[reg] < 0;
3567#endif
3568}
3569#else
3570static inline int in_reg_window (int reg, frame_state *udata) { return 0; }
3571#endif /* INCOMING_REGNO */
3572
3573/* Get the address of register REG as saved in UDATA, where SUB_UDATA is a
ca55abae
JM
3574 frame called by UDATA or 0. */
3575
71038426
RH
3576static word_type *
3577get_reg_addr (unsigned reg, frame_state *udata, frame_state *sub_udata)
ca55abae 3578{
71038426
RH
3579 while (udata->saved[reg] == REG_SAVED_REG)
3580 {
3581 reg = udata->reg_or_offset[reg];
3582 if (in_reg_window (reg, udata))
3583 {
3584 udata = sub_udata;
3585 sub_udata = NULL;
3586 }
3587 }
ca55abae 3588 if (udata->saved[reg] == REG_SAVED_OFFSET)
71038426 3589 return (word_type *)(udata->cfa + udata->reg_or_offset[reg]);
ca55abae
JM
3590 else
3591 abort ();
3592}
3593
71038426
RH
3594/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
3595 frame called by UDATA or 0. */
3596
3597static inline void *
3598get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
3599{
3600 return (void *)(ptr_type) *get_reg_addr (reg, udata, sub_udata);
3601}
3602
ca55abae
JM
3603/* Overwrite the saved value for register REG in frame UDATA with VAL. */
3604
71038426 3605static inline void
ca55abae
JM
3606put_reg (unsigned reg, void *val, frame_state *udata)
3607{
71038426 3608 *get_reg_addr (reg, udata, NULL) = (word_type)(ptr_type) val;
ca55abae
JM
3609}
3610
2f3ca9e7
JM
3611/* Copy the saved value for register REG from frame UDATA to frame
3612 TARGET_UDATA. Unlike the previous two functions, this can handle
3613 registers that are not one word large. */
3614
3615static void
3616copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
3617{
71038426
RH
3618 word_type *preg = get_reg_addr (reg, udata, NULL);
3619 word_type *ptreg = get_reg_addr (reg, target_udata, NULL);
3620
3621 memcpy (ptreg, preg, __builtin_dwarf_reg_size (reg));
2f3ca9e7
JM
3622}
3623
71038426 3624/* Retrieve the return address for frame UDATA. */
ca55abae
JM
3625
3626static inline void *
3627get_return_addr (frame_state *udata, frame_state *sub_udata)
3628{
3629 return __builtin_extract_return_addr
3630 (get_reg (udata->retaddr_column, udata, sub_udata));
3631}
3632
3633/* Overwrite the return address for frame UDATA with VAL. */
3634
3635static inline void
3636put_return_addr (void *val, frame_state *udata)
3637{
3638 val = __builtin_frob_return_addr (val);
3639 put_reg (udata->retaddr_column, val, udata);
3640}
3641
3642/* Given the current frame UDATA and its return address PC, return the
3643 information about the calling frame in CALLER_UDATA. */
3644
3645static void *
3646next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
3647{
3648 caller_udata = __frame_state_for (pc, caller_udata);
3649 if (! caller_udata)
3650 return 0;
3651
3652 /* Now go back to our caller's stack frame. If our caller's CFA register
3653 was saved in our stack frame, restore it; otherwise, assume the CFA
3654 register is SP and restore it to our CFA value. */
3655 if (udata->saved[caller_udata->cfa_reg])
3656 caller_udata->cfa = get_reg (caller_udata->cfa_reg, udata, 0);
3657 else
3658 caller_udata->cfa = udata->cfa;
3659 caller_udata->cfa += caller_udata->cfa_offset;
3660
3661 return caller_udata;
3662}
3663
e6cfb550
AM
3664/* Hook to call before __terminate if only cleanup handlers remain. */
3665void
3666__unwinding_cleanup ()
ca55abae 3667{
e6cfb550 3668}
ca55abae 3669
e6cfb550
AM
3670/* throw_helper performs some of the common grunt work for a throw. This
3671 routine is called by throw and rethrows. This is pretty much split
3672 out from the old __throw routine. An addition has been added which allows
3673 for a dummy call to a routine __unwinding_cleanup() when there are nothing
3674 but cleanups remaining. This allows a debugger to examine the state
3675 at which the throw was executed, before any cleanups, rather than
51980de6
JM
3676 at the terminate point after the stack has been unwound.
3677
3678 EH is the current eh_context structure.
3679 PC is the address of the call to __throw.
3680 MY_UDATA is the unwind information for __throw.
3681 OFFSET_P is where we return the SP adjustment offset. */
ca55abae 3682
e6cfb550 3683static void *
51980de6 3684throw_helper (eh, pc, my_udata, offset_p)
e6cfb550
AM
3685 struct eh_context *eh;
3686 void *pc;
3687 frame_state *my_udata;
51980de6 3688 long *offset_p;
e6cfb550 3689{
51980de6 3690 frame_state ustruct2, *udata = &ustruct2;
e6cfb550
AM
3691 frame_state ustruct;
3692 frame_state *sub_udata = &ustruct;
3693 void *saved_pc = pc;
3694 void *handler;
3695 void *handler_p;
3696 void *pc_p;
3697 frame_state saved_ustruct;
3698 int new_eh_model;
3699 int cleanup = 0;
3700 int only_cleanup = 0;
3701 int rethrow = 0;
3702 int saved_state = 0;
51980de6 3703 long args_size;
e6cfb550
AM
3704 __eh_info *eh_info = (__eh_info *)eh->info;
3705
3706 /* Do we find a handler based on a re-throw PC? */
3707 if (eh->table_index != (void *) 0)
3708 rethrow = 1;
3709
51980de6
JM
3710 memcpy (udata, my_udata, sizeof (*udata));
3711
e6cfb550 3712 handler = (void *) 0;
ca55abae
JM
3713 for (;;)
3714 {
3715 frame_state *p = udata;
3716 udata = next_stack_level (pc, udata, sub_udata);
3717 sub_udata = p;
3718
3719 /* If we couldn't find the next frame, we lose. */
3720 if (! udata)
3721 break;
3722
a1622f83 3723 if (udata->eh_ptr == NULL)
e6cfb550 3724 new_eh_model = 0;
a1622f83 3725 else
e6cfb550 3726 new_eh_model = (((exception_descriptor *)(udata->eh_ptr))->
a1622f83
AM
3727 runtime_id_field == NEW_EH_RUNTIME);
3728
e6cfb550
AM
3729 if (rethrow)
3730 {
3731 rethrow = 0;
3732 handler = find_exception_handler (eh->table_index, udata->eh_ptr,
3733 eh_info, 1, &cleanup);
3734 eh->table_index = (void *)0;
3735 }
a1622f83 3736 else
e6cfb550
AM
3737 if (new_eh_model)
3738 handler = find_exception_handler (pc, udata->eh_ptr, eh_info,
3739 0, &cleanup);
3740 else
3741 handler = old_find_exception_handler (pc, udata->eh_ptr);
3742
3743 /* If we found one, we can stop searching, if its not a cleanup.
3744 for cleanups, we save the state, and keep looking. This allows
3745 us to call a debug hook if there are nothing but cleanups left. */
ca55abae 3746 if (handler)
1b528097
JM
3747 {
3748 if (cleanup)
3749 {
3750 if (!saved_state)
3751 {
3752 saved_ustruct = *udata;
3753 handler_p = handler;
3754 pc_p = pc;
3755 saved_state = 1;
3756 only_cleanup = 1;
3757 }
3758 }
3759 else
3760 {
3761 only_cleanup = 0;
3762 break;
3763 }
3764 }
ca55abae 3765
6020d360
JM
3766 /* Otherwise, we continue searching. We subtract 1 from PC to avoid
3767 hitting the beginning of the next region. */
3768 pc = get_return_addr (udata, sub_udata) - 1;
ca55abae
JM
3769 }
3770
e6cfb550
AM
3771 if (saved_state)
3772 {
3773 udata = &saved_ustruct;
3774 handler = handler_p;
3775 pc = pc_p;
3776 if (only_cleanup)
3777 __unwinding_cleanup ();
3778 }
3779
ca55abae
JM
3780 /* If we haven't found a handler by now, this is an unhandled
3781 exception. */
e6cfb550
AM
3782 if (! handler)
3783 __terminate();
ca55abae 3784
9a0d1e1b 3785 eh->handler_label = handler;
9a0d1e1b 3786
51980de6
JM
3787 args_size = udata->args_size;
3788
154bba13 3789 if (pc == saved_pc)
ca55abae
JM
3790 /* We found a handler in the throw context, no need to unwind. */
3791 udata = my_udata;
3792 else
3793 {
3794 int i;
ca55abae
JM
3795
3796 /* Unwind all the frames between this one and the handler by copying
3797 their saved register values into our register save slots. */
3798
3799 /* Remember the PC where we found the handler. */
3800 void *handler_pc = pc;
3801
3802 /* Start from the throw context again. */
154bba13 3803 pc = saved_pc;
ca55abae
JM
3804 memcpy (udata, my_udata, sizeof (*udata));
3805
3806 while (pc != handler_pc)
3807 {
3808 frame_state *p = udata;
3809 udata = next_stack_level (pc, udata, sub_udata);
3810 sub_udata = p;
3811
3812 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
d1485032 3813 if (i != udata->retaddr_column && udata->saved[i])
ca55abae 3814 {
ca55abae
JM
3815 /* If you modify the saved value of the return address
3816 register on the SPARC, you modify the return address for
3817 your caller's frame. Don't do that here, as it will
3818 confuse get_return_addr. */
3819 if (in_reg_window (i, udata)
3820 && udata->saved[udata->retaddr_column] == REG_SAVED_REG
3821 && udata->reg_or_offset[udata->retaddr_column] == i)
3822 continue;
2f3ca9e7 3823 copy_reg (i, udata, my_udata);
ca55abae
JM
3824 }
3825
6020d360 3826 pc = get_return_addr (udata, sub_udata) - 1;
ca55abae
JM
3827 }
3828
ca55abae
JM
3829 /* But we do need to update the saved return address register from
3830 the last frame we unwind, or the handler frame will have the wrong
3831 return address. */
3832 if (udata->saved[udata->retaddr_column] == REG_SAVED_REG)
3833 {
3834 i = udata->reg_or_offset[udata->retaddr_column];
3835 if (in_reg_window (i, udata))
f3447109 3836 copy_reg (i, udata, my_udata);
ca55abae 3837 }
ca55abae 3838 }
e6cfb550
AM
3839 /* udata now refers to the frame called by the handler frame. */
3840
51980de6
JM
3841 /* We adjust SP by the difference between __throw's CFA and the CFA for
3842 the frame called by the handler frame, because those CFAs correspond
3843 to the SP values at the two call sites. We need to further adjust by
3844 the args_size of the handler frame itself to get the handler frame's
3845 SP from before the args were pushed for that call. */
3846#ifdef STACK_GROWS_DOWNWARD
3847 *offset_p = udata->cfa - my_udata->cfa + args_size;
3848#else
3849 *offset_p = my_udata->cfa - udata->cfa - args_size;
3850#endif
3851
e6cfb550
AM
3852 return handler;
3853}
3854
3855
3856/* We first search for an exception handler, and if we don't find
3857 it, we call __terminate on the current stack frame so that we may
3858 use the debugger to walk the stack and understand why no handler
3859 was found.
3860
3861 If we find one, then we unwind the frames down to the one that
3862 has the handler and transfer control into the handler. */
3863
3864/*extern void __throw(void) __attribute__ ((__noreturn__));*/
3865
3866void
3867__throw ()
3868{
3869 struct eh_context *eh = (*get_eh_context) ();
3870 void *pc, *handler;
51980de6
JM
3871 long offset;
3872
3873 /* XXX maybe make my_ustruct static so we don't have to look it up for
3874 each throw. */
e6cfb550
AM
3875 frame_state my_ustruct, *my_udata = &my_ustruct;
3876
3877 /* This is required for C++ semantics. We must call terminate if we
3878 try and rethrow an exception, when there is no exception currently
3879 active. */
3880 if (! eh->info)
3881 __terminate ();
3882
3883 /* Start at our stack frame. */
3884label:
51980de6
JM
3885 my_udata = __frame_state_for (&&label, my_udata);
3886 if (! my_udata)
e6cfb550
AM
3887 __terminate ();
3888
3889 /* We need to get the value from the CFA register. */
51980de6 3890 my_udata->cfa = __builtin_dwarf_cfa ();
e6cfb550
AM
3891
3892 /* Do any necessary initialization to access arbitrary stack frames.
3893 On the SPARC, this means flushing the register windows. */
3894 __builtin_unwind_init ();
3895
3896 /* Now reset pc to the right throw point. */
3897 pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
3898
51980de6 3899 handler = throw_helper (eh, pc, my_udata, &offset);
e6cfb550
AM
3900
3901 /* Now go! */
3902
51980de6 3903 __builtin_eh_return ((void *)eh, offset, handler);
e6cfb550
AM
3904
3905 /* Epilogue: restore the handler frame's register values and return
3906 to the stub. */
3907}
3908
3909/*extern void __rethrow(void *) __attribute__ ((__noreturn__));*/
3910
3911void
3912__rethrow (index)
3913 void *index;
3914{
3915 struct eh_context *eh = (*get_eh_context) ();
3916 void *pc, *handler;
51980de6
JM
3917 long offset;
3918
3919 /* XXX maybe make my_ustruct static so we don't have to look it up for
3920 each throw. */
e6cfb550
AM
3921 frame_state my_ustruct, *my_udata = &my_ustruct;
3922
3923 /* This is required for C++ semantics. We must call terminate if we
3924 try and rethrow an exception, when there is no exception currently
3925 active. */
3926 if (! eh->info)
3927 __terminate ();
3928
3929 /* This is the table index we want to rethrow from. The value of
3930 the END_REGION label is used for the PC of the throw, and the
3931 search begins with the next table entry. */
3932 eh->table_index = index;
3933
3934 /* Start at our stack frame. */
3935label:
51980de6
JM
3936 my_udata = __frame_state_for (&&label, my_udata);
3937 if (! my_udata)
e6cfb550
AM
3938 __terminate ();
3939
3940 /* We need to get the value from the CFA register. */
51980de6 3941 my_udata->cfa = __builtin_dwarf_cfa ();
e6cfb550
AM
3942
3943 /* Do any necessary initialization to access arbitrary stack frames.
3944 On the SPARC, this means flushing the register windows. */
3945 __builtin_unwind_init ();
3946
3947 /* Now reset pc to the right throw point. */
3948 pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
3949
51980de6 3950 handler = throw_helper (eh, pc, my_udata, &offset);
ca55abae 3951
71038426 3952 /* Now go! */
9a0d1e1b 3953
51980de6 3954 __builtin_eh_return ((void *)eh, offset, handler);
ca55abae
JM
3955
3956 /* Epilogue: restore the handler frame's register values and return
3957 to the stub. */
3958}
0776059e 3959#endif /* DWARF2_UNWIND_INFO */
ca55abae 3960
ad912eec 3961#endif /* L_eh */
efc955c7
JM
3962\f
3963#ifdef L_pure
2c62c124
JM
3964#ifndef inhibit_libc
3965/* This gets us __GNU_LIBRARY__. */
3966#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
3967#include <stdio.h>
3968
3969#ifdef __GNU_LIBRARY__
3970 /* Avoid forcing the library's meaning of `write' on the user program
3971 by using the "internal" name (for use within the library) */
3972#define write(fd, buf, n) __write((fd), (buf), (n))
3973#endif
3974#endif /* inhibit_libc */
3975
efc955c7 3976#define MESSAGE "pure virtual method called\n"
2c62c124 3977
efc955c7
JM
3978void
3979__pure_virtual ()
3980{
2c62c124 3981#ifndef inhibit_libc
efc955c7 3982 write (2, MESSAGE, sizeof (MESSAGE) - 1);
2c62c124 3983#endif
4f2905fb 3984 __terminate ();
efc955c7
JM
3985}
3986#endif
This page took 1.299345 seconds and 5 git commands to generate.