]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/libgcc2.c
* sh.md (movdf_k, movsf_i, movsf_ie): new alternative for
[thirdparty/gcc.git] / gcc / libgcc2.c
CommitLineData
62c63f32 1/* More subroutines needed by GCC output code on some machines. */
2/* Compile this one with gcc. */
2fea28a7 3/* Copyright (C) 1989, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
62c63f32 4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING. If not, write to
0355838f 19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
62c63f32 21
f9b6c2c9 22/* As a special exception, if you link this library with other files,
23 some of which are compiled with GCC, to produce an executable,
24 this library does not by itself cause the resulting executable
25 to be covered by the GNU General Public License.
62c63f32 26 This exception does not however invalidate any other reasons why
27 the executable file might be covered by the GNU General Public License. */
28
29/* It is incorrect to include config.h here, because this file is being
30 compiled for the target, and hence definitions concerning only the host
31 do not apply. */
32
c538053c 33#include "tconfig.h"
33927595 34#include "machmode.h"
9a0ce7db 35#include "defaults.h"
b13ae905 36#ifndef L_trampoline
057feb08 37#include <stddef.h>
b13ae905 38#endif
62c63f32 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
9a0ce7db 45#if (SUPPORTS_WEAK == 1) && defined (ASM_OUTPUT_DEF)
46#define WEAK_ALIAS
47#endif
48
51356f86 49/* Permit the tm.h file to select the endianness to use just for this
50 file. This is used when the endianness is determined when the
51 compiler is run. */
52
53#ifndef LIBGCC2_WORDS_BIG_ENDIAN
54#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
55#endif
56
ade0e71b 57/* In the first part of this file, we are interfacing to calls generated
58 by the compiler itself. These calls pass values into these routines
59 which have very specific modes (rather than very specific types), and
60 these compiler-generated calls also expect any return values to have
61 very specific modes (rather than very specific types). Thus, we need
62 to avoid using regular C language type names in this part of the file
63 because the sizes for those types can be configured to be anything.
64 Instead we use the following special type names. */
65
1ce0972e 66typedef unsigned int UQItype __attribute__ ((mode (QI)));
67typedef int SItype __attribute__ ((mode (SI)));
68typedef unsigned int USItype __attribute__ ((mode (SI)));
69typedef int DItype __attribute__ ((mode (DI)));
70typedef unsigned int UDItype __attribute__ ((mode (DI)));
5acb5b2d 71
1ce0972e 72typedef float SFtype __attribute__ ((mode (SF)));
73typedef float DFtype __attribute__ ((mode (DF)));
5acb5b2d 74
0e1cc047 75#if LONG_DOUBLE_TYPE_SIZE == 96
1ce0972e 76typedef float XFtype __attribute__ ((mode (XF)));
bd3c175d 77#endif
78#if LONG_DOUBLE_TYPE_SIZE == 128
1ce0972e 79typedef float TFtype __attribute__ ((mode (TF)));
bd3c175d 80#endif
ade0e71b 81
5acb5b2d 82typedef int word_type __attribute__ ((mode (__word__)));
61d95568 83
91a48688 84/* Make sure that we don't accidentally use any normal C language built-in
ade0e71b 85 type names in the first part of this file. Instead we want to use *only*
86 the type names defined above. The following macro definitions insure
13280659 87 that if we *do* accidentally use some normal C language built-in type name,
ade0e71b 88 we will get a syntax error. */
89
90#define char bogus_type
91#define short bogus_type
92#define int bogus_type
93#define long bogus_type
94#define unsigned bogus_type
95#define float bogus_type
96#define double bogus_type
97
98#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
99
100/* DIstructs are pairs of SItype values in the order determined by
51356f86 101 LIBGCC2_WORDS_BIG_ENDIAN. */
62c63f32 102
51356f86 103#if LIBGCC2_WORDS_BIG_ENDIAN
ade0e71b 104 struct DIstruct {SItype high, low;};
62c63f32 105#else
ade0e71b 106 struct DIstruct {SItype low, high;};
62c63f32 107#endif
108
ade0e71b 109/* We need this union to unpack/pack DImode values, since we don't have
110 any arithmetic yet. Incoming DImode parameters are stored into the
111 `ll' field, and the unpacked result is read from the struct `s'. */
62c63f32 112
113typedef union
114{
ade0e71b 115 struct DIstruct s;
116 DItype ll;
117} DIunion;
62c63f32 118
a47053cf 119#if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\
120 || defined (L_divdi3) || defined (L_udivdi3) \
121 || defined (L_moddi3) || defined (L_umoddi3))
62c63f32 122
123#include "longlong.h"
124
125#endif /* udiv or mul */
126
ade0e71b 127extern DItype __fixunssfdi (SFtype a);
128extern DItype __fixunsdfdi (DFtype a);
4164cab8 129#if LONG_DOUBLE_TYPE_SIZE == 96
c61285e8 130extern DItype __fixunsxfdi (XFtype a);
4164cab8 131#endif
132#if LONG_DOUBLE_TYPE_SIZE == 128
dccb35e9 133extern DItype __fixunstfdi (TFtype a);
4164cab8 134#endif
62c63f32 135\f
136#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
137#if defined (L_divdi3) || defined (L_moddi3)
138static inline
139#endif
ade0e71b 140DItype
62c63f32 141__negdi2 (u)
ade0e71b 142 DItype u;
62c63f32 143{
ade0e71b 144 DIunion w;
145 DIunion uu;
62c63f32 146
147 uu.ll = u;
148
149 w.s.low = -uu.s.low;
ade0e71b 150 w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
62c63f32 151
152 return w.ll;
153}
154#endif
155\f
62c63f32 156#ifdef L_lshrdi3
ade0e71b 157DItype
62c63f32 158__lshrdi3 (u, b)
ade0e71b 159 DItype u;
60a744a6 160 word_type b;
62c63f32 161{
ade0e71b 162 DIunion w;
60a744a6 163 word_type bm;
ade0e71b 164 DIunion uu;
62c63f32 165
166 if (b == 0)
167 return u;
168
169 uu.ll = u;
170
ade0e71b 171 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
62c63f32 172 if (bm <= 0)
173 {
174 w.s.high = 0;
ade0e71b 175 w.s.low = (USItype)uu.s.high >> -bm;
62c63f32 176 }
177 else
178 {
ade0e71b 179 USItype carries = (USItype)uu.s.high << bm;
180 w.s.high = (USItype)uu.s.high >> b;
181 w.s.low = ((USItype)uu.s.low >> b) | carries;
62c63f32 182 }
183
184 return w.ll;
185}
186#endif
187
188#ifdef L_ashldi3
ade0e71b 189DItype
62c63f32 190__ashldi3 (u, b)
ade0e71b 191 DItype u;
60a744a6 192 word_type b;
62c63f32 193{
ade0e71b 194 DIunion w;
60a744a6 195 word_type bm;
ade0e71b 196 DIunion uu;
62c63f32 197
198 if (b == 0)
199 return u;
200
201 uu.ll = u;
202
ade0e71b 203 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
62c63f32 204 if (bm <= 0)
205 {
206 w.s.low = 0;
ade0e71b 207 w.s.high = (USItype)uu.s.low << -bm;
62c63f32 208 }
209 else
210 {
ade0e71b 211 USItype carries = (USItype)uu.s.low >> bm;
212 w.s.low = (USItype)uu.s.low << b;
213 w.s.high = ((USItype)uu.s.high << b) | carries;
62c63f32 214 }
215
216 return w.ll;
217}
218#endif
219
220#ifdef L_ashrdi3
ade0e71b 221DItype
62c63f32 222__ashrdi3 (u, b)
ade0e71b 223 DItype u;
60a744a6 224 word_type b;
62c63f32 225{
ade0e71b 226 DIunion w;
60a744a6 227 word_type bm;
ade0e71b 228 DIunion uu;
62c63f32 229
230 if (b == 0)
231 return u;
232
233 uu.ll = u;
234
ade0e71b 235 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
62c63f32 236 if (bm <= 0)
237 {
238 /* w.s.high = 1..1 or 0..0 */
ade0e71b 239 w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
62c63f32 240 w.s.low = uu.s.high >> -bm;
241 }
242 else
243 {
ade0e71b 244 USItype carries = (USItype)uu.s.high << bm;
62c63f32 245 w.s.high = uu.s.high >> b;
ade0e71b 246 w.s.low = ((USItype)uu.s.low >> b) | carries;
62c63f32 247 }
248
249 return w.ll;
250}
251#endif
252\f
5e4e1583 253#ifdef L_ffsdi2
254DItype
255__ffsdi2 (u)
256 DItype u;
257{
258 DIunion uu, w;
259 uu.ll = u;
260 w.s.high = 0;
261 w.s.low = ffs (uu.s.low);
262 if (w.s.low != 0)
2708a425 263 return w.ll;
5e4e1583 264 w.s.low = ffs (uu.s.high);
265 if (w.s.low != 0)
266 {
267 w.s.low += BITS_PER_UNIT * sizeof (SItype);
2708a425 268 return w.ll;
5e4e1583 269 }
2708a425 270 return w.ll;
5e4e1583 271}
272#endif
273\f
62c63f32 274#ifdef L_muldi3
ade0e71b 275DItype
62c63f32 276__muldi3 (u, v)
ade0e71b 277 DItype u, v;
62c63f32 278{
ade0e71b 279 DIunion w;
280 DIunion uu, vv;
62c63f32 281
282 uu.ll = u,
283 vv.ll = v;
284
285 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
ade0e71b 286 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
287 + (USItype) uu.s.high * (USItype) vv.s.low);
62c63f32 288
289 return w.ll;
290}
291#endif
292\f
a46ef09f 293#ifdef L_udiv_w_sdiv
b10877f3 294#if defined (sdiv_qrnnd)
ba628a68 295USItype
a46ef09f 296__udiv_w_sdiv (rp, a1, a0, d)
ba628a68 297 USItype *rp, a1, a0, d;
298{
299 USItype q, r;
300 USItype c0, c1, b1;
301
302 if ((SItype) d >= 0)
303 {
363bfed7 304 if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
ba628a68 305 {
306 /* dividend, divisor, and quotient are nonnegative */
307 sdiv_qrnnd (q, r, a1, a0, d);
308 }
309 else
310 {
311 /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
363bfed7 312 sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
ba628a68 313 /* Divide (c1*2^32 + c0) by d */
314 sdiv_qrnnd (q, r, c1, c0, d);
315 /* Add 2^31 to quotient */
363bfed7 316 q += (USItype) 1 << (SI_TYPE_SIZE - 1);
ba628a68 317 }
318 }
319 else
320 {
321 b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
322 c1 = a1 >> 1; /* A/2 */
363bfed7 323 c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
ba628a68 324
325 if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
326 {
327 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
328
329 r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
330 if ((d & 1) != 0)
331 {
332 if (r >= q)
333 r = r - q;
334 else if (q - r <= d)
335 {
336 r = r - q + d;
337 q--;
338 }
339 else
340 {
341 r = r - q + 2*d;
342 q -= 2;
343 }
344 }
345 }
346 else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
347 {
348 c1 = (b1 - 1) - c1;
349 c0 = ~c0; /* logical NOT */
350
351 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
352
353 q = ~q; /* (A/2)/b1 */
354 r = (b1 - 1) - r;
355
356 r = 2*r + (a0 & 1); /* A/(2*b1) */
357
358 if ((d & 1) != 0)
359 {
360 if (r >= q)
361 r = r - q;
362 else if (q - r <= d)
363 {
364 r = r - q + d;
365 q--;
366 }
367 else
368 {
369 r = r - q + 2*d;
370 q -= 2;
371 }
372 }
373 }
374 else /* Implies c1 = b1 */
375 { /* Hence a1 = d - 1 = 2*b1 - 1 */
376 if (a0 >= -d)
377 {
378 q = -1;
379 r = a0 + d;
380 }
381 else
382 {
383 q = -2;
384 r = a0 + 2*d;
385 }
386 }
387 }
388
389 *rp = r;
390 return q;
391}
b10877f3 392#else
393/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */
394USItype
395__udiv_w_sdiv (rp, a1, a0, d)
396 USItype *rp, a1, a0, d;
397{}
398#endif
ba628a68 399#endif
400\f
a47053cf 401#if (defined (L_udivdi3) || defined (L_divdi3) || \
402 defined (L_umoddi3) || defined (L_moddi3))
403#define L_udivmoddi4
404#endif
405
62c63f32 406#ifdef L_udivmoddi4
ade0e71b 407static const UQItype __clz_tab[] =
62c63f32 408{
409 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,
410 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,
411 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,
412 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,
413 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,
414 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,
415 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,
416 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,
417};
418
a47053cf 419#if (defined (L_udivdi3) || defined (L_divdi3) || \
420 defined (L_umoddi3) || defined (L_moddi3))
421static inline
422#endif
ade0e71b 423UDItype
62c63f32 424__udivmoddi4 (n, d, rp)
ade0e71b 425 UDItype n, d;
426 UDItype *rp;
62c63f32 427{
ade0e71b 428 DIunion ww;
429 DIunion nn, dd;
430 DIunion rr;
431 USItype d0, d1, n0, n1, n2;
432 USItype q0, q1;
433 USItype b, bm;
62c63f32 434
435 nn.ll = n;
436 dd.ll = d;
437
438 d0 = dd.s.low;
439 d1 = dd.s.high;
440 n0 = nn.s.low;
441 n1 = nn.s.high;
442
443#if !UDIV_NEEDS_NORMALIZATION
444 if (d1 == 0)
445 {
446 if (d0 > n1)
447 {
448 /* 0q = nn / 0D */
449
450 udiv_qrnnd (q0, n0, n1, n0, d0);
451 q1 = 0;
452
453 /* Remainder in n0. */
454 }
455 else
456 {
457 /* qq = NN / 0d */
458
459 if (d0 == 0)
460 d0 = 1 / d0; /* Divide intentionally by zero. */
461
462 udiv_qrnnd (q1, n1, 0, n1, d0);
463 udiv_qrnnd (q0, n0, n1, n0, d0);
464
465 /* Remainder in n0. */
466 }
467
468 if (rp != 0)
469 {
470 rr.s.low = n0;
471 rr.s.high = 0;
472 *rp = rr.ll;
473 }
474 }
475
476#else /* UDIV_NEEDS_NORMALIZATION */
477
478 if (d1 == 0)
479 {
480 if (d0 > n1)
481 {
482 /* 0q = nn / 0D */
483
484 count_leading_zeros (bm, d0);
485
486 if (bm != 0)
487 {
488 /* Normalize, i.e. make the most significant bit of the
489 denominator set. */
490
491 d0 = d0 << bm;
ade0e71b 492 n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
62c63f32 493 n0 = n0 << bm;
494 }
495
496 udiv_qrnnd (q0, n0, n1, n0, d0);
497 q1 = 0;
498
499 /* Remainder in n0 >> bm. */
500 }
501 else
502 {
503 /* qq = NN / 0d */
504
505 if (d0 == 0)
506 d0 = 1 / d0; /* Divide intentionally by zero. */
507
508 count_leading_zeros (bm, d0);
509
510 if (bm == 0)
511 {
512 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
513 conclude (the most significant bit of n1 is set) /\ (the
514 leading quotient digit q1 = 1).
515
516 This special case is necessary, not an optimization.
ade0e71b 517 (Shifts counts of SI_TYPE_SIZE are undefined.) */
62c63f32 518
519 n1 -= d0;
520 q1 = 1;
521 }
522 else
523 {
524 /* Normalize. */
525
ade0e71b 526 b = SI_TYPE_SIZE - bm;
62c63f32 527
528 d0 = d0 << bm;
529 n2 = n1 >> b;
530 n1 = (n1 << bm) | (n0 >> b);
531 n0 = n0 << bm;
532
533 udiv_qrnnd (q1, n1, n2, n1, d0);
534 }
535
a92771b8 536 /* n1 != d0... */
62c63f32 537
538 udiv_qrnnd (q0, n0, n1, n0, d0);
539
540 /* Remainder in n0 >> bm. */
541 }
542
543 if (rp != 0)
544 {
545 rr.s.low = n0 >> bm;
546 rr.s.high = 0;
547 *rp = rr.ll;
548 }
549 }
550#endif /* UDIV_NEEDS_NORMALIZATION */
551
552 else
553 {
554 if (d1 > n1)
555 {
556 /* 00 = nn / DD */
557
558 q0 = 0;
559 q1 = 0;
560
561 /* Remainder in n1n0. */
562 if (rp != 0)
563 {
564 rr.s.low = n0;
565 rr.s.high = n1;
566 *rp = rr.ll;
567 }
568 }
569 else
570 {
571 /* 0q = NN / dd */
572
573 count_leading_zeros (bm, d1);
574 if (bm == 0)
575 {
576 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
577 conclude (the most significant bit of n1 is set) /\ (the
578 quotient digit q0 = 0 or 1).
579
580 This special case is necessary, not an optimization. */
581
582 /* The condition on the next line takes advantage of that
583 n1 >= d1 (true due to program flow). */
584 if (n1 > d1 || n0 >= d0)
585 {
586 q0 = 1;
587 sub_ddmmss (n1, n0, n1, n0, d1, d0);
588 }
589 else
590 q0 = 0;
591
592 q1 = 0;
593
594 if (rp != 0)
595 {
596 rr.s.low = n0;
597 rr.s.high = n1;
598 *rp = rr.ll;
599 }
600 }
601 else
602 {
ade0e71b 603 USItype m1, m0;
62c63f32 604 /* Normalize. */
605
ade0e71b 606 b = SI_TYPE_SIZE - bm;
62c63f32 607
608 d1 = (d1 << bm) | (d0 >> b);
609 d0 = d0 << bm;
610 n2 = n1 >> b;
611 n1 = (n1 << bm) | (n0 >> b);
612 n0 = n0 << bm;
613
614 udiv_qrnnd (q0, n1, n2, n1, d1);
615 umul_ppmm (m1, m0, q0, d0);
616
617 if (m1 > n1 || (m1 == n1 && m0 > n0))
618 {
619 q0--;
620 sub_ddmmss (m1, m0, m1, m0, d1, d0);
621 }
622
623 q1 = 0;
624
625 /* Remainder in (n1n0 - m1m0) >> bm. */
626 if (rp != 0)
627 {
628 sub_ddmmss (n1, n0, n1, n0, m1, m0);
629 rr.s.low = (n1 << b) | (n0 >> bm);
630 rr.s.high = n1 >> bm;
631 *rp = rr.ll;
632 }
633 }
634 }
635 }
636
637 ww.s.low = q0;
638 ww.s.high = q1;
639 return ww.ll;
640}
641#endif
642
643#ifdef L_divdi3
ade0e71b 644UDItype __udivmoddi4 ();
c61285e8 645
ade0e71b 646DItype
62c63f32 647__divdi3 (u, v)
ade0e71b 648 DItype u, v;
62c63f32 649{
60a744a6 650 word_type c = 0;
ade0e71b 651 DIunion uu, vv;
652 DItype w;
62c63f32 653
654 uu.ll = u;
655 vv.ll = v;
656
657 if (uu.s.high < 0)
658 c = ~c,
659 uu.ll = __negdi2 (uu.ll);
660 if (vv.s.high < 0)
661 c = ~c,
662 vv.ll = __negdi2 (vv.ll);
663
ade0e71b 664 w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
62c63f32 665 if (c)
666 w = __negdi2 (w);
667
668 return w;
669}
670#endif
671
672#ifdef L_moddi3
ade0e71b 673UDItype __udivmoddi4 ();
674DItype
62c63f32 675__moddi3 (u, v)
ade0e71b 676 DItype u, v;
62c63f32 677{
60a744a6 678 word_type c = 0;
ade0e71b 679 DIunion uu, vv;
680 DItype w;
62c63f32 681
682 uu.ll = u;
683 vv.ll = v;
684
685 if (uu.s.high < 0)
686 c = ~c,
687 uu.ll = __negdi2 (uu.ll);
688 if (vv.s.high < 0)
689 vv.ll = __negdi2 (vv.ll);
690
691 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
692 if (c)
693 w = __negdi2 (w);
694
695 return w;
696}
697#endif
698
699#ifdef L_umoddi3
ade0e71b 700UDItype __udivmoddi4 ();
701UDItype
62c63f32 702__umoddi3 (u, v)
ade0e71b 703 UDItype u, v;
62c63f32 704{
7f7ec5cf 705 UDItype w;
62c63f32 706
707 (void) __udivmoddi4 (u, v, &w);
708
709 return w;
710}
711#endif
712
713#ifdef L_udivdi3
ade0e71b 714UDItype __udivmoddi4 ();
715UDItype
62c63f32 716__udivdi3 (n, d)
ade0e71b 717 UDItype n, d;
62c63f32 718{
ade0e71b 719 return __udivmoddi4 (n, d, (UDItype *) 0);
62c63f32 720}
721#endif
722\f
723#ifdef L_cmpdi2
61d95568 724word_type
62c63f32 725__cmpdi2 (a, b)
ade0e71b 726 DItype a, b;
62c63f32 727{
ade0e71b 728 DIunion au, bu;
62c63f32 729
730 au.ll = a, bu.ll = b;
731
732 if (au.s.high < bu.s.high)
733 return 0;
734 else if (au.s.high > bu.s.high)
735 return 2;
ade0e71b 736 if ((USItype) au.s.low < (USItype) bu.s.low)
62c63f32 737 return 0;
ade0e71b 738 else if ((USItype) au.s.low > (USItype) bu.s.low)
62c63f32 739 return 2;
740 return 1;
741}
742#endif
743
744#ifdef L_ucmpdi2
61d95568 745word_type
62c63f32 746__ucmpdi2 (a, b)
ade0e71b 747 DItype a, b;
62c63f32 748{
ade0e71b 749 DIunion au, bu;
62c63f32 750
751 au.ll = a, bu.ll = b;
752
ade0e71b 753 if ((USItype) au.s.high < (USItype) bu.s.high)
62c63f32 754 return 0;
ade0e71b 755 else if ((USItype) au.s.high > (USItype) bu.s.high)
62c63f32 756 return 2;
ade0e71b 757 if ((USItype) au.s.low < (USItype) bu.s.low)
62c63f32 758 return 0;
ade0e71b 759 else if ((USItype) au.s.low > (USItype) bu.s.low)
62c63f32 760 return 2;
761 return 1;
762}
763#endif
764\f
ade0e71b 765#if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
766#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
767#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
768
769DItype
770__fixunstfdi (a)
771 TFtype a;
772{
773 TFtype b;
774 UDItype v;
775
776 if (a < 0)
777 return 0;
778
779 /* Compute high word of result, as a flonum. */
780 b = (a / HIGH_WORD_COEFF);
781 /* Convert that to fixed (but not to DItype!),
782 and shift it into the high word. */
783 v = (USItype) b;
784 v <<= WORD_SIZE;
785 /* Remove high part from the TFtype, leaving the low part as flonum. */
786 a -= (TFtype)v;
787 /* Convert that to fixed (but not to DItype!) and add it in.
788 Sometimes A comes out negative. This is significant, since
789 A has more bits than a long int does. */
790 if (a < 0)
791 v -= (USItype) (- a);
792 else
793 v += (USItype) a;
794 return v;
795}
796#endif
797
798#if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
799DItype
800__fixtfdi (a)
801 TFtype a;
802{
803 if (a < 0)
804 return - __fixunstfdi (-a);
805 return __fixunstfdi (a);
806}
807#endif
808
0e1cc047 809#if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
810#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
811#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
812
813DItype
814__fixunsxfdi (a)
815 XFtype a;
816{
817 XFtype b;
818 UDItype v;
819
820 if (a < 0)
821 return 0;
822
823 /* Compute high word of result, as a flonum. */
824 b = (a / HIGH_WORD_COEFF);
825 /* Convert that to fixed (but not to DItype!),
826 and shift it into the high word. */
827 v = (USItype) b;
828 v <<= WORD_SIZE;
829 /* Remove high part from the XFtype, leaving the low part as flonum. */
830 a -= (XFtype)v;
831 /* Convert that to fixed (but not to DItype!) and add it in.
832 Sometimes A comes out negative. This is significant, since
833 A has more bits than a long int does. */
834 if (a < 0)
835 v -= (USItype) (- a);
836 else
837 v += (USItype) a;
838 return v;
839}
840#endif
841
842#if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
843DItype
844__fixxfdi (a)
845 XFtype a;
846{
847 if (a < 0)
848 return - __fixunsxfdi (-a);
849 return __fixunsxfdi (a);
850}
851#endif
852
62c63f32 853#ifdef L_fixunsdfdi
ade0e71b 854#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
855#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
62c63f32 856
ade0e71b 857DItype
62c63f32 858__fixunsdfdi (a)
ade0e71b 859 DFtype a;
62c63f32 860{
ade0e71b 861 DFtype b;
862 UDItype v;
62c63f32 863
864 if (a < 0)
865 return 0;
866
867 /* Compute high word of result, as a flonum. */
868 b = (a / HIGH_WORD_COEFF);
ade0e71b 869 /* Convert that to fixed (but not to DItype!),
62c63f32 870 and shift it into the high word. */
ade0e71b 871 v = (USItype) b;
62c63f32 872 v <<= WORD_SIZE;
ade0e71b 873 /* Remove high part from the DFtype, leaving the low part as flonum. */
874 a -= (DFtype)v;
875 /* Convert that to fixed (but not to DItype!) and add it in.
62c63f32 876 Sometimes A comes out negative. This is significant, since
877 A has more bits than a long int does. */
878 if (a < 0)
ade0e71b 879 v -= (USItype) (- a);
62c63f32 880 else
ade0e71b 881 v += (USItype) a;
62c63f32 882 return v;
883}
884#endif
885
886#ifdef L_fixdfdi
ade0e71b 887DItype
62c63f32 888__fixdfdi (a)
ade0e71b 889 DFtype a;
62c63f32 890{
891 if (a < 0)
892 return - __fixunsdfdi (-a);
893 return __fixunsdfdi (a);
894}
895#endif
896
897#ifdef L_fixunssfdi
ade0e71b 898#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
899#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
62c63f32 900
ade0e71b 901DItype
902__fixunssfdi (SFtype original_a)
62c63f32 903{
ade0e71b 904 /* Convert the SFtype to a DFtype, because that is surely not going
62c63f32 905 to lose any bits. Some day someone else can write a faster version
ade0e71b 906 that avoids converting to DFtype, and verify it really works right. */
907 DFtype a = original_a;
908 DFtype b;
909 UDItype v;
62c63f32 910
911 if (a < 0)
912 return 0;
913
914 /* Compute high word of result, as a flonum. */
915 b = (a / HIGH_WORD_COEFF);
ade0e71b 916 /* Convert that to fixed (but not to DItype!),
62c63f32 917 and shift it into the high word. */
ade0e71b 918 v = (USItype) b;
62c63f32 919 v <<= WORD_SIZE;
ade0e71b 920 /* Remove high part from the DFtype, leaving the low part as flonum. */
921 a -= (DFtype)v;
922 /* Convert that to fixed (but not to DItype!) and add it in.
62c63f32 923 Sometimes A comes out negative. This is significant, since
924 A has more bits than a long int does. */
925 if (a < 0)
ade0e71b 926 v -= (USItype) (- a);
62c63f32 927 else
ade0e71b 928 v += (USItype) a;
62c63f32 929 return v;
930}
931#endif
932
933#ifdef L_fixsfdi
ade0e71b 934DItype
935__fixsfdi (SFtype a)
62c63f32 936{
937 if (a < 0)
938 return - __fixunssfdi (-a);
939 return __fixunssfdi (a);
940}
941#endif
942
0e1cc047 943#if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
944#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
945#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
946#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
947
948XFtype
949__floatdixf (u)
950 DItype u;
951{
952 XFtype d;
953 SItype negate = 0;
954
955 if (u < 0)
956 u = -u, negate = 1;
957
958 d = (USItype) (u >> WORD_SIZE);
959 d *= HIGH_HALFWORD_COEFF;
960 d *= HIGH_HALFWORD_COEFF;
961 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
962
963 return (negate ? -d : d);
964}
965#endif
966
ade0e71b 967#if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
968#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
969#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
970#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
971
972TFtype
973__floatditf (u)
974 DItype u;
975{
976 TFtype d;
977 SItype negate = 0;
978
979 if (u < 0)
980 u = -u, negate = 1;
981
982 d = (USItype) (u >> WORD_SIZE);
983 d *= HIGH_HALFWORD_COEFF;
984 d *= HIGH_HALFWORD_COEFF;
985 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
986
987 return (negate ? -d : d);
988}
989#endif
990
62c63f32 991#ifdef L_floatdidf
ade0e71b 992#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
993#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
994#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
62c63f32 995
ade0e71b 996DFtype
62c63f32 997__floatdidf (u)
ade0e71b 998 DItype u;
62c63f32 999{
ade0e71b 1000 DFtype d;
1001 SItype negate = 0;
62c63f32 1002
1003 if (u < 0)
1004 u = -u, negate = 1;
1005
ade0e71b 1006 d = (USItype) (u >> WORD_SIZE);
62c63f32 1007 d *= HIGH_HALFWORD_COEFF;
1008 d *= HIGH_HALFWORD_COEFF;
ade0e71b 1009 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
62c63f32 1010
1011 return (negate ? -d : d);
1012}
1013#endif
1014
1015#ifdef L_floatdisf
ade0e71b 1016#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
1017#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
1018#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
b37ebc51 1019#define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
d16023de 1020
1021/* Define codes for all the float formats that we know of. Note
1022 that this is copied from real.h. */
1023
1024#define UNKNOWN_FLOAT_FORMAT 0
1025#define IEEE_FLOAT_FORMAT 1
1026#define VAX_FLOAT_FORMAT 2
1027#define IBM_FLOAT_FORMAT 3
1028
1029/* Default to IEEE float if not specified. Nearly all machines use it. */
1030#ifndef HOST_FLOAT_FORMAT
1031#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
1032#endif
1033
1034#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
b37ebc51 1035#define DF_SIZE 53
1036#define SF_SIZE 24
d16023de 1037#endif
1038
1039#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
b37ebc51 1040#define DF_SIZE 56
1041#define SF_SIZE 24
d16023de 1042#endif
1043
1044#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
b37ebc51 1045#define DF_SIZE 56
1046#define SF_SIZE 24
b37ebc51 1047#endif
62c63f32 1048
ade0e71b 1049SFtype
62c63f32 1050__floatdisf (u)
ade0e71b 1051 DItype u;
62c63f32 1052{
a06dece2 1053 /* Do the calculation in DFmode
1054 so that we don't lose any of the precision of the high word
1055 while multiplying it. */
1056 DFtype f;
ade0e71b 1057 SItype negate = 0;
62c63f32 1058
1059 if (u < 0)
1060 u = -u, negate = 1;
1061
b37ebc51 1062 /* Protect against double-rounding error.
1063 Represent any low-order bits, that might be truncated in DFmode,
1064 by a bit that won't be lost. The bit can go in anywhere below the
1065 rounding position of the SFmode. A fixed mask and bit position
1066 handles all usual configurations. It doesn't handle the case
1067 of 128-bit DImode, however. */
1068 if (DF_SIZE < DI_SIZE
1069 && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1070 {
1071#define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
1072 if (u >= ((UDItype) 1 << DF_SIZE))
1073 {
1074 if ((USItype) u & (REP_BIT - 1))
1075 u |= REP_BIT;
1076 }
1077 }
ade0e71b 1078 f = (USItype) (u >> WORD_SIZE);
62c63f32 1079 f *= HIGH_HALFWORD_COEFF;
1080 f *= HIGH_HALFWORD_COEFF;
ade0e71b 1081 f += (USItype) (u & (HIGH_WORD_COEFF - 1));
62c63f32 1082
a06dece2 1083 return (SFtype) (negate ? -f : f);
62c63f32 1084}
1085#endif
1086
0e1cc047 1087#if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
3873e172 1088/* Reenable the normal types, in case limits.h needs them. */
1089#undef char
1090#undef short
1091#undef int
1092#undef long
1093#undef unsigned
1094#undef float
1095#undef double
35e6d592 1096#undef MIN
1097#undef MAX
ab195728 1098#include <limits.h>
0e1cc047 1099
1100USItype
1101__fixunsxfsi (a)
1102 XFtype a;
1103{
1104 if (a >= - (DFtype) LONG_MIN)
1105 return (SItype) (a + LONG_MIN) - LONG_MIN;
1106 return (SItype) a;
1107}
1108#endif
1109
62c63f32 1110#ifdef L_fixunsdfsi
3873e172 1111/* Reenable the normal types, in case limits.h needs them. */
1112#undef char
1113#undef short
1114#undef int
1115#undef long
1116#undef unsigned
1117#undef float
1118#undef double
35e6d592 1119#undef MIN
1120#undef MAX
ab195728 1121#include <limits.h>
62c63f32 1122
ade0e71b 1123USItype
62c63f32 1124__fixunsdfsi (a)
ade0e71b 1125 DFtype a;
62c63f32 1126{
ade0e71b 1127 if (a >= - (DFtype) LONG_MIN)
62c63f32 1128 return (SItype) (a + LONG_MIN) - LONG_MIN;
1129 return (SItype) a;
1130}
1131#endif
1132
1133#ifdef L_fixunssfsi
3873e172 1134/* Reenable the normal types, in case limits.h needs them. */
1135#undef char
1136#undef short
1137#undef int
1138#undef long
1139#undef unsigned
1140#undef float
1141#undef double
35e6d592 1142#undef MIN
1143#undef MAX
ab195728 1144#include <limits.h>
62c63f32 1145
ade0e71b 1146USItype
1147__fixunssfsi (SFtype a)
62c63f32 1148{
ade0e71b 1149 if (a >= - (SFtype) LONG_MIN)
62c63f32 1150 return (SItype) (a + LONG_MIN) - LONG_MIN;
1151 return (SItype) a;
1152}
1153#endif
1154\f
ade0e71b 1155/* From here on down, the routines use normal data types. */
1156
1157#define SItype bogus_type
1158#define USItype bogus_type
1159#define DItype bogus_type
1160#define UDItype bogus_type
1161#define SFtype bogus_type
1162#define DFtype bogus_type
1163
1164#undef char
1165#undef short
1166#undef int
1167#undef long
1168#undef unsigned
1169#undef float
1170#undef double
e674bcb7 1171\f
1172#ifdef L__gcc_bcmp
1173
1174/* Like bcmp except the sign is meaningful.
c3418f42 1175 Result is negative if S1 is less than S2,
e674bcb7 1176 positive if S1 is greater, 0 if S1 and S2 are equal. */
1177
1178int
1179__gcc_bcmp (s1, s2, size)
e4ee4217 1180 unsigned char *s1, *s2;
e674bcb7 1181 size_t size;
1182{
1183 while (size > 0)
1184 {
e4ee4217 1185 unsigned char c1 = *s1++, c2 = *s2++;
e674bcb7 1186 if (c1 != c2)
1187 return c1 - c2;
1188 size--;
1189 }
1190 return 0;
1191}
ade0e71b 1192
e674bcb7 1193#endif
1194\f\f
aa743289 1195#ifdef L__dummy
1196void
1197__dummy () {}
1198#endif
1199
62c63f32 1200#ifdef L_varargs
1201#ifdef __i860__
2afc9c04 1202#if defined(__svr4__) || defined(__alliant__)
62c63f32 1203 asm (" .text");
1204 asm (" .align 4");
1205
ffcdee45 1206/* The Alliant needs the added underscore. */
62c63f32 1207 asm (".globl __builtin_saveregs");
1208asm ("__builtin_saveregs:");
ffcdee45 1209 asm (".globl ___builtin_saveregs");
1210asm ("___builtin_saveregs:");
1211
1212 asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
62c63f32 1213 asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
1214 area and also for a new va_list
1215 structure */
1216 /* Save all argument registers in the arg reg save area. The
1217 arg reg save area must have the following layout (according
1218 to the svr4 ABI):
1219
1220 struct {
1221 union {
1222 float freg[8];
1223 double dreg[4];
1224 } float_regs;
1225 long ireg[12];
1226 };
1227 */
1228
1229 asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
1230 asm (" fst.q %f12,16(%sp)");
1231
1232 asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
1233 asm (" st.l %r17,36(%sp)");
1234 asm (" st.l %r18,40(%sp)");
1235 asm (" st.l %r19,44(%sp)");
1236 asm (" st.l %r20,48(%sp)");
1237 asm (" st.l %r21,52(%sp)");
1238 asm (" st.l %r22,56(%sp)");
1239 asm (" st.l %r23,60(%sp)");
1240 asm (" st.l %r24,64(%sp)");
1241 asm (" st.l %r25,68(%sp)");
1242 asm (" st.l %r26,72(%sp)");
1243 asm (" st.l %r27,76(%sp)");
1244
1245 asm (" adds 80,%sp,%r16"); /* compute the address of the new
1246 va_list structure. Put in into
1247 r16 so that it will be returned
1248 to the caller. */
1249
1250 /* Initialize all fields of the new va_list structure. This
1251 structure looks like:
1252
1253 typedef struct {
1254 unsigned long ireg_used;
1255 unsigned long freg_used;
1256 long *reg_base;
1257 long *mem_ptr;
1258 } va_list;
1259 */
1260
1261 asm (" st.l %r0, 0(%r16)"); /* nfixed */
1262 asm (" st.l %r0, 4(%r16)"); /* nfloating */
1263 asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
1264 asm (" bri %r1"); /* delayed return */
1265 asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
1266
99bf8eeb 1267#else /* not __svr4__ */
a588d976 1268#if defined(__PARAGON__)
1269 /*
1270 * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1271 * and we stand a better chance of hooking into libraries
1272 * compiled by PGI. [andyp@ssd.intel.com]
1273 */
1274 asm (" .text");
1275 asm (" .align 4");
1276 asm (".globl __builtin_saveregs");
1277asm ("__builtin_saveregs:");
1278 asm (".globl ___builtin_saveregs");
1279asm ("___builtin_saveregs:");
1280
1281 asm (" andnot 0x0f,sp,sp"); /* round down to 16-byte boundary */
1282 asm (" adds -96,sp,sp"); /* allocate stack space for reg save
1283 area and also for a new va_list
1284 structure */
1285 /* Save all argument registers in the arg reg save area. The
1286 arg reg save area must have the following layout (according
1287 to the svr4 ABI):
1288
1289 struct {
1290 union {
1291 float freg[8];
1292 double dreg[4];
1293 } float_regs;
1294 long ireg[12];
1295 };
1296 */
1297
1298 asm (" fst.q f8, 0(sp)");
1299 asm (" fst.q f12,16(sp)");
1300 asm (" st.l r16,32(sp)");
1301 asm (" st.l r17,36(sp)");
1302 asm (" st.l r18,40(sp)");
1303 asm (" st.l r19,44(sp)");
1304 asm (" st.l r20,48(sp)");
1305 asm (" st.l r21,52(sp)");
1306 asm (" st.l r22,56(sp)");
1307 asm (" st.l r23,60(sp)");
1308 asm (" st.l r24,64(sp)");
1309 asm (" st.l r25,68(sp)");
1310 asm (" st.l r26,72(sp)");
1311 asm (" st.l r27,76(sp)");
1312
1313 asm (" adds 80,sp,r16"); /* compute the address of the new
1314 va_list structure. Put in into
1315 r16 so that it will be returned
1316 to the caller. */
1317
1318 /* Initialize all fields of the new va_list structure. This
1319 structure looks like:
1320
1321 typedef struct {
1322 unsigned long ireg_used;
1323 unsigned long freg_used;
1324 long *reg_base;
1325 long *mem_ptr;
1326 } va_list;
1327 */
1328
1329 asm (" st.l r0, 0(r16)"); /* nfixed */
1330 asm (" st.l r0, 4(r16)"); /* nfloating */
1331 asm (" st.l sp, 8(r16)"); /* __va_ctl points to __va_struct. */
1332 asm (" bri r1"); /* delayed return */
1333 asm (" st.l r28,12(r16)"); /* pointer to overflow args */
1334#else /* not __PARAGON__ */
62c63f32 1335 asm (" .text");
1336 asm (" .align 4");
1337
1338 asm (".globl ___builtin_saveregs");
1339 asm ("___builtin_saveregs:");
1340 asm (" mov sp,r30");
1341 asm (" andnot 0x0f,sp,sp");
1342 asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
1343
1344/* Fill in the __va_struct. */
1345 asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
1346 asm (" st.l r17, 4(sp)"); /* int fixed[12] */
1347 asm (" st.l r18, 8(sp)");
1348 asm (" st.l r19,12(sp)");
1349 asm (" st.l r20,16(sp)");
1350 asm (" st.l r21,20(sp)");
1351 asm (" st.l r22,24(sp)");
1352 asm (" st.l r23,28(sp)");
1353 asm (" st.l r24,32(sp)");
1354 asm (" st.l r25,36(sp)");
1355 asm (" st.l r26,40(sp)");
1356 asm (" st.l r27,44(sp)");
1357
1358 asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
1359 asm (" fst.q f12,64(sp)"); /* int floating[8] */
1360
1361/* Fill in the __va_ctl. */
1362 asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
1363 asm (" st.l r28,84(sp)"); /* pointer to more args */
1364 asm (" st.l r0, 88(sp)"); /* nfixed */
1365 asm (" st.l r0, 92(sp)"); /* nfloating */
1366
1367 asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
1368 asm (" bri r1");
1369 asm (" mov r30,sp");
1370 /* recover stack and pass address to start
1371 of data. */
a588d976 1372#endif /* not __PARAGON__ */
99bf8eeb 1373#endif /* not __svr4__ */
62c63f32 1374#else /* not __i860__ */
1375#ifdef __sparc__
b13ae905 1376 asm (".global __builtin_saveregs");
1377 asm ("__builtin_saveregs:");
62c63f32 1378 asm (".global ___builtin_saveregs");
1379 asm ("___builtin_saveregs:");
0cb31e48 1380#ifdef NEED_PROC_COMMAND
1381 asm (".proc 020");
b13ae905 1382#endif
62c63f32 1383 asm ("st %i0,[%fp+68]");
1384 asm ("st %i1,[%fp+72]");
1385 asm ("st %i2,[%fp+76]");
1386 asm ("st %i3,[%fp+80]");
1387 asm ("st %i4,[%fp+84]");
1388 asm ("retl");
1389 asm ("st %i5,[%fp+88]");
0cb31e48 1390#ifdef NEED_TYPE_COMMAND
1391 asm (".type __builtin_saveregs,#function");
1392 asm (".size __builtin_saveregs,.-__builtin_saveregs");
1393#endif
62c63f32 1394#else /* not __sparc__ */
1395#if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1396
1397 asm (" .text");
1398 asm (" .ent __builtin_saveregs");
1399 asm (" .globl __builtin_saveregs");
1400 asm ("__builtin_saveregs:");
1401 asm (" sw $4,0($30)");
1402 asm (" sw $5,4($30)");
1403 asm (" sw $6,8($30)");
1404 asm (" sw $7,12($30)");
1405 asm (" j $31");
1406 asm (" .end __builtin_saveregs");
a92771b8 1407#else /* not __mips__, etc. */
49fa6225 1408
1409void *
62c63f32 1410__builtin_saveregs ()
1411{
1412 abort ();
1413}
49fa6225 1414
62c63f32 1415#endif /* not __mips__ */
1416#endif /* not __sparc__ */
1417#endif /* not __i860__ */
1418#endif
1419\f
1420#ifdef L_eprintf
bae05c53 1421#ifndef inhibit_libc
b8bb46a6 1422
62c63f32 1423#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1424#include <stdio.h>
1425/* This is used by the `assert' macro. */
1426void
1427__eprintf (string, expression, line, filename)
0cb31e48 1428 const char *string;
1429 const char *expression;
62c63f32 1430 int line;
0cb31e48 1431 const char *filename;
62c63f32 1432{
1433 fprintf (stderr, string, expression, line, filename);
1434 fflush (stderr);
1435 abort ();
1436}
b8bb46a6 1437
1438#endif
62c63f32 1439#endif
1440
1441#ifdef L_bb
62c63f32 1442
543e7f6c 1443/* Structure emitted by -a */
62c63f32 1444struct bb
1445{
543e7f6c 1446 long zero_word;
1447 const char *filename;
1448 long *counts;
1449 long ncounts;
1450 struct bb *next;
1451 const unsigned long *addresses;
1452
1453 /* Older GCC's did not emit these fields. */
1454 long nwords;
1455 const char **functions;
1456 const long *line_nums;
1457 const char **filenames;
eb6cf4cb 1458 char *flags;
62c63f32 1459};
1460
543e7f6c 1461#ifdef BLOCK_PROFILER_CODE
1462BLOCK_PROFILER_CODE
1463#else
6e94b6ac 1464#ifndef inhibit_libc
543e7f6c 1465
1466/* Simple minded basic block profiling output dumper for
c3418f42 1467 systems that don't provide tcov support. At present,
543e7f6c 1468 it requires atexit and stdio. */
1469
92bc8f0b 1470#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
543e7f6c 1471#include <stdio.h>
e7cd69a0 1472char *ctime ();
62c63f32 1473
2fea28a7 1474#include "gbl-ctors.h"
543e7f6c 1475
5233d224 1476static struct bb *bb_head;
543e7f6c 1477
1478/* Return the number of digits needed to print a value */
1479/* __inline__ */ static int num_digits (long value, int base)
62c63f32 1480{
543e7f6c 1481 int minus = (value < 0 && base != 16);
1482 unsigned long v = (minus) ? -value : value;
1483 int ret = minus;
62c63f32 1484
543e7f6c 1485 do
1486 {
1487 v /= base;
1488 ret++;
1489 }
1490 while (v);
1491
1492 return ret;
62c63f32 1493}
1494
543e7f6c 1495void
1496__bb_exit_func (void)
1497{
1498 FILE *file = fopen ("bb.out", "a");
1499 long time_value;
1500
1501 if (!file)
1502 perror ("bb.out");
1503
1504 else
1505 {
1506 struct bb *ptr;
1507
1508 /* This is somewhat type incorrect, but it avoids worrying about
1509 exactly where time.h is included from. It should be ok unless
eb6cf4cb 1510 a void * differs from other pointer formats, or if sizeof (long)
543e7f6c 1511 is < sizeof (time_t). It would be nice if we could assume the
1512 use of rationale standards here. */
1513
eb6cf4cb 1514 time ((void *) &time_value);
543e7f6c 1515 fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1516
1517 /* We check the length field explicitly in order to allow compatibility
1518 with older GCC's which did not provide it. */
1519
a92771b8 1520 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
543e7f6c 1521 {
1522 int i;
1523 int func_p = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
1524 int line_p = (func_p && ptr->line_nums);
1525 int file_p = (func_p && ptr->filenames);
1526 long ncounts = ptr->ncounts;
1527 long cnt_max = 0;
1528 long line_max = 0;
1529 long addr_max = 0;
1530 int file_len = 0;
1531 int func_len = 0;
1532 int blk_len = num_digits (ncounts, 10);
1533 int cnt_len;
1534 int line_len;
1535 int addr_len;
1536
1537 fprintf (file, "File %s, %ld basic blocks \n\n",
1538 ptr->filename, ncounts);
1539
1540 /* Get max values for each field. */
1541 for (i = 0; i < ncounts; i++)
1542 {
1543 const char *p;
1544 int len;
1545
1546 if (cnt_max < ptr->counts[i])
1547 cnt_max = ptr->counts[i];
1548
1549 if (addr_max < ptr->addresses[i])
1550 addr_max = ptr->addresses[i];
1551
1552 if (line_p && line_max < ptr->line_nums[i])
1553 line_max = ptr->line_nums[i];
1554
1555 if (func_p)
1556 {
1557 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1558 len = strlen (p);
1559 if (func_len < len)
1560 func_len = len;
1561 }
1562
1563 if (file_p)
1564 {
1565 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1566 len = strlen (p);
1567 if (file_len < len)
1568 file_len = len;
1569 }
1570 }
1571
1572 addr_len = num_digits (addr_max, 16);
1573 cnt_len = num_digits (cnt_max, 10);
1574 line_len = num_digits (line_max, 10);
1575
1576 /* Now print out the basic block information. */
1577 for (i = 0; i < ncounts; i++)
1578 {
1579 fprintf (file,
dcaf9054 1580 " Block #%*d: executed %*ld time(s) address= 0x%.*lx",
543e7f6c 1581 blk_len, i+1,
1582 cnt_len, ptr->counts[i],
1583 addr_len, ptr->addresses[i]);
1584
1585 if (func_p)
dcaf9054 1586 fprintf (file, " function= %-*s", func_len,
543e7f6c 1587 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1588
1589 if (line_p)
36b7c7ce 1590 fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
543e7f6c 1591
1592 if (file_p)
dcaf9054 1593 fprintf (file, " file= %s",
543e7f6c 1594 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1595
1596 fprintf (file, "\n");
1597 }
1598
1599 fprintf (file, "\n");
1600 fflush (file);
1601 }
1602
1603 fprintf (file, "\n\n");
1604 fclose (file);
1605 }
1606}
1607
1608void
1609__bb_init_func (struct bb *blocks)
1610{
1611 /* User is supposed to check whether the first word is non-0,
a92771b8 1612 but just in case.... */
543e7f6c 1613
1614 if (blocks->zero_word)
1615 return;
1616
1617#ifdef ON_EXIT
1618 /* Initialize destructor. */
1619 if (!bb_head)
1620 ON_EXIT (__bb_exit_func, 0);
62c63f32 1621#endif
543e7f6c 1622
1623 /* Set up linked list. */
1624 blocks->zero_word = 1;
1625 blocks->next = bb_head;
1626 bb_head = blocks;
1627}
1628
eb6cf4cb 1629#ifndef MACHINE_STATE_SAVE
1630#define MACHINE_STATE_SAVE(ID)
1631#endif
1632#ifndef MACHINE_STATE_RESTORE
1633#define MACHINE_STATE_RESTORE(ID)
1634#endif
1635
1636#include <string.h>
1637
a92771b8 1638/* Number of buckets in hashtable of basic block addresses. */
eb6cf4cb 1639
1640#define BB_BUCKETS 311
1641
a92771b8 1642/* Maximum length of string in file bb.in. */
eb6cf4cb 1643
1644#define BBINBUFSIZE 500
1645
1646/* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
a92771b8 1647 "BBINBUFSIZE" but want to avoid trouble with preprocessors. */
eb6cf4cb 1648
1649#define BBINBUFSIZESTR "499"
1650
1651struct bb_edge
1652{
1653 struct bb_edge *next;
1654 unsigned long src_addr;
1655 unsigned long dst_addr;
1656 unsigned long count;
1657};
1658
1659enum bb_func_mode
1660{
1661 TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1662};
1663
1664struct bb_func
1665{
1666 struct bb_func *next;
1667 char *funcname;
1668 char *filename;
1669 enum bb_func_mode mode;
1670};
1671
1672/* This is the connection to the outside world.
1673 The BLOCK_PROFILER macro must set __bb.blocks
a92771b8 1674 and __bb.blockno. */
eb6cf4cb 1675
1676struct {
1677 unsigned long blockno;
1678 struct bb *blocks;
1679} __bb;
1680
1681/* Vars to store addrs of source and destination basic blocks
a92771b8 1682 of a jump. */
eb6cf4cb 1683
1684static unsigned long bb_src = 0;
1685static unsigned long bb_dst = 0;
1686
a92771b8 1687static FILE *bb_tracefile = (FILE *) 0;
1688static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1689static struct bb_func *bb_func_head = (struct bb_func *) 0;
eb6cf4cb 1690static unsigned long bb_callcount = 0;
1691static int bb_mode = 0;
1692
a92771b8 1693static unsigned long *bb_stack = (unsigned long *) 0;
eb6cf4cb 1694static size_t bb_stacksize = 0;
1695
1696static int reported = 0;
1697
1698/* Trace modes:
1699Always : Print execution frequencies of basic blocks
1700 to file bb.out.
1701bb_mode & 1 != 0 : Dump trace of basic blocks to file bbtrace[.gz]
1702bb_mode & 2 != 0 : Print jump frequencies to file bb.out.
1703bb_mode & 4 != 0 : Cut call instructions from basic block flow.
1704bb_mode & 8 != 0 : Insert return instructions in basic block flow.
1705*/
1706
1707#ifdef HAVE_POPEN
1708
1709/*#include <sys/types.h>*/
1710#include <sys/stat.h>
1711/*#include <malloc.h>*/
1712
a92771b8 1713/* Commands executed by gopen. */
eb6cf4cb 1714
1715#define GOPENDECOMPRESS "gzip -cd "
1716#define GOPENCOMPRESS "gzip -c >"
1717
1718/* Like fopen but pipes through gzip. mode may only be "r" or "w".
1719 If it does not compile, simply replace gopen by fopen and delete
a92771b8 1720 '.gz' from any first parameter to gopen. */
eb6cf4cb 1721
1722static FILE *
1723gopen (fn, mode)
1724 char *fn;
1725 char *mode;
1726{
1727 int use_gzip;
1728 char *p;
1729
1730 if (mode[1])
a92771b8 1731 return (FILE *) 0;
eb6cf4cb 1732
1733 if (mode[0] != 'r' && mode[0] != 'w')
a92771b8 1734 return (FILE *) 0;
eb6cf4cb 1735
1736 p = fn + strlen (fn)-1;
1737 use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z')) ||
1738 (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1739
1740 if (use_gzip)
1741 {
1742 if (mode[0]=='r')
1743 {
1744 FILE *f;
a92771b8 1745 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1746 + sizeof (GOPENDECOMPRESS));
eb6cf4cb 1747 strcpy (s, GOPENDECOMPRESS);
1748 strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1749 f = popen (s, mode);
1750 free (s);
1751 return f;
1752 }
1753
1754 else
1755 {
1756 FILE *f;
a92771b8 1757 char *s = (char *) malloc (sizeof (char) * strlen (fn)
1758 + sizeof (GOPENCOMPRESS));
eb6cf4cb 1759 strcpy (s, GOPENCOMPRESS);
1760 strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1761 if (!(f = popen (s, mode)))
1762 f = fopen (s, mode);
1763 free (s);
1764 return f;
1765 }
1766 }
1767
1768 else
1769 return fopen (fn, mode);
1770}
1771
1772static int
1773gclose (f)
1774 FILE *f;
1775{
1776 struct stat buf;
1777
1778 if (f != NULL)
1779 {
1780 if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1781 return pclose (f);
1782
1783 return fclose (f);
1784 }
1785 return 0;
1786}
1787
1788#endif /* HAVE_POPEN */
1789
a92771b8 1790/* Called once per program. */
eb6cf4cb 1791
1792static void
1793__bb_exit_trace_func ()
1794{
1795 FILE *file = fopen ("bb.out", "a");
1796 struct bb_func *f;
1797 struct bb_edge *e;
1798 struct bb *b;
1799
1800 if (!file)
1801 perror ("bb.out");
1802
1803 if (bb_mode & 1)
1804 {
1805 if (!bb_tracefile)
1806 perror ("bbtrace");
1807 else
1808#ifdef HAVE_POPEN
1809 gclose (bb_tracefile);
1810#else
1811 fclose (bb_tracefile);
1812#endif /* HAVE_POPEN */
1813 }
1814
a92771b8 1815 /* Check functions in `bb.in'. */
eb6cf4cb 1816
1817 if (file)
1818 {
1819 long time_value;
1820 const struct bb_func *p;
1821 int printed_something = 0;
1822 struct bb *ptr;
1823 long blk;
1824
a92771b8 1825 /* This is somewhat type incorrect. */
eb6cf4cb 1826 time ((void *) &time_value);
1827
a92771b8 1828 for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
eb6cf4cb 1829 {
a92771b8 1830 for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
eb6cf4cb 1831 {
a92771b8 1832 if (!ptr->filename || p->filename != (char *) 0 && strcmp (p->filename, ptr->filename))
eb6cf4cb 1833 continue;
1834 for (blk = 0; blk < ptr->ncounts; blk++)
1835 {
1836 if (!strcmp (p->funcname, ptr->functions[blk]))
1837 goto found;
1838 }
1839 }
1840
1841 if (!printed_something)
1842 {
1843 fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1844 printed_something = 1;
1845 }
1846
1847 fprintf (file, "\tFunction %s", p->funcname);
1848 if (p->filename)
1849 fprintf (file, " of file %s", p->filename);
1850 fprintf (file, "\n" );
1851
1852found: ;
1853 }
1854
1855 if (printed_something)
1856 fprintf (file, "\n");
1857
1858 }
1859
1860 if (bb_mode & 2)
1861 {
1862 if (!bb_hashbuckets)
1863 {
1864 if (!reported)
1865 {
1866 fprintf (stderr, "Profiler: out of memory\n");
1867 reported = 1;
1868 }
1869 return;
1870 }
1871
1872 else if (file)
1873 {
1874 long time_value;
1875 int i;
1876 unsigned long addr_max = 0;
1877 unsigned long cnt_max = 0;
1878 int cnt_len;
1879 int addr_len;
1880
1881 /* This is somewhat type incorrect, but it avoids worrying about
1882 exactly where time.h is included from. It should be ok unless
1883 a void * differs from other pointer formats, or if sizeof (long)
1884 is < sizeof (time_t). It would be nice if we could assume the
1885 use of rationale standards here. */
1886
1887 time ((void *) &time_value);
1888 fprintf (file, "Basic block jump tracing");
1889
1890 switch (bb_mode & 12)
1891 {
1892 case 0:
1893 fprintf (file, " (with call)");
1894 break;
1895
1896 case 4:
a92771b8 1897 /* Print nothing. */
eb6cf4cb 1898 break;
1899
1900 case 8:
1901 fprintf (file, " (with call & ret)");
1902 break;
1903
1904 case 12:
1905 fprintf (file, " (with ret)");
1906 break;
1907 }
1908
1909 fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1910
1911 for (i = 0; i < BB_BUCKETS; i++)
1912 {
1913 struct bb_edge *bucket = bb_hashbuckets[i];
1914 for ( ; bucket; bucket = bucket->next )
1915 {
1916 if (addr_max < bucket->src_addr)
1917 addr_max = bucket->src_addr;
1918 if (addr_max < bucket->dst_addr)
1919 addr_max = bucket->dst_addr;
1920 if (cnt_max < bucket->count)
1921 cnt_max = bucket->count;
1922 }
1923 }
1924 addr_len = num_digits (addr_max, 16);
1925 cnt_len = num_digits (cnt_max, 10);
1926
1927 for ( i = 0; i < BB_BUCKETS; i++)
1928 {
1929 struct bb_edge *bucket = bb_hashbuckets[i];
1930 for ( ; bucket; bucket = bucket->next )
1931 {
1932 fprintf (file, "Jump from block 0x%.*lx to "
1933 "block 0x%.*lx executed %*d time(s)\n",
1934 addr_len, bucket->src_addr,
1935 addr_len, bucket->dst_addr,
1936 cnt_len, bucket->count);
1937 }
1938 }
1939
1940 fprintf (file, "\n");
1941
1942 }
1943 }
1944
1945 if (file)
1946 fclose (file);
1947
a92771b8 1948 /* Free allocated memory. */
eb6cf4cb 1949
1950 f = bb_func_head;
1951 while (f)
1952 {
1953 struct bb_func *old = f;
1954
1955 f = f->next;
1956 if (old->funcname) free (old->funcname);
1957 if (old->filename) free (old->filename);
1958 free (old);
1959 }
1960
1961 if (bb_stack)
1962 free (bb_stack);
1963
1964 if (bb_hashbuckets)
1965 {
1966 int i;
1967
1968 for (i = 0; i < BB_BUCKETS; i++)
1969 {
1970 struct bb_edge *old, *bucket = bb_hashbuckets[i];
1971
1972 while (bucket)
1973 {
1974 old = bucket;
1975 bucket = bucket->next;
1976 free (old);
1977 }
1978 }
1979 free (bb_hashbuckets);
1980 }
1981
1982 for (b = bb_head; b; b = b->next)
1983 if (b->flags) free (b->flags);
1984}
1985
a92771b8 1986/* Called once per program. */
eb6cf4cb 1987
1988static void
1989__bb_init_prg ()
1990{
1991
1992 FILE *file;
1993 char buf[BBINBUFSIZE];
1994 const char *p;
1995 const char *pos;
1996 enum bb_func_mode m;
1997
1998#ifdef ON_EXIT
1999 /* Initialize destructor. */
2000 ON_EXIT (__bb_exit_func, 0);
2001#endif
2002
2003 if (!(file = fopen ("bb.in", "r")))
2004 return;
2005
2006 while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
2007 {
2008 p = buf;
2009 if (*p == '-')
2010 {
2011 m = TRACE_OFF;
2012 p++;
2013 }
2014 else
2015 {
2016 m = TRACE_ON;
2017 }
2018 if (!strcmp (p, "__bb_trace__"))
2019 bb_mode |= 1;
2020 else if (!strcmp (p, "__bb_jumps__"))
2021 bb_mode |= 2;
2022 else if (!strcmp (p, "__bb_hidecall__"))
2023 bb_mode |= 4;
2024 else if (!strcmp (p, "__bb_showret__"))
2025 bb_mode |= 8;
2026 else
2027 {
a92771b8 2028 struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
eb6cf4cb 2029 if (f)
2030 {
2031 unsigned long l;
2032 f->next = bb_func_head;
2033 if (pos = strchr (p, ':'))
2034 {
a92771b8 2035 if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
eb6cf4cb 2036 continue;
2037 strcpy (f->funcname, pos+1);
2038 l = pos-p;
a92771b8 2039 if ((f->filename = (char *) malloc (l+1)))
eb6cf4cb 2040 {
2041 strncpy (f->filename, p, l);
2042 f->filename[l] = '\0';
2043 }
2044 else
a92771b8 2045 f->filename = (char *) 0;
eb6cf4cb 2046 }
2047 else
2048 {
a92771b8 2049 if (!(f->funcname = (char *) malloc (strlen (p)+1)))
eb6cf4cb 2050 continue;
2051 strcpy (f->funcname, p);
a92771b8 2052 f->filename = (char *) 0;
eb6cf4cb 2053 }
2054 f->mode = m;
2055 bb_func_head = f;
2056 }
2057 }
2058 }
2059 fclose (file);
2060
2061#ifdef HAVE_POPEN
2062
2063 if (bb_mode & 1)
2064 bb_tracefile = gopen ("bbtrace.gz", "w");
2065
2066#else
2067
2068 if (bb_mode & 1)
2069 bb_tracefile = fopen ("bbtrace", "w");
2070
2071#endif /* HAVE_POPEN */
2072
2073 if (bb_mode & 2)
2074 {
2075 bb_hashbuckets = (struct bb_edge **)
2076 malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2077 if (bb_hashbuckets)
4905a506 2078 bzero ((char *) bb_hashbuckets, BB_BUCKETS);
eb6cf4cb 2079 }
2080
2081 if (bb_mode & 12)
2082 {
2083 bb_stacksize = 10;
2084 bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2085 }
2086
2087#ifdef ON_EXIT
2088 /* Initialize destructor. */
2089 ON_EXIT (__bb_exit_trace_func, 0);
2090#endif
2091
2092}
2093
a92771b8 2094/* Called upon entering a basic block. */
eb6cf4cb 2095
2096void
2097__bb_trace_func ()
2098{
2099 struct bb_edge *bucket;
2100
2101 MACHINE_STATE_SAVE("1")
2102
2103 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2104 goto skip;
2105
2106 bb_dst = __bb.blocks->addresses[__bb.blockno];
2107 __bb.blocks->counts[__bb.blockno]++;
2108
2109 if (bb_tracefile)
2110 {
2111 fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2112 }
2113
2114 if (bb_hashbuckets)
2115 {
2116 struct bb_edge **startbucket, **oldnext;
2117
2118 oldnext = startbucket =
a92771b8 2119 & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
eb6cf4cb 2120 bucket = *startbucket;
2121
2122 for (bucket = *startbucket; bucket;
2123 oldnext = &(bucket->next), bucket = *oldnext)
2124 {
2125 if ( bucket->src_addr == bb_src &&
2126 bucket->dst_addr == bb_dst )
2127 {
2128 bucket->count++;
2129 *oldnext = bucket->next;
2130 bucket->next = *startbucket;
2131 *startbucket = bucket;
2132 goto ret;
2133 }
2134 }
2135
2136 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2137
2138 if (!bucket)
2139 {
2140 if (!reported)
2141 {
2142 fprintf (stderr, "Profiler: out of memory\n");
2143 reported = 1;
2144 }
2145 }
2146
2147 else
2148 {
2149 bucket->src_addr = bb_src;
2150 bucket->dst_addr = bb_dst;
2151 bucket->next = *startbucket;
2152 *startbucket = bucket;
2153 bucket->count = 1;
2154 }
2155 }
2156
2157ret:
2158 bb_src = bb_dst;
2159
2160skip:
2161 ;
2162
2163 MACHINE_STATE_RESTORE("1")
2164
2165}
2166
a92771b8 2167/* Called when returning from a function and `__bb_showret__' is set. */
eb6cf4cb 2168
2169static void
2170__bb_trace_func_ret ()
2171{
2172 struct bb_edge *bucket;
2173
2174 if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2175 goto skip;
2176
2177 if (bb_hashbuckets)
2178 {
2179 struct bb_edge **startbucket, **oldnext;
2180
2181 oldnext = startbucket =
a92771b8 2182 & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
eb6cf4cb 2183 bucket = *startbucket;
2184
2185 for (bucket = *startbucket; bucket;
2186 oldnext = &(bucket->next), bucket = *oldnext)
2187 {
2188 if ( bucket->src_addr == bb_dst &&
2189 bucket->dst_addr == bb_src )
2190 {
2191 bucket->count++;
2192 *oldnext = bucket->next;
2193 bucket->next = *startbucket;
2194 *startbucket = bucket;
2195 goto ret;
2196 }
2197 }
2198
2199 bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2200
2201 if (!bucket)
2202 {
2203 if (!reported)
2204 {
2205 fprintf (stderr, "Profiler: out of memory\n");
2206 reported = 1;
2207 }
2208 }
2209
2210 else
2211 {
2212 bucket->src_addr = bb_dst;
2213 bucket->dst_addr = bb_src;
2214 bucket->next = *startbucket;
2215 *startbucket = bucket;
2216 bucket->count = 1;
2217 }
2218 }
2219
2220ret:
2221 bb_dst = bb_src;
2222
2223skip:
2224 ;
2225
2226}
2227
a92771b8 2228/* Called upon entering the first function of a file. */
eb6cf4cb 2229
2230static void
2231__bb_init_file (blocks)
2232 struct bb *blocks;
2233{
2234
2235 const struct bb_func *p;
2236 long blk, ncounts = blocks->ncounts;
2237 const char **functions = blocks->functions;
2238
2239 /* Set up linked list. */
2240 blocks->zero_word = 1;
2241 blocks->next = bb_head;
2242 bb_head = blocks;
2243
2244 blocks->flags = 0;
2245 if (!bb_func_head ||
a92771b8 2246 !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
eb6cf4cb 2247 return;
2248
2249 for (blk = 0; blk < ncounts; blk++)
2250 blocks->flags[blk] = 0;
2251
2252 for (blk = 0; blk < ncounts; blk++)
2253 {
2254 for (p = bb_func_head; p; p = p->next)
2255 {
2256 if (!strcmp (p->funcname, functions[blk]) &&
2257 (!p->filename || !strcmp (p->filename, blocks->filename)))
2258 {
2259 blocks->flags[blk] |= p->mode;
2260 }
2261 }
2262 }
2263
2264}
2265
a92771b8 2266/* Called when exiting from a function. */
eb6cf4cb 2267
2268void
2269__bb_trace_ret ()
2270{
2271
2272 MACHINE_STATE_SAVE("2")
2273
2274 if (bb_callcount)
2275 {
2276 if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2277 {
2278 bb_src = bb_stack[bb_callcount];
2279 if (bb_mode & 8)
2280 __bb_trace_func_ret ();
2281 }
2282
2283 bb_callcount -= 1;
2284 }
2285
2286 MACHINE_STATE_RESTORE("2")
2287
2288}
2289
a92771b8 2290/* Called when entering a function. */
eb6cf4cb 2291
2292void
2293__bb_init_trace_func (blocks, blockno)
2294 struct bb *blocks;
2295 unsigned long blockno;
2296{
2297 static int trace_init = 0;
2298
2299 MACHINE_STATE_SAVE("3")
2300
2301 if (!blocks->zero_word)
2302 {
2303 if (!trace_init)
2304 {
2305 trace_init = 1;
2306 __bb_init_prg ();
2307 }
2308 __bb_init_file (blocks);
2309 }
2310
2311 if (bb_callcount)
2312 {
2313
2314 bb_callcount += 1;
2315
2316 if (bb_mode & 12)
2317 {
2318 if (bb_callcount >= bb_stacksize)
2319 {
2320 size_t newsize = bb_callcount + 100;
2321
2322 bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2323 if (! bb_stack)
2324 {
2325 if (!reported)
2326 {
2327 fprintf (stderr, "Profiler: out of memory\n");
2328 reported = 1;
2329 }
2330 bb_stacksize = 0;
2331 goto stack_overflow;
2332 }
2333 bb_stacksize = newsize;
2334 }
2335 bb_stack[bb_callcount] = bb_src;
2336
2337 if (bb_mode & 4)
2338 bb_src = 0;
2339
2340 }
2341
2342stack_overflow:;
2343
2344 }
2345
2346 else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2347 {
2348 bb_callcount = 1;
2349 bb_src = 0;
2350
2351 if (bb_stack)
2352 bb_stack[bb_callcount] = bb_src;
2353 }
2354
2355 MACHINE_STATE_RESTORE("3")
2356}
2357
6e94b6ac 2358#endif /* not inhibit_libc */
2359#endif /* not BLOCK_PROFILER_CODE */
2360#endif /* L_bb */
62c63f32 2361\f
90d8d045 2362/* Default free-store management functions for C++, per sections 12.5 and
a92771b8 2363 17.3.3 of the Working Paper. */
62c63f32 2364
1e65f6cf 2365#ifdef L_op_new
90d8d045 2366/* operator new (size_t), described in 17.3.3.5. This function is used by
a92771b8 2367 C++ programs to allocate a block of memory to hold a single object. */
62c63f32 2368
90d8d045 2369typedef void (*vfp)(void);
62c63f32 2370extern vfp __new_handler;
2ed78eb4 2371extern void __default_new_handler (void);
62c63f32 2372
9a0ce7db 2373#ifdef WEAK_ALIAS
2374void * __builtin_new (size_t sz)
2375 __attribute__ ((weak, alias ("___builtin_new")));
2376void *
2377___builtin_new (size_t sz)
2378#else
62c63f32 2379void *
1e65f6cf 2380__builtin_new (size_t sz)
9a0ce7db 2381#endif
62c63f32 2382{
2383 void *p;
2ed78eb4 2384 vfp handler = (__new_handler) ? __new_handler : __default_new_handler;
62c63f32 2385
1b1e5c67 2386 /* malloc (0) is unpredictable; avoid it. */
2387 if (sz == 0)
2388 sz = 1;
7e1284c9 2389 p = (void *) malloc (sz);
929629d0 2390 while (p == 0)
2391 {
2ed78eb4 2392 (*handler) ();
929629d0 2393 p = (void *) malloc (sz);
2394 }
2395
62c63f32 2396 return p;
2397}
1e65f6cf 2398#endif /* L_op_new */
62c63f32 2399
bbf03111 2400#ifdef L_op_vnew
90d8d045 2401/* void * operator new [] (size_t), described in 17.3.3.6. This function
2402 is used by C++ programs to allocate a block of memory for an array. */
2403
2404extern void * __builtin_new (size_t);
2405
9a0ce7db 2406#ifdef WEAK_ALIAS
2407void * __builtin_vec_new (size_t sz)
2408 __attribute__ ((weak, alias ("___builtin_vec_new")));
2409void *
2410___builtin_vec_new (size_t sz)
2411#else
90d8d045 2412void *
2413__builtin_vec_new (size_t sz)
9a0ce7db 2414#endif
90d8d045 2415{
2416 return __builtin_new (sz);
2417}
bbf03111 2418#endif /* L_op_vnew */
90d8d045 2419
1e65f6cf 2420#ifdef L_new_handler
90d8d045 2421/* set_new_handler (fvoid_t *) and the default new handler, described in
2422 17.3.3.2 and 17.3.3.5. These functions define the result of a failure
a92771b8 2423 to allocate the amount of memory requested from operator new or new []. */
330e7c0c 2424
bae05c53 2425#ifndef inhibit_libc
330e7c0c 2426/* This gets us __GNU_LIBRARY__. */
eb213bff 2427#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
330e7c0c 2428#include <stdio.h>
2429
2430#ifdef __GNU_LIBRARY__
2431 /* Avoid forcing the library's meaning of `write' on the user program
1bc66e78 2432 by using the "internal" name (for use within the library) */
330e7c0c 2433#define write(fd, buf, n) __write((fd), (buf), (n))
2434#endif
bae05c53 2435#endif /* inhibit_libc */
330e7c0c 2436
62c63f32 2437typedef void (*vfp)(void);
90d8d045 2438void __default_new_handler (void);
62c63f32 2439
a92771b8 2440vfp __new_handler = (vfp) 0;
62c63f32 2441
62c63f32 2442vfp
90d8d045 2443set_new_handler (vfp handler)
62c63f32 2444{
2445 vfp prev_handler;
2446
2447 prev_handler = __new_handler;
929629d0 2448 if (handler == 0) handler = __default_new_handler;
62c63f32 2449 __new_handler = handler;
2450 return prev_handler;
2451}
2452
0cb31e48 2453#define MESSAGE "Virtual memory exceeded in `new'\n"
2454
90d8d045 2455void
929629d0 2456__default_new_handler ()
62c63f32 2457{
560e7d64 2458#ifndef inhibit_libc
62c63f32 2459 /* don't use fprintf (stderr, ...) because it may need to call malloc. */
2460 /* This should really print the name of the program, but that is hard to
2461 do. We need a standard, clean way to get at the name. */
0cb31e48 2462 write (2, MESSAGE, sizeof (MESSAGE));
560e7d64 2463#endif
62c63f32 2464 /* don't call exit () because that may call global destructors which
2465 may cause a loop. */
2466 _exit (-1);
2467}
2468#endif
62c63f32 2469
1e65f6cf 2470#ifdef L_op_delete
90d8d045 2471/* operator delete (void *), described in 17.3.3.3. This function is used
2472 by C++ programs to return to the free store a block of memory allocated
a92771b8 2473 as a single object. */
90d8d045 2474
9a0ce7db 2475#ifdef WEAK_ALIAS
2476void __builtin_delete (void *ptr)
2477 __attribute__ ((weak, alias ("___builtin_delete")));
2478void
2479___builtin_delete (void *ptr)
2480#else
62c63f32 2481void
1e65f6cf 2482__builtin_delete (void *ptr)
9a0ce7db 2483#endif
62c63f32 2484{
2485 if (ptr)
2486 free (ptr);
2487}
62c63f32 2488#endif
90d8d045 2489
bbf03111 2490#ifdef L_op_vdel
90d8d045 2491/* operator delete [] (void *), described in 17.3.3.4. This function is
2492 used by C++ programs to return to the free store a block of memory
a92771b8 2493 allocated as an array. */
90d8d045 2494
2495extern void __builtin_delete (void *);
2496
9a0ce7db 2497#ifdef WEAK_ALIAS
2498void __builtin_vec_delete (void *ptr)
2499 __attribute__ ((weak, alias ("___builtin_vec_delete")));
2500void
2501___builtin_vec_delete (void *ptr)
2502#else
90d8d045 2503void
2504__builtin_vec_delete (void *ptr)
9a0ce7db 2505#endif
90d8d045 2506{
2507 __builtin_delete (ptr);
2508}
2509#endif
2510
2511/* End of C++ free-store management functions */
1e65f6cf 2512\f
62c63f32 2513#ifdef L_shtab
2514unsigned int __shtab[] = {
2515 0x00000001, 0x00000002, 0x00000004, 0x00000008,
2516 0x00000010, 0x00000020, 0x00000040, 0x00000080,
2517 0x00000100, 0x00000200, 0x00000400, 0x00000800,
2518 0x00001000, 0x00002000, 0x00004000, 0x00008000,
2519 0x00010000, 0x00020000, 0x00040000, 0x00080000,
2520 0x00100000, 0x00200000, 0x00400000, 0x00800000,
2521 0x01000000, 0x02000000, 0x04000000, 0x08000000,
2522 0x10000000, 0x20000000, 0x40000000, 0x80000000
2523 };
2524#endif
2525\f
2526#ifdef L_clear_cache
2527/* Clear part of an instruction cache. */
2528
2529#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2530
2531void
2532__clear_cache (beg, end)
2533 char *beg, *end;
2534{
efa58f1a 2535#ifdef CLEAR_INSN_CACHE
2536 CLEAR_INSN_CACHE (beg, end);
2537#else
62c63f32 2538#ifdef INSN_CACHE_SIZE
2539 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
5233d224 2540 static int initialized;
62c63f32 2541 int offset;
10307b3e 2542 void *start_addr
2543 void *end_addr;
62c63f32 2544 typedef (*function_ptr) ();
2545
2546#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2547 /* It's cheaper to clear the whole cache.
2548 Put in a series of jump instructions so that calling the beginning
2549 of the cache will clear the whole thing. */
2550
2551 if (! initialized)
2552 {
2553 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2554 & -INSN_CACHE_LINE_WIDTH);
2555 int end_ptr = ptr + INSN_CACHE_SIZE;
2556
2557 while (ptr < end_ptr)
2558 {
2559 *(INSTRUCTION_TYPE *)ptr
2560 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2561 ptr += INSN_CACHE_LINE_WIDTH;
2562 }
a92771b8 2563 *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
62c63f32 2564
2565 initialized = 1;
2566 }
2567
2568 /* Call the beginning of the sequence. */
2569 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2570 & -INSN_CACHE_LINE_WIDTH))
2571 ());
2572
2573#else /* Cache is large. */
2574
2575 if (! initialized)
2576 {
2577 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2578 & -INSN_CACHE_LINE_WIDTH);
2579
2580 while (ptr < (int) array + sizeof array)
2581 {
2582 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2583 ptr += INSN_CACHE_LINE_WIDTH;
2584 }
2585
2586 initialized = 1;
2587 }
2588
2589 /* Find the location in array that occupies the same cache line as BEG. */
2590
2591 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2592 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2593 & -INSN_CACHE_PLANE_SIZE)
2594 + offset);
2595
2596 /* Compute the cache alignment of the place to stop clearing. */
2597#if 0 /* This is not needed for gcc's purposes. */
2598 /* If the block to clear is bigger than a cache plane,
2599 we clear the entire cache, and OFFSET is already correct. */
2600 if (end < beg + INSN_CACHE_PLANE_SIZE)
2601#endif
2602 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2603 & -INSN_CACHE_LINE_WIDTH)
2604 & (INSN_CACHE_PLANE_SIZE - 1));
2605
2606#if INSN_CACHE_DEPTH > 1
2607 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2608 if (end_addr <= start_addr)
2609 end_addr += INSN_CACHE_PLANE_SIZE;
2610
2611 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2612 {
2613 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2614 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2615
2616 while (addr != stop)
2617 {
2618 /* Call the return instruction at ADDR. */
2619 ((function_ptr) addr) ();
2620
2621 addr += INSN_CACHE_LINE_WIDTH;
2622 }
2623 }
2624#else /* just one plane */
2625 do
2626 {
2627 /* Call the return instruction at START_ADDR. */
2628 ((function_ptr) start_addr) ();
2629
2630 start_addr += INSN_CACHE_LINE_WIDTH;
2631 }
2632 while ((start_addr % INSN_CACHE_SIZE) != offset);
2633#endif /* just one plane */
2634#endif /* Cache is large */
2635#endif /* Cache exists */
efa58f1a 2636#endif /* CLEAR_INSN_CACHE */
62c63f32 2637}
2638
2639#endif /* L_clear_cache */
2640\f
2641#ifdef L_trampoline
2642
2643/* Jump to a trampoline, loading the static chain address. */
2644
e30b7e49 2645#ifdef WINNT
2646
2647long getpagesize()
2648{
2649#ifdef _ALPHA_
2650 return 8192;
2651#else
2652 return 4096;
2653#endif
2654}
2655
2656int mprotect(addr, len, prot)
2657 char *addr;
2658 int len, prot;
2659{
2660 int np, op;
2661
2662 if (prot == 7) np = 0x40;
2663 else if (prot == 5) np = 0x20;
2664 else if (prot == 4) np = 0x10;
2665 else if (prot == 3) np = 0x04;
2666 else if (prot == 1) np = 0x02;
2667 else if (prot == 0) np = 0x01;
2668
2669 if (VirtualProtect (addr, len, np, &op))
2670 return 0;
2671 else
2672 return -1;
2673
2674}
2675
2676#endif
2677
62c63f32 2678#ifdef TRANSFER_FROM_TRAMPOLINE
2679TRANSFER_FROM_TRAMPOLINE
2680#endif
2681
e4f25d58 2682#if defined (NeXT) && defined (__MACH__)
2683
2684/* Make stack executable so we can call trampolines on stack.
2685 This is called from INITIALIZE_TRAMPOLINE in next.h. */
4a197d83 2686#ifdef NeXTStep21
2687 #include <mach.h>
2688#else
2689 #include <mach/mach.h>
2690#endif
e4f25d58 2691
2692void
2693__enable_execute_stack (addr)
2694 char *addr;
2695{
2696 kern_return_t r;
2697 char *eaddr = addr + TRAMPOLINE_SIZE;
2698 vm_address_t a = (vm_address_t) addr;
2699
2700 /* turn on execute access on stack */
2701 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2702 if (r != KERN_SUCCESS)
2703 {
2704 mach_error("vm_protect VM_PROT_ALL", r);
2705 exit(1);
2706 }
2707
2708 /* We inline the i-cache invalidation for speed */
2709
2710#ifdef CLEAR_INSN_CACHE
2711 CLEAR_INSN_CACHE (addr, eaddr);
2712#else
2713 __clear_cache ((int) addr, (int) eaddr);
2714#endif
2715}
2716
2717#endif /* defined (NeXT) && defined (__MACH__) */
2718
62c63f32 2719#ifdef __convex__
2720
2721/* Make stack executable so we can call trampolines on stack.
2722 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
2723
2724#include <sys/mman.h>
2725#include <sys/vmparam.h>
2726#include <machine/machparam.h>
2727
2728void
2729__enable_execute_stack ()
2730{
2731 int fp;
2732 static unsigned lowest = USRSTACK;
2733 unsigned current = (unsigned) &fp & -NBPG;
2734
2735 if (lowest > current)
2736 {
2737 unsigned len = lowest - current;
2738 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2739 lowest = current;
2740 }
2741
a92771b8 2742 /* Clear instruction cache in case an old trampoline is in it. */
62c63f32 2743 asm ("pich");
2744}
2745#endif /* __convex__ */
b13ae905 2746
767a6cf5 2747#ifdef __DOLPHIN__
2748
a92771b8 2749/* Modified from the convex -code above. */
767a6cf5 2750
2751#include <sys/param.h>
2752#include <errno.h>
2753#include <sys/m88kbcs.h>
2754
2755void
2756__enable_execute_stack ()
2757{
2758 int save_errno;
2759 static unsigned long lowest = USRSTACK;
2760 unsigned long current = (unsigned long) &save_errno & -NBPC;
2761
2762 /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2763 address is seen as 'negative'. That is the case with the stack. */
2764
2765 save_errno=errno;
2766 if (lowest > current)
2767 {
2768 unsigned len=lowest-current;
2769 memctl(current,len,MCT_TEXT);
2770 lowest = current;
2771 }
2772 else
2773 memctl(current,NBPC,MCT_TEXT);
2774 errno=save_errno;
2775}
2776
2777#endif /* __DOLPHIN__ */
2778
b13ae905 2779#ifdef __pyr__
2780
eb213bff 2781#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
b13ae905 2782#include <stdio.h>
2783#include <sys/mman.h>
2784#include <sys/types.h>
2785#include <sys/param.h>
2786#include <sys/vmmac.h>
2787
2788/* Modified from the convex -code above.
a92771b8 2789 mremap promises to clear the i-cache. */
b13ae905 2790
2791void
2792__enable_execute_stack ()
2793{
2794 int fp;
2795 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2796 PROT_READ|PROT_WRITE|PROT_EXEC))
2797 {
2798 perror ("mprotect in __enable_execute_stack");
2799 fflush (stderr);
2800 abort ();
2801 }
2802}
2803#endif /* __pyr__ */
62c63f32 2804#endif /* L_trampoline */
2805\f
2806#ifdef L__main
2807
2808#include "gbl-ctors.h"
0c945479 2809/* Some systems use __main in a way incompatible with its use in gcc, in these
2810 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2811 give the same symbol without quotes for an alternative entry point. You
a92771b8 2812 must define both, or neither. */
0c945479 2813#ifndef NAME__MAIN
2814#define NAME__MAIN "__main"
2815#define SYMBOL__MAIN __main
2816#endif
62c63f32 2817
8313a782 2818#ifdef INIT_SECTION_ASM_OP
2819#undef HAS_INIT_SECTION
2820#define HAS_INIT_SECTION
2821#endif
2822
2823#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
62c63f32 2824/* Run all the global destructors on exit from the program. */
2825
2826void
2827__do_global_dtors ()
2828{
3a158972 2829#ifdef DO_GLOBAL_DTORS_BODY
2830 DO_GLOBAL_DTORS_BODY;
2831#else
a0b2c9a2 2832 func_ptr *p;
2833 for (p = __DTOR_LIST__ + 1; *p; )
2834 (*p++) ();
3a158972 2835#endif
62c63f32 2836}
b7c87ff2 2837#endif
62c63f32 2838
8313a782 2839#ifndef HAS_INIT_SECTION
62c63f32 2840/* Run all the global constructors on entry to the program. */
2841
42d70a07 2842#ifndef ON_EXIT
62c63f32 2843#define ON_EXIT(a, b)
2844#else
2845/* Make sure the exit routine is pulled in to define the globals as
2846 bss symbols, just in case the linker does not automatically pull
2847 bss definitions from the library. */
2848
2849extern int _exit_dummy_decl;
2850int *_exit_dummy_ref = &_exit_dummy_decl;
2851#endif /* ON_EXIT */
2852
2853void
2854__do_global_ctors ()
2855{
2856 DO_GLOBAL_CTORS_BODY;
42d70a07 2857 ON_EXIT (__do_global_dtors, 0);
62c63f32 2858}
8313a782 2859#endif /* no HAS_INIT_SECTION */
62c63f32 2860
8313a782 2861#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
62c63f32 2862/* Subroutine called automatically by `main'.
2863 Compiling a global function named `main'
2864 produces an automatic call to this function at the beginning.
2865
2866 For many systems, this routine calls __do_global_ctors.
2867 For systems which support a .init section we use the .init section
2868 to run __do_global_ctors, so we need not do anything here. */
2869
2870void
0c945479 2871SYMBOL__MAIN ()
62c63f32 2872{
2873 /* Support recursive calls to `main': run initializers just once. */
5233d224 2874 static int initialized;
62c63f32 2875 if (! initialized)
2876 {
2877 initialized = 1;
2878 __do_global_ctors ();
2879 }
2880}
8313a782 2881#endif /* no HAS_INIT_SECTION or INVOKE__main */
62c63f32 2882
2883#endif /* L__main */
2884\f
a0f2694a 2885#ifdef L_ctors
62c63f32 2886
2887#include "gbl-ctors.h"
2888
2889/* Provide default definitions for the lists of constructors and
2890 destructors, so that we don't get linker errors. These symbols are
2891 intentionally bss symbols, so that gld and/or collect will provide
2892 the right values. */
2893
2894/* We declare the lists here with two elements each,
2895 so that they are valid empty lists if no other definition is loaded. */
b13ae905 2896#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
4f49af36 2897#if defined(__NeXT__) || defined(_AIX)
d069195c 2898/* After 2.3, try this definition on all systems. */
2899func_ptr __CTOR_LIST__[2] = {0, 0};
2900func_ptr __DTOR_LIST__[2] = {0, 0};
2901#else
62c63f32 2902func_ptr __CTOR_LIST__[2];
2903func_ptr __DTOR_LIST__[2];
d069195c 2904#endif
b13ae905 2905#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
a0f2694a 2906#endif /* L_ctors */
2907\f
2908#ifdef L_exit
2909
2910#include "gbl-ctors.h"
62c63f32 2911
2fea28a7 2912#ifdef NEED_ATEXIT
2913# ifdef ON_EXIT
2914# undef ON_EXIT
2915# endif
2916int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
2917#endif
2918
62c63f32 2919#ifndef ON_EXIT
2920
2fea28a7 2921#ifdef NEED_ATEXIT
2922# include <errno.h>
2923
2924extern void *malloc ();
2925extern void *realloc ();
2926
2927static func_ptr *atexit_chain = NULL;
2928static long atexit_chain_length = 0;
2929static volatile long last_atexit_chain_slot = -1;
2930
2931int atexit (func_ptr func)
2932{
2933 if (++last_atexit_chain_slot == atexit_chain_length)
2934 {
2935 atexit_chain_length += 32;
2936 if (atexit_chain)
2937 atexit_chain = realloc (atexit_chain,
2938 atexit_chain_length * sizeof (func_ptr));
2939 else
2940 atexit_chain = malloc (atexit_chain_length * sizeof (func_ptr));
2941 if (! atexit_chain)
2942 {
2943 atexit_chain_length = 0;
2944 last_atexit_chain_slot = -1;
2945 errno = ENOMEM;
2946 return (-1);
2947 }
2948 }
2949 atexit_chain[last_atexit_chain_slot] = func;
2950 return (0);
2951}
2952#endif /* NEED_ATEXIT */
2953
62c63f32 2954/* If we have no known way of registering our own __do_global_dtors
2955 routine so that it will be invoked at program exit time, then we
2956 have to define our own exit routine which will get this to happen. */
2957
2958extern void __do_global_dtors ();
2959extern void _cleanup ();
e4ffd279 2960extern void _exit () __attribute__ ((noreturn));
62c63f32 2961
2962void
2963exit (status)
2964 int status;
2965{
edda1d14 2966#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
2fea28a7 2967#ifdef NEED_ATEXIT
2968 if (atexit_chain)
2969 {
2970 for ( ; last_atexit_chain_slot-- >= 0; )
2971 {
2972 (*atexit_chain[last_atexit_chain_slot + 1]) ();
2973 atexit_chain[last_atexit_chain_slot + 1] = NULL;
2974 }
2975 free (atexit_chain);
2976 atexit_chain = NULL;
2977 }
2978#else /* No NEED_ATEXIT */
62c63f32 2979 __do_global_dtors ();
2fea28a7 2980#endif /* No NEED_ATEXIT */
8e5cc536 2981#endif
62c63f32 2982#ifdef EXIT_BODY
2983 EXIT_BODY;
2984#else
2985 _cleanup ();
2986#endif
2987 _exit (status);
2988}
2989
2990#else
2991int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
2992#endif
2993
2994#endif /* L_exit */
2995\f
99962ae2 2996#ifdef L_eh
485aaaaf 2997
2998#ifdef EH_TABLE_LOOKUP
2999
3000EH_TABLE_LOOKUP
3001
3002#else
3003
99962ae2 3004typedef struct {
3005 void *start;
3006 void *end;
3007 void *exception_handler;
3008} exception_table;
3009
3010struct exception_table_node {
3011 exception_table *table;
3012 void *start;
3013 void *end;
3014 struct exception_table_node *next;
3015};
3016
5233d224 3017static int except_table_pos;
3018static void *except_pc;
3019static struct exception_table_node *exception_table_list;
99962ae2 3020
3021static exception_table *
3022find_exception_table (pc)
a92771b8 3023 void *pc;
99962ae2 3024{
3025 register struct exception_table_node *table = exception_table_list;
3026 for ( ; table != 0; table = table->next)
3027 {
3028 if (table->start <= pc && table->end > pc)
3029 return table->table;
3030 }
3031 return 0;
3032}
3033
3034/* this routine takes a pc, and the address of the exception handler associated
3035 with the closest exception table handler entry associated with that PC,
3036 or 0 if there are no table entries the PC fits in. The algorithm works
3037 something like this:
3038
3039 while(current_entry exists) {
3040 if(current_entry.start < pc )
3041 current_entry = next_entry;
3042 else {
3043 if(prev_entry.start <= pc && prev_entry.end > pc) {
3044 save pointer to prev_entry;
3045 return prev_entry.exception_handler;
3046 }
3047 else return 0;
3048 }
3049 }
3050 return 0;
3051
3052 Assuming a correctly sorted table (ascending order) this routine should
b090827b 3053 return the tightest match...
99962ae2 3054
3055 In the advent of a tie, we have to give the last entry, as it represents
a92771b8 3056 an inner block. */
99962ae2 3057
3058void *
3059__find_first_exception_table_match(pc)
3060void *pc;
3061{
3062 exception_table *table = find_exception_table (pc);
3063 int pos = 0;
3064 int best = 0;
3065 if (table == 0)
a92771b8 3066 return (void *) 0;
99962ae2 3067#if 0
a92771b8 3068 printf ("find_first_exception_table_match(): pc = %x!\n", pc);
99962ae2 3069#endif
3070
3071 except_pc = pc;
3072
3073#if 0
3074 /* We can't do this yet, as we don't know that the table is sorted. */
3075 do {
3076 ++pos;
3077 if (table[pos].start > except_pc)
3078 /* found the first table[pos].start > except_pc, so the previous
3079 entry better be the one we want! */
3080 break;
a92771b8 3081 } while (table[pos].exception_handler != (void *) -1);
99962ae2 3082
3083 --pos;
3084 if (table[pos].start <= except_pc && table[pos].end > except_pc)
3085 {
3086 except_table_pos = pos;
3087#if 0
a92771b8 3088 printf ("find_first_eh_table_match(): found match: %x\n", table[pos].exception_handler);
99962ae2 3089#endif
3090 return table[pos].exception_handler;
3091 }
3092#else
a92771b8 3093 while (table[++pos].exception_handler != (void *) -1) {
99962ae2 3094 if (table[pos].start <= except_pc && table[pos].end > except_pc)
3095 {
3096 /* This can apply. Make sure it is better or as good as the previous
3097 best. */
a92771b8 3098 /* The best one ends first. */
99962ae2 3099 if (best == 0 || (table[pos].end <= table[best].end
3100 /* The best one starts last. */
3101 && table[pos].start >= table[best].start))
3102 best = pos;
3103 }
3104 }
3105 if (best != 0)
3106 return table[best].exception_handler;
3107#endif
3108
3109#if 0
485aaaaf 3110 printf ("find_first_eh_table_match(): else: returning NULL!\n");
99962ae2 3111#endif
485aaaaf 3112 return (void *) 0;
99962ae2 3113}
3114
3115void
3116__register_exceptions (exception_table *table)
3117{
bb42cfad 3118 struct exception_table_node *node;
99962ae2 3119 exception_table *range = table + 1;
bb42cfad 3120
a92771b8 3121 if (range->start == (void *) -1)
bb42cfad 3122 return;
3123
a92771b8 3124 node = (struct exception_table_node *)
bb42cfad 3125 malloc (sizeof (struct exception_table_node));
99962ae2 3126 node->table = table;
3127
3128 /* This look can be optimized away either if the table
a92771b8 3129 is sorted, or if we pass in extra parameters. */
99962ae2 3130 node->start = range->start;
3131 node->end = range->end;
a92771b8 3132 for (range++ ; range->start != (void *) (-1); range++)
99962ae2 3133 {
3134 if (range->start < node->start)
3135 node->start = range->start;
8b5eb22c 3136 if (range->end > node->end)
99962ae2 3137 node->end = range->end;
3138 }
3139
3140 node->next = exception_table_list;
3141 exception_table_list = node;
3142}
485aaaaf 3143#endif
3144
3145void *
3146__throw_type_match (void *catch_type, void *throw_type, void *obj)
3147{
3148#if 0
3149 printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3150 catch_type, throw_type);
3151#endif
3152 if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3153 return obj;
3154 return 0;
3155}
8b5eb22c 3156
c2f6861c 3157/* Throw stub routine.
3158
3159 This is work in progress, but not completed yet. */
3160
3161void
3162__throw ()
3163{
3164 abort ();
3165}
3166
3167/* This value identifies the place from which an exception is being
3168 thrown. */
3169
3170void *__eh_pc;
3171
14cfd367 3172void
3173__empty ()
3174{
3175}
3176
c14211ff 3177#if #machine(i386)
8b5eb22c 3178void
3179__unwind_function(void *ptr)
3180{
3181 asm("movl 8(%esp),%ecx");
3182 /* Undo current frame */
3183 asm("movl %ebp,%esp");
3184 asm("popl %ebp");
96c8d78f 3185 /* like ret, but stay here */
8b5eb22c 3186 asm("addl $4,%esp");
3187
a92771b8 3188 /* Now, undo previous frame. */
8b5eb22c 3189 /* This is a test routine, as we have to dynamically probe to find out
a92771b8 3190 what to pop for certain, this is just a guess. */
8b5eb22c 3191 asm("leal -16(%ebp),%esp");
e8618d8a 3192 asm("pop %ebx");
3193 asm("pop %esi");
3194 asm("pop %edi");
8b5eb22c 3195 asm("movl %ebp,%esp");
3196 asm("popl %ebp");
3197
3198 asm("movl %ecx,0(%esp)");
3199 asm("ret");
3200}
3d7c6a2b 3201#elif #machine(rs6000) && !defined _ARCH_PPC
20c30d66 3202__unwind_function(void *ptr)
3203{
3204 asm("mr 31,1");
3205 asm("l 1,0(1)");
3206 asm("l 31,-4(1)");
3207 asm("# br");
3208
3209 asm("mr 31,1");
3210 asm("l 1,0(1)");
a92771b8 3211 /* use 31 as a scratch register to restore the link register. */
20c30d66 3212 asm("l 31, 8(1);mtlr 31 # l lr,8(1)");
3213 asm("l 31,-4(1)");
3214 asm("# br");
3215 asm("mtctr 3;bctr # b 3");
3216}
3d7c6a2b 3217#elif (#machine(rs6000) || #machine(powerpc)) && defined _ARCH_PPC
fa23dea9 3218__unwind_function(void *ptr)
3219{
3220 asm("mr 31,1");
3221 asm("lwz 1,0(1)");
3222 asm("lwz 31,-4(1)");
3223 asm("# br");
3224
3225 asm("mr 31,1");
3226 asm("lwz 1,0(1)");
a92771b8 3227 /* use 31 as a scratch register to restore the link register. */
fa23dea9 3228 asm("lwz 31, 8(1);mtlr 31 # l lr,8(1)");
3229 asm("lwz 31,-4(1)");
3230 asm("# br");
3231 asm("mtctr 3;bctr # b 3");
3232}
fd4acd92 3233#elif #machine(vax)
3234__unwind_function(void *ptr)
3235{
3236 __label__ return_again;
3237
3238 /* Replace our frame's return address with the label below.
3239 During execution, we will first return here instead of to
3240 caller, then second return takes caller's frame off the stack.
3241 Two returns matches two actual calls, so is less likely to
3242 confuse debuggers. `16' corresponds to RETURN_ADDRESS_OFFSET. */
3243 __asm ("movl %0,16(fp)" : : "p" (&& return_again));
3244 return;
3245
3246 return_again:
3247 return;
3248}
e8618d8a 3249#else
3250__unwind_function(void *ptr)
3251{
3252 abort ();
3253}
fa23dea9 3254#endif /* powerpc */
99962ae2 3255#endif /* L_eh */
1b43d412 3256\f
3257#ifdef L_pure
560e7d64 3258#ifndef inhibit_libc
3259/* This gets us __GNU_LIBRARY__. */
3260#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
3261#include <stdio.h>
3262
3263#ifdef __GNU_LIBRARY__
3264 /* Avoid forcing the library's meaning of `write' on the user program
3265 by using the "internal" name (for use within the library) */
3266#define write(fd, buf, n) __write((fd), (buf), (n))
3267#endif
3268#endif /* inhibit_libc */
3269
1b43d412 3270#define MESSAGE "pure virtual method called\n"
560e7d64 3271
1b43d412 3272void
3273__pure_virtual ()
3274{
560e7d64 3275#ifndef inhibit_libc
1b43d412 3276 write (2, MESSAGE, sizeof (MESSAGE) - 1);
560e7d64 3277#endif
1b43d412 3278 _exit (-1);
3279}
3280#endif