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