157766Selan /* More subroutines needed by GCC output code on some machines. */
257766Selan /* Compile this one with gcc. */
357766Selan /* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
457766Selan
557766Selan This file is part of GNU CC.
657766Selan
757766Selan GNU CC is free software; you can redistribute it and/or modify
857766Selan it under the terms of the GNU General Public License as published by
957766Selan the Free Software Foundation; either version 2, or (at your option)
1057766Selan any later version.
1157766Selan
1257766Selan GNU CC is distributed in the hope that it will be useful,
1357766Selan but WITHOUT ANY WARRANTY; without even the implied warranty of
1457766Selan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1557766Selan GNU General Public License for more details.
1657766Selan
1757766Selan You should have received a copy of the GNU General Public License
1857766Selan along with GNU CC; see the file COPYING. If not, write to
1957766Selan the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
2057766Selan
2157766Selan /* As a special exception, if you link this library with files
2257766Selan compiled with GCC to produce an executable, this does not cause
2357766Selan the resulting executable to be covered by the GNU General Public License.
2457766Selan This exception does not however invalidate any other reasons why
2557766Selan the executable file might be covered by the GNU General Public License. */
2657766Selan
2757766Selan /* It is incorrect to include config.h here, because this file is being
2857766Selan compiled for the target, and hence definitions concerning only the host
2957766Selan do not apply. */
3057766Selan
3157766Selan #include "tconfig.h"
3257766Selan #include "machmode.h"
3357766Selan #ifndef L_trampoline
3457766Selan #include "gstddef.h"
3557766Selan #endif
3657766Selan
3757766Selan /* Don't use `fancy_abort' here even if config.h says to use it. */
3857766Selan #ifdef abort
3957766Selan #undef abort
4057766Selan #endif
4157766Selan
4257766Selan /* In the first part of this file, we are interfacing to calls generated
4357766Selan by the compiler itself. These calls pass values into these routines
4457766Selan which have very specific modes (rather than very specific types), and
4557766Selan these compiler-generated calls also expect any return values to have
4657766Selan very specific modes (rather than very specific types). Thus, we need
4757766Selan to avoid using regular C language type names in this part of the file
4857766Selan because the sizes for those types can be configured to be anything.
4957766Selan Instead we use the following special type names. */
5057766Selan
5157766Selan typedef unsigned int UQItype __attribute__ ((mode (QI)));
5257766Selan typedef int SItype __attribute__ ((mode (SI)));
5357766Selan typedef unsigned int USItype __attribute__ ((mode (SI)));
5457766Selan typedef int DItype __attribute__ ((mode (DI)));
5557766Selan typedef unsigned int UDItype __attribute__ ((mode (DI)));
5657766Selan typedef float SFtype __attribute__ ((mode (SF)));
5757766Selan typedef float DFtype __attribute__ ((mode (DF)));
5857766Selan #if 0
5957766Selan typedef float XFtype __attribute__ ((mode (XF)));
6057766Selan #endif
6157766Selan #if LONG_DOUBLE_TYPE_SIZE == 128
6257766Selan typedef float TFtype __attribute__ ((mode (TF)));
6357766Selan #endif
6457766Selan
6557766Selan /* Make sure that we don't accidentaly use any normal C language built-in
6657766Selan type names in the first part of this file. Instead we want to use *only*
6757766Selan the type names defined above. The following macro definitions insure
6857766Selan that if we *do* accidently use soem normal C language built-in type name,
6957766Selan we will get a syntax error. */
7057766Selan
7157766Selan #define char bogus_type
7257766Selan #define short bogus_type
7357766Selan #define int bogus_type
7457766Selan #define long bogus_type
7557766Selan #define unsigned bogus_type
7657766Selan #define float bogus_type
7757766Selan #define double bogus_type
7857766Selan
7957766Selan #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
8057766Selan
8157766Selan /* DIstructs are pairs of SItype values in the order determined by
8257766Selan WORDS_BIG_ENDIAN. */
8357766Selan
8457766Selan #if WORDS_BIG_ENDIAN
8557766Selan struct DIstruct {SItype high, low;};
8657766Selan #else
8757766Selan struct DIstruct {SItype low, high;};
8857766Selan #endif
8957766Selan
9057766Selan /* We need this union to unpack/pack DImode values, since we don't have
9157766Selan any arithmetic yet. Incoming DImode parameters are stored into the
9257766Selan `ll' field, and the unpacked result is read from the struct `s'. */
9357766Selan
9457766Selan typedef union
9557766Selan {
9657766Selan struct DIstruct s;
9757766Selan DItype ll;
9857766Selan } DIunion;
9957766Selan
10057766Selan #if defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)
10157766Selan
10257766Selan #include "longlong.h"
10357766Selan
10457766Selan #endif /* udiv or mul */
10557766Selan
10657766Selan extern DItype __fixunssfdi (SFtype a);
10757766Selan extern DItype __fixunsdfdi (DFtype a);
10857766Selan
10957766Selan #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
11057766Selan #if defined (L_divdi3) || defined (L_moddi3)
11157766Selan static inline
11257766Selan #endif
11357766Selan DItype
__negdi2(u)11457766Selan __negdi2 (u)
11557766Selan DItype u;
11657766Selan {
11757766Selan DIunion w;
11857766Selan DIunion uu;
11957766Selan
12057766Selan uu.ll = u;
12157766Selan
12257766Selan w.s.low = -uu.s.low;
12357766Selan w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
12457766Selan
12557766Selan return w.ll;
12657766Selan }
12757766Selan #endif
12857766Selan
12957766Selan #ifdef L_lshldi3
13057766Selan DItype
__lshldi3(u,b)13157766Selan __lshldi3 (u, b)
13257766Selan DItype u;
13357766Selan SItype b;
13457766Selan {
13557766Selan DIunion w;
13657766Selan SItype bm;
13757766Selan DIunion uu;
13857766Selan
13957766Selan if (b == 0)
14057766Selan return u;
14157766Selan
14257766Selan uu.ll = u;
14357766Selan
14457766Selan bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
14557766Selan if (bm <= 0)
14657766Selan {
14757766Selan w.s.low = 0;
14857766Selan w.s.high = (USItype)uu.s.low << -bm;
14957766Selan }
15057766Selan else
15157766Selan {
15257766Selan USItype carries = (USItype)uu.s.low >> bm;
15357766Selan w.s.low = (USItype)uu.s.low << b;
15457766Selan w.s.high = ((USItype)uu.s.high << b) | carries;
15557766Selan }
15657766Selan
15757766Selan return w.ll;
15857766Selan }
15957766Selan #endif
16057766Selan
16157766Selan #ifdef L_lshrdi3
16257766Selan DItype
__lshrdi3(u,b)16357766Selan __lshrdi3 (u, b)
16457766Selan DItype u;
16557766Selan SItype b;
16657766Selan {
16757766Selan DIunion w;
16857766Selan SItype bm;
16957766Selan DIunion uu;
17057766Selan
17157766Selan if (b == 0)
17257766Selan return u;
17357766Selan
17457766Selan uu.ll = u;
17557766Selan
17657766Selan bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
17757766Selan if (bm <= 0)
17857766Selan {
17957766Selan w.s.high = 0;
18057766Selan w.s.low = (USItype)uu.s.high >> -bm;
18157766Selan }
18257766Selan else
18357766Selan {
18457766Selan USItype carries = (USItype)uu.s.high << bm;
18557766Selan w.s.high = (USItype)uu.s.high >> b;
18657766Selan w.s.low = ((USItype)uu.s.low >> b) | carries;
18757766Selan }
18857766Selan
18957766Selan return w.ll;
19057766Selan }
19157766Selan #endif
19257766Selan
19357766Selan #ifdef L_ashldi3
19457766Selan DItype
__ashldi3(u,b)19557766Selan __ashldi3 (u, b)
19657766Selan DItype u;
19757766Selan SItype b;
19857766Selan {
19957766Selan DIunion w;
20057766Selan SItype bm;
20157766Selan DIunion uu;
20257766Selan
20357766Selan if (b == 0)
20457766Selan return u;
20557766Selan
20657766Selan uu.ll = u;
20757766Selan
20857766Selan bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
20957766Selan if (bm <= 0)
21057766Selan {
21157766Selan w.s.low = 0;
21257766Selan w.s.high = (USItype)uu.s.low << -bm;
21357766Selan }
21457766Selan else
21557766Selan {
21657766Selan USItype carries = (USItype)uu.s.low >> bm;
21757766Selan w.s.low = (USItype)uu.s.low << b;
21857766Selan w.s.high = ((USItype)uu.s.high << b) | carries;
21957766Selan }
22057766Selan
22157766Selan return w.ll;
22257766Selan }
22357766Selan #endif
22457766Selan
22557766Selan #ifdef L_ashrdi3
22657766Selan DItype
__ashrdi3(u,b)22757766Selan __ashrdi3 (u, b)
22857766Selan DItype u;
22957766Selan SItype b;
23057766Selan {
23157766Selan DIunion w;
23257766Selan SItype bm;
23357766Selan DIunion uu;
23457766Selan
23557766Selan if (b == 0)
23657766Selan return u;
23757766Selan
23857766Selan uu.ll = u;
23957766Selan
24057766Selan bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
24157766Selan if (bm <= 0)
24257766Selan {
24357766Selan /* w.s.high = 1..1 or 0..0 */
24457766Selan w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
24557766Selan w.s.low = uu.s.high >> -bm;
24657766Selan }
24757766Selan else
24857766Selan {
24957766Selan USItype carries = (USItype)uu.s.high << bm;
25057766Selan w.s.high = uu.s.high >> b;
25157766Selan w.s.low = ((USItype)uu.s.low >> b) | carries;
25257766Selan }
25357766Selan
25457766Selan return w.ll;
25557766Selan }
25657766Selan #endif
25757766Selan
25857766Selan #ifdef L_muldi3
25957766Selan DItype
__muldi3(u,v)26057766Selan __muldi3 (u, v)
26157766Selan DItype u, v;
26257766Selan {
26357766Selan DIunion w;
26457766Selan DIunion uu, vv;
26557766Selan
26657766Selan uu.ll = u,
26757766Selan vv.ll = v;
26857766Selan
26957766Selan w.ll = __umulsidi3 (uu.s.low, vv.s.low);
27057766Selan w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
27157766Selan + (USItype) uu.s.high * (USItype) vv.s.low);
27257766Selan
27357766Selan return w.ll;
27457766Selan }
27557766Selan #endif
27657766Selan
27757766Selan #ifdef L_udiv_w_sdiv
27857766Selan USItype
__udiv_w_sdiv(rp,a1,a0,d)27957766Selan __udiv_w_sdiv (rp, a1, a0, d)
28057766Selan USItype *rp, a1, a0, d;
28157766Selan {
28257766Selan USItype q, r;
28357766Selan USItype c0, c1, b1;
28457766Selan
28557766Selan if ((SItype) d >= 0)
28657766Selan {
28757766Selan if (a1 < d - a1 - (a0 >> 31))
28857766Selan {
28957766Selan /* dividend, divisor, and quotient are nonnegative */
29057766Selan sdiv_qrnnd (q, r, a1, a0, d);
29157766Selan }
29257766Selan else
29357766Selan {
29457766Selan /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
29557766Selan sub_ddmmss (c1, c0, a1, a0, d >> 1, d << 31);
29657766Selan /* Divide (c1*2^32 + c0) by d */
29757766Selan sdiv_qrnnd (q, r, c1, c0, d);
29857766Selan /* Add 2^31 to quotient */
29957766Selan q += (USItype) 1 << 31;
30057766Selan }
30157766Selan }
30257766Selan else
30357766Selan {
30457766Selan b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */
30557766Selan c1 = a1 >> 1; /* A/2 */
30657766Selan c0 = (a1 << 31) + (a0 >> 1);
30757766Selan
30857766Selan if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */
30957766Selan {
31057766Selan sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
31157766Selan
31257766Selan r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */
31357766Selan if ((d & 1) != 0)
31457766Selan {
31557766Selan if (r >= q)
31657766Selan r = r - q;
31757766Selan else if (q - r <= d)
31857766Selan {
31957766Selan r = r - q + d;
32057766Selan q--;
32157766Selan }
32257766Selan else
32357766Selan {
32457766Selan r = r - q + 2*d;
32557766Selan q -= 2;
32657766Selan }
32757766Selan }
32857766Selan }
32957766Selan else if (c1 < b1) /* So 2^31 <= (A/2)/b1 < 2^32 */
33057766Selan {
33157766Selan c1 = (b1 - 1) - c1;
33257766Selan c0 = ~c0; /* logical NOT */
33357766Selan
33457766Selan sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
33557766Selan
33657766Selan q = ~q; /* (A/2)/b1 */
33757766Selan r = (b1 - 1) - r;
33857766Selan
33957766Selan r = 2*r + (a0 & 1); /* A/(2*b1) */
34057766Selan
34157766Selan if ((d & 1) != 0)
34257766Selan {
34357766Selan if (r >= q)
34457766Selan r = r - q;
34557766Selan else if (q - r <= d)
34657766Selan {
34757766Selan r = r - q + d;
34857766Selan q--;
34957766Selan }
35057766Selan else
35157766Selan {
35257766Selan r = r - q + 2*d;
35357766Selan q -= 2;
35457766Selan }
35557766Selan }
35657766Selan }
35757766Selan else /* Implies c1 = b1 */
35857766Selan { /* Hence a1 = d - 1 = 2*b1 - 1 */
35957766Selan if (a0 >= -d)
36057766Selan {
36157766Selan q = -1;
36257766Selan r = a0 + d;
36357766Selan }
36457766Selan else
36557766Selan {
36657766Selan q = -2;
36757766Selan r = a0 + 2*d;
36857766Selan }
36957766Selan }
37057766Selan }
37157766Selan
37257766Selan *rp = r;
37357766Selan return q;
37457766Selan }
37557766Selan #endif
37657766Selan
37757766Selan #ifdef L_udivmoddi4
37857766Selan static const UQItype __clz_tab[] =
37957766Selan {
38057766Selan 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,
38157766Selan 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,
38257766Selan 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,
38357766Selan 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,
38457766Selan 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,
38557766Selan 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,
38657766Selan 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,
38757766Selan 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,
38857766Selan };
38957766Selan
39057766Selan UDItype
__udivmoddi4(n,d,rp)39157766Selan __udivmoddi4 (n, d, rp)
39257766Selan UDItype n, d;
39357766Selan UDItype *rp;
39457766Selan {
39557766Selan DIunion ww;
39657766Selan DIunion nn, dd;
39757766Selan DIunion rr;
39857766Selan USItype d0, d1, n0, n1, n2;
39957766Selan USItype q0, q1;
40057766Selan USItype b, bm;
40157766Selan
40257766Selan nn.ll = n;
40357766Selan dd.ll = d;
40457766Selan
40557766Selan d0 = dd.s.low;
40657766Selan d1 = dd.s.high;
40757766Selan n0 = nn.s.low;
40857766Selan n1 = nn.s.high;
40957766Selan
41057766Selan #if !UDIV_NEEDS_NORMALIZATION
41157766Selan if (d1 == 0)
41257766Selan {
41357766Selan if (d0 > n1)
41457766Selan {
41557766Selan /* 0q = nn / 0D */
41657766Selan
41757766Selan udiv_qrnnd (q0, n0, n1, n0, d0);
41857766Selan q1 = 0;
41957766Selan
42057766Selan /* Remainder in n0. */
42157766Selan }
42257766Selan else
42357766Selan {
42457766Selan /* qq = NN / 0d */
42557766Selan
42657766Selan if (d0 == 0)
42757766Selan d0 = 1 / d0; /* Divide intentionally by zero. */
42857766Selan
42957766Selan udiv_qrnnd (q1, n1, 0, n1, d0);
43057766Selan udiv_qrnnd (q0, n0, n1, n0, d0);
43157766Selan
43257766Selan /* Remainder in n0. */
43357766Selan }
43457766Selan
43557766Selan if (rp != 0)
43657766Selan {
43757766Selan rr.s.low = n0;
43857766Selan rr.s.high = 0;
43957766Selan *rp = rr.ll;
44057766Selan }
44157766Selan }
44257766Selan
44357766Selan #else /* UDIV_NEEDS_NORMALIZATION */
44457766Selan
44557766Selan if (d1 == 0)
44657766Selan {
44757766Selan if (d0 > n1)
44857766Selan {
44957766Selan /* 0q = nn / 0D */
45057766Selan
45157766Selan count_leading_zeros (bm, d0);
45257766Selan
45357766Selan if (bm != 0)
45457766Selan {
45557766Selan /* Normalize, i.e. make the most significant bit of the
45657766Selan denominator set. */
45757766Selan
45857766Selan d0 = d0 << bm;
45957766Selan n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
46057766Selan n0 = n0 << bm;
46157766Selan }
46257766Selan
46357766Selan udiv_qrnnd (q0, n0, n1, n0, d0);
46457766Selan q1 = 0;
46557766Selan
46657766Selan /* Remainder in n0 >> bm. */
46757766Selan }
46857766Selan else
46957766Selan {
47057766Selan /* qq = NN / 0d */
47157766Selan
47257766Selan if (d0 == 0)
47357766Selan d0 = 1 / d0; /* Divide intentionally by zero. */
47457766Selan
47557766Selan count_leading_zeros (bm, d0);
47657766Selan
47757766Selan if (bm == 0)
47857766Selan {
47957766Selan /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
48057766Selan conclude (the most significant bit of n1 is set) /\ (the
48157766Selan leading quotient digit q1 = 1).
48257766Selan
48357766Selan This special case is necessary, not an optimization.
48457766Selan (Shifts counts of SI_TYPE_SIZE are undefined.) */
48557766Selan
48657766Selan n1 -= d0;
48757766Selan q1 = 1;
48857766Selan }
48957766Selan else
49057766Selan {
49157766Selan /* Normalize. */
49257766Selan
49357766Selan b = SI_TYPE_SIZE - bm;
49457766Selan
49557766Selan d0 = d0 << bm;
49657766Selan n2 = n1 >> b;
49757766Selan n1 = (n1 << bm) | (n0 >> b);
49857766Selan n0 = n0 << bm;
49957766Selan
50057766Selan udiv_qrnnd (q1, n1, n2, n1, d0);
50157766Selan }
50257766Selan
50357766Selan /* n1 != d0... */
50457766Selan
50557766Selan udiv_qrnnd (q0, n0, n1, n0, d0);
50657766Selan
50757766Selan /* Remainder in n0 >> bm. */
50857766Selan }
50957766Selan
51057766Selan if (rp != 0)
51157766Selan {
51257766Selan rr.s.low = n0 >> bm;
51357766Selan rr.s.high = 0;
51457766Selan *rp = rr.ll;
51557766Selan }
51657766Selan }
51757766Selan #endif /* UDIV_NEEDS_NORMALIZATION */
51857766Selan
51957766Selan else
52057766Selan {
52157766Selan if (d1 > n1)
52257766Selan {
52357766Selan /* 00 = nn / DD */
52457766Selan
52557766Selan q0 = 0;
52657766Selan q1 = 0;
52757766Selan
52857766Selan /* Remainder in n1n0. */
52957766Selan if (rp != 0)
53057766Selan {
53157766Selan rr.s.low = n0;
53257766Selan rr.s.high = n1;
53357766Selan *rp = rr.ll;
53457766Selan }
53557766Selan }
53657766Selan else
53757766Selan {
53857766Selan /* 0q = NN / dd */
53957766Selan
54057766Selan count_leading_zeros (bm, d1);
54157766Selan if (bm == 0)
54257766Selan {
54357766Selan /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
54457766Selan conclude (the most significant bit of n1 is set) /\ (the
54557766Selan quotient digit q0 = 0 or 1).
54657766Selan
54757766Selan This special case is necessary, not an optimization. */
54857766Selan
54957766Selan /* The condition on the next line takes advantage of that
55057766Selan n1 >= d1 (true due to program flow). */
55157766Selan if (n1 > d1 || n0 >= d0)
55257766Selan {
55357766Selan q0 = 1;
55457766Selan sub_ddmmss (n1, n0, n1, n0, d1, d0);
55557766Selan }
55657766Selan else
55757766Selan q0 = 0;
55857766Selan
55957766Selan q1 = 0;
56057766Selan
56157766Selan if (rp != 0)
56257766Selan {
56357766Selan rr.s.low = n0;
56457766Selan rr.s.high = n1;
56557766Selan *rp = rr.ll;
56657766Selan }
56757766Selan }
56857766Selan else
56957766Selan {
57057766Selan USItype m1, m0;
57157766Selan /* Normalize. */
57257766Selan
57357766Selan b = SI_TYPE_SIZE - bm;
57457766Selan
57557766Selan d1 = (d1 << bm) | (d0 >> b);
57657766Selan d0 = d0 << bm;
57757766Selan n2 = n1 >> b;
57857766Selan n1 = (n1 << bm) | (n0 >> b);
57957766Selan n0 = n0 << bm;
58057766Selan
58157766Selan udiv_qrnnd (q0, n1, n2, n1, d1);
58257766Selan umul_ppmm (m1, m0, q0, d0);
58357766Selan
58457766Selan if (m1 > n1 || (m1 == n1 && m0 > n0))
58557766Selan {
58657766Selan q0--;
58757766Selan sub_ddmmss (m1, m0, m1, m0, d1, d0);
58857766Selan }
58957766Selan
59057766Selan q1 = 0;
59157766Selan
59257766Selan /* Remainder in (n1n0 - m1m0) >> bm. */
59357766Selan if (rp != 0)
59457766Selan {
59557766Selan sub_ddmmss (n1, n0, n1, n0, m1, m0);
59657766Selan rr.s.low = (n1 << b) | (n0 >> bm);
59757766Selan rr.s.high = n1 >> bm;
59857766Selan *rp = rr.ll;
59957766Selan }
60057766Selan }
60157766Selan }
60257766Selan }
60357766Selan
60457766Selan ww.s.low = q0;
60557766Selan ww.s.high = q1;
60657766Selan return ww.ll;
60757766Selan }
60857766Selan #endif
60957766Selan
61057766Selan #ifdef L_divdi3
61157766Selan UDItype __udivmoddi4 ();
61257766Selan DItype
__divdi3(u,v)61357766Selan __divdi3 (u, v)
61457766Selan DItype u, v;
61557766Selan {
61657766Selan SItype c = 0;
61757766Selan DIunion uu, vv;
61857766Selan DItype w;
61957766Selan
62057766Selan uu.ll = u;
62157766Selan vv.ll = v;
62257766Selan
62357766Selan if (uu.s.high < 0)
62457766Selan c = ~c,
62557766Selan uu.ll = __negdi2 (uu.ll);
62657766Selan if (vv.s.high < 0)
62757766Selan c = ~c,
62857766Selan vv.ll = __negdi2 (vv.ll);
62957766Selan
63057766Selan w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
63157766Selan if (c)
63257766Selan w = __negdi2 (w);
63357766Selan
63457766Selan return w;
63557766Selan }
63657766Selan #endif
63757766Selan
63857766Selan #ifdef L_moddi3
63957766Selan UDItype __udivmoddi4 ();
64057766Selan DItype
__moddi3(u,v)64157766Selan __moddi3 (u, v)
64257766Selan DItype u, v;
64357766Selan {
64457766Selan SItype c = 0;
64557766Selan DIunion uu, vv;
64657766Selan DItype w;
64757766Selan
64857766Selan uu.ll = u;
64957766Selan vv.ll = v;
65057766Selan
65157766Selan if (uu.s.high < 0)
65257766Selan c = ~c,
65357766Selan uu.ll = __negdi2 (uu.ll);
65457766Selan if (vv.s.high < 0)
65557766Selan vv.ll = __negdi2 (vv.ll);
65657766Selan
65757766Selan (void) __udivmoddi4 (uu.ll, vv.ll, &w);
65857766Selan if (c)
65957766Selan w = __negdi2 (w);
66057766Selan
66157766Selan return w;
66257766Selan }
66357766Selan #endif
66457766Selan
66557766Selan #ifdef L_umoddi3
66657766Selan UDItype __udivmoddi4 ();
66757766Selan UDItype
__umoddi3(u,v)66857766Selan __umoddi3 (u, v)
66957766Selan UDItype u, v;
67057766Selan {
67157766Selan DItype w;
67257766Selan
67357766Selan (void) __udivmoddi4 (u, v, &w);
67457766Selan
67557766Selan return w;
67657766Selan }
67757766Selan #endif
67857766Selan
67957766Selan #ifdef L_udivdi3
68057766Selan UDItype __udivmoddi4 ();
68157766Selan UDItype
__udivdi3(n,d)68257766Selan __udivdi3 (n, d)
68357766Selan UDItype n, d;
68457766Selan {
68557766Selan return __udivmoddi4 (n, d, (UDItype *) 0);
68657766Selan }
68757766Selan #endif
68857766Selan
68957766Selan #ifdef L_cmpdi2
69057766Selan SItype
__cmpdi2(a,b)69157766Selan __cmpdi2 (a, b)
69257766Selan DItype a, b;
69357766Selan {
69457766Selan DIunion au, bu;
69557766Selan
69657766Selan au.ll = a, bu.ll = b;
69757766Selan
69857766Selan if (au.s.high < bu.s.high)
69957766Selan return 0;
70057766Selan else if (au.s.high > bu.s.high)
70157766Selan return 2;
70257766Selan if ((USItype) au.s.low < (USItype) bu.s.low)
70357766Selan return 0;
70457766Selan else if ((USItype) au.s.low > (USItype) bu.s.low)
70557766Selan return 2;
70657766Selan return 1;
70757766Selan }
70857766Selan #endif
70957766Selan
71057766Selan #ifdef L_ucmpdi2
71157766Selan SItype
__ucmpdi2(a,b)71257766Selan __ucmpdi2 (a, b)
71357766Selan DItype a, b;
71457766Selan {
71557766Selan DIunion au, bu;
71657766Selan
71757766Selan au.ll = a, bu.ll = b;
71857766Selan
71957766Selan if ((USItype) au.s.high < (USItype) bu.s.high)
72057766Selan return 0;
72157766Selan else if ((USItype) au.s.high > (USItype) bu.s.high)
72257766Selan return 2;
72357766Selan if ((USItype) au.s.low < (USItype) bu.s.low)
72457766Selan return 0;
72557766Selan else if ((USItype) au.s.low > (USItype) bu.s.low)
72657766Selan return 2;
72757766Selan return 1;
72857766Selan }
72957766Selan #endif
73057766Selan
73157766Selan #if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
73257766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
73357766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
73457766Selan
73557766Selan DItype
__fixunstfdi(a)73657766Selan __fixunstfdi (a)
73757766Selan TFtype a;
73857766Selan {
73957766Selan TFtype b;
74057766Selan UDItype v;
74157766Selan
74257766Selan if (a < 0)
74357766Selan return 0;
74457766Selan
74557766Selan /* Compute high word of result, as a flonum. */
74657766Selan b = (a / HIGH_WORD_COEFF);
74757766Selan /* Convert that to fixed (but not to DItype!),
74857766Selan and shift it into the high word. */
74957766Selan v = (USItype) b;
75057766Selan v <<= WORD_SIZE;
75157766Selan /* Remove high part from the TFtype, leaving the low part as flonum. */
75257766Selan a -= (TFtype)v;
75357766Selan /* Convert that to fixed (but not to DItype!) and add it in.
75457766Selan Sometimes A comes out negative. This is significant, since
75557766Selan A has more bits than a long int does. */
75657766Selan if (a < 0)
75757766Selan v -= (USItype) (- a);
75857766Selan else
75957766Selan v += (USItype) a;
76057766Selan return v;
76157766Selan }
76257766Selan #endif
76357766Selan
76457766Selan #if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
76557766Selan DItype
__fixtfdi(a)76657766Selan __fixtfdi (a)
76757766Selan TFtype a;
76857766Selan {
76957766Selan if (a < 0)
77057766Selan return - __fixunstfdi (-a);
77157766Selan return __fixunstfdi (a);
77257766Selan }
77357766Selan #endif
77457766Selan
77557766Selan #ifdef L_fixunsdfdi
77657766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
77757766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
77857766Selan
77957766Selan DItype
__fixunsdfdi(a)78057766Selan __fixunsdfdi (a)
78157766Selan DFtype a;
78257766Selan {
78357766Selan DFtype b;
78457766Selan UDItype v;
78557766Selan
78657766Selan if (a < 0)
78757766Selan return 0;
78857766Selan
78957766Selan /* Compute high word of result, as a flonum. */
79057766Selan b = (a / HIGH_WORD_COEFF);
79157766Selan /* Convert that to fixed (but not to DItype!),
79257766Selan and shift it into the high word. */
79357766Selan v = (USItype) b;
79457766Selan v <<= WORD_SIZE;
79557766Selan /* Remove high part from the DFtype, leaving the low part as flonum. */
79657766Selan a -= (DFtype)v;
79757766Selan /* Convert that to fixed (but not to DItype!) and add it in.
79857766Selan Sometimes A comes out negative. This is significant, since
79957766Selan A has more bits than a long int does. */
80057766Selan if (a < 0)
80157766Selan v -= (USItype) (- a);
80257766Selan else
80357766Selan v += (USItype) a;
80457766Selan return v;
80557766Selan }
80657766Selan #endif
80757766Selan
80857766Selan #ifdef L_fixdfdi
80957766Selan DItype
__fixdfdi(a)81057766Selan __fixdfdi (a)
81157766Selan DFtype a;
81257766Selan {
81357766Selan if (a < 0)
81457766Selan return - __fixunsdfdi (-a);
81557766Selan return __fixunsdfdi (a);
81657766Selan }
81757766Selan #endif
81857766Selan
81957766Selan #ifdef L_fixunssfdi
82057766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
82157766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
82257766Selan
82357766Selan DItype
__fixunssfdi(SFtype original_a)82457766Selan __fixunssfdi (SFtype original_a)
82557766Selan {
82657766Selan /* Convert the SFtype to a DFtype, because that is surely not going
82757766Selan to lose any bits. Some day someone else can write a faster version
82857766Selan that avoids converting to DFtype, and verify it really works right. */
82957766Selan DFtype a = original_a;
83057766Selan DFtype b;
83157766Selan UDItype v;
83257766Selan
83357766Selan if (a < 0)
83457766Selan return 0;
83557766Selan
83657766Selan /* Compute high word of result, as a flonum. */
83757766Selan b = (a / HIGH_WORD_COEFF);
83857766Selan /* Convert that to fixed (but not to DItype!),
83957766Selan and shift it into the high word. */
84057766Selan v = (USItype) b;
84157766Selan v <<= WORD_SIZE;
84257766Selan /* Remove high part from the DFtype, leaving the low part as flonum. */
84357766Selan a -= (DFtype)v;
84457766Selan /* Convert that to fixed (but not to DItype!) and add it in.
84557766Selan Sometimes A comes out negative. This is significant, since
84657766Selan A has more bits than a long int does. */
84757766Selan if (a < 0)
84857766Selan v -= (USItype) (- a);
84957766Selan else
85057766Selan v += (USItype) a;
85157766Selan return v;
85257766Selan }
85357766Selan #endif
85457766Selan
85557766Selan #ifdef L_fixsfdi
85657766Selan DItype
__fixsfdi(SFtype a)85757766Selan __fixsfdi (SFtype a)
85857766Selan {
85957766Selan if (a < 0)
86057766Selan return - __fixunssfdi (-a);
86157766Selan return __fixunssfdi (a);
86257766Selan }
86357766Selan #endif
86457766Selan
86557766Selan #if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
86657766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
86757766Selan #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
86857766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
86957766Selan
87057766Selan TFtype
__floatditf(u)87157766Selan __floatditf (u)
87257766Selan DItype u;
87357766Selan {
87457766Selan TFtype d;
87557766Selan SItype negate = 0;
87657766Selan
87757766Selan if (u < 0)
87857766Selan u = -u, negate = 1;
87957766Selan
88057766Selan d = (USItype) (u >> WORD_SIZE);
88157766Selan d *= HIGH_HALFWORD_COEFF;
88257766Selan d *= HIGH_HALFWORD_COEFF;
88357766Selan d += (USItype) (u & (HIGH_WORD_COEFF - 1));
88457766Selan
88557766Selan return (negate ? -d : d);
88657766Selan }
88757766Selan #endif
88857766Selan
88957766Selan #ifdef L_floatdidf
89057766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
89157766Selan #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
89257766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
89357766Selan
89457766Selan DFtype
__floatdidf(u)89557766Selan __floatdidf (u)
89657766Selan DItype u;
89757766Selan {
89857766Selan DFtype d;
89957766Selan SItype negate = 0;
90057766Selan
90157766Selan if (u < 0)
90257766Selan u = -u, negate = 1;
90357766Selan
90457766Selan d = (USItype) (u >> WORD_SIZE);
90557766Selan d *= HIGH_HALFWORD_COEFF;
90657766Selan d *= HIGH_HALFWORD_COEFF;
90757766Selan d += (USItype) (u & (HIGH_WORD_COEFF - 1));
90857766Selan
90957766Selan return (negate ? -d : d);
91057766Selan }
91157766Selan #endif
91257766Selan
91357766Selan #ifdef L_floatdisf
91457766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
91557766Selan #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
91657766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
91757766Selan
91857766Selan SFtype
__floatdisf(u)91957766Selan __floatdisf (u)
92057766Selan DItype u;
92157766Selan {
92257766Selan SFtype f;
92357766Selan SItype negate = 0;
92457766Selan
92557766Selan if (u < 0)
92657766Selan u = -u, negate = 1;
92757766Selan
92857766Selan f = (USItype) (u >> WORD_SIZE);
92957766Selan f *= HIGH_HALFWORD_COEFF;
93057766Selan f *= HIGH_HALFWORD_COEFF;
93157766Selan f += (USItype) (u & (HIGH_WORD_COEFF - 1));
93257766Selan
93357766Selan return (negate ? -f : f);
93457766Selan }
93557766Selan #endif
93657766Selan
93757766Selan #ifdef L_fixunsdfsi
93857766Selan #include "glimits.h"
93957766Selan
94057766Selan USItype
__fixunsdfsi(a)94157766Selan __fixunsdfsi (a)
94257766Selan DFtype a;
94357766Selan {
94457766Selan if (a >= - (DFtype) LONG_MIN)
94557766Selan return (SItype) (a + LONG_MIN) - LONG_MIN;
94657766Selan return (SItype) a;
94757766Selan }
94857766Selan #endif
94957766Selan
95057766Selan #ifdef L_fixunssfsi
95157766Selan #include "glimits.h"
95257766Selan
95357766Selan USItype
__fixunssfsi(SFtype a)95457766Selan __fixunssfsi (SFtype a)
95557766Selan {
95657766Selan if (a >= - (SFtype) LONG_MIN)
95757766Selan return (SItype) (a + LONG_MIN) - LONG_MIN;
95857766Selan return (SItype) a;
95957766Selan }
96057766Selan #endif
96157766Selan
96257766Selan /* From here on down, the routines use normal data types. */
96357766Selan
96457766Selan #define SItype bogus_type
96557766Selan #define USItype bogus_type
96657766Selan #define DItype bogus_type
96757766Selan #define UDItype bogus_type
96857766Selan #define SFtype bogus_type
96957766Selan #define DFtype bogus_type
97057766Selan
97157766Selan #undef char
97257766Selan #undef short
97357766Selan #undef int
97457766Selan #undef long
97557766Selan #undef unsigned
97657766Selan #undef float
97757766Selan #undef double
97857766Selan
97957766Selan #ifdef L__gcc_bcmp
98057766Selan
98157766Selan /* Like bcmp except the sign is meaningful.
98257766Selan Reult is negative if S1 is less than S2,
98357766Selan positive if S1 is greater, 0 if S1 and S2 are equal. */
98457766Selan
985*60378Selan #include <sys/types.h>
986*60378Selan
98757766Selan int
__gcc_bcmp(s1,s2,size)98857766Selan __gcc_bcmp (s1, s2, size)
98957766Selan unsigned char *s1, *s2;
99057766Selan size_t size;
99157766Selan {
99257766Selan while (size > 0)
99357766Selan {
99457766Selan unsigned char c1 = *s1++, c2 = *s2++;
99557766Selan if (c1 != c2)
99657766Selan return c1 - c2;
99757766Selan size--;
99857766Selan }
99957766Selan return 0;
100057766Selan }
100157766Selan
100257766Selan #endif
100357766Selan
100457766Selan #ifdef L_varargs
100557766Selan #ifdef __i860__
100657766Selan #if defined(__svr4__) || defined(__alliant__)
100757766Selan asm (" .text");
100857766Selan asm (" .align 4");
100957766Selan
101057766Selan /* The Alliant needs the added underscore. */
101157766Selan asm (".globl __builtin_saveregs");
101257766Selan asm ("__builtin_saveregs:");
101357766Selan asm (".globl ___builtin_saveregs");
101457766Selan asm ("___builtin_saveregs:");
101557766Selan
101657766Selan asm (" andnot 0x0f,%sp,%sp"); /* round down to 16-byte boundary */
101757766Selan asm (" adds -96,%sp,%sp"); /* allocate stack space for reg save
101857766Selan area and also for a new va_list
101957766Selan structure */
102057766Selan /* Save all argument registers in the arg reg save area. The
102157766Selan arg reg save area must have the following layout (according
102257766Selan to the svr4 ABI):
102357766Selan
102457766Selan struct {
102557766Selan union {
102657766Selan float freg[8];
102757766Selan double dreg[4];
102857766Selan } float_regs;
102957766Selan long ireg[12];
103057766Selan };
103157766Selan */
103257766Selan
103357766Selan asm (" fst.q %f8, 0(%sp)"); /* save floating regs (f8-f15) */
103457766Selan asm (" fst.q %f12,16(%sp)");
103557766Selan
103657766Selan asm (" st.l %r16,32(%sp)"); /* save integer regs (r16-r27) */
103757766Selan asm (" st.l %r17,36(%sp)");
103857766Selan asm (" st.l %r18,40(%sp)");
103957766Selan asm (" st.l %r19,44(%sp)");
104057766Selan asm (" st.l %r20,48(%sp)");
104157766Selan asm (" st.l %r21,52(%sp)");
104257766Selan asm (" st.l %r22,56(%sp)");
104357766Selan asm (" st.l %r23,60(%sp)");
104457766Selan asm (" st.l %r24,64(%sp)");
104557766Selan asm (" st.l %r25,68(%sp)");
104657766Selan asm (" st.l %r26,72(%sp)");
104757766Selan asm (" st.l %r27,76(%sp)");
104857766Selan
104957766Selan asm (" adds 80,%sp,%r16"); /* compute the address of the new
105057766Selan va_list structure. Put in into
105157766Selan r16 so that it will be returned
105257766Selan to the caller. */
105357766Selan
105457766Selan /* Initialize all fields of the new va_list structure. This
105557766Selan structure looks like:
105657766Selan
105757766Selan typedef struct {
105857766Selan unsigned long ireg_used;
105957766Selan unsigned long freg_used;
106057766Selan long *reg_base;
106157766Selan long *mem_ptr;
106257766Selan } va_list;
106357766Selan */
106457766Selan
106557766Selan asm (" st.l %r0, 0(%r16)"); /* nfixed */
106657766Selan asm (" st.l %r0, 4(%r16)"); /* nfloating */
106757766Selan asm (" st.l %sp, 8(%r16)"); /* __va_ctl points to __va_struct. */
106857766Selan asm (" bri %r1"); /* delayed return */
106957766Selan asm (" st.l %r28,12(%r16)"); /* pointer to overflow args */
107057766Selan
107157766Selan #else /* not __SVR4__ */
107257766Selan asm (" .text");
107357766Selan asm (" .align 4");
107457766Selan
107557766Selan asm (".globl ___builtin_saveregs");
107657766Selan asm ("___builtin_saveregs:");
107757766Selan asm (" mov sp,r30");
107857766Selan asm (" andnot 0x0f,sp,sp");
107957766Selan asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
108057766Selan
108157766Selan /* Fill in the __va_struct. */
108257766Selan asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
108357766Selan asm (" st.l r17, 4(sp)"); /* int fixed[12] */
108457766Selan asm (" st.l r18, 8(sp)");
108557766Selan asm (" st.l r19,12(sp)");
108657766Selan asm (" st.l r20,16(sp)");
108757766Selan asm (" st.l r21,20(sp)");
108857766Selan asm (" st.l r22,24(sp)");
108957766Selan asm (" st.l r23,28(sp)");
109057766Selan asm (" st.l r24,32(sp)");
109157766Selan asm (" st.l r25,36(sp)");
109257766Selan asm (" st.l r26,40(sp)");
109357766Selan asm (" st.l r27,44(sp)");
109457766Selan
109557766Selan asm (" fst.q f8, 48(sp)"); /* save floating regs (f8-f15) */
109657766Selan asm (" fst.q f12,64(sp)"); /* int floating[8] */
109757766Selan
109857766Selan /* Fill in the __va_ctl. */
109957766Selan asm (" st.l sp, 80(sp)"); /* __va_ctl points to __va_struct. */
110057766Selan asm (" st.l r28,84(sp)"); /* pointer to more args */
110157766Selan asm (" st.l r0, 88(sp)"); /* nfixed */
110257766Selan asm (" st.l r0, 92(sp)"); /* nfloating */
110357766Selan
110457766Selan asm (" adds 80,sp,r16"); /* return address of the __va_ctl. */
110557766Selan asm (" bri r1");
110657766Selan asm (" mov r30,sp");
110757766Selan /* recover stack and pass address to start
110857766Selan of data. */
110957766Selan #endif /* not __SVR4__ */
111057766Selan #else /* not __i860__ */
111157766Selan #ifdef __sparc__
111257766Selan asm (".global __builtin_saveregs");
111357766Selan asm ("__builtin_saveregs:");
111457766Selan asm (".global ___builtin_saveregs");
111557766Selan asm ("___builtin_saveregs:");
111657766Selan #ifdef NEED_PROC_COMMAND
111757766Selan asm (".proc 020");
111857766Selan #endif
111957766Selan asm ("st %i0,[%fp+68]");
112057766Selan asm ("st %i1,[%fp+72]");
112157766Selan asm ("st %i2,[%fp+76]");
112257766Selan asm ("st %i3,[%fp+80]");
112357766Selan asm ("st %i4,[%fp+84]");
112457766Selan asm ("retl");
112557766Selan asm ("st %i5,[%fp+88]");
112657766Selan #ifdef NEED_TYPE_COMMAND
112757766Selan asm (".type __builtin_saveregs,#function");
112857766Selan asm (".size __builtin_saveregs,.-__builtin_saveregs");
112957766Selan #endif
113057766Selan #else /* not __sparc__ */
113157766Selan #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
113257766Selan
113357766Selan asm (" .text");
113457766Selan asm (" .ent __builtin_saveregs");
113557766Selan asm (" .globl __builtin_saveregs");
113657766Selan asm ("__builtin_saveregs:");
113757766Selan asm (" sw $4,0($30)");
113857766Selan asm (" sw $5,4($30)");
113957766Selan asm (" sw $6,8($30)");
114057766Selan asm (" sw $7,12($30)");
114157766Selan asm (" j $31");
114257766Selan asm (" .end __builtin_saveregs");
114357766Selan #else /* not __mips__, etc. */
__builtin_saveregs()114457766Selan __builtin_saveregs ()
114557766Selan {
114657766Selan abort ();
114757766Selan }
114857766Selan #endif /* not __mips__ */
114957766Selan #endif /* not __sparc__ */
115057766Selan #endif /* not __i860__ */
115157766Selan #endif
115257766Selan
115357766Selan #ifdef L_eprintf
115457766Selan #ifndef inhibit_eprintf
115557766Selan
115657766Selan #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
115757766Selan #include <stdio.h>
115857766Selan /* This is used by the `assert' macro. */
115957766Selan void
__eprintf(string,expression,line,filename)116057766Selan __eprintf (string, expression, line, filename)
116157766Selan const char *string;
116257766Selan const char *expression;
116357766Selan int line;
116457766Selan const char *filename;
116557766Selan {
116657766Selan fprintf (stderr, string, expression, line, filename);
116757766Selan fflush (stderr);
116857766Selan abort ();
116957766Selan }
117057766Selan
117157766Selan #endif
117257766Selan #endif
117357766Selan
117457766Selan #ifdef L_bb
117557766Selan /* Avoid warning from ranlib about empty object file. */
117657766Selan void
__bb_avoid_warning()117757766Selan __bb_avoid_warning ()
117857766Selan {}
117957766Selan
118057766Selan #if defined (__sun__) && defined (__mc68000__)
118157766Selan struct bb
118257766Selan {
118357766Selan int initialized;
118457766Selan char *filename;
118557766Selan int *counts;
118657766Selan int ncounts;
118757766Selan int zero_word;
118857766Selan int *addresses;
118957766Selan };
119057766Selan
119157766Selan extern int ___tcov_init;
119257766Selan
119357766Selan __bb_init_func (blocks)
119457766Selan struct bb *blocks;
119557766Selan {
119657766Selan if (! ___tcov_init)
119757766Selan ___tcov_init_func ();
119857766Selan
119957766Selan ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);
120057766Selan }
120157766Selan
120257766Selan #endif
120357766Selan #endif
120457766Selan
120557766Selan /* frills for C++ */
120657766Selan
120757766Selan #ifdef L_builtin_new
1208*60378Selan
1209*60378Selan #include <sys/types.h>
1210*60378Selan
121157766Selan typedef void (*vfp)(void);
121257766Selan
121357766Selan extern vfp __new_handler;
121457766Selan
121557766Selan void *
__builtin_new(sz)121657766Selan __builtin_new (sz)
121757766Selan size_t sz;
121857766Selan {
121957766Selan void *p;
122057766Selan
122157766Selan /* malloc (0) is unpredictable; avoid it. */
122257766Selan if (sz == 0)
122357766Selan sz = 1;
122457766Selan p = (void *) malloc (sz);
122557766Selan if (p == 0)
122657766Selan (*__new_handler) ();
122757766Selan return p;
122857766Selan }
122957766Selan #endif
123057766Selan
123157766Selan #ifdef L_caps_New
123257766Selan
123357766Selan /* This gets us __GNU_LIBRARY__. */
123457766Selan #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
123557766Selan #include <stdio.h>
1236*60378Selan #include <sys/types.h>
123757766Selan
123857766Selan #ifdef __GNU_LIBRARY__
123957766Selan /* Avoid forcing the library's meaning of `write' on the user program
124057766Selan by using the "internal" name (for use within the library) */
124157766Selan #define write(fd, buf, n) __write((fd), (buf), (n))
124257766Selan #endif
124357766Selan
124457766Selan typedef void (*vfp)(void);
124557766Selan
124657766Selan extern void *__builtin_new (size_t);
124757766Selan static void default_new_handler (void);
124857766Selan
124957766Selan vfp __new_handler = default_new_handler;
125057766Selan
1251*60378Selan
125257766Selan void *
__builtin_vec_new(p,maxindex,size,ctor)125357766Selan __builtin_vec_new (p, maxindex, size, ctor)
125457766Selan void *p;
125557766Selan size_t maxindex;
125657766Selan size_t size;
125757766Selan void (*ctor)(void *);
125857766Selan {
125957766Selan size_t i;
126057766Selan size_t nelts = maxindex + 1;
126157766Selan void *rval;
126257766Selan
126357766Selan if (p == 0)
126457766Selan p = __builtin_new (nelts * size);
126557766Selan
126657766Selan rval = p;
126757766Selan
126857766Selan for (i = 0; i < nelts; i++)
126957766Selan {
127057766Selan (*ctor) (p);
127157766Selan p += size;
127257766Selan }
127357766Selan
127457766Selan return rval;
127557766Selan }
127657766Selan
127757766Selan vfp
__set_new_handler(handler)127857766Selan __set_new_handler (handler)
127957766Selan vfp handler;
128057766Selan {
128157766Selan vfp prev_handler;
128257766Selan
128357766Selan prev_handler = __new_handler;
128457766Selan if (handler == 0) handler = default_new_handler;
128557766Selan __new_handler = handler;
128657766Selan return prev_handler;
128757766Selan }
128857766Selan
128957766Selan vfp
set_new_handler(handler)129057766Selan set_new_handler (handler)
129157766Selan vfp handler;
129257766Selan {
129357766Selan return __set_new_handler (handler);
129457766Selan }
129557766Selan
129657766Selan #define MESSAGE "Virtual memory exceeded in `new'\n"
129757766Selan
129857766Selan static void
default_new_handler()129957766Selan default_new_handler ()
130057766Selan {
130157766Selan /* don't use fprintf (stderr, ...) because it may need to call malloc. */
130257766Selan /* This should really print the name of the program, but that is hard to
130357766Selan do. We need a standard, clean way to get at the name. */
130457766Selan write (2, MESSAGE, sizeof (MESSAGE));
130557766Selan /* don't call exit () because that may call global destructors which
130657766Selan may cause a loop. */
130757766Selan _exit (-1);
130857766Selan }
130957766Selan #endif
131057766Selan
131157766Selan #ifdef L_builtin_del
1312*60378Selan
1313*60378Selan #include <sys/types.h>
1314*60378Selan
131557766Selan typedef void (*vfp)(void);
131657766Selan
131757766Selan void
__builtin_delete(ptr)131857766Selan __builtin_delete (ptr)
131957766Selan void *ptr;
132057766Selan {
132157766Selan if (ptr)
132257766Selan free (ptr);
132357766Selan }
132457766Selan
132557766Selan void
__builtin_vec_delete(ptr,maxindex,size,dtor,auto_delete_vec,auto_delete)132657766Selan __builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete)
132757766Selan void *ptr;
132857766Selan size_t maxindex;
132957766Selan size_t size;
133057766Selan void (*dtor)(void *, int);
133157766Selan int auto_delete;
133257766Selan {
133357766Selan size_t i;
133457766Selan size_t nelts = maxindex + 1;
133557766Selan void *p = ptr;
133657766Selan
133757766Selan ptr += nelts * size;
133857766Selan
133957766Selan for (i = 0; i < nelts; i++)
134057766Selan {
134157766Selan ptr -= size;
134257766Selan (*dtor) (ptr, auto_delete);
134357766Selan }
134457766Selan
134557766Selan if (auto_delete_vec)
134657766Selan __builtin_delete (p);
134757766Selan }
134857766Selan
134957766Selan #endif
135057766Selan
135157766Selan #ifdef L_shtab
135257766Selan unsigned int __shtab[] = {
135357766Selan 0x00000001, 0x00000002, 0x00000004, 0x00000008,
135457766Selan 0x00000010, 0x00000020, 0x00000040, 0x00000080,
135557766Selan 0x00000100, 0x00000200, 0x00000400, 0x00000800,
135657766Selan 0x00001000, 0x00002000, 0x00004000, 0x00008000,
135757766Selan 0x00010000, 0x00020000, 0x00040000, 0x00080000,
135857766Selan 0x00100000, 0x00200000, 0x00400000, 0x00800000,
135957766Selan 0x01000000, 0x02000000, 0x04000000, 0x08000000,
136057766Selan 0x10000000, 0x20000000, 0x40000000, 0x80000000
136157766Selan };
136257766Selan #endif
136357766Selan
136457766Selan #ifdef L_clear_cache
136557766Selan /* Clear part of an instruction cache. */
136657766Selan
136757766Selan #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
136857766Selan
136957766Selan void
__clear_cache(beg,end)137057766Selan __clear_cache (beg, end)
137157766Selan char *beg, *end;
137257766Selan {
137357766Selan #ifdef INSN_CACHE_SIZE
137457766Selan static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
137557766Selan static int initialized = 0;
137657766Selan int offset;
137757766Selan void *start_addr
137857766Selan void *end_addr;
137957766Selan typedef (*function_ptr) ();
138057766Selan
138157766Selan #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
138257766Selan /* It's cheaper to clear the whole cache.
138357766Selan Put in a series of jump instructions so that calling the beginning
138457766Selan of the cache will clear the whole thing. */
138557766Selan
138657766Selan if (! initialized)
138757766Selan {
138857766Selan int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
138957766Selan & -INSN_CACHE_LINE_WIDTH);
139057766Selan int end_ptr = ptr + INSN_CACHE_SIZE;
139157766Selan
139257766Selan while (ptr < end_ptr)
139357766Selan {
139457766Selan *(INSTRUCTION_TYPE *)ptr
139557766Selan = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
139657766Selan ptr += INSN_CACHE_LINE_WIDTH;
139757766Selan }
139857766Selan *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
139957766Selan
140057766Selan initialized = 1;
140157766Selan }
140257766Selan
140357766Selan /* Call the beginning of the sequence. */
140457766Selan (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
140557766Selan & -INSN_CACHE_LINE_WIDTH))
140657766Selan ());
140757766Selan
140857766Selan #else /* Cache is large. */
140957766Selan
141057766Selan if (! initialized)
141157766Selan {
141257766Selan int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
141357766Selan & -INSN_CACHE_LINE_WIDTH);
141457766Selan
141557766Selan while (ptr < (int) array + sizeof array)
141657766Selan {
141757766Selan *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
141857766Selan ptr += INSN_CACHE_LINE_WIDTH;
141957766Selan }
142057766Selan
142157766Selan initialized = 1;
142257766Selan }
142357766Selan
142457766Selan /* Find the location in array that occupies the same cache line as BEG. */
142557766Selan
142657766Selan offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
142757766Selan start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
142857766Selan & -INSN_CACHE_PLANE_SIZE)
142957766Selan + offset);
143057766Selan
143157766Selan /* Compute the cache alignment of the place to stop clearing. */
143257766Selan #if 0 /* This is not needed for gcc's purposes. */
143357766Selan /* If the block to clear is bigger than a cache plane,
143457766Selan we clear the entire cache, and OFFSET is already correct. */
143557766Selan if (end < beg + INSN_CACHE_PLANE_SIZE)
143657766Selan #endif
143757766Selan offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
143857766Selan & -INSN_CACHE_LINE_WIDTH)
143957766Selan & (INSN_CACHE_PLANE_SIZE - 1));
144057766Selan
144157766Selan #if INSN_CACHE_DEPTH > 1
144257766Selan end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
144357766Selan if (end_addr <= start_addr)
144457766Selan end_addr += INSN_CACHE_PLANE_SIZE;
144557766Selan
144657766Selan for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
144757766Selan {
144857766Selan int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
144957766Selan int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
145057766Selan
145157766Selan while (addr != stop)
145257766Selan {
145357766Selan /* Call the return instruction at ADDR. */
145457766Selan ((function_ptr) addr) ();
145557766Selan
145657766Selan addr += INSN_CACHE_LINE_WIDTH;
145757766Selan }
145857766Selan }
145957766Selan #else /* just one plane */
146057766Selan do
146157766Selan {
146257766Selan /* Call the return instruction at START_ADDR. */
146357766Selan ((function_ptr) start_addr) ();
146457766Selan
146557766Selan start_addr += INSN_CACHE_LINE_WIDTH;
146657766Selan }
146757766Selan while ((start_addr % INSN_CACHE_SIZE) != offset);
146857766Selan #endif /* just one plane */
146957766Selan #endif /* Cache is large */
147057766Selan #endif /* Cache exists */
147157766Selan }
147257766Selan
147357766Selan #endif /* L_clear_cache */
147457766Selan
147557766Selan #ifdef L_trampoline
147657766Selan
147757766Selan /* Jump to a trampoline, loading the static chain address. */
147857766Selan
147957766Selan #ifdef TRANSFER_FROM_TRAMPOLINE
148057766Selan TRANSFER_FROM_TRAMPOLINE
148157766Selan #endif
148257766Selan
148357766Selan #ifdef __convex__
148457766Selan
148557766Selan /* Make stack executable so we can call trampolines on stack.
148657766Selan This is called from INITIALIZE_TRAMPOLINE in convex.h. */
148757766Selan
148857766Selan #include <sys/mman.h>
148957766Selan #include <sys/vmparam.h>
149057766Selan #include <machine/machparam.h>
149157766Selan
149257766Selan void
__enable_execute_stack()149357766Selan __enable_execute_stack ()
149457766Selan {
149557766Selan int fp;
149657766Selan static unsigned lowest = USRSTACK;
149757766Selan unsigned current = (unsigned) &fp & -NBPG;
149857766Selan
149957766Selan if (lowest > current)
150057766Selan {
150157766Selan unsigned len = lowest - current;
150257766Selan mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
150357766Selan lowest = current;
150457766Selan }
150557766Selan
150657766Selan /* Clear instruction cache in case an old trampoline is in it. */
150757766Selan asm ("pich");
150857766Selan }
150957766Selan #endif /* __convex__ */
151057766Selan
151157766Selan #ifdef __pyr__
151257766Selan
151357766Selan #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
151457766Selan #include <stdio.h>
151557766Selan #include <sys/mman.h>
151657766Selan #include <sys/types.h>
151757766Selan #include <sys/param.h>
151857766Selan #include <sys/vmmac.h>
151957766Selan
152057766Selan /* Modified from the convex -code above.
152157766Selan mremap promises to clear the i-cache. */
152257766Selan
152357766Selan void
__enable_execute_stack()152457766Selan __enable_execute_stack ()
152557766Selan {
152657766Selan int fp;
152757766Selan if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
152857766Selan PROT_READ|PROT_WRITE|PROT_EXEC))
152957766Selan {
153057766Selan perror ("mprotect in __enable_execute_stack");
153157766Selan fflush (stderr);
153257766Selan abort ();
153357766Selan }
153457766Selan }
153557766Selan #endif /* __pyr__ */
153657766Selan #endif /* L_trampoline */
153757766Selan
153857766Selan #ifdef L__main
153957766Selan
154057766Selan #include "gbl-ctors.h"
154157766Selan
154257766Selan /* Run all the global destructors on exit from the program. */
154357766Selan
154457766Selan void
__do_global_dtors()154557766Selan __do_global_dtors ()
154657766Selan {
154757766Selan #ifdef DO_GLOBAL_DTORS_BODY
154857766Selan DO_GLOBAL_DTORS_BODY;
154957766Selan #else
155057766Selan unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0];
155157766Selan unsigned i;
155257766Selan
155357766Selan /* Some systems place the number of pointers
155457766Selan in the first word of the table.
155557766Selan On other systems, that word is -1.
155657766Selan In all cases, the table is null-terminated. */
155757766Selan
155857766Selan /* If the length is not recorded, count up to the null. */
155957766Selan if (nptrs == -1)
156057766Selan for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
156157766Selan
156257766Selan /* GNU LD format. */
156357766Selan for (i = nptrs; i >= 1; i--)
156457766Selan __DTOR_LIST__[i] ();
156557766Selan #endif
156657766Selan }
156757766Selan
156857766Selan #ifndef INIT_SECTION_ASM_OP
156957766Selan /* Run all the global constructors on entry to the program. */
157057766Selan
157157766Selan #ifndef ON_EXIT
157257766Selan #define ON_EXIT(a, b)
157357766Selan #else
157457766Selan /* Make sure the exit routine is pulled in to define the globals as
157557766Selan bss symbols, just in case the linker does not automatically pull
157657766Selan bss definitions from the library. */
157757766Selan
157857766Selan extern int _exit_dummy_decl;
157957766Selan int *_exit_dummy_ref = &_exit_dummy_decl;
158057766Selan #endif /* ON_EXIT */
158157766Selan
158257766Selan void
__do_global_ctors()158357766Selan __do_global_ctors ()
158457766Selan {
158557766Selan DO_GLOBAL_CTORS_BODY;
158657766Selan ON_EXIT (__do_global_dtors, 0);
158757766Selan }
158857766Selan #endif /* no INIT_SECTION_ASM_OP */
158957766Selan
159057766Selan #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
159157766Selan /* Subroutine called automatically by `main'.
159257766Selan Compiling a global function named `main'
159357766Selan produces an automatic call to this function at the beginning.
159457766Selan
159557766Selan For many systems, this routine calls __do_global_ctors.
159657766Selan For systems which support a .init section we use the .init section
159757766Selan to run __do_global_ctors, so we need not do anything here. */
159857766Selan
159957766Selan void
__main()160057766Selan __main ()
160157766Selan {
160257766Selan /* Support recursive calls to `main': run initializers just once. */
160357766Selan static int initialized = 0;
160457766Selan if (! initialized)
160557766Selan {
160657766Selan initialized = 1;
160757766Selan __do_global_ctors ();
160857766Selan }
160957766Selan }
161057766Selan #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
161157766Selan
161257766Selan #endif /* L__main */
161357766Selan
161457766Selan #ifdef L_ctors
161557766Selan
161657766Selan #include "gbl-ctors.h"
161757766Selan
161857766Selan /* Provide default definitions for the lists of constructors and
161957766Selan destructors, so that we don't get linker errors. These symbols are
162057766Selan intentionally bss symbols, so that gld and/or collect will provide
162157766Selan the right values. */
162257766Selan
162357766Selan /* We declare the lists here with two elements each,
162457766Selan so that they are valid empty lists if no other definition is loaded. */
162557766Selan #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
162657766Selan #ifdef __NeXT__
162757766Selan /* After 2.3, try this definition on all systems. */
162857766Selan func_ptr __CTOR_LIST__[2] = {0, 0};
162957766Selan func_ptr __DTOR_LIST__[2] = {0, 0};
163057766Selan #else
163157766Selan func_ptr __CTOR_LIST__[2];
163257766Selan func_ptr __DTOR_LIST__[2];
163357766Selan #endif
163457766Selan #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
163557766Selan #endif /* L_ctors */
163657766Selan
163757766Selan #ifdef L_exit
163857766Selan
163957766Selan #include "gbl-ctors.h"
164057766Selan
164157766Selan #ifndef ON_EXIT
164257766Selan
164357766Selan /* If we have no known way of registering our own __do_global_dtors
164457766Selan routine so that it will be invoked at program exit time, then we
164557766Selan have to define our own exit routine which will get this to happen. */
164657766Selan
164757766Selan extern void __do_global_dtors ();
164857766Selan extern void _cleanup ();
164957766Selan extern volatile void _exit ();
165057766Selan
165157766Selan void
exit(status)165257766Selan exit (status)
165357766Selan int status;
165457766Selan {
165557766Selan __do_global_dtors ();
165657766Selan #ifdef EXIT_BODY
165757766Selan EXIT_BODY;
165857766Selan #else
165957766Selan _cleanup ();
166057766Selan #endif
166157766Selan _exit (status);
166257766Selan }
166357766Selan
166457766Selan #else
166557766Selan int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */
166657766Selan #endif
166757766Selan
166857766Selan #endif /* L_exit */
166957766Selan
167057766Selan /* In a.out systems, we need to have these dummy constructor and destructor
167157766Selan lists in the library.
167257766Selan
167357766Selan When using `collect', the first link will resolve __CTOR_LIST__
167457766Selan and __DTOR_LIST__ to these symbols. We will then run "nm" on the
167557766Selan result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink.
167657766Selan Since we don't do the second link if no constructors existed, these
167757766Selan dummies must be fully functional empty lists.
167857766Selan
167957766Selan When using `gnu ld', these symbols will be used if there are no
168057766Selan constructors. If there are constructors, the N_SETV symbol defined
168157766Selan by the linker from the N_SETT's in input files will define __CTOR_LIST__
168257766Selan and __DTOR_LIST__ rather than its being allocated as common storage
168357766Selan by the definitions below.
168457766Selan
168557766Selan When using a linker that supports constructor and destructor segments,
168657766Selan these definitions will not be used, since crtbegin.o and crtend.o
168757766Selan (from crtstuff.c) will have already defined __CTOR_LIST__ and
168857766Selan __DTOR_LIST__. The crt*.o files are passed directly to the linker
168957766Selan on its command line, by gcc. */
169057766Selan
169157766Selan /* The list needs two elements: one is ignored (the old count); the
169257766Selan second is the terminating zero. Since both values are zero, this
169357766Selan declaration is not initialized, and it becomes `common'. */
169457766Selan
169557766Selan #ifdef L_ctor_list
169657766Selan #include "gbl-ctors.h"
169757766Selan func_ptr __CTOR_LIST__[2];
169857766Selan #endif
169957766Selan
170057766Selan #ifdef L_dtor_list
170157766Selan #include "gbl-ctors.h"
170257766Selan func_ptr __DTOR_LIST__[2];
170357766Selan #endif
1704