]> gcc.gnu.org Git - gcc.git/blame - gcc/libgcc2.c
Make more robust in two places.
[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. */
3/* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
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
19the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21/* As a special exception, if you link this library with files
22 compiled with GCC to produce an executable, this does not cause
23 the resulting executable to be covered by the GNU General Public License.
24 This exception does not however invalidate any other reasons why
25 the executable file might be covered by the GNU General Public License. */
26
27/* It is incorrect to include config.h here, because this file is being
28 compiled for the target, and hence definitions concerning only the host
29 do not apply. */
30
0dadecf6 31#include "tconfig.h"
bfe655f9 32#include "machmode.h"
b335c2cc 33#ifndef L_trampoline
203b91b9 34#include "gstddef.h"
b335c2cc 35#endif
203b91b9
RS
36
37/* Don't use `fancy_abort' here even if config.h says to use it. */
38#ifdef abort
39#undef abort
40#endif
41
ab495388
RS
42/* In the first part of this file, we are interfacing to calls generated
43 by the compiler itself. These calls pass values into these routines
44 which have very specific modes (rather than very specific types), and
45 these compiler-generated calls also expect any return values to have
46 very specific modes (rather than very specific types). Thus, we need
47 to avoid using regular C language type names in this part of the file
48 because the sizes for those types can be configured to be anything.
49 Instead we use the following special type names. */
50
51typedef unsigned int UQItype __attribute__ ((mode (QI)));
52typedef int SItype __attribute__ ((mode (SI)));
53typedef unsigned int USItype __attribute__ ((mode (SI)));
54typedef int DItype __attribute__ ((mode (DI)));
55typedef unsigned int UDItype __attribute__ ((mode (DI)));
56typedef float SFtype __attribute__ ((mode (SF)));
57typedef float DFtype __attribute__ ((mode (DF)));
e0799b34 58#if LONG_DOUBLE_TYPE_SIZE == 96
ab495388 59typedef float XFtype __attribute__ ((mode (XF)));
258d1356
CH
60#endif
61#if LONG_DOUBLE_TYPE_SIZE == 128
ab495388 62typedef float TFtype __attribute__ ((mode (TF)));
258d1356 63#endif
ab495388 64
4be7c28f
JW
65#if BITS_PER_WORD==16
66typedef int word_type __attribute__ ((mode (HI)));
67#endif
68#if BITS_PER_WORD==32
69typedef int word_type __attribute__ ((mode (SI)));
70#endif
71#if BITS_PER_WORD==64
72typedef int word_type __attribute__ ((mode (DI)));
73#endif
74
a1c37766 75/* Make sure that we don't accidentally use any normal C language built-in
ab495388
RS
76 type names in the first part of this file. Instead we want to use *only*
77 the type names defined above. The following macro definitions insure
19197caa 78 that if we *do* accidentally use some normal C language built-in type name,
ab495388
RS
79 we will get a syntax error. */
80
81#define char bogus_type
82#define short bogus_type
83#define int bogus_type
84#define long bogus_type
85#define unsigned bogus_type
86#define float bogus_type
87#define double bogus_type
88
89#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
90
91/* DIstructs are pairs of SItype values in the order determined by
203b91b9
RS
92 WORDS_BIG_ENDIAN. */
93
94#if WORDS_BIG_ENDIAN
ab495388 95 struct DIstruct {SItype high, low;};
203b91b9 96#else
ab495388 97 struct DIstruct {SItype low, high;};
203b91b9
RS
98#endif
99
ab495388
RS
100/* We need this union to unpack/pack DImode values, since we don't have
101 any arithmetic yet. Incoming DImode parameters are stored into the
102 `ll' field, and the unpacked result is read from the struct `s'. */
203b91b9
RS
103
104typedef union
105{
ab495388
RS
106 struct DIstruct s;
107 DItype ll;
108} DIunion;
203b91b9 109
3904131a 110#if defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)
203b91b9
RS
111
112#include "longlong.h"
113
114#endif /* udiv or mul */
115
ab495388
RS
116extern DItype __fixunssfdi (SFtype a);
117extern DItype __fixunsdfdi (DFtype a);
96fc2623 118#if LONG_DOUBLE_TYPE_SIZE == 96
f70ad14c 119extern DItype __fixunsxfdi (XFtype a);
96fc2623
RS
120#endif
121#if LONG_DOUBLE_TYPE_SIZE == 128
cc3cdac3 122extern DItype __fixunstfdi (TFtype a);
96fc2623 123#endif
203b91b9
RS
124\f
125#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
126#if defined (L_divdi3) || defined (L_moddi3)
127static inline
128#endif
ab495388 129DItype
203b91b9 130__negdi2 (u)
ab495388 131 DItype u;
203b91b9 132{
ab495388
RS
133 DIunion w;
134 DIunion uu;
203b91b9
RS
135
136 uu.ll = u;
137
138 w.s.low = -uu.s.low;
ab495388 139 w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
203b91b9
RS
140
141 return w.ll;
142}
143#endif
144\f
145#ifdef L_lshldi3
ab495388 146DItype
203b91b9 147__lshldi3 (u, b)
ab495388
RS
148 DItype u;
149 SItype b;
203b91b9 150{
ab495388
RS
151 DIunion w;
152 SItype bm;
153 DIunion uu;
203b91b9
RS
154
155 if (b == 0)
156 return u;
157
158 uu.ll = u;
159
ab495388 160 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
203b91b9
RS
161 if (bm <= 0)
162 {
163 w.s.low = 0;
ab495388 164 w.s.high = (USItype)uu.s.low << -bm;
203b91b9
RS
165 }
166 else
167 {
ab495388
RS
168 USItype carries = (USItype)uu.s.low >> bm;
169 w.s.low = (USItype)uu.s.low << b;
170 w.s.high = ((USItype)uu.s.high << b) | carries;
203b91b9
RS
171 }
172
173 return w.ll;
174}
175#endif
176
177#ifdef L_lshrdi3
ab495388 178DItype
203b91b9 179__lshrdi3 (u, b)
ab495388
RS
180 DItype u;
181 SItype b;
203b91b9 182{
ab495388
RS
183 DIunion w;
184 SItype bm;
185 DIunion uu;
203b91b9
RS
186
187 if (b == 0)
188 return u;
189
190 uu.ll = u;
191
ab495388 192 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
203b91b9
RS
193 if (bm <= 0)
194 {
195 w.s.high = 0;
ab495388 196 w.s.low = (USItype)uu.s.high >> -bm;
203b91b9
RS
197 }
198 else
199 {
ab495388
RS
200 USItype carries = (USItype)uu.s.high << bm;
201 w.s.high = (USItype)uu.s.high >> b;
202 w.s.low = ((USItype)uu.s.low >> b) | carries;
203b91b9
RS
203 }
204
205 return w.ll;
206}
207#endif
208
209#ifdef L_ashldi3
ab495388 210DItype
203b91b9 211__ashldi3 (u, b)
ab495388
RS
212 DItype u;
213 SItype b;
203b91b9 214{
ab495388
RS
215 DIunion w;
216 SItype bm;
217 DIunion uu;
203b91b9
RS
218
219 if (b == 0)
220 return u;
221
222 uu.ll = u;
223
ab495388 224 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
203b91b9
RS
225 if (bm <= 0)
226 {
227 w.s.low = 0;
ab495388 228 w.s.high = (USItype)uu.s.low << -bm;
203b91b9
RS
229 }
230 else
231 {
ab495388
RS
232 USItype carries = (USItype)uu.s.low >> bm;
233 w.s.low = (USItype)uu.s.low << b;
234 w.s.high = ((USItype)uu.s.high << b) | carries;
203b91b9
RS
235 }
236
237 return w.ll;
238}
239#endif
240
241#ifdef L_ashrdi3
ab495388 242DItype
203b91b9 243__ashrdi3 (u, b)
ab495388
RS
244 DItype u;
245 SItype b;
203b91b9 246{
ab495388
RS
247 DIunion w;
248 SItype bm;
249 DIunion uu;
203b91b9
RS
250
251 if (b == 0)
252 return u;
253
254 uu.ll = u;
255
ab495388 256 bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
203b91b9
RS
257 if (bm <= 0)
258 {
259 /* w.s.high = 1..1 or 0..0 */
ab495388 260 w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
203b91b9
RS
261 w.s.low = uu.s.high >> -bm;
262 }
263 else
264 {
ab495388 265 USItype carries = (USItype)uu.s.high << bm;
203b91b9 266 w.s.high = uu.s.high >> b;
ab495388 267 w.s.low = ((USItype)uu.s.low >> b) | carries;
203b91b9
RS
268 }
269
270 return w.ll;
271}
272#endif
273\f
aa66bd06
RS
274#ifdef L_ffsdi2
275DItype
276__ffsdi2 (u)
277 DItype u;
278{
279 DIunion uu, w;
280 uu.ll = u;
281 w.s.high = 0;
282 w.s.low = ffs (uu.s.low);
283 if (w.s.low != 0)
de6cbba6 284 return w.ll;
aa66bd06
RS
285 w.s.low = ffs (uu.s.high);
286 if (w.s.low != 0)
287 {
288 w.s.low += BITS_PER_UNIT * sizeof (SItype);
de6cbba6 289 return w.ll;
aa66bd06 290 }
de6cbba6 291 return w.ll;
aa66bd06
RS
292}
293#endif
294\f
203b91b9 295#ifdef L_muldi3
ab495388 296DItype
203b91b9 297__muldi3 (u, v)
ab495388 298 DItype u, v;
203b91b9 299{
ab495388
RS
300 DIunion w;
301 DIunion uu, vv;
203b91b9
RS
302
303 uu.ll = u,
304 vv.ll = v;
305
306 w.ll = __umulsidi3 (uu.s.low, vv.s.low);
ab495388
RS
307 w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
308 + (USItype) uu.s.high * (USItype) vv.s.low);
203b91b9
RS
309
310 return w.ll;
311}
312#endif
313\f
3904131a 314#ifdef L_udiv_w_sdiv
431b1ee0 315USItype
3904131a 316__udiv_w_sdiv (rp, a1, a0, d)
431b1ee0
TG
317 USItype *rp, a1, a0, d;
318{
319 USItype q, r;
320 USItype c0, c1, b1;
321
322 if ((SItype) d >= 0)
323 {
7bc7d45a 324 if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
431b1ee0
TG
325 {
326 /* dividend, divisor, and quotient are nonnegative */
327 sdiv_qrnnd (q, r, a1, a0, d);
328 }
329 else
330 {
331 /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
7bc7d45a 332 sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
431b1ee0
TG
333 /* Divide (c1*2^32 + c0) by d */
334 sdiv_qrnnd (q, r, c1, c0, d);
335 /* Add 2^31 to quotient */
7bc7d45a 336 q += (USItype) 1 << (SI_TYPE_SIZE - 1);
431b1ee0
TG
337 }
338 }
339 else
340 {
341 b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
342 c1 = a1 >> 1; /* A/2 */
7bc7d45a 343 c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
431b1ee0
TG
344
345 if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
346 {
347 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
348
349 r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
350 if ((d & 1) != 0)
351 {
352 if (r >= q)
353 r = r - q;
354 else if (q - r <= d)
355 {
356 r = r - q + d;
357 q--;
358 }
359 else
360 {
361 r = r - q + 2*d;
362 q -= 2;
363 }
364 }
365 }
366 else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
367 {
368 c1 = (b1 - 1) - c1;
369 c0 = ~c0; /* logical NOT */
370
371 sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
372
373 q = ~q; /* (A/2)/b1 */
374 r = (b1 - 1) - r;
375
376 r = 2*r + (a0 & 1); /* A/(2*b1) */
377
378 if ((d & 1) != 0)
379 {
380 if (r >= q)
381 r = r - q;
382 else if (q - r <= d)
383 {
384 r = r - q + d;
385 q--;
386 }
387 else
388 {
389 r = r - q + 2*d;
390 q -= 2;
391 }
392 }
393 }
394 else /* Implies c1 = b1 */
395 { /* Hence a1 = d - 1 = 2*b1 - 1 */
396 if (a0 >= -d)
397 {
398 q = -1;
399 r = a0 + d;
400 }
401 else
402 {
403 q = -2;
404 r = a0 + 2*d;
405 }
406 }
407 }
408
409 *rp = r;
410 return q;
411}
412#endif
413\f
203b91b9 414#ifdef L_udivmoddi4
ab495388 415static const UQItype __clz_tab[] =
203b91b9
RS
416{
417 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,
418 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,
419 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,
420 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,
421 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,
422 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,
423 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,
424 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,
425};
426
ab495388 427UDItype
203b91b9 428__udivmoddi4 (n, d, rp)
ab495388
RS
429 UDItype n, d;
430 UDItype *rp;
203b91b9 431{
ab495388
RS
432 DIunion ww;
433 DIunion nn, dd;
434 DIunion rr;
435 USItype d0, d1, n0, n1, n2;
436 USItype q0, q1;
437 USItype b, bm;
203b91b9
RS
438
439 nn.ll = n;
440 dd.ll = d;
441
442 d0 = dd.s.low;
443 d1 = dd.s.high;
444 n0 = nn.s.low;
445 n1 = nn.s.high;
446
447#if !UDIV_NEEDS_NORMALIZATION
448 if (d1 == 0)
449 {
450 if (d0 > n1)
451 {
452 /* 0q = nn / 0D */
453
454 udiv_qrnnd (q0, n0, n1, n0, d0);
455 q1 = 0;
456
457 /* Remainder in n0. */
458 }
459 else
460 {
461 /* qq = NN / 0d */
462
463 if (d0 == 0)
464 d0 = 1 / d0; /* Divide intentionally by zero. */
465
466 udiv_qrnnd (q1, n1, 0, n1, d0);
467 udiv_qrnnd (q0, n0, n1, n0, d0);
468
469 /* Remainder in n0. */
470 }
471
472 if (rp != 0)
473 {
474 rr.s.low = n0;
475 rr.s.high = 0;
476 *rp = rr.ll;
477 }
478 }
479
480#else /* UDIV_NEEDS_NORMALIZATION */
481
482 if (d1 == 0)
483 {
484 if (d0 > n1)
485 {
486 /* 0q = nn / 0D */
487
488 count_leading_zeros (bm, d0);
489
490 if (bm != 0)
491 {
492 /* Normalize, i.e. make the most significant bit of the
493 denominator set. */
494
495 d0 = d0 << bm;
ab495388 496 n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
203b91b9
RS
497 n0 = n0 << bm;
498 }
499
500 udiv_qrnnd (q0, n0, n1, n0, d0);
501 q1 = 0;
502
503 /* Remainder in n0 >> bm. */
504 }
505 else
506 {
507 /* qq = NN / 0d */
508
509 if (d0 == 0)
510 d0 = 1 / d0; /* Divide intentionally by zero. */
511
512 count_leading_zeros (bm, d0);
513
514 if (bm == 0)
515 {
516 /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
517 conclude (the most significant bit of n1 is set) /\ (the
518 leading quotient digit q1 = 1).
519
520 This special case is necessary, not an optimization.
ab495388 521 (Shifts counts of SI_TYPE_SIZE are undefined.) */
203b91b9
RS
522
523 n1 -= d0;
524 q1 = 1;
525 }
526 else
527 {
528 /* Normalize. */
529
ab495388 530 b = SI_TYPE_SIZE - bm;
203b91b9
RS
531
532 d0 = d0 << bm;
533 n2 = n1 >> b;
534 n1 = (n1 << bm) | (n0 >> b);
535 n0 = n0 << bm;
536
537 udiv_qrnnd (q1, n1, n2, n1, d0);
538 }
539
540 /* n1 != d0... */
541
542 udiv_qrnnd (q0, n0, n1, n0, d0);
543
544 /* Remainder in n0 >> bm. */
545 }
546
547 if (rp != 0)
548 {
549 rr.s.low = n0 >> bm;
550 rr.s.high = 0;
551 *rp = rr.ll;
552 }
553 }
554#endif /* UDIV_NEEDS_NORMALIZATION */
555
556 else
557 {
558 if (d1 > n1)
559 {
560 /* 00 = nn / DD */
561
562 q0 = 0;
563 q1 = 0;
564
565 /* Remainder in n1n0. */
566 if (rp != 0)
567 {
568 rr.s.low = n0;
569 rr.s.high = n1;
570 *rp = rr.ll;
571 }
572 }
573 else
574 {
575 /* 0q = NN / dd */
576
577 count_leading_zeros (bm, d1);
578 if (bm == 0)
579 {
580 /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
581 conclude (the most significant bit of n1 is set) /\ (the
582 quotient digit q0 = 0 or 1).
583
584 This special case is necessary, not an optimization. */
585
586 /* The condition on the next line takes advantage of that
587 n1 >= d1 (true due to program flow). */
588 if (n1 > d1 || n0 >= d0)
589 {
590 q0 = 1;
591 sub_ddmmss (n1, n0, n1, n0, d1, d0);
592 }
593 else
594 q0 = 0;
595
596 q1 = 0;
597
598 if (rp != 0)
599 {
600 rr.s.low = n0;
601 rr.s.high = n1;
602 *rp = rr.ll;
603 }
604 }
605 else
606 {
ab495388 607 USItype m1, m0;
203b91b9
RS
608 /* Normalize. */
609
ab495388 610 b = SI_TYPE_SIZE - bm;
203b91b9
RS
611
612 d1 = (d1 << bm) | (d0 >> b);
613 d0 = d0 << bm;
614 n2 = n1 >> b;
615 n1 = (n1 << bm) | (n0 >> b);
616 n0 = n0 << bm;
617
618 udiv_qrnnd (q0, n1, n2, n1, d1);
619 umul_ppmm (m1, m0, q0, d0);
620
621 if (m1 > n1 || (m1 == n1 && m0 > n0))
622 {
623 q0--;
624 sub_ddmmss (m1, m0, m1, m0, d1, d0);
625 }
626
627 q1 = 0;
628
629 /* Remainder in (n1n0 - m1m0) >> bm. */
630 if (rp != 0)
631 {
632 sub_ddmmss (n1, n0, n1, n0, m1, m0);
633 rr.s.low = (n1 << b) | (n0 >> bm);
634 rr.s.high = n1 >> bm;
635 *rp = rr.ll;
636 }
637 }
638 }
639 }
640
641 ww.s.low = q0;
642 ww.s.high = q1;
643 return ww.ll;
644}
645#endif
646
647#ifdef L_divdi3
ab495388 648UDItype __udivmoddi4 ();
f70ad14c 649
ab495388 650DItype
203b91b9 651__divdi3 (u, v)
ab495388 652 DItype u, v;
203b91b9 653{
ab495388
RS
654 SItype c = 0;
655 DIunion uu, vv;
656 DItype w;
203b91b9
RS
657
658 uu.ll = u;
659 vv.ll = v;
660
661 if (uu.s.high < 0)
662 c = ~c,
663 uu.ll = __negdi2 (uu.ll);
664 if (vv.s.high < 0)
665 c = ~c,
666 vv.ll = __negdi2 (vv.ll);
667
ab495388 668 w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
203b91b9
RS
669 if (c)
670 w = __negdi2 (w);
671
672 return w;
673}
674#endif
675
676#ifdef L_moddi3
ab495388
RS
677UDItype __udivmoddi4 ();
678DItype
203b91b9 679__moddi3 (u, v)
ab495388 680 DItype u, v;
203b91b9 681{
ab495388
RS
682 SItype c = 0;
683 DIunion uu, vv;
684 DItype w;
203b91b9
RS
685
686 uu.ll = u;
687 vv.ll = v;
688
689 if (uu.s.high < 0)
690 c = ~c,
691 uu.ll = __negdi2 (uu.ll);
692 if (vv.s.high < 0)
693 vv.ll = __negdi2 (vv.ll);
694
695 (void) __udivmoddi4 (uu.ll, vv.ll, &w);
696 if (c)
697 w = __negdi2 (w);
698
699 return w;
700}
701#endif
702
703#ifdef L_umoddi3
ab495388
RS
704UDItype __udivmoddi4 ();
705UDItype
203b91b9 706__umoddi3 (u, v)
ab495388 707 UDItype u, v;
203b91b9 708{
ab495388 709 DItype w;
203b91b9
RS
710
711 (void) __udivmoddi4 (u, v, &w);
712
713 return w;
714}
715#endif
716
717#ifdef L_udivdi3
ab495388
RS
718UDItype __udivmoddi4 ();
719UDItype
203b91b9 720__udivdi3 (n, d)
ab495388 721 UDItype n, d;
203b91b9 722{
ab495388 723 return __udivmoddi4 (n, d, (UDItype *) 0);
203b91b9
RS
724}
725#endif
726\f
727#ifdef L_cmpdi2
4be7c28f 728word_type
203b91b9 729__cmpdi2 (a, b)
ab495388 730 DItype a, b;
203b91b9 731{
ab495388 732 DIunion au, bu;
203b91b9
RS
733
734 au.ll = a, bu.ll = b;
735
736 if (au.s.high < bu.s.high)
737 return 0;
738 else if (au.s.high > bu.s.high)
739 return 2;
ab495388 740 if ((USItype) au.s.low < (USItype) bu.s.low)
203b91b9 741 return 0;
ab495388 742 else if ((USItype) au.s.low > (USItype) bu.s.low)
203b91b9
RS
743 return 2;
744 return 1;
745}
746#endif
747
748#ifdef L_ucmpdi2
4be7c28f 749word_type
203b91b9 750__ucmpdi2 (a, b)
ab495388 751 DItype a, b;
203b91b9 752{
ab495388 753 DIunion au, bu;
203b91b9
RS
754
755 au.ll = a, bu.ll = b;
756
ab495388 757 if ((USItype) au.s.high < (USItype) bu.s.high)
203b91b9 758 return 0;
ab495388 759 else if ((USItype) au.s.high > (USItype) bu.s.high)
203b91b9 760 return 2;
ab495388 761 if ((USItype) au.s.low < (USItype) bu.s.low)
203b91b9 762 return 0;
ab495388 763 else if ((USItype) au.s.low > (USItype) bu.s.low)
203b91b9
RS
764 return 2;
765 return 1;
766}
767#endif
768\f
ab495388
RS
769#if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
770#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
771#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
772
773DItype
774__fixunstfdi (a)
775 TFtype a;
776{
777 TFtype b;
778 UDItype v;
779
780 if (a < 0)
781 return 0;
782
783 /* Compute high word of result, as a flonum. */
784 b = (a / HIGH_WORD_COEFF);
785 /* Convert that to fixed (but not to DItype!),
786 and shift it into the high word. */
787 v = (USItype) b;
788 v <<= WORD_SIZE;
789 /* Remove high part from the TFtype, leaving the low part as flonum. */
790 a -= (TFtype)v;
791 /* Convert that to fixed (but not to DItype!) and add it in.
792 Sometimes A comes out negative. This is significant, since
793 A has more bits than a long int does. */
794 if (a < 0)
795 v -= (USItype) (- a);
796 else
797 v += (USItype) a;
798 return v;
799}
800#endif
801
802#if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
803DItype
804__fixtfdi (a)
805 TFtype a;
806{
807 if (a < 0)
808 return - __fixunstfdi (-a);
809 return __fixunstfdi (a);
810}
811#endif
812
e0799b34
RS
813#if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
814#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
815#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
816
817DItype
818__fixunsxfdi (a)
819 XFtype a;
820{
821 XFtype b;
822 UDItype v;
823
824 if (a < 0)
825 return 0;
826
827 /* Compute high word of result, as a flonum. */
828 b = (a / HIGH_WORD_COEFF);
829 /* Convert that to fixed (but not to DItype!),
830 and shift it into the high word. */
831 v = (USItype) b;
832 v <<= WORD_SIZE;
833 /* Remove high part from the XFtype, leaving the low part as flonum. */
834 a -= (XFtype)v;
835 /* Convert that to fixed (but not to DItype!) and add it in.
836 Sometimes A comes out negative. This is significant, since
837 A has more bits than a long int does. */
838 if (a < 0)
839 v -= (USItype) (- a);
840 else
841 v += (USItype) a;
842 return v;
843}
844#endif
845
846#if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
847DItype
848__fixxfdi (a)
849 XFtype a;
850{
851 if (a < 0)
852 return - __fixunsxfdi (-a);
853 return __fixunsxfdi (a);
854}
855#endif
856
203b91b9 857#ifdef L_fixunsdfdi
ab495388
RS
858#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
859#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
203b91b9 860
ab495388 861DItype
203b91b9 862__fixunsdfdi (a)
ab495388 863 DFtype a;
203b91b9 864{
ab495388
RS
865 DFtype b;
866 UDItype v;
203b91b9
RS
867
868 if (a < 0)
869 return 0;
870
871 /* Compute high word of result, as a flonum. */
872 b = (a / HIGH_WORD_COEFF);
ab495388 873 /* Convert that to fixed (but not to DItype!),
203b91b9 874 and shift it into the high word. */
ab495388 875 v = (USItype) b;
203b91b9 876 v <<= WORD_SIZE;
ab495388
RS
877 /* Remove high part from the DFtype, leaving the low part as flonum. */
878 a -= (DFtype)v;
879 /* Convert that to fixed (but not to DItype!) and add it in.
203b91b9
RS
880 Sometimes A comes out negative. This is significant, since
881 A has more bits than a long int does. */
882 if (a < 0)
ab495388 883 v -= (USItype) (- a);
203b91b9 884 else
ab495388 885 v += (USItype) a;
203b91b9
RS
886 return v;
887}
888#endif
889
890#ifdef L_fixdfdi
ab495388 891DItype
203b91b9 892__fixdfdi (a)
ab495388 893 DFtype a;
203b91b9
RS
894{
895 if (a < 0)
896 return - __fixunsdfdi (-a);
897 return __fixunsdfdi (a);
898}
899#endif
900
901#ifdef L_fixunssfdi
ab495388
RS
902#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
903#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
203b91b9 904
ab495388
RS
905DItype
906__fixunssfdi (SFtype original_a)
203b91b9 907{
ab495388 908 /* Convert the SFtype to a DFtype, because that is surely not going
203b91b9 909 to lose any bits. Some day someone else can write a faster version
ab495388
RS
910 that avoids converting to DFtype, and verify it really works right. */
911 DFtype a = original_a;
912 DFtype b;
913 UDItype v;
203b91b9
RS
914
915 if (a < 0)
916 return 0;
917
918 /* Compute high word of result, as a flonum. */
919 b = (a / HIGH_WORD_COEFF);
ab495388 920 /* Convert that to fixed (but not to DItype!),
203b91b9 921 and shift it into the high word. */
ab495388 922 v = (USItype) b;
203b91b9 923 v <<= WORD_SIZE;
ab495388
RS
924 /* Remove high part from the DFtype, leaving the low part as flonum. */
925 a -= (DFtype)v;
926 /* Convert that to fixed (but not to DItype!) and add it in.
203b91b9
RS
927 Sometimes A comes out negative. This is significant, since
928 A has more bits than a long int does. */
929 if (a < 0)
ab495388 930 v -= (USItype) (- a);
203b91b9 931 else
ab495388 932 v += (USItype) a;
203b91b9
RS
933 return v;
934}
935#endif
936
937#ifdef L_fixsfdi
ab495388
RS
938DItype
939__fixsfdi (SFtype a)
203b91b9
RS
940{
941 if (a < 0)
942 return - __fixunssfdi (-a);
943 return __fixunssfdi (a);
944}
945#endif
946
e0799b34
RS
947#if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
948#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
949#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
950#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
951
952XFtype
953__floatdixf (u)
954 DItype u;
955{
956 XFtype d;
957 SItype negate = 0;
958
959 if (u < 0)
960 u = -u, negate = 1;
961
962 d = (USItype) (u >> WORD_SIZE);
963 d *= HIGH_HALFWORD_COEFF;
964 d *= HIGH_HALFWORD_COEFF;
965 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
966
967 return (negate ? -d : d);
968}
969#endif
970
ab495388
RS
971#if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
972#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
973#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
974#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
975
976TFtype
977__floatditf (u)
978 DItype u;
979{
980 TFtype d;
981 SItype negate = 0;
982
983 if (u < 0)
984 u = -u, negate = 1;
985
986 d = (USItype) (u >> WORD_SIZE);
987 d *= HIGH_HALFWORD_COEFF;
988 d *= HIGH_HALFWORD_COEFF;
989 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
990
991 return (negate ? -d : d);
992}
993#endif
994
203b91b9 995#ifdef L_floatdidf
ab495388
RS
996#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
997#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
998#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
203b91b9 999
ab495388 1000DFtype
203b91b9 1001__floatdidf (u)
ab495388 1002 DItype u;
203b91b9 1003{
ab495388
RS
1004 DFtype d;
1005 SItype negate = 0;
203b91b9
RS
1006
1007 if (u < 0)
1008 u = -u, negate = 1;
1009
ab495388 1010 d = (USItype) (u >> WORD_SIZE);
203b91b9
RS
1011 d *= HIGH_HALFWORD_COEFF;
1012 d *= HIGH_HALFWORD_COEFF;
ab495388 1013 d += (USItype) (u & (HIGH_WORD_COEFF - 1));
203b91b9
RS
1014
1015 return (negate ? -d : d);
1016}
1017#endif
1018
1019#ifdef L_floatdisf
ab495388
RS
1020#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
1021#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
1022#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
203b91b9 1023
ab495388 1024SFtype
203b91b9 1025__floatdisf (u)
ab495388 1026 DItype u;
203b91b9 1027{
56b03d5f
RS
1028 /* Do the calculation in DFmode
1029 so that we don't lose any of the precision of the high word
1030 while multiplying it. */
1031 DFtype f;
ab495388 1032 SItype negate = 0;
203b91b9
RS
1033
1034 if (u < 0)
1035 u = -u, negate = 1;
1036
ab495388 1037 f = (USItype) (u >> WORD_SIZE);
203b91b9
RS
1038 f *= HIGH_HALFWORD_COEFF;
1039 f *= HIGH_HALFWORD_COEFF;
ab495388 1040 f += (USItype) (u & (HIGH_WORD_COEFF - 1));
203b91b9 1041
56b03d5f 1042 return (SFtype) (negate ? -f : f);
203b91b9
RS
1043}
1044#endif
1045
e0799b34
RS
1046#if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
1047#include "glimits.h"
1048
1049USItype
1050__fixunsxfsi (a)
1051 XFtype a;
1052{
1053 if (a >= - (DFtype) LONG_MIN)
1054 return (SItype) (a + LONG_MIN) - LONG_MIN;
1055 return (SItype) a;
1056}
1057#endif
1058
203b91b9 1059#ifdef L_fixunsdfsi
0c7b7f30 1060#include "glimits.h"
203b91b9 1061
ab495388 1062USItype
203b91b9 1063__fixunsdfsi (a)
ab495388 1064 DFtype a;
203b91b9 1065{
ab495388 1066 if (a >= - (DFtype) LONG_MIN)
203b91b9
RS
1067 return (SItype) (a + LONG_MIN) - LONG_MIN;
1068 return (SItype) a;
1069}
1070#endif
1071
1072#ifdef L_fixunssfsi
0c7b7f30 1073#include "glimits.h"
203b91b9 1074
ab495388
RS
1075USItype
1076__fixunssfsi (SFtype a)
203b91b9 1077{
ab495388 1078 if (a >= - (SFtype) LONG_MIN)
203b91b9
RS
1079 return (SItype) (a + LONG_MIN) - LONG_MIN;
1080 return (SItype) a;
1081}
1082#endif
1083\f
ab495388
RS
1084/* From here on down, the routines use normal data types. */
1085
1086#define SItype bogus_type
1087#define USItype bogus_type
1088#define DItype bogus_type
1089#define UDItype bogus_type
1090#define SFtype bogus_type
1091#define DFtype bogus_type
1092
1093#undef char
1094#undef short
1095#undef int
1096#undef long
1097#undef unsigned
1098#undef float
1099#undef double
9bd23d2c
RS
1100\f
1101#ifdef L__gcc_bcmp
1102
1103/* Like bcmp except the sign is meaningful.
1104 Reult is negative if S1 is less than S2,
1105 positive if S1 is greater, 0 if S1 and S2 are equal. */
1106
1107int
1108__gcc_bcmp (s1, s2, size)
78e33213 1109 unsigned char *s1, *s2;
9bd23d2c
RS
1110 size_t size;
1111{
1112 while (size > 0)
1113 {
78e33213 1114 unsigned char c1 = *s1++, c2 = *s2++;
9bd23d2c
RS
1115 if (c1 != c2)
1116 return c1 - c2;
1117 size--;
1118 }
1119 return 0;
1120}
ab495388 1121
9bd23d2c
RS
1122#endif
1123\f\f
203b91b9
RS
1124#ifdef L_varargs
1125#ifdef __i860__
600032fc 1126#if defined(__svr4__) || defined(__alliant__)
203b91b9
RS
1127 asm (" .text");
1128 asm (" .align 4");
1129
27d21d32 1130/* The Alliant needs the added underscore. */
203b91b9
RS
1131 asm (".globl __builtin_saveregs");
1132asm ("__builtin_saveregs:");
27d21d32
RS
1133 asm (".globl ___builtin_saveregs");
1134asm ("___builtin_saveregs:");
1135
1136 asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
203b91b9
RS
1137 asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
1138 area and also for a new va_list
1139 structure */
1140 /* Save all argument registers in the arg reg save area. The
1141 arg reg save area must have the following layout (according
1142 to the svr4 ABI):
1143
1144 struct {
1145 union {
1146 float freg[8];
1147 double dreg[4];
1148 } float_regs;
1149 long ireg[12];
1150 };
1151 */
1152
1153 asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
1154 asm (" fst.q %f12,16(%sp)");
1155
1156 asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
1157 asm (" st.l %r17,36(%sp)");
1158 asm (" st.l %r18,40(%sp)");
1159 asm (" st.l %r19,44(%sp)");
1160 asm (" st.l %r20,48(%sp)");
1161 asm (" st.l %r21,52(%sp)");
1162 asm (" st.l %r22,56(%sp)");
1163 asm (" st.l %r23,60(%sp)");
1164 asm (" st.l %r24,64(%sp)");
1165 asm (" st.l %r25,68(%sp)");
1166 asm (" st.l %r26,72(%sp)");
1167 asm (" st.l %r27,76(%sp)");
1168
1169 asm (" adds 80,%sp,%r16"); /* compute the address of the new
1170 va_list structure. Put in into
1171 r16 so that it will be returned
1172 to the caller. */
1173
1174 /* Initialize all fields of the new va_list structure. This
1175 structure looks like:
1176
1177 typedef struct {
1178 unsigned long ireg_used;
1179 unsigned long freg_used;
1180 long *reg_base;
1181 long *mem_ptr;
1182 } va_list;
1183 */
1184
1185 asm (" st.l %r0, 0(%r16)"); /* nfixed */
1186 asm (" st.l %r0, 4(%r16)"); /* nfloating */
1187 asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
1188 asm (" bri %r1"); /* delayed return */
1189 asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
1190
24e4939e 1191#else /* not __svr4__ */
6aadf9c2
RS
1192#if defined(__PARAGON__)
1193 /*
1194 * we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1195 * and we stand a better chance of hooking into libraries
1196 * compiled by PGI. [andyp@ssd.intel.com]
1197 */
1198 asm (" .text");
1199 asm (" .align 4");
1200 asm (".globl __builtin_saveregs");
1201asm ("__builtin_saveregs:");
1202 asm (".globl ___builtin_saveregs");
1203asm ("___builtin_saveregs:");
1204
1205 asm (" andnot 0x0f,sp,sp"); /* round down to 16-byte boundary */
1206 asm (" adds -96,sp,sp"); /* allocate stack space for reg save
1207 area and also for a new va_list
1208 structure */
1209 /* Save all argument registers in the arg reg save area. The
1210 arg reg save area must have the following layout (according
1211 to the svr4 ABI):
1212
1213 struct {
1214 union {
1215 float freg[8];
1216 double dreg[4];
1217 } float_regs;
1218 long ireg[12];
1219 };
1220 */
1221
1222 asm (" fst.q f8, 0(sp)");
1223 asm (" fst.q f12,16(sp)");
1224 asm (" st.l r16,32(sp)");
1225 asm (" st.l r17,36(sp)");
1226 asm (" st.l r18,40(sp)");
1227 asm (" st.l r19,44(sp)");
1228 asm (" st.l r20,48(sp)");
1229 asm (" st.l r21,52(sp)");
1230 asm (" st.l r22,56(sp)");
1231 asm (" st.l r23,60(sp)");
1232 asm (" st.l r24,64(sp)");
1233 asm (" st.l r25,68(sp)");
1234 asm (" st.l r26,72(sp)");
1235 asm (" st.l r27,76(sp)");
1236
1237 asm (" adds 80,sp,r16"); /* compute the address of the new
1238 va_list structure. Put in into
1239 r16 so that it will be returned
1240 to the caller. */
1241
1242 /* Initialize all fields of the new va_list structure. This
1243 structure looks like:
1244
1245 typedef struct {
1246 unsigned long ireg_used;
1247 unsigned long freg_used;
1248 long *reg_base;
1249 long *mem_ptr;
1250 } va_list;
1251 */
1252
1253 asm (" st.l r0, 0(r16)"); /* nfixed */
1254 asm (" st.l r0, 4(r16)"); /* nfloating */
1255 asm (" st.l sp, 8(r16)"); /* __va_ctl points to __va_struct. */
1256 asm (" bri r1"); /* delayed return */
1257 asm (" st.l r28,12(r16)"); /* pointer to overflow args */
1258#else /* not __PARAGON__ */
203b91b9
RS
1259 asm (" .text");
1260 asm (" .align 4");
1261
1262 asm (".globl ___builtin_saveregs");
1263 asm ("___builtin_saveregs:");
1264 asm (" mov sp,r30");
1265 asm (" andnot 0x0f,sp,sp");
1266 asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
1267
1268/* Fill in the __va_struct. */
1269 asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
1270 asm (" st.l r17, 4(sp)"); /* int fixed[12] */
1271 asm (" st.l r18, 8(sp)");
1272 asm (" st.l r19,12(sp)");
1273 asm (" st.l r20,16(sp)");
1274 asm (" st.l r21,20(sp)");
1275 asm (" st.l r22,24(sp)");
1276 asm (" st.l r23,28(sp)");
1277 asm (" st.l r24,32(sp)");
1278 asm (" st.l r25,36(sp)");
1279 asm (" st.l r26,40(sp)");
1280 asm (" st.l r27,44(sp)");
1281
1282 asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
1283 asm (" fst.q f12,64(sp)"); /* int floating[8] */
1284
1285/* Fill in the __va_ctl. */
1286 asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
1287 asm (" st.l r28,84(sp)"); /* pointer to more args */
1288 asm (" st.l r0, 88(sp)"); /* nfixed */
1289 asm (" st.l r0, 92(sp)"); /* nfloating */
1290
1291 asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
1292 asm (" bri r1");
1293 asm (" mov r30,sp");
1294 /* recover stack and pass address to start
1295 of data. */
6aadf9c2 1296#endif /* not __PARAGON__ */
24e4939e 1297#endif /* not __svr4__ */
203b91b9
RS
1298#else /* not __i860__ */
1299#ifdef __sparc__
b335c2cc
TW
1300 asm (".global __builtin_saveregs");
1301 asm ("__builtin_saveregs:");
203b91b9
RS
1302 asm (".global ___builtin_saveregs");
1303 asm ("___builtin_saveregs:");
b1166fae
RS
1304#ifdef NEED_PROC_COMMAND
1305 asm (".proc 020");
b335c2cc 1306#endif
203b91b9
RS
1307 asm ("st %i0,[%fp+68]");
1308 asm ("st %i1,[%fp+72]");
1309 asm ("st %i2,[%fp+76]");
1310 asm ("st %i3,[%fp+80]");
1311 asm ("st %i4,[%fp+84]");
1312 asm ("retl");
1313 asm ("st %i5,[%fp+88]");
b1166fae
RS
1314#ifdef NEED_TYPE_COMMAND
1315 asm (".type __builtin_saveregs,#function");
1316 asm (".size __builtin_saveregs,.-__builtin_saveregs");
1317#endif
203b91b9
RS
1318#else /* not __sparc__ */
1319#if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1320
1321 asm (" .text");
1322 asm (" .ent __builtin_saveregs");
1323 asm (" .globl __builtin_saveregs");
1324 asm ("__builtin_saveregs:");
1325 asm (" sw $4,0($30)");
1326 asm (" sw $5,4($30)");
1327 asm (" sw $6,8($30)");
1328 asm (" sw $7,12($30)");
1329 asm (" j $31");
1330 asm (" .end __builtin_saveregs");
1331#else /* not __mips__, etc. */
1332__builtin_saveregs ()
1333{
1334 abort ();
1335}
1336#endif /* not __mips__ */
1337#endif /* not __sparc__ */
1338#endif /* not __i860__ */
1339#endif
1340\f
1341#ifdef L_eprintf
c74d5583 1342#ifndef inhibit_libc
bba2431c 1343
203b91b9
RS
1344#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
1345#include <stdio.h>
1346/* This is used by the `assert' macro. */
1347void
1348__eprintf (string, expression, line, filename)
b1166fae
RS
1349 const char *string;
1350 const char *expression;
203b91b9 1351 int line;
b1166fae 1352 const char *filename;
203b91b9
RS
1353{
1354 fprintf (stderr, string, expression, line, filename);
1355 fflush (stderr);
1356 abort ();
1357}
bba2431c
RS
1358
1359#endif
203b91b9
RS
1360#endif
1361
1362#ifdef L_bb
203b91b9 1363
92832bb5 1364/* Structure emitted by -a */
203b91b9
RS
1365struct bb
1366{
92832bb5
MM
1367 long zero_word;
1368 const char *filename;
1369 long *counts;
1370 long ncounts;
1371 struct bb *next;
1372 const unsigned long *addresses;
1373
1374 /* Older GCC's did not emit these fields. */
1375 long nwords;
1376 const char **functions;
1377 const long *line_nums;
1378 const char **filenames;
203b91b9
RS
1379};
1380
92832bb5
MM
1381#ifdef BLOCK_PROFILER_CODE
1382BLOCK_PROFILER_CODE
1383#else
c7544ff7 1384#ifndef inhibit_libc
92832bb5
MM
1385
1386/* Simple minded basic block profiling output dumper for
1387 systems that don't provde tcov support. At present,
1388 it requires atexit and stdio. */
1389
ebd41309 1390#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
92832bb5 1391#include <stdio.h>
203b91b9 1392
92832bb5
MM
1393#ifdef HAVE_ATEXIT
1394extern void atexit (void (*) (void));
1395#define ON_EXIT(FUNC,ARG) atexit ((FUNC))
1396#else
1397#ifdef sun
1398extern void on_exit (void*, void*);
1399#define ON_EXIT(FUNC,ARG) on_exit ((FUNC), (ARG))
1400#endif
1401#endif
1402
1403static struct bb *bb_head = (struct bb *)0;
1404
1405/* Return the number of digits needed to print a value */
1406/* __inline__ */ static int num_digits (long value, int base)
203b91b9 1407{
92832bb5
MM
1408 int minus = (value < 0 && base != 16);
1409 unsigned long v = (minus) ? -value : value;
1410 int ret = minus;
203b91b9 1411
92832bb5
MM
1412 do
1413 {
1414 v /= base;
1415 ret++;
1416 }
1417 while (v);
1418
1419 return ret;
203b91b9
RS
1420}
1421
92832bb5
MM
1422void
1423__bb_exit_func (void)
1424{
1425 FILE *file = fopen ("bb.out", "a");
1426 long time_value;
1427
1428 if (!file)
1429 perror ("bb.out");
1430
1431 else
1432 {
1433 struct bb *ptr;
1434
1435 /* This is somewhat type incorrect, but it avoids worrying about
1436 exactly where time.h is included from. It should be ok unless
1437 a void * differs from other pointer formats, or if sizeof(long)
1438 is < sizeof (time_t). It would be nice if we could assume the
1439 use of rationale standards here. */
1440
1441 time((void *) &time_value);
1442 fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1443
1444 /* We check the length field explicitly in order to allow compatibility
1445 with older GCC's which did not provide it. */
1446
1447 for (ptr = bb_head; ptr != (struct bb *)0; ptr = ptr->next)
1448 {
1449 int i;
1450 int func_p = (ptr->nwords >= sizeof (struct bb) && ptr->nwords <= 1000);
1451 int line_p = (func_p && ptr->line_nums);
1452 int file_p = (func_p && ptr->filenames);
1453 long ncounts = ptr->ncounts;
1454 long cnt_max = 0;
1455 long line_max = 0;
1456 long addr_max = 0;
1457 int file_len = 0;
1458 int func_len = 0;
1459 int blk_len = num_digits (ncounts, 10);
1460 int cnt_len;
1461 int line_len;
1462 int addr_len;
1463
1464 fprintf (file, "File %s, %ld basic blocks \n\n",
1465 ptr->filename, ncounts);
1466
1467 /* Get max values for each field. */
1468 for (i = 0; i < ncounts; i++)
1469 {
1470 const char *p;
1471 int len;
1472
1473 if (cnt_max < ptr->counts[i])
1474 cnt_max = ptr->counts[i];
1475
1476 if (addr_max < ptr->addresses[i])
1477 addr_max = ptr->addresses[i];
1478
1479 if (line_p && line_max < ptr->line_nums[i])
1480 line_max = ptr->line_nums[i];
1481
1482 if (func_p)
1483 {
1484 p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1485 len = strlen (p);
1486 if (func_len < len)
1487 func_len = len;
1488 }
1489
1490 if (file_p)
1491 {
1492 p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1493 len = strlen (p);
1494 if (file_len < len)
1495 file_len = len;
1496 }
1497 }
1498
1499 addr_len = num_digits (addr_max, 16);
1500 cnt_len = num_digits (cnt_max, 10);
1501 line_len = num_digits (line_max, 10);
1502
1503 /* Now print out the basic block information. */
1504 for (i = 0; i < ncounts; i++)
1505 {
1506 fprintf (file,
3cca99e8 1507 " Block #%*d: executed %*ld time(s) address= 0x%.*lx",
92832bb5
MM
1508 blk_len, i+1,
1509 cnt_len, ptr->counts[i],
1510 addr_len, ptr->addresses[i]);
1511
1512 if (func_p)
3cca99e8 1513 fprintf (file, " function= %-*s", func_len,
92832bb5
MM
1514 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1515
1516 if (line_p)
3cca99e8 1517 fprintf (file, " line= %*d", line_len, ptr->line_nums[i]);
92832bb5
MM
1518
1519 if (file_p)
3cca99e8 1520 fprintf (file, " file= %s",
92832bb5
MM
1521 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1522
1523 fprintf (file, "\n");
1524 }
1525
1526 fprintf (file, "\n");
1527 fflush (file);
1528 }
1529
1530 fprintf (file, "\n\n");
1531 fclose (file);
1532 }
1533}
1534
1535void
1536__bb_init_func (struct bb *blocks)
1537{
1538 /* User is supposed to check whether the first word is non-0,
1539 but just in case.... */
1540
1541 if (blocks->zero_word)
1542 return;
1543
1544#ifdef ON_EXIT
1545 /* Initialize destructor. */
1546 if (!bb_head)
1547 ON_EXIT (__bb_exit_func, 0);
203b91b9 1548#endif
92832bb5
MM
1549
1550 /* Set up linked list. */
1551 blocks->zero_word = 1;
1552 blocks->next = bb_head;
1553 bb_head = blocks;
1554}
1555
c7544ff7
RS
1556#endif /* not inhibit_libc */
1557#endif /* not BLOCK_PROFILER_CODE */
1558#endif /* L_bb */
203b91b9
RS
1559\f
1560/* frills for C++ */
1561
ec06f00a 1562#ifdef L_op_new
203b91b9
RS
1563typedef void (*vfp)(void);
1564
1565extern vfp __new_handler;
1566
ec06f00a 1567/* void * operator new (size_t sz) */
203b91b9 1568void *
ec06f00a 1569__builtin_new (size_t sz)
203b91b9
RS
1570{
1571 void *p;
1572
bcea2185
RS
1573 /* malloc (0) is unpredictable; avoid it. */
1574 if (sz == 0)
1575 sz = 1;
ecbe06a1 1576 p = (void *) malloc (sz);
203b91b9
RS
1577 if (p == 0)
1578 (*__new_handler) ();
1579 return p;
1580}
ec06f00a 1581#endif /* L_op_new */
203b91b9 1582
ec06f00a 1583#ifdef L_new_handler
fffa6914 1584
c74d5583 1585#ifndef inhibit_libc
fffa6914 1586/* This gets us __GNU_LIBRARY__. */
98126ed6 1587#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
fffa6914
RS
1588#include <stdio.h>
1589
1590#ifdef __GNU_LIBRARY__
1591 /* Avoid forcing the library's meaning of `write' on the user program
e45d9b98 1592 by using the "internal" name (for use within the library) */
fffa6914
RS
1593#define write(fd, buf, n) __write((fd), (buf), (n))
1594#endif
c74d5583 1595#endif /* inhibit_libc */
fffa6914 1596
203b91b9
RS
1597typedef void (*vfp)(void);
1598
b6422cca
RS
1599extern void *__builtin_new (size_t);
1600static void default_new_handler (void);
203b91b9
RS
1601
1602vfp __new_handler = default_new_handler;
1603
203b91b9
RS
1604vfp
1605__set_new_handler (handler)
1606 vfp handler;
1607{
1608 vfp prev_handler;
1609
1610 prev_handler = __new_handler;
1611 if (handler == 0) handler = default_new_handler;
1612 __new_handler = handler;
1613 return prev_handler;
1614}
1615
1616vfp
1617set_new_handler (handler)
1618 vfp handler;
1619{
1620 return __set_new_handler (handler);
1621}
1622
b1166fae
RS
1623#define MESSAGE "Virtual memory exceeded in `new'\n"
1624
203b91b9
RS
1625static void
1626default_new_handler ()
1627{
1628 /* don't use fprintf (stderr, ...) because it may need to call malloc. */
1629 /* This should really print the name of the program, but that is hard to
1630 do. We need a standard, clean way to get at the name. */
b1166fae 1631 write (2, MESSAGE, sizeof (MESSAGE));
203b91b9
RS
1632 /* don't call exit () because that may call global destructors which
1633 may cause a loop. */
1634 _exit (-1);
1635}
1636#endif
203b91b9 1637
ec06f00a
JW
1638#ifdef L_op_delete
1639/* void operator delete (void *ptr) */
203b91b9 1640void
ec06f00a 1641__builtin_delete (void *ptr)
203b91b9
RS
1642{
1643 if (ptr)
1644 free (ptr);
1645}
203b91b9 1646#endif
ec06f00a 1647\f
203b91b9
RS
1648#ifdef L_shtab
1649unsigned int __shtab[] = {
1650 0x00000001, 0x00000002, 0x00000004, 0x00000008,
1651 0x00000010, 0x00000020, 0x00000040, 0x00000080,
1652 0x00000100, 0x00000200, 0x00000400, 0x00000800,
1653 0x00001000, 0x00002000, 0x00004000, 0x00008000,
1654 0x00010000, 0x00020000, 0x00040000, 0x00080000,
1655 0x00100000, 0x00200000, 0x00400000, 0x00800000,
1656 0x01000000, 0x02000000, 0x04000000, 0x08000000,
1657 0x10000000, 0x20000000, 0x40000000, 0x80000000
1658 };
1659#endif
1660\f
1661#ifdef L_clear_cache
1662/* Clear part of an instruction cache. */
1663
1664#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1665
1666void
1667__clear_cache (beg, end)
1668 char *beg, *end;
1669{
e1178973
KKT
1670#ifdef CLEAR_INSN_CACHE
1671 CLEAR_INSN_CACHE (beg, end);
1672#else
203b91b9
RS
1673#ifdef INSN_CACHE_SIZE
1674 static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1675 static int initialized = 0;
1676 int offset;
b6422cca
RS
1677 void *start_addr
1678 void *end_addr;
203b91b9
RS
1679 typedef (*function_ptr) ();
1680
1681#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1682 /* It's cheaper to clear the whole cache.
1683 Put in a series of jump instructions so that calling the beginning
1684 of the cache will clear the whole thing. */
1685
1686 if (! initialized)
1687 {
1688 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1689 & -INSN_CACHE_LINE_WIDTH);
1690 int end_ptr = ptr + INSN_CACHE_SIZE;
1691
1692 while (ptr < end_ptr)
1693 {
1694 *(INSTRUCTION_TYPE *)ptr
1695 = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1696 ptr += INSN_CACHE_LINE_WIDTH;
1697 }
1698 *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1699
1700 initialized = 1;
1701 }
1702
1703 /* Call the beginning of the sequence. */
1704 (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1705 & -INSN_CACHE_LINE_WIDTH))
1706 ());
1707
1708#else /* Cache is large. */
1709
1710 if (! initialized)
1711 {
1712 int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1713 & -INSN_CACHE_LINE_WIDTH);
1714
1715 while (ptr < (int) array + sizeof array)
1716 {
1717 *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1718 ptr += INSN_CACHE_LINE_WIDTH;
1719 }
1720
1721 initialized = 1;
1722 }
1723
1724 /* Find the location in array that occupies the same cache line as BEG. */
1725
1726 offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1727 start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1728 & -INSN_CACHE_PLANE_SIZE)
1729 + offset);
1730
1731 /* Compute the cache alignment of the place to stop clearing. */
1732#if 0 /* This is not needed for gcc's purposes. */
1733 /* If the block to clear is bigger than a cache plane,
1734 we clear the entire cache, and OFFSET is already correct. */
1735 if (end < beg + INSN_CACHE_PLANE_SIZE)
1736#endif
1737 offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1738 & -INSN_CACHE_LINE_WIDTH)
1739 & (INSN_CACHE_PLANE_SIZE - 1));
1740
1741#if INSN_CACHE_DEPTH > 1
1742 end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1743 if (end_addr <= start_addr)
1744 end_addr += INSN_CACHE_PLANE_SIZE;
1745
1746 for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1747 {
1748 int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1749 int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1750
1751 while (addr != stop)
1752 {
1753 /* Call the return instruction at ADDR. */
1754 ((function_ptr) addr) ();
1755
1756 addr += INSN_CACHE_LINE_WIDTH;
1757 }
1758 }
1759#else /* just one plane */
1760 do
1761 {
1762 /* Call the return instruction at START_ADDR. */
1763 ((function_ptr) start_addr) ();
1764
1765 start_addr += INSN_CACHE_LINE_WIDTH;
1766 }
1767 while ((start_addr % INSN_CACHE_SIZE) != offset);
1768#endif /* just one plane */
1769#endif /* Cache is large */
1770#endif /* Cache exists */
e1178973 1771#endif /* CLEAR_INSN_CACHE */
203b91b9
RS
1772}
1773
1774#endif /* L_clear_cache */
1775\f
1776#ifdef L_trampoline
1777
1778/* Jump to a trampoline, loading the static chain address. */
1779
1780#ifdef TRANSFER_FROM_TRAMPOLINE
1781TRANSFER_FROM_TRAMPOLINE
1782#endif
1783
c1381fd3
KKT
1784#if defined (NeXT) && defined (__MACH__)
1785
1786/* Make stack executable so we can call trampolines on stack.
1787 This is called from INITIALIZE_TRAMPOLINE in next.h. */
1788
1789#include <mach/mach.h>
1790
1791void
1792__enable_execute_stack (addr)
1793 char *addr;
1794{
1795 kern_return_t r;
1796 char *eaddr = addr + TRAMPOLINE_SIZE;
1797 vm_address_t a = (vm_address_t) addr;
1798
1799 /* turn on execute access on stack */
1800 r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
1801 if (r != KERN_SUCCESS)
1802 {
1803 mach_error("vm_protect VM_PROT_ALL", r);
1804 exit(1);
1805 }
1806
1807 /* We inline the i-cache invalidation for speed */
1808
1809#ifdef CLEAR_INSN_CACHE
1810 CLEAR_INSN_CACHE (addr, eaddr);
1811#else
1812 __clear_cache ((int) addr, (int) eaddr);
1813#endif
1814}
1815
1816#endif /* defined (NeXT) && defined (__MACH__) */
1817
203b91b9
RS
1818#ifdef __convex__
1819
1820/* Make stack executable so we can call trampolines on stack.
1821 This is called from INITIALIZE_TRAMPOLINE in convex.h. */
1822
1823#include <sys/mman.h>
1824#include <sys/vmparam.h>
1825#include <machine/machparam.h>
1826
1827void
1828__enable_execute_stack ()
1829{
1830 int fp;
1831 static unsigned lowest = USRSTACK;
1832 unsigned current = (unsigned) &fp & -NBPG;
1833
1834 if (lowest > current)
1835 {
1836 unsigned len = lowest - current;
1837 mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1838 lowest = current;
1839 }
1840
1841 /* Clear instruction cache in case an old trampoline is in it. */
1842 asm ("pich");
1843}
1844#endif /* __convex__ */
b335c2cc
TW
1845
1846#ifdef __pyr__
1847
98126ed6 1848#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
b335c2cc
TW
1849#include <stdio.h>
1850#include <sys/mman.h>
1851#include <sys/types.h>
1852#include <sys/param.h>
1853#include <sys/vmmac.h>
1854
1855/* Modified from the convex -code above.
1856 mremap promises to clear the i-cache. */
1857
1858void
1859__enable_execute_stack ()
1860{
1861 int fp;
1862 if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
1863 PROT_READ|PROT_WRITE|PROT_EXEC))
1864 {
1865 perror ("mprotect in __enable_execute_stack");
1866 fflush (stderr);
1867 abort ();
1868 }
1869}
1870#endif /* __pyr__ */
203b91b9
RS
1871#endif /* L_trampoline */
1872\f
1873#ifdef L__main
1874
1875#include "gbl-ctors.h"
c06cff95
RS
1876/* Some systems use __main in a way incompatible with its use in gcc, in these
1877 cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
1878 give the same symbol without quotes for an alternative entry point. You
1879 must define both, or niether. */
1880#ifndef NAME__MAIN
1881#define NAME__MAIN "__main"
1882#define SYMBOL__MAIN __main
1883#endif
203b91b9
RS
1884
1885/* Run all the global destructors on exit from the program. */
1886
1887void
1888__do_global_dtors ()
1889{
89cf554b
RS
1890#ifdef DO_GLOBAL_DTORS_BODY
1891 DO_GLOBAL_DTORS_BODY;
1892#else
0dadecf6 1893 unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0];
b6422cca 1894 unsigned i;
203b91b9
RS
1895
1896 /* Some systems place the number of pointers
1897 in the first word of the table.
1898 On other systems, that word is -1.
1899 In all cases, the table is null-terminated. */
1900
1901 /* If the length is not recorded, count up to the null. */
1902 if (nptrs == -1)
1903 for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
1904
1905 /* GNU LD format. */
1906 for (i = nptrs; i >= 1; i--)
1907 __DTOR_LIST__[i] ();
89cf554b 1908#endif
203b91b9
RS
1909}
1910
1911#ifndef INIT_SECTION_ASM_OP
1912/* Run all the global constructors on entry to the program. */
1913
135461d9 1914#ifndef ON_EXIT
203b91b9
RS
1915#define ON_EXIT(a, b)
1916#else
1917/* Make sure the exit routine is pulled in to define the globals as
1918 bss symbols, just in case the linker does not automatically pull
1919 bss definitions from the library. */
1920
1921extern int _exit_dummy_decl;
1922int *_exit_dummy_ref = &_exit_dummy_decl;
1923#endif /* ON_EXIT */
1924
1925void
1926__do_global_ctors ()
1927{
1928 DO_GLOBAL_CTORS_BODY;
135461d9 1929 ON_EXIT (__do_global_dtors, 0);
203b91b9 1930}
b335c2cc 1931#endif /* no INIT_SECTION_ASM_OP */
203b91b9 1932
b335c2cc 1933#if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
203b91b9
RS
1934/* Subroutine called automatically by `main'.
1935 Compiling a global function named `main'
1936 produces an automatic call to this function at the beginning.
1937
1938 For many systems, this routine calls __do_global_ctors.
1939 For systems which support a .init section we use the .init section
1940 to run __do_global_ctors, so we need not do anything here. */
1941
1942void
c06cff95 1943SYMBOL__MAIN ()
203b91b9
RS
1944{
1945 /* Support recursive calls to `main': run initializers just once. */
b6422cca 1946 static int initialized = 0;
203b91b9
RS
1947 if (! initialized)
1948 {
1949 initialized = 1;
1950 __do_global_ctors ();
1951 }
1952}
b335c2cc 1953#endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
203b91b9
RS
1954
1955#endif /* L__main */
1956\f
ad38743d 1957#ifdef L_ctors
203b91b9
RS
1958
1959#include "gbl-ctors.h"
1960
1961/* Provide default definitions for the lists of constructors and
1962 destructors, so that we don't get linker errors. These symbols are
1963 intentionally bss symbols, so that gld and/or collect will provide
1964 the right values. */
1965
1966/* We declare the lists here with two elements each,
1967 so that they are valid empty lists if no other definition is loaded. */
b335c2cc 1968#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
d15d0264
RS
1969#ifdef __NeXT__
1970/* After 2.3, try this definition on all systems. */
1971func_ptr __CTOR_LIST__[2] = {0, 0};
1972func_ptr __DTOR_LIST__[2] = {0, 0};
1973#else
203b91b9
RS
1974func_ptr __CTOR_LIST__[2];
1975func_ptr __DTOR_LIST__[2];
d15d0264 1976#endif
b335c2cc 1977#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
ad38743d
RS
1978#endif /* L_ctors */
1979\f
1980#ifdef L_exit
1981
1982#include "gbl-ctors.h"
203b91b9
RS
1983
1984#ifndef ON_EXIT
1985
1986/* If we have no known way of registering our own __do_global_dtors
1987 routine so that it will be invoked at program exit time, then we
1988 have to define our own exit routine which will get this to happen. */
1989
1990extern void __do_global_dtors ();
1991extern void _cleanup ();
ad38743d 1992extern volatile void _exit ();
203b91b9
RS
1993
1994void
1995exit (status)
1996 int status;
1997{
1998 __do_global_dtors ();
1999#ifdef EXIT_BODY
2000 EXIT_BODY;
2001#else
2002 _cleanup ();
2003#endif
2004 _exit (status);
2005}
2006
2007#else
2008int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
2009#endif
2010
2011#endif /* L_exit */
2012\f
2013/* In a.out systems, we need to have these dummy constructor and destructor
2014 lists in the library.
2015
2016 When using `collect', the first link will resolve __CTOR_LIST__
2017 and __DTOR_LIST__ to these symbols. We will then run "nm" on the
2018 result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink.
2019 Since we don't do the second link if no constructors existed, these
2020 dummies must be fully functional empty lists.
2021
2022 When using `gnu ld', these symbols will be used if there are no
2023 constructors. If there are constructors, the N_SETV symbol defined
2024 by the linker from the N_SETT's in input files will define __CTOR_LIST__
2025 and __DTOR_LIST__ rather than its being allocated as common storage
2026 by the definitions below.
2027
2028 When using a linker that supports constructor and destructor segments,
2029 these definitions will not be used, since crtbegin.o and crtend.o
2030 (from crtstuff.c) will have already defined __CTOR_LIST__ and
2031 __DTOR_LIST__. The crt*.o files are passed directly to the linker
2032 on its command line, by gcc. */
2033
2034/* The list needs two elements: one is ignored (the old count); the
2035 second is the terminating zero. Since both values are zero, this
2036 declaration is not initialized, and it becomes `common'. */
2037
2038#ifdef L_ctor_list
2039#include "gbl-ctors.h"
2040func_ptr __CTOR_LIST__[2];
2041#endif
2042
2043#ifdef L_dtor_list
2044#include "gbl-ctors.h"
2045func_ptr __DTOR_LIST__[2];
2046#endif
This page took 0.378444 seconds and 5 git commands to generate.