xref: /csrg-svn/contrib/gcc-2.3.3/libgcc2.c (revision 60378)
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