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