xref: /csrg-svn/contrib/gcc-2.3.3/libgcc2.c (revision 57766)
1*57766Selan /* More subroutines needed by GCC output code on some machines.  */
2*57766Selan /* Compile this one with gcc.  */
3*57766Selan /* Copyright (C) 1989, 1992 Free Software Foundation, Inc.
4*57766Selan 
5*57766Selan This file is part of GNU CC.
6*57766Selan 
7*57766Selan GNU CC is free software; you can redistribute it and/or modify
8*57766Selan it under the terms of the GNU General Public License as published by
9*57766Selan the Free Software Foundation; either version 2, or (at your option)
10*57766Selan any later version.
11*57766Selan 
12*57766Selan GNU CC is distributed in the hope that it will be useful,
13*57766Selan but WITHOUT ANY WARRANTY; without even the implied warranty of
14*57766Selan MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*57766Selan GNU General Public License for more details.
16*57766Selan 
17*57766Selan You should have received a copy of the GNU General Public License
18*57766Selan along with GNU CC; see the file COPYING.  If not, write to
19*57766Selan the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20*57766Selan 
21*57766Selan /* As a special exception, if you link this library with files
22*57766Selan    compiled with GCC to produce an executable, this does not cause
23*57766Selan    the resulting executable to be covered by the GNU General Public License.
24*57766Selan    This exception does not however invalidate any other reasons why
25*57766Selan    the executable file might be covered by the GNU General Public License.  */
26*57766Selan 
27*57766Selan /* It is incorrect to include config.h here, because this file is being
28*57766Selan    compiled for the target, and hence definitions concerning only the host
29*57766Selan    do not apply.  */
30*57766Selan 
31*57766Selan #include "tconfig.h"
32*57766Selan #include "machmode.h"
33*57766Selan #ifndef L_trampoline
34*57766Selan #include "gstddef.h"
35*57766Selan #endif
36*57766Selan 
37*57766Selan /* Don't use `fancy_abort' here even if config.h says to use it.  */
38*57766Selan #ifdef abort
39*57766Selan #undef abort
40*57766Selan #endif
41*57766Selan 
42*57766Selan /* In the first part of this file, we are interfacing to calls generated
43*57766Selan    by the compiler itself.  These calls pass values into these routines
44*57766Selan    which have very specific modes (rather than very specific types), and
45*57766Selan    these compiler-generated calls also expect any return values to have
46*57766Selan    very specific modes (rather than very specific types).  Thus, we need
47*57766Selan    to avoid using regular C language type names in this part of the file
48*57766Selan    because the sizes for those types can be configured to be anything.
49*57766Selan    Instead we use the following special type names.  */
50*57766Selan 
51*57766Selan typedef unsigned int UQItype	__attribute__ ((mode (QI)));
52*57766Selan typedef 	 int SItype	__attribute__ ((mode (SI)));
53*57766Selan typedef unsigned int USItype	__attribute__ ((mode (SI)));
54*57766Selan typedef		 int DItype	__attribute__ ((mode (DI)));
55*57766Selan typedef unsigned int UDItype	__attribute__ ((mode (DI)));
56*57766Selan typedef 	float SFtype	__attribute__ ((mode (SF)));
57*57766Selan typedef		float DFtype	__attribute__ ((mode (DF)));
58*57766Selan #if 0
59*57766Selan typedef		float XFtype	__attribute__ ((mode (XF)));
60*57766Selan #endif
61*57766Selan #if LONG_DOUBLE_TYPE_SIZE == 128
62*57766Selan typedef		float TFtype	__attribute__ ((mode (TF)));
63*57766Selan #endif
64*57766Selan 
65*57766Selan /* Make sure that we don't accidentaly use any normal C language built-in
66*57766Selan    type names in the first part of this file.  Instead we want to use *only*
67*57766Selan    the type names defined above.  The following macro definitions insure
68*57766Selan    that if we *do* accidently use soem normal C language built-in type name,
69*57766Selan    we will get a syntax error.  */
70*57766Selan 
71*57766Selan #define char bogus_type
72*57766Selan #define short bogus_type
73*57766Selan #define int bogus_type
74*57766Selan #define long bogus_type
75*57766Selan #define unsigned bogus_type
76*57766Selan #define float bogus_type
77*57766Selan #define double bogus_type
78*57766Selan 
79*57766Selan #define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
80*57766Selan 
81*57766Selan /* DIstructs are pairs of SItype values in the order determined by
82*57766Selan    WORDS_BIG_ENDIAN.  */
83*57766Selan 
84*57766Selan #if WORDS_BIG_ENDIAN
85*57766Selan   struct DIstruct {SItype high, low;};
86*57766Selan #else
87*57766Selan   struct DIstruct {SItype low, high;};
88*57766Selan #endif
89*57766Selan 
90*57766Selan /* We need this union to unpack/pack DImode values, since we don't have
91*57766Selan    any arithmetic yet.  Incoming DImode parameters are stored into the
92*57766Selan    `ll' field, and the unpacked result is read from the struct `s'.  */
93*57766Selan 
94*57766Selan typedef union
95*57766Selan {
96*57766Selan   struct DIstruct s;
97*57766Selan   DItype ll;
98*57766Selan } DIunion;
99*57766Selan 
100*57766Selan #if defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)
101*57766Selan 
102*57766Selan #include "longlong.h"
103*57766Selan 
104*57766Selan #endif /* udiv or mul */
105*57766Selan 
106*57766Selan extern DItype __fixunssfdi (SFtype a);
107*57766Selan extern DItype __fixunsdfdi (DFtype a);
108*57766Selan 
109*57766Selan #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
110*57766Selan #if defined (L_divdi3) || defined (L_moddi3)
111*57766Selan static inline
112*57766Selan #endif
113*57766Selan DItype
114*57766Selan __negdi2 (u)
115*57766Selan      DItype u;
116*57766Selan {
117*57766Selan   DIunion w;
118*57766Selan   DIunion uu;
119*57766Selan 
120*57766Selan   uu.ll = u;
121*57766Selan 
122*57766Selan   w.s.low = -uu.s.low;
123*57766Selan   w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
124*57766Selan 
125*57766Selan   return w.ll;
126*57766Selan }
127*57766Selan #endif
128*57766Selan 
129*57766Selan #ifdef L_lshldi3
130*57766Selan DItype
131*57766Selan __lshldi3 (u, b)
132*57766Selan      DItype u;
133*57766Selan      SItype b;
134*57766Selan {
135*57766Selan   DIunion w;
136*57766Selan   SItype bm;
137*57766Selan   DIunion uu;
138*57766Selan 
139*57766Selan   if (b == 0)
140*57766Selan     return u;
141*57766Selan 
142*57766Selan   uu.ll = u;
143*57766Selan 
144*57766Selan   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
145*57766Selan   if (bm <= 0)
146*57766Selan     {
147*57766Selan       w.s.low = 0;
148*57766Selan       w.s.high = (USItype)uu.s.low << -bm;
149*57766Selan     }
150*57766Selan   else
151*57766Selan     {
152*57766Selan       USItype carries = (USItype)uu.s.low >> bm;
153*57766Selan       w.s.low = (USItype)uu.s.low << b;
154*57766Selan       w.s.high = ((USItype)uu.s.high << b) | carries;
155*57766Selan     }
156*57766Selan 
157*57766Selan   return w.ll;
158*57766Selan }
159*57766Selan #endif
160*57766Selan 
161*57766Selan #ifdef L_lshrdi3
162*57766Selan DItype
163*57766Selan __lshrdi3 (u, b)
164*57766Selan      DItype u;
165*57766Selan      SItype b;
166*57766Selan {
167*57766Selan   DIunion w;
168*57766Selan   SItype bm;
169*57766Selan   DIunion uu;
170*57766Selan 
171*57766Selan   if (b == 0)
172*57766Selan     return u;
173*57766Selan 
174*57766Selan   uu.ll = u;
175*57766Selan 
176*57766Selan   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
177*57766Selan   if (bm <= 0)
178*57766Selan     {
179*57766Selan       w.s.high = 0;
180*57766Selan       w.s.low = (USItype)uu.s.high >> -bm;
181*57766Selan     }
182*57766Selan   else
183*57766Selan     {
184*57766Selan       USItype carries = (USItype)uu.s.high << bm;
185*57766Selan       w.s.high = (USItype)uu.s.high >> b;
186*57766Selan       w.s.low = ((USItype)uu.s.low >> b) | carries;
187*57766Selan     }
188*57766Selan 
189*57766Selan   return w.ll;
190*57766Selan }
191*57766Selan #endif
192*57766Selan 
193*57766Selan #ifdef L_ashldi3
194*57766Selan DItype
195*57766Selan __ashldi3 (u, b)
196*57766Selan      DItype u;
197*57766Selan      SItype b;
198*57766Selan {
199*57766Selan   DIunion w;
200*57766Selan   SItype bm;
201*57766Selan   DIunion uu;
202*57766Selan 
203*57766Selan   if (b == 0)
204*57766Selan     return u;
205*57766Selan 
206*57766Selan   uu.ll = u;
207*57766Selan 
208*57766Selan   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
209*57766Selan   if (bm <= 0)
210*57766Selan     {
211*57766Selan       w.s.low = 0;
212*57766Selan       w.s.high = (USItype)uu.s.low << -bm;
213*57766Selan     }
214*57766Selan   else
215*57766Selan     {
216*57766Selan       USItype carries = (USItype)uu.s.low >> bm;
217*57766Selan       w.s.low = (USItype)uu.s.low << b;
218*57766Selan       w.s.high = ((USItype)uu.s.high << b) | carries;
219*57766Selan     }
220*57766Selan 
221*57766Selan   return w.ll;
222*57766Selan }
223*57766Selan #endif
224*57766Selan 
225*57766Selan #ifdef L_ashrdi3
226*57766Selan DItype
227*57766Selan __ashrdi3 (u, b)
228*57766Selan      DItype u;
229*57766Selan      SItype b;
230*57766Selan {
231*57766Selan   DIunion w;
232*57766Selan   SItype bm;
233*57766Selan   DIunion uu;
234*57766Selan 
235*57766Selan   if (b == 0)
236*57766Selan     return u;
237*57766Selan 
238*57766Selan   uu.ll = u;
239*57766Selan 
240*57766Selan   bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
241*57766Selan   if (bm <= 0)
242*57766Selan     {
243*57766Selan       /* w.s.high = 1..1 or 0..0 */
244*57766Selan       w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
245*57766Selan       w.s.low = uu.s.high >> -bm;
246*57766Selan     }
247*57766Selan   else
248*57766Selan     {
249*57766Selan       USItype carries = (USItype)uu.s.high << bm;
250*57766Selan       w.s.high = uu.s.high >> b;
251*57766Selan       w.s.low = ((USItype)uu.s.low >> b) | carries;
252*57766Selan     }
253*57766Selan 
254*57766Selan   return w.ll;
255*57766Selan }
256*57766Selan #endif
257*57766Selan 
258*57766Selan #ifdef L_muldi3
259*57766Selan DItype
260*57766Selan __muldi3 (u, v)
261*57766Selan      DItype u, v;
262*57766Selan {
263*57766Selan   DIunion w;
264*57766Selan   DIunion uu, vv;
265*57766Selan 
266*57766Selan   uu.ll = u,
267*57766Selan   vv.ll = v;
268*57766Selan 
269*57766Selan   w.ll = __umulsidi3 (uu.s.low, vv.s.low);
270*57766Selan   w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
271*57766Selan 	       + (USItype) uu.s.high * (USItype) vv.s.low);
272*57766Selan 
273*57766Selan   return w.ll;
274*57766Selan }
275*57766Selan #endif
276*57766Selan 
277*57766Selan #ifdef L_udiv_w_sdiv
278*57766Selan USItype
279*57766Selan __udiv_w_sdiv (rp, a1, a0, d)
280*57766Selan      USItype *rp, a1, a0, d;
281*57766Selan {
282*57766Selan   USItype q, r;
283*57766Selan   USItype c0, c1, b1;
284*57766Selan 
285*57766Selan   if ((SItype) d >= 0)
286*57766Selan     {
287*57766Selan       if (a1 < d - a1 - (a0 >> 31))
288*57766Selan 	{
289*57766Selan 	  /* dividend, divisor, and quotient are nonnegative */
290*57766Selan 	  sdiv_qrnnd (q, r, a1, a0, d);
291*57766Selan 	}
292*57766Selan       else
293*57766Selan 	{
294*57766Selan 	  /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
295*57766Selan 	  sub_ddmmss (c1, c0, a1, a0, d >> 1, d << 31);
296*57766Selan 	  /* Divide (c1*2^32 + c0) by d */
297*57766Selan 	  sdiv_qrnnd (q, r, c1, c0, d);
298*57766Selan 	  /* Add 2^31 to quotient */
299*57766Selan 	  q += (USItype) 1 << 31;
300*57766Selan 	}
301*57766Selan     }
302*57766Selan   else
303*57766Selan     {
304*57766Selan       b1 = d >> 1;			/* d/2, between 2^30 and 2^31 - 1 */
305*57766Selan       c1 = a1 >> 1;			/* A/2 */
306*57766Selan       c0 = (a1 << 31) + (a0 >> 1);
307*57766Selan 
308*57766Selan       if (a1 < b1)			/* A < 2^32*b1, so A/2 < 2^31*b1 */
309*57766Selan 	{
310*57766Selan 	  sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
311*57766Selan 
312*57766Selan 	  r = 2*r + (a0 & 1);		/* Remainder from A/(2*b1) */
313*57766Selan 	  if ((d & 1) != 0)
314*57766Selan 	    {
315*57766Selan 	      if (r >= q)
316*57766Selan 		r = r - q;
317*57766Selan 	      else if (q - r <= d)
318*57766Selan 		{
319*57766Selan 		  r = r - q + d;
320*57766Selan 		  q--;
321*57766Selan 		}
322*57766Selan 	      else
323*57766Selan 		{
324*57766Selan 		  r = r - q + 2*d;
325*57766Selan 		  q -= 2;
326*57766Selan 		}
327*57766Selan 	    }
328*57766Selan 	}
329*57766Selan       else if (c1 < b1)			/* So 2^31 <= (A/2)/b1 < 2^32 */
330*57766Selan 	{
331*57766Selan 	  c1 = (b1 - 1) - c1;
332*57766Selan 	  c0 = ~c0;			/* logical NOT */
333*57766Selan 
334*57766Selan 	  sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
335*57766Selan 
336*57766Selan 	  q = ~q;			/* (A/2)/b1 */
337*57766Selan 	  r = (b1 - 1) - r;
338*57766Selan 
339*57766Selan 	  r = 2*r + (a0 & 1);		/* A/(2*b1) */
340*57766Selan 
341*57766Selan 	  if ((d & 1) != 0)
342*57766Selan 	    {
343*57766Selan 	      if (r >= q)
344*57766Selan 		r = r - q;
345*57766Selan 	      else if (q - r <= d)
346*57766Selan 		{
347*57766Selan 		  r = r - q + d;
348*57766Selan 		  q--;
349*57766Selan 		}
350*57766Selan 	      else
351*57766Selan 		{
352*57766Selan 		  r = r - q + 2*d;
353*57766Selan 		  q -= 2;
354*57766Selan 		}
355*57766Selan 	    }
356*57766Selan 	}
357*57766Selan       else				/* Implies c1 = b1 */
358*57766Selan 	{				/* Hence a1 = d - 1 = 2*b1 - 1 */
359*57766Selan 	  if (a0 >= -d)
360*57766Selan 	    {
361*57766Selan 	      q = -1;
362*57766Selan 	      r = a0 + d;
363*57766Selan 	    }
364*57766Selan 	  else
365*57766Selan 	    {
366*57766Selan 	      q = -2;
367*57766Selan 	      r = a0 + 2*d;
368*57766Selan 	    }
369*57766Selan 	}
370*57766Selan     }
371*57766Selan 
372*57766Selan   *rp = r;
373*57766Selan   return q;
374*57766Selan }
375*57766Selan #endif
376*57766Selan 
377*57766Selan #ifdef L_udivmoddi4
378*57766Selan static const UQItype __clz_tab[] =
379*57766Selan {
380*57766Selan   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,
381*57766Selan   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,
382*57766Selan   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,
383*57766Selan   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,
384*57766Selan   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,
385*57766Selan   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,
386*57766Selan   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,
387*57766Selan   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,
388*57766Selan };
389*57766Selan 
390*57766Selan UDItype
391*57766Selan __udivmoddi4 (n, d, rp)
392*57766Selan      UDItype n, d;
393*57766Selan      UDItype *rp;
394*57766Selan {
395*57766Selan   DIunion ww;
396*57766Selan   DIunion nn, dd;
397*57766Selan   DIunion rr;
398*57766Selan   USItype d0, d1, n0, n1, n2;
399*57766Selan   USItype q0, q1;
400*57766Selan   USItype b, bm;
401*57766Selan 
402*57766Selan   nn.ll = n;
403*57766Selan   dd.ll = d;
404*57766Selan 
405*57766Selan   d0 = dd.s.low;
406*57766Selan   d1 = dd.s.high;
407*57766Selan   n0 = nn.s.low;
408*57766Selan   n1 = nn.s.high;
409*57766Selan 
410*57766Selan #if !UDIV_NEEDS_NORMALIZATION
411*57766Selan   if (d1 == 0)
412*57766Selan     {
413*57766Selan       if (d0 > n1)
414*57766Selan 	{
415*57766Selan 	  /* 0q = nn / 0D */
416*57766Selan 
417*57766Selan 	  udiv_qrnnd (q0, n0, n1, n0, d0);
418*57766Selan 	  q1 = 0;
419*57766Selan 
420*57766Selan 	  /* Remainder in n0.  */
421*57766Selan 	}
422*57766Selan       else
423*57766Selan 	{
424*57766Selan 	  /* qq = NN / 0d */
425*57766Selan 
426*57766Selan 	  if (d0 == 0)
427*57766Selan 	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
428*57766Selan 
429*57766Selan 	  udiv_qrnnd (q1, n1, 0, n1, d0);
430*57766Selan 	  udiv_qrnnd (q0, n0, n1, n0, d0);
431*57766Selan 
432*57766Selan 	  /* Remainder in n0.  */
433*57766Selan 	}
434*57766Selan 
435*57766Selan       if (rp != 0)
436*57766Selan 	{
437*57766Selan 	  rr.s.low = n0;
438*57766Selan 	  rr.s.high = 0;
439*57766Selan 	  *rp = rr.ll;
440*57766Selan 	}
441*57766Selan     }
442*57766Selan 
443*57766Selan #else /* UDIV_NEEDS_NORMALIZATION */
444*57766Selan 
445*57766Selan   if (d1 == 0)
446*57766Selan     {
447*57766Selan       if (d0 > n1)
448*57766Selan 	{
449*57766Selan 	  /* 0q = nn / 0D */
450*57766Selan 
451*57766Selan 	  count_leading_zeros (bm, d0);
452*57766Selan 
453*57766Selan 	  if (bm != 0)
454*57766Selan 	    {
455*57766Selan 	      /* Normalize, i.e. make the most significant bit of the
456*57766Selan 		 denominator set.  */
457*57766Selan 
458*57766Selan 	      d0 = d0 << bm;
459*57766Selan 	      n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
460*57766Selan 	      n0 = n0 << bm;
461*57766Selan 	    }
462*57766Selan 
463*57766Selan 	  udiv_qrnnd (q0, n0, n1, n0, d0);
464*57766Selan 	  q1 = 0;
465*57766Selan 
466*57766Selan 	  /* Remainder in n0 >> bm.  */
467*57766Selan 	}
468*57766Selan       else
469*57766Selan 	{
470*57766Selan 	  /* qq = NN / 0d */
471*57766Selan 
472*57766Selan 	  if (d0 == 0)
473*57766Selan 	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
474*57766Selan 
475*57766Selan 	  count_leading_zeros (bm, d0);
476*57766Selan 
477*57766Selan 	  if (bm == 0)
478*57766Selan 	    {
479*57766Selan 	      /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
480*57766Selan 		 conclude (the most significant bit of n1 is set) /\ (the
481*57766Selan 		 leading quotient digit q1 = 1).
482*57766Selan 
483*57766Selan 		 This special case is necessary, not an optimization.
484*57766Selan 		 (Shifts counts of SI_TYPE_SIZE are undefined.)  */
485*57766Selan 
486*57766Selan 	      n1 -= d0;
487*57766Selan 	      q1 = 1;
488*57766Selan 	    }
489*57766Selan 	  else
490*57766Selan 	    {
491*57766Selan 	      /* Normalize.  */
492*57766Selan 
493*57766Selan 	      b = SI_TYPE_SIZE - bm;
494*57766Selan 
495*57766Selan 	      d0 = d0 << bm;
496*57766Selan 	      n2 = n1 >> b;
497*57766Selan 	      n1 = (n1 << bm) | (n0 >> b);
498*57766Selan 	      n0 = n0 << bm;
499*57766Selan 
500*57766Selan 	      udiv_qrnnd (q1, n1, n2, n1, d0);
501*57766Selan 	    }
502*57766Selan 
503*57766Selan 	  /* n1 != d0... */
504*57766Selan 
505*57766Selan 	  udiv_qrnnd (q0, n0, n1, n0, d0);
506*57766Selan 
507*57766Selan 	  /* Remainder in n0 >> bm.  */
508*57766Selan 	}
509*57766Selan 
510*57766Selan       if (rp != 0)
511*57766Selan 	{
512*57766Selan 	  rr.s.low = n0 >> bm;
513*57766Selan 	  rr.s.high = 0;
514*57766Selan 	  *rp = rr.ll;
515*57766Selan 	}
516*57766Selan     }
517*57766Selan #endif /* UDIV_NEEDS_NORMALIZATION */
518*57766Selan 
519*57766Selan   else
520*57766Selan     {
521*57766Selan       if (d1 > n1)
522*57766Selan 	{
523*57766Selan 	  /* 00 = nn / DD */
524*57766Selan 
525*57766Selan 	  q0 = 0;
526*57766Selan 	  q1 = 0;
527*57766Selan 
528*57766Selan 	  /* Remainder in n1n0.  */
529*57766Selan 	  if (rp != 0)
530*57766Selan 	    {
531*57766Selan 	      rr.s.low = n0;
532*57766Selan 	      rr.s.high = n1;
533*57766Selan 	      *rp = rr.ll;
534*57766Selan 	    }
535*57766Selan 	}
536*57766Selan       else
537*57766Selan 	{
538*57766Selan 	  /* 0q = NN / dd */
539*57766Selan 
540*57766Selan 	  count_leading_zeros (bm, d1);
541*57766Selan 	  if (bm == 0)
542*57766Selan 	    {
543*57766Selan 	      /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
544*57766Selan 		 conclude (the most significant bit of n1 is set) /\ (the
545*57766Selan 		 quotient digit q0 = 0 or 1).
546*57766Selan 
547*57766Selan 		 This special case is necessary, not an optimization.  */
548*57766Selan 
549*57766Selan 	      /* The condition on the next line takes advantage of that
550*57766Selan 		 n1 >= d1 (true due to program flow).  */
551*57766Selan 	      if (n1 > d1 || n0 >= d0)
552*57766Selan 		{
553*57766Selan 		  q0 = 1;
554*57766Selan 		  sub_ddmmss (n1, n0, n1, n0, d1, d0);
555*57766Selan 		}
556*57766Selan 	      else
557*57766Selan 		q0 = 0;
558*57766Selan 
559*57766Selan 	      q1 = 0;
560*57766Selan 
561*57766Selan 	      if (rp != 0)
562*57766Selan 		{
563*57766Selan 		  rr.s.low = n0;
564*57766Selan 		  rr.s.high = n1;
565*57766Selan 		  *rp = rr.ll;
566*57766Selan 		}
567*57766Selan 	    }
568*57766Selan 	  else
569*57766Selan 	    {
570*57766Selan 	      USItype m1, m0;
571*57766Selan 	      /* Normalize.  */
572*57766Selan 
573*57766Selan 	      b = SI_TYPE_SIZE - bm;
574*57766Selan 
575*57766Selan 	      d1 = (d1 << bm) | (d0 >> b);
576*57766Selan 	      d0 = d0 << bm;
577*57766Selan 	      n2 = n1 >> b;
578*57766Selan 	      n1 = (n1 << bm) | (n0 >> b);
579*57766Selan 	      n0 = n0 << bm;
580*57766Selan 
581*57766Selan 	      udiv_qrnnd (q0, n1, n2, n1, d1);
582*57766Selan 	      umul_ppmm (m1, m0, q0, d0);
583*57766Selan 
584*57766Selan 	      if (m1 > n1 || (m1 == n1 && m0 > n0))
585*57766Selan 		{
586*57766Selan 		  q0--;
587*57766Selan 		  sub_ddmmss (m1, m0, m1, m0, d1, d0);
588*57766Selan 		}
589*57766Selan 
590*57766Selan 	      q1 = 0;
591*57766Selan 
592*57766Selan 	      /* Remainder in (n1n0 - m1m0) >> bm.  */
593*57766Selan 	      if (rp != 0)
594*57766Selan 		{
595*57766Selan 		  sub_ddmmss (n1, n0, n1, n0, m1, m0);
596*57766Selan 		  rr.s.low = (n1 << b) | (n0 >> bm);
597*57766Selan 		  rr.s.high = n1 >> bm;
598*57766Selan 		  *rp = rr.ll;
599*57766Selan 		}
600*57766Selan 	    }
601*57766Selan 	}
602*57766Selan     }
603*57766Selan 
604*57766Selan   ww.s.low = q0;
605*57766Selan   ww.s.high = q1;
606*57766Selan   return ww.ll;
607*57766Selan }
608*57766Selan #endif
609*57766Selan 
610*57766Selan #ifdef L_divdi3
611*57766Selan UDItype __udivmoddi4 ();
612*57766Selan DItype
613*57766Selan __divdi3 (u, v)
614*57766Selan      DItype u, v;
615*57766Selan {
616*57766Selan   SItype c = 0;
617*57766Selan   DIunion uu, vv;
618*57766Selan   DItype w;
619*57766Selan 
620*57766Selan   uu.ll = u;
621*57766Selan   vv.ll = v;
622*57766Selan 
623*57766Selan   if (uu.s.high < 0)
624*57766Selan     c = ~c,
625*57766Selan     uu.ll = __negdi2 (uu.ll);
626*57766Selan   if (vv.s.high < 0)
627*57766Selan     c = ~c,
628*57766Selan     vv.ll = __negdi2 (vv.ll);
629*57766Selan 
630*57766Selan   w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
631*57766Selan   if (c)
632*57766Selan     w = __negdi2 (w);
633*57766Selan 
634*57766Selan   return w;
635*57766Selan }
636*57766Selan #endif
637*57766Selan 
638*57766Selan #ifdef L_moddi3
639*57766Selan UDItype __udivmoddi4 ();
640*57766Selan DItype
641*57766Selan __moddi3 (u, v)
642*57766Selan      DItype u, v;
643*57766Selan {
644*57766Selan   SItype c = 0;
645*57766Selan   DIunion uu, vv;
646*57766Selan   DItype w;
647*57766Selan 
648*57766Selan   uu.ll = u;
649*57766Selan   vv.ll = v;
650*57766Selan 
651*57766Selan   if (uu.s.high < 0)
652*57766Selan     c = ~c,
653*57766Selan     uu.ll = __negdi2 (uu.ll);
654*57766Selan   if (vv.s.high < 0)
655*57766Selan     vv.ll = __negdi2 (vv.ll);
656*57766Selan 
657*57766Selan   (void) __udivmoddi4 (uu.ll, vv.ll, &w);
658*57766Selan   if (c)
659*57766Selan     w = __negdi2 (w);
660*57766Selan 
661*57766Selan   return w;
662*57766Selan }
663*57766Selan #endif
664*57766Selan 
665*57766Selan #ifdef L_umoddi3
666*57766Selan UDItype __udivmoddi4 ();
667*57766Selan UDItype
668*57766Selan __umoddi3 (u, v)
669*57766Selan      UDItype u, v;
670*57766Selan {
671*57766Selan   DItype w;
672*57766Selan 
673*57766Selan   (void) __udivmoddi4 (u, v, &w);
674*57766Selan 
675*57766Selan   return w;
676*57766Selan }
677*57766Selan #endif
678*57766Selan 
679*57766Selan #ifdef L_udivdi3
680*57766Selan UDItype __udivmoddi4 ();
681*57766Selan UDItype
682*57766Selan __udivdi3 (n, d)
683*57766Selan      UDItype n, d;
684*57766Selan {
685*57766Selan   return __udivmoddi4 (n, d, (UDItype *) 0);
686*57766Selan }
687*57766Selan #endif
688*57766Selan 
689*57766Selan #ifdef L_cmpdi2
690*57766Selan SItype
691*57766Selan __cmpdi2 (a, b)
692*57766Selan      DItype a, b;
693*57766Selan {
694*57766Selan   DIunion au, bu;
695*57766Selan 
696*57766Selan   au.ll = a, bu.ll = b;
697*57766Selan 
698*57766Selan   if (au.s.high < bu.s.high)
699*57766Selan     return 0;
700*57766Selan   else if (au.s.high > bu.s.high)
701*57766Selan     return 2;
702*57766Selan   if ((USItype) au.s.low < (USItype) bu.s.low)
703*57766Selan     return 0;
704*57766Selan   else if ((USItype) au.s.low > (USItype) bu.s.low)
705*57766Selan     return 2;
706*57766Selan   return 1;
707*57766Selan }
708*57766Selan #endif
709*57766Selan 
710*57766Selan #ifdef L_ucmpdi2
711*57766Selan SItype
712*57766Selan __ucmpdi2 (a, b)
713*57766Selan      DItype a, b;
714*57766Selan {
715*57766Selan   DIunion au, bu;
716*57766Selan 
717*57766Selan   au.ll = a, bu.ll = b;
718*57766Selan 
719*57766Selan   if ((USItype) au.s.high < (USItype) bu.s.high)
720*57766Selan     return 0;
721*57766Selan   else if ((USItype) au.s.high > (USItype) bu.s.high)
722*57766Selan     return 2;
723*57766Selan   if ((USItype) au.s.low < (USItype) bu.s.low)
724*57766Selan     return 0;
725*57766Selan   else if ((USItype) au.s.low > (USItype) bu.s.low)
726*57766Selan     return 2;
727*57766Selan   return 1;
728*57766Selan }
729*57766Selan #endif
730*57766Selan 
731*57766Selan #if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
732*57766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
733*57766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
734*57766Selan 
735*57766Selan DItype
736*57766Selan __fixunstfdi (a)
737*57766Selan      TFtype a;
738*57766Selan {
739*57766Selan   TFtype b;
740*57766Selan   UDItype v;
741*57766Selan 
742*57766Selan   if (a < 0)
743*57766Selan     return 0;
744*57766Selan 
745*57766Selan   /* Compute high word of result, as a flonum.  */
746*57766Selan   b = (a / HIGH_WORD_COEFF);
747*57766Selan   /* Convert that to fixed (but not to DItype!),
748*57766Selan      and shift it into the high word.  */
749*57766Selan   v = (USItype) b;
750*57766Selan   v <<= WORD_SIZE;
751*57766Selan   /* Remove high part from the TFtype, leaving the low part as flonum.  */
752*57766Selan   a -= (TFtype)v;
753*57766Selan   /* Convert that to fixed (but not to DItype!) and add it in.
754*57766Selan      Sometimes A comes out negative.  This is significant, since
755*57766Selan      A has more bits than a long int does.  */
756*57766Selan   if (a < 0)
757*57766Selan     v -= (USItype) (- a);
758*57766Selan   else
759*57766Selan     v += (USItype) a;
760*57766Selan   return v;
761*57766Selan }
762*57766Selan #endif
763*57766Selan 
764*57766Selan #if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
765*57766Selan DItype
766*57766Selan __fixtfdi (a)
767*57766Selan      TFtype a;
768*57766Selan {
769*57766Selan   if (a < 0)
770*57766Selan     return - __fixunstfdi (-a);
771*57766Selan   return __fixunstfdi (a);
772*57766Selan }
773*57766Selan #endif
774*57766Selan 
775*57766Selan #ifdef L_fixunsdfdi
776*57766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
777*57766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
778*57766Selan 
779*57766Selan DItype
780*57766Selan __fixunsdfdi (a)
781*57766Selan      DFtype a;
782*57766Selan {
783*57766Selan   DFtype b;
784*57766Selan   UDItype v;
785*57766Selan 
786*57766Selan   if (a < 0)
787*57766Selan     return 0;
788*57766Selan 
789*57766Selan   /* Compute high word of result, as a flonum.  */
790*57766Selan   b = (a / HIGH_WORD_COEFF);
791*57766Selan   /* Convert that to fixed (but not to DItype!),
792*57766Selan      and shift it into the high word.  */
793*57766Selan   v = (USItype) b;
794*57766Selan   v <<= WORD_SIZE;
795*57766Selan   /* Remove high part from the DFtype, leaving the low part as flonum.  */
796*57766Selan   a -= (DFtype)v;
797*57766Selan   /* Convert that to fixed (but not to DItype!) and add it in.
798*57766Selan      Sometimes A comes out negative.  This is significant, since
799*57766Selan      A has more bits than a long int does.  */
800*57766Selan   if (a < 0)
801*57766Selan     v -= (USItype) (- a);
802*57766Selan   else
803*57766Selan     v += (USItype) a;
804*57766Selan   return v;
805*57766Selan }
806*57766Selan #endif
807*57766Selan 
808*57766Selan #ifdef L_fixdfdi
809*57766Selan DItype
810*57766Selan __fixdfdi (a)
811*57766Selan      DFtype a;
812*57766Selan {
813*57766Selan   if (a < 0)
814*57766Selan     return - __fixunsdfdi (-a);
815*57766Selan   return __fixunsdfdi (a);
816*57766Selan }
817*57766Selan #endif
818*57766Selan 
819*57766Selan #ifdef L_fixunssfdi
820*57766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
821*57766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
822*57766Selan 
823*57766Selan DItype
824*57766Selan __fixunssfdi (SFtype original_a)
825*57766Selan {
826*57766Selan   /* Convert the SFtype to a DFtype, because that is surely not going
827*57766Selan      to lose any bits.  Some day someone else can write a faster version
828*57766Selan      that avoids converting to DFtype, and verify it really works right.  */
829*57766Selan   DFtype a = original_a;
830*57766Selan   DFtype b;
831*57766Selan   UDItype v;
832*57766Selan 
833*57766Selan   if (a < 0)
834*57766Selan     return 0;
835*57766Selan 
836*57766Selan   /* Compute high word of result, as a flonum.  */
837*57766Selan   b = (a / HIGH_WORD_COEFF);
838*57766Selan   /* Convert that to fixed (but not to DItype!),
839*57766Selan      and shift it into the high word.  */
840*57766Selan   v = (USItype) b;
841*57766Selan   v <<= WORD_SIZE;
842*57766Selan   /* Remove high part from the DFtype, leaving the low part as flonum.  */
843*57766Selan   a -= (DFtype)v;
844*57766Selan   /* Convert that to fixed (but not to DItype!) and add it in.
845*57766Selan      Sometimes A comes out negative.  This is significant, since
846*57766Selan      A has more bits than a long int does.  */
847*57766Selan   if (a < 0)
848*57766Selan     v -= (USItype) (- a);
849*57766Selan   else
850*57766Selan     v += (USItype) a;
851*57766Selan   return v;
852*57766Selan }
853*57766Selan #endif
854*57766Selan 
855*57766Selan #ifdef L_fixsfdi
856*57766Selan DItype
857*57766Selan __fixsfdi (SFtype a)
858*57766Selan {
859*57766Selan   if (a < 0)
860*57766Selan     return - __fixunssfdi (-a);
861*57766Selan   return __fixunssfdi (a);
862*57766Selan }
863*57766Selan #endif
864*57766Selan 
865*57766Selan #if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
866*57766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
867*57766Selan #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
868*57766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
869*57766Selan 
870*57766Selan TFtype
871*57766Selan __floatditf (u)
872*57766Selan      DItype u;
873*57766Selan {
874*57766Selan   TFtype d;
875*57766Selan   SItype negate = 0;
876*57766Selan 
877*57766Selan   if (u < 0)
878*57766Selan     u = -u, negate = 1;
879*57766Selan 
880*57766Selan   d = (USItype) (u >> WORD_SIZE);
881*57766Selan   d *= HIGH_HALFWORD_COEFF;
882*57766Selan   d *= HIGH_HALFWORD_COEFF;
883*57766Selan   d += (USItype) (u & (HIGH_WORD_COEFF - 1));
884*57766Selan 
885*57766Selan   return (negate ? -d : d);
886*57766Selan }
887*57766Selan #endif
888*57766Selan 
889*57766Selan #ifdef L_floatdidf
890*57766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
891*57766Selan #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
892*57766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
893*57766Selan 
894*57766Selan DFtype
895*57766Selan __floatdidf (u)
896*57766Selan      DItype u;
897*57766Selan {
898*57766Selan   DFtype d;
899*57766Selan   SItype negate = 0;
900*57766Selan 
901*57766Selan   if (u < 0)
902*57766Selan     u = -u, negate = 1;
903*57766Selan 
904*57766Selan   d = (USItype) (u >> WORD_SIZE);
905*57766Selan   d *= HIGH_HALFWORD_COEFF;
906*57766Selan   d *= HIGH_HALFWORD_COEFF;
907*57766Selan   d += (USItype) (u & (HIGH_WORD_COEFF - 1));
908*57766Selan 
909*57766Selan   return (negate ? -d : d);
910*57766Selan }
911*57766Selan #endif
912*57766Selan 
913*57766Selan #ifdef L_floatdisf
914*57766Selan #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
915*57766Selan #define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
916*57766Selan #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
917*57766Selan 
918*57766Selan SFtype
919*57766Selan __floatdisf (u)
920*57766Selan      DItype u;
921*57766Selan {
922*57766Selan   SFtype f;
923*57766Selan   SItype negate = 0;
924*57766Selan 
925*57766Selan   if (u < 0)
926*57766Selan     u = -u, negate = 1;
927*57766Selan 
928*57766Selan   f = (USItype) (u >> WORD_SIZE);
929*57766Selan   f *= HIGH_HALFWORD_COEFF;
930*57766Selan   f *= HIGH_HALFWORD_COEFF;
931*57766Selan   f += (USItype) (u & (HIGH_WORD_COEFF - 1));
932*57766Selan 
933*57766Selan   return (negate ? -f : f);
934*57766Selan }
935*57766Selan #endif
936*57766Selan 
937*57766Selan #ifdef L_fixunsdfsi
938*57766Selan #include "glimits.h"
939*57766Selan 
940*57766Selan USItype
941*57766Selan __fixunsdfsi (a)
942*57766Selan      DFtype a;
943*57766Selan {
944*57766Selan   if (a >= - (DFtype) LONG_MIN)
945*57766Selan     return (SItype) (a + LONG_MIN) - LONG_MIN;
946*57766Selan   return (SItype) a;
947*57766Selan }
948*57766Selan #endif
949*57766Selan 
950*57766Selan #ifdef L_fixunssfsi
951*57766Selan #include "glimits.h"
952*57766Selan 
953*57766Selan USItype
954*57766Selan __fixunssfsi (SFtype a)
955*57766Selan {
956*57766Selan   if (a >= - (SFtype) LONG_MIN)
957*57766Selan     return (SItype) (a + LONG_MIN) - LONG_MIN;
958*57766Selan   return (SItype) a;
959*57766Selan }
960*57766Selan #endif
961*57766Selan 
962*57766Selan /* From here on down, the routines use normal data types.  */
963*57766Selan 
964*57766Selan #define SItype bogus_type
965*57766Selan #define USItype bogus_type
966*57766Selan #define DItype bogus_type
967*57766Selan #define UDItype bogus_type
968*57766Selan #define SFtype bogus_type
969*57766Selan #define DFtype bogus_type
970*57766Selan 
971*57766Selan #undef char
972*57766Selan #undef short
973*57766Selan #undef int
974*57766Selan #undef long
975*57766Selan #undef unsigned
976*57766Selan #undef float
977*57766Selan #undef double
978*57766Selan 
979*57766Selan #ifdef L__gcc_bcmp
980*57766Selan 
981*57766Selan /* Like bcmp except the sign is meaningful.
982*57766Selan    Reult is negative if S1 is less than S2,
983*57766Selan    positive if S1 is greater, 0 if S1 and S2 are equal.  */
984*57766Selan 
985*57766Selan int
986*57766Selan __gcc_bcmp (s1, s2, size)
987*57766Selan      unsigned char *s1, *s2;
988*57766Selan      size_t size;
989*57766Selan {
990*57766Selan   while (size > 0)
991*57766Selan     {
992*57766Selan       unsigned char c1 = *s1++, c2 = *s2++;
993*57766Selan       if (c1 != c2)
994*57766Selan 	return c1 - c2;
995*57766Selan       size--;
996*57766Selan     }
997*57766Selan   return 0;
998*57766Selan }
999*57766Selan 
1000*57766Selan #endif
1001*57766Selan 
1002*57766Selan #ifdef L_varargs
1003*57766Selan #ifdef __i860__
1004*57766Selan #if defined(__svr4__) || defined(__alliant__)
1005*57766Selan 	asm ("	.text");
1006*57766Selan 	asm ("	.align	4");
1007*57766Selan 
1008*57766Selan /* The Alliant needs the added underscore.  */
1009*57766Selan 	asm (".globl	__builtin_saveregs");
1010*57766Selan asm ("__builtin_saveregs:");
1011*57766Selan 	asm (".globl	___builtin_saveregs");
1012*57766Selan asm ("___builtin_saveregs:");
1013*57766Selan 
1014*57766Selan         asm ("	andnot	0x0f,%sp,%sp");	/* round down to 16-byte boundary */
1015*57766Selan 	asm ("	adds	-96,%sp,%sp");  /* allocate stack space for reg save
1016*57766Selan 					   area and also for a new va_list
1017*57766Selan 					   structure */
1018*57766Selan 	/* Save all argument registers in the arg reg save area.  The
1019*57766Selan 	   arg reg save area must have the following layout (according
1020*57766Selan 	   to the svr4 ABI):
1021*57766Selan 
1022*57766Selan 		struct {
1023*57766Selan 		  union  {
1024*57766Selan 		    float freg[8];
1025*57766Selan 		    double dreg[4];
1026*57766Selan 		  } float_regs;
1027*57766Selan 		  long	ireg[12];
1028*57766Selan 		};
1029*57766Selan 	*/
1030*57766Selan 
1031*57766Selan 	asm ("	fst.q	%f8,  0(%sp)"); /* save floating regs (f8-f15)  */
1032*57766Selan 	asm ("	fst.q	%f12,16(%sp)");
1033*57766Selan 
1034*57766Selan 	asm ("	st.l	%r16,32(%sp)"); /* save integer regs (r16-r27) */
1035*57766Selan 	asm ("	st.l	%r17,36(%sp)");
1036*57766Selan 	asm ("	st.l	%r18,40(%sp)");
1037*57766Selan 	asm ("	st.l	%r19,44(%sp)");
1038*57766Selan 	asm ("	st.l	%r20,48(%sp)");
1039*57766Selan 	asm ("	st.l	%r21,52(%sp)");
1040*57766Selan 	asm ("	st.l	%r22,56(%sp)");
1041*57766Selan 	asm ("	st.l	%r23,60(%sp)");
1042*57766Selan 	asm ("	st.l	%r24,64(%sp)");
1043*57766Selan 	asm ("	st.l	%r25,68(%sp)");
1044*57766Selan 	asm ("	st.l	%r26,72(%sp)");
1045*57766Selan 	asm ("	st.l	%r27,76(%sp)");
1046*57766Selan 
1047*57766Selan 	asm ("	adds	80,%sp,%r16");  /* compute the address of the new
1048*57766Selan 					   va_list structure.  Put in into
1049*57766Selan 					   r16 so that it will be returned
1050*57766Selan 					   to the caller.  */
1051*57766Selan 
1052*57766Selan 	/* Initialize all fields of the new va_list structure.  This
1053*57766Selan 	   structure looks like:
1054*57766Selan 
1055*57766Selan 		typedef struct {
1056*57766Selan 		    unsigned long	ireg_used;
1057*57766Selan 		    unsigned long	freg_used;
1058*57766Selan 		    long		*reg_base;
1059*57766Selan 		    long		*mem_ptr;
1060*57766Selan 		} va_list;
1061*57766Selan 	*/
1062*57766Selan 
1063*57766Selan 	asm ("	st.l	%r0, 0(%r16)"); /* nfixed */
1064*57766Selan 	asm ("	st.l	%r0, 4(%r16)"); /* nfloating */
1065*57766Selan 	asm ("  st.l    %sp, 8(%r16)"); /* __va_ctl points to __va_struct.  */
1066*57766Selan 	asm ("	bri	%r1");		/* delayed return */
1067*57766Selan 	asm ("	st.l	%r28,12(%r16)"); /* pointer to overflow args */
1068*57766Selan 
1069*57766Selan #else /* not __SVR4__ */
1070*57766Selan 	asm ("	.text");
1071*57766Selan 	asm ("	.align	4");
1072*57766Selan 
1073*57766Selan 	asm (".globl	___builtin_saveregs");
1074*57766Selan 	asm ("___builtin_saveregs:");
1075*57766Selan 	asm ("	mov	sp,r30");
1076*57766Selan 	asm ("	andnot	0x0f,sp,sp");
1077*57766Selan 	asm ("	adds	-96,sp,sp");  /* allocate sufficient space on the stack */
1078*57766Selan 
1079*57766Selan /* Fill in the __va_struct.  */
1080*57766Selan 	asm ("	st.l	r16, 0(sp)"); /* save integer regs (r16-r27) */
1081*57766Selan 	asm ("	st.l	r17, 4(sp)"); /* int	fixed[12] */
1082*57766Selan 	asm ("	st.l	r18, 8(sp)");
1083*57766Selan 	asm ("	st.l	r19,12(sp)");
1084*57766Selan 	asm ("	st.l	r20,16(sp)");
1085*57766Selan 	asm ("	st.l	r21,20(sp)");
1086*57766Selan 	asm ("	st.l	r22,24(sp)");
1087*57766Selan 	asm ("	st.l	r23,28(sp)");
1088*57766Selan 	asm ("	st.l	r24,32(sp)");
1089*57766Selan 	asm ("	st.l	r25,36(sp)");
1090*57766Selan 	asm ("	st.l	r26,40(sp)");
1091*57766Selan 	asm ("	st.l	r27,44(sp)");
1092*57766Selan 
1093*57766Selan 	asm ("	fst.q	f8, 48(sp)"); /* save floating regs (f8-f15) */
1094*57766Selan 	asm ("	fst.q	f12,64(sp)"); /* int floating[8] */
1095*57766Selan 
1096*57766Selan /* Fill in the __va_ctl.  */
1097*57766Selan 	asm ("  st.l    sp, 80(sp)"); /* __va_ctl points to __va_struct.  */
1098*57766Selan 	asm ("	st.l	r28,84(sp)"); /* pointer to more args */
1099*57766Selan 	asm ("	st.l	r0, 88(sp)"); /* nfixed */
1100*57766Selan 	asm ("	st.l	r0, 92(sp)"); /* nfloating */
1101*57766Selan 
1102*57766Selan 	asm ("	adds	80,sp,r16");  /* return address of the __va_ctl.  */
1103*57766Selan 	asm ("	bri	r1");
1104*57766Selan 	asm ("	mov	r30,sp");
1105*57766Selan 				/* recover stack and pass address to start
1106*57766Selan 				   of data.  */
1107*57766Selan #endif /* not __SVR4__ */
1108*57766Selan #else /* not __i860__ */
1109*57766Selan #ifdef __sparc__
1110*57766Selan 	asm (".global __builtin_saveregs");
1111*57766Selan 	asm ("__builtin_saveregs:");
1112*57766Selan 	asm (".global ___builtin_saveregs");
1113*57766Selan 	asm ("___builtin_saveregs:");
1114*57766Selan #ifdef NEED_PROC_COMMAND
1115*57766Selan 	asm (".proc 020");
1116*57766Selan #endif
1117*57766Selan 	asm ("st %i0,[%fp+68]");
1118*57766Selan 	asm ("st %i1,[%fp+72]");
1119*57766Selan 	asm ("st %i2,[%fp+76]");
1120*57766Selan 	asm ("st %i3,[%fp+80]");
1121*57766Selan 	asm ("st %i4,[%fp+84]");
1122*57766Selan 	asm ("retl");
1123*57766Selan 	asm ("st %i5,[%fp+88]");
1124*57766Selan #ifdef NEED_TYPE_COMMAND
1125*57766Selan 	asm (".type __builtin_saveregs,#function");
1126*57766Selan 	asm (".size __builtin_saveregs,.-__builtin_saveregs");
1127*57766Selan #endif
1128*57766Selan #else /* not __sparc__ */
1129*57766Selan #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1130*57766Selan 
1131*57766Selan   asm ("	.text");
1132*57766Selan   asm ("	.ent __builtin_saveregs");
1133*57766Selan   asm ("	.globl __builtin_saveregs");
1134*57766Selan   asm ("__builtin_saveregs:");
1135*57766Selan   asm ("	sw	$4,0($30)");
1136*57766Selan   asm ("	sw	$5,4($30)");
1137*57766Selan   asm ("	sw	$6,8($30)");
1138*57766Selan   asm ("	sw	$7,12($30)");
1139*57766Selan   asm ("	j	$31");
1140*57766Selan   asm ("	.end __builtin_saveregs");
1141*57766Selan #else /* not __mips__, etc. */
1142*57766Selan __builtin_saveregs ()
1143*57766Selan {
1144*57766Selan   abort ();
1145*57766Selan }
1146*57766Selan #endif /* not __mips__ */
1147*57766Selan #endif /* not __sparc__ */
1148*57766Selan #endif /* not __i860__ */
1149*57766Selan #endif
1150*57766Selan 
1151*57766Selan #ifdef L_eprintf
1152*57766Selan #ifndef inhibit_eprintf
1153*57766Selan 
1154*57766Selan #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1155*57766Selan #include <stdio.h>
1156*57766Selan /* This is used by the `assert' macro.  */
1157*57766Selan void
1158*57766Selan __eprintf (string, expression, line, filename)
1159*57766Selan      const char *string;
1160*57766Selan      const char *expression;
1161*57766Selan      int line;
1162*57766Selan      const char *filename;
1163*57766Selan {
1164*57766Selan   fprintf (stderr, string, expression, line, filename);
1165*57766Selan   fflush (stderr);
1166*57766Selan   abort ();
1167*57766Selan }
1168*57766Selan 
1169*57766Selan #endif
1170*57766Selan #endif
1171*57766Selan 
1172*57766Selan #ifdef L_bb
1173*57766Selan /* Avoid warning from ranlib about empty object file.  */
1174*57766Selan void
1175*57766Selan __bb_avoid_warning ()
1176*57766Selan {}
1177*57766Selan 
1178*57766Selan #if defined (__sun__) && defined (__mc68000__)
1179*57766Selan struct bb
1180*57766Selan {
1181*57766Selan   int initialized;
1182*57766Selan   char *filename;
1183*57766Selan   int *counts;
1184*57766Selan   int ncounts;
1185*57766Selan   int zero_word;
1186*57766Selan   int *addresses;
1187*57766Selan };
1188*57766Selan 
1189*57766Selan extern int ___tcov_init;
1190*57766Selan 
1191*57766Selan __bb_init_func (blocks)
1192*57766Selan 	struct bb *blocks;
1193*57766Selan {
1194*57766Selan   if (! ___tcov_init)
1195*57766Selan     ___tcov_init_func ();
1196*57766Selan 
1197*57766Selan   ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);
1198*57766Selan }
1199*57766Selan 
1200*57766Selan #endif
1201*57766Selan #endif
1202*57766Selan 
1203*57766Selan /* frills for C++ */
1204*57766Selan 
1205*57766Selan #ifdef L_builtin_new
1206*57766Selan typedef void (*vfp)(void);
1207*57766Selan 
1208*57766Selan extern vfp __new_handler;
1209*57766Selan 
1210*57766Selan void *
1211*57766Selan __builtin_new (sz)
1212*57766Selan      size_t sz;
1213*57766Selan {
1214*57766Selan   void *p;
1215*57766Selan 
1216*57766Selan   /* malloc (0) is unpredictable; avoid it.  */
1217*57766Selan   if (sz == 0)
1218*57766Selan     sz = 1;
1219*57766Selan   p = (void *) malloc (sz);
1220*57766Selan   if (p == 0)
1221*57766Selan     (*__new_handler) ();
1222*57766Selan   return p;
1223*57766Selan }
1224*57766Selan #endif
1225*57766Selan 
1226*57766Selan #ifdef L_caps_New
1227*57766Selan 
1228*57766Selan /* This gets us __GNU_LIBRARY__.  */
1229*57766Selan #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1230*57766Selan #include <stdio.h>
1231*57766Selan 
1232*57766Selan #ifdef __GNU_LIBRARY__
1233*57766Selan   /* Avoid forcing the library's meaning of `write' on the user program
1234*57766Selan      by using the "internal" name (for use within the library)  */
1235*57766Selan #define write(fd, buf, n)	__write((fd), (buf), (n))
1236*57766Selan #endif
1237*57766Selan 
1238*57766Selan typedef void (*vfp)(void);
1239*57766Selan 
1240*57766Selan extern void *__builtin_new (size_t);
1241*57766Selan static void default_new_handler (void);
1242*57766Selan 
1243*57766Selan vfp __new_handler = default_new_handler;
1244*57766Selan 
1245*57766Selan void *
1246*57766Selan __builtin_vec_new (p, maxindex, size, ctor)
1247*57766Selan      void *p;
1248*57766Selan      size_t maxindex;
1249*57766Selan      size_t size;
1250*57766Selan      void (*ctor)(void *);
1251*57766Selan {
1252*57766Selan   size_t i;
1253*57766Selan   size_t nelts = maxindex + 1;
1254*57766Selan   void *rval;
1255*57766Selan 
1256*57766Selan   if (p == 0)
1257*57766Selan     p = __builtin_new (nelts * size);
1258*57766Selan 
1259*57766Selan   rval = p;
1260*57766Selan 
1261*57766Selan   for (i = 0; i < nelts; i++)
1262*57766Selan     {
1263*57766Selan       (*ctor) (p);
1264*57766Selan       p += size;
1265*57766Selan     }
1266*57766Selan 
1267*57766Selan   return rval;
1268*57766Selan }
1269*57766Selan 
1270*57766Selan vfp
1271*57766Selan __set_new_handler (handler)
1272*57766Selan      vfp handler;
1273*57766Selan {
1274*57766Selan   vfp prev_handler;
1275*57766Selan 
1276*57766Selan   prev_handler = __new_handler;
1277*57766Selan   if (handler == 0) handler = default_new_handler;
1278*57766Selan   __new_handler = handler;
1279*57766Selan   return prev_handler;
1280*57766Selan }
1281*57766Selan 
1282*57766Selan vfp
1283*57766Selan set_new_handler (handler)
1284*57766Selan      vfp handler;
1285*57766Selan {
1286*57766Selan   return __set_new_handler (handler);
1287*57766Selan }
1288*57766Selan 
1289*57766Selan #define MESSAGE "Virtual memory exceeded in `new'\n"
1290*57766Selan 
1291*57766Selan static void
1292*57766Selan default_new_handler ()
1293*57766Selan {
1294*57766Selan   /* don't use fprintf (stderr, ...) because it may need to call malloc.  */
1295*57766Selan   /* This should really print the name of the program, but that is hard to
1296*57766Selan      do.  We need a standard, clean way to get at the name.  */
1297*57766Selan   write (2, MESSAGE, sizeof (MESSAGE));
1298*57766Selan   /* don't call exit () because that may call global destructors which
1299*57766Selan      may cause a loop.  */
1300*57766Selan   _exit (-1);
1301*57766Selan }
1302*57766Selan #endif
1303*57766Selan 
1304*57766Selan #ifdef L_builtin_del
1305*57766Selan typedef void (*vfp)(void);
1306*57766Selan 
1307*57766Selan void
1308*57766Selan __builtin_delete (ptr)
1309*57766Selan      void *ptr;
1310*57766Selan {
1311*57766Selan   if (ptr)
1312*57766Selan     free (ptr);
1313*57766Selan }
1314*57766Selan 
1315*57766Selan void
1316*57766Selan __builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete)
1317*57766Selan      void *ptr;
1318*57766Selan      size_t maxindex;
1319*57766Selan      size_t size;
1320*57766Selan      void (*dtor)(void *, int);
1321*57766Selan      int auto_delete;
1322*57766Selan {
1323*57766Selan   size_t i;
1324*57766Selan   size_t nelts = maxindex + 1;
1325*57766Selan   void *p = ptr;
1326*57766Selan 
1327*57766Selan   ptr += nelts * size;
1328*57766Selan 
1329*57766Selan   for (i = 0; i < nelts; i++)
1330*57766Selan     {
1331*57766Selan       ptr -= size;
1332*57766Selan       (*dtor) (ptr, auto_delete);
1333*57766Selan     }
1334*57766Selan 
1335*57766Selan   if (auto_delete_vec)
1336*57766Selan     __builtin_delete (p);
1337*57766Selan }
1338*57766Selan 
1339*57766Selan #endif
1340*57766Selan 
1341*57766Selan #ifdef L_shtab
1342*57766Selan unsigned int __shtab[] = {
1343*57766Selan     0x00000001, 0x00000002, 0x00000004, 0x00000008,
1344*57766Selan     0x00000010, 0x00000020, 0x00000040, 0x00000080,
1345*57766Selan     0x00000100, 0x00000200, 0x00000400, 0x00000800,
1346*57766Selan     0x00001000, 0x00002000, 0x00004000, 0x00008000,
1347*57766Selan     0x00010000, 0x00020000, 0x00040000, 0x00080000,
1348*57766Selan     0x00100000, 0x00200000, 0x00400000, 0x00800000,
1349*57766Selan     0x01000000, 0x02000000, 0x04000000, 0x08000000,
1350*57766Selan     0x10000000, 0x20000000, 0x40000000, 0x80000000
1351*57766Selan   };
1352*57766Selan #endif
1353*57766Selan 
1354*57766Selan #ifdef L_clear_cache
1355*57766Selan /* Clear part of an instruction cache.  */
1356*57766Selan 
1357*57766Selan #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
1358*57766Selan 
1359*57766Selan void
1360*57766Selan __clear_cache (beg, end)
1361*57766Selan      char *beg, *end;
1362*57766Selan {
1363*57766Selan #ifdef INSN_CACHE_SIZE
1364*57766Selan   static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
1365*57766Selan   static int initialized = 0;
1366*57766Selan   int offset;
1367*57766Selan   void *start_addr
1368*57766Selan   void *end_addr;
1369*57766Selan   typedef (*function_ptr) ();
1370*57766Selan 
1371*57766Selan #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
1372*57766Selan   /* It's cheaper to clear the whole cache.
1373*57766Selan      Put in a series of jump instructions so that calling the beginning
1374*57766Selan      of the cache will clear the whole thing.  */
1375*57766Selan 
1376*57766Selan   if (! initialized)
1377*57766Selan     {
1378*57766Selan       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1379*57766Selan 		 & -INSN_CACHE_LINE_WIDTH);
1380*57766Selan       int end_ptr = ptr + INSN_CACHE_SIZE;
1381*57766Selan 
1382*57766Selan       while (ptr < end_ptr)
1383*57766Selan 	{
1384*57766Selan 	  *(INSTRUCTION_TYPE *)ptr
1385*57766Selan 	    = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
1386*57766Selan 	  ptr += INSN_CACHE_LINE_WIDTH;
1387*57766Selan 	}
1388*57766Selan       *(INSTRUCTION_TYPE *)(ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
1389*57766Selan 
1390*57766Selan       initialized = 1;
1391*57766Selan     }
1392*57766Selan 
1393*57766Selan   /* Call the beginning of the sequence.  */
1394*57766Selan   (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1395*57766Selan 		    & -INSN_CACHE_LINE_WIDTH))
1396*57766Selan    ());
1397*57766Selan 
1398*57766Selan #else /* Cache is large.  */
1399*57766Selan 
1400*57766Selan   if (! initialized)
1401*57766Selan     {
1402*57766Selan       int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
1403*57766Selan 		 & -INSN_CACHE_LINE_WIDTH);
1404*57766Selan 
1405*57766Selan       while (ptr < (int) array + sizeof array)
1406*57766Selan 	{
1407*57766Selan 	  *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
1408*57766Selan 	  ptr += INSN_CACHE_LINE_WIDTH;
1409*57766Selan 	}
1410*57766Selan 
1411*57766Selan       initialized = 1;
1412*57766Selan     }
1413*57766Selan 
1414*57766Selan   /* Find the location in array that occupies the same cache line as BEG.  */
1415*57766Selan 
1416*57766Selan   offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
1417*57766Selan   start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
1418*57766Selan 		 & -INSN_CACHE_PLANE_SIZE)
1419*57766Selan 		+ offset);
1420*57766Selan 
1421*57766Selan   /* Compute the cache alignment of the place to stop clearing.  */
1422*57766Selan #if 0  /* This is not needed for gcc's purposes.  */
1423*57766Selan   /* If the block to clear is bigger than a cache plane,
1424*57766Selan      we clear the entire cache, and OFFSET is already correct.  */
1425*57766Selan   if (end < beg + INSN_CACHE_PLANE_SIZE)
1426*57766Selan #endif
1427*57766Selan     offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
1428*57766Selan 	       & -INSN_CACHE_LINE_WIDTH)
1429*57766Selan 	      & (INSN_CACHE_PLANE_SIZE - 1));
1430*57766Selan 
1431*57766Selan #if INSN_CACHE_DEPTH > 1
1432*57766Selan   end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
1433*57766Selan   if (end_addr <= start_addr)
1434*57766Selan     end_addr += INSN_CACHE_PLANE_SIZE;
1435*57766Selan 
1436*57766Selan   for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
1437*57766Selan     {
1438*57766Selan       int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
1439*57766Selan       int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
1440*57766Selan 
1441*57766Selan       while (addr != stop)
1442*57766Selan 	{
1443*57766Selan 	  /* Call the return instruction at ADDR.  */
1444*57766Selan 	  ((function_ptr) addr) ();
1445*57766Selan 
1446*57766Selan 	  addr += INSN_CACHE_LINE_WIDTH;
1447*57766Selan 	}
1448*57766Selan     }
1449*57766Selan #else /* just one plane */
1450*57766Selan   do
1451*57766Selan     {
1452*57766Selan       /* Call the return instruction at START_ADDR.  */
1453*57766Selan       ((function_ptr) start_addr) ();
1454*57766Selan 
1455*57766Selan       start_addr += INSN_CACHE_LINE_WIDTH;
1456*57766Selan     }
1457*57766Selan   while ((start_addr % INSN_CACHE_SIZE) != offset);
1458*57766Selan #endif /* just one plane */
1459*57766Selan #endif /* Cache is large */
1460*57766Selan #endif /* Cache exists */
1461*57766Selan }
1462*57766Selan 
1463*57766Selan #endif /* L_clear_cache */
1464*57766Selan 
1465*57766Selan #ifdef L_trampoline
1466*57766Selan 
1467*57766Selan /* Jump to a trampoline, loading the static chain address.  */
1468*57766Selan 
1469*57766Selan #ifdef TRANSFER_FROM_TRAMPOLINE
1470*57766Selan TRANSFER_FROM_TRAMPOLINE
1471*57766Selan #endif
1472*57766Selan 
1473*57766Selan #ifdef __convex__
1474*57766Selan 
1475*57766Selan /* Make stack executable so we can call trampolines on stack.
1476*57766Selan    This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
1477*57766Selan 
1478*57766Selan #include <sys/mman.h>
1479*57766Selan #include <sys/vmparam.h>
1480*57766Selan #include <machine/machparam.h>
1481*57766Selan 
1482*57766Selan void
1483*57766Selan __enable_execute_stack ()
1484*57766Selan {
1485*57766Selan   int fp;
1486*57766Selan   static unsigned lowest = USRSTACK;
1487*57766Selan   unsigned current = (unsigned) &fp & -NBPG;
1488*57766Selan 
1489*57766Selan   if (lowest > current)
1490*57766Selan     {
1491*57766Selan       unsigned len = lowest - current;
1492*57766Selan       mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
1493*57766Selan       lowest = current;
1494*57766Selan     }
1495*57766Selan 
1496*57766Selan   /* Clear instruction cache in case an old trampoline is in it. */
1497*57766Selan   asm ("pich");
1498*57766Selan }
1499*57766Selan #endif /* __convex__ */
1500*57766Selan 
1501*57766Selan #ifdef __pyr__
1502*57766Selan 
1503*57766Selan #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1504*57766Selan #include <stdio.h>
1505*57766Selan #include <sys/mman.h>
1506*57766Selan #include <sys/types.h>
1507*57766Selan #include <sys/param.h>
1508*57766Selan #include <sys/vmmac.h>
1509*57766Selan 
1510*57766Selan /* Modified from the convex -code above.
1511*57766Selan    mremap promises to clear the i-cache. */
1512*57766Selan 
1513*57766Selan void
1514*57766Selan __enable_execute_stack ()
1515*57766Selan {
1516*57766Selan   int fp;
1517*57766Selan   if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
1518*57766Selan 		PROT_READ|PROT_WRITE|PROT_EXEC))
1519*57766Selan     {
1520*57766Selan       perror ("mprotect in __enable_execute_stack");
1521*57766Selan       fflush (stderr);
1522*57766Selan       abort ();
1523*57766Selan     }
1524*57766Selan }
1525*57766Selan #endif /* __pyr__ */
1526*57766Selan #endif /* L_trampoline */
1527*57766Selan 
1528*57766Selan #ifdef L__main
1529*57766Selan 
1530*57766Selan #include "gbl-ctors.h"
1531*57766Selan 
1532*57766Selan /* Run all the global destructors on exit from the program.  */
1533*57766Selan 
1534*57766Selan void
1535*57766Selan __do_global_dtors ()
1536*57766Selan {
1537*57766Selan #ifdef DO_GLOBAL_DTORS_BODY
1538*57766Selan   DO_GLOBAL_DTORS_BODY;
1539*57766Selan #else
1540*57766Selan   unsigned nptrs = (unsigned HOST_WIDE_INT) __DTOR_LIST__[0];
1541*57766Selan   unsigned i;
1542*57766Selan 
1543*57766Selan   /* Some systems place the number of pointers
1544*57766Selan      in the first word of the table.
1545*57766Selan      On other systems, that word is -1.
1546*57766Selan      In all cases, the table is null-terminated.  */
1547*57766Selan 
1548*57766Selan   /* If the length is not recorded, count up to the null.  */
1549*57766Selan   if (nptrs == -1)
1550*57766Selan     for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++);
1551*57766Selan 
1552*57766Selan   /* GNU LD format.  */
1553*57766Selan   for (i = nptrs; i >= 1; i--)
1554*57766Selan     __DTOR_LIST__[i] ();
1555*57766Selan #endif
1556*57766Selan }
1557*57766Selan 
1558*57766Selan #ifndef INIT_SECTION_ASM_OP
1559*57766Selan /* Run all the global constructors on entry to the program.  */
1560*57766Selan 
1561*57766Selan #ifndef ON_EXIT
1562*57766Selan #define ON_EXIT(a, b)
1563*57766Selan #else
1564*57766Selan /* Make sure the exit routine is pulled in to define the globals as
1565*57766Selan    bss symbols, just in case the linker does not automatically pull
1566*57766Selan    bss definitions from the library.  */
1567*57766Selan 
1568*57766Selan extern int _exit_dummy_decl;
1569*57766Selan int *_exit_dummy_ref = &_exit_dummy_decl;
1570*57766Selan #endif /* ON_EXIT */
1571*57766Selan 
1572*57766Selan void
1573*57766Selan __do_global_ctors ()
1574*57766Selan {
1575*57766Selan   DO_GLOBAL_CTORS_BODY;
1576*57766Selan   ON_EXIT (__do_global_dtors, 0);
1577*57766Selan }
1578*57766Selan #endif /* no INIT_SECTION_ASM_OP */
1579*57766Selan 
1580*57766Selan #if !defined (INIT_SECTION_ASM_OP) || defined (INVOKE__main)
1581*57766Selan /* Subroutine called automatically by `main'.
1582*57766Selan    Compiling a global function named `main'
1583*57766Selan    produces an automatic call to this function at the beginning.
1584*57766Selan 
1585*57766Selan    For many systems, this routine calls __do_global_ctors.
1586*57766Selan    For systems which support a .init section we use the .init section
1587*57766Selan    to run __do_global_ctors, so we need not do anything here.  */
1588*57766Selan 
1589*57766Selan void
1590*57766Selan __main ()
1591*57766Selan {
1592*57766Selan   /* Support recursive calls to `main': run initializers just once.  */
1593*57766Selan   static int initialized = 0;
1594*57766Selan   if (! initialized)
1595*57766Selan     {
1596*57766Selan       initialized = 1;
1597*57766Selan       __do_global_ctors ();
1598*57766Selan     }
1599*57766Selan }
1600*57766Selan #endif /* no INIT_SECTION_ASM_OP or INVOKE__main */
1601*57766Selan 
1602*57766Selan #endif /* L__main */
1603*57766Selan 
1604*57766Selan #ifdef L_ctors
1605*57766Selan 
1606*57766Selan #include "gbl-ctors.h"
1607*57766Selan 
1608*57766Selan /* Provide default definitions for the lists of constructors and
1609*57766Selan    destructors, so that we don't get linker errors.  These symbols are
1610*57766Selan    intentionally bss symbols, so that gld and/or collect will provide
1611*57766Selan    the right values.  */
1612*57766Selan 
1613*57766Selan /* We declare the lists here with two elements each,
1614*57766Selan    so that they are valid empty lists if no other definition is loaded.  */
1615*57766Selan #if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
1616*57766Selan #ifdef __NeXT__
1617*57766Selan /* After 2.3, try this definition on all systems.  */
1618*57766Selan func_ptr __CTOR_LIST__[2] = {0, 0};
1619*57766Selan func_ptr __DTOR_LIST__[2] = {0, 0};
1620*57766Selan #else
1621*57766Selan func_ptr __CTOR_LIST__[2];
1622*57766Selan func_ptr __DTOR_LIST__[2];
1623*57766Selan #endif
1624*57766Selan #endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
1625*57766Selan #endif /* L_ctors */
1626*57766Selan 
1627*57766Selan #ifdef L_exit
1628*57766Selan 
1629*57766Selan #include "gbl-ctors.h"
1630*57766Selan 
1631*57766Selan #ifndef ON_EXIT
1632*57766Selan 
1633*57766Selan /* If we have no known way of registering our own __do_global_dtors
1634*57766Selan    routine so that it will be invoked at program exit time, then we
1635*57766Selan    have to define our own exit routine which will get this to happen.  */
1636*57766Selan 
1637*57766Selan extern void __do_global_dtors ();
1638*57766Selan extern void _cleanup ();
1639*57766Selan extern volatile void _exit ();
1640*57766Selan 
1641*57766Selan void
1642*57766Selan exit (status)
1643*57766Selan      int status;
1644*57766Selan {
1645*57766Selan   __do_global_dtors ();
1646*57766Selan #ifdef EXIT_BODY
1647*57766Selan   EXIT_BODY;
1648*57766Selan #else
1649*57766Selan   _cleanup ();
1650*57766Selan #endif
1651*57766Selan   _exit (status);
1652*57766Selan }
1653*57766Selan 
1654*57766Selan #else
1655*57766Selan int _exit_dummy_decl = 0;	/* prevent compiler & linker warnings */
1656*57766Selan #endif
1657*57766Selan 
1658*57766Selan #endif /* L_exit */
1659*57766Selan 
1660*57766Selan /* In a.out systems, we need to have these dummy constructor and destructor
1661*57766Selan    lists in the library.
1662*57766Selan 
1663*57766Selan    When using `collect', the first link will resolve __CTOR_LIST__
1664*57766Selan    and __DTOR_LIST__ to these symbols.  We will then run "nm" on the
1665*57766Selan    result, build the correct __CTOR_LIST__ and __DTOR_LIST__, and relink.
1666*57766Selan    Since we don't do the second link if no constructors existed, these
1667*57766Selan    dummies must be fully functional empty lists.
1668*57766Selan 
1669*57766Selan    When using `gnu ld', these symbols will be used if there are no
1670*57766Selan    constructors.  If there are constructors, the N_SETV symbol defined
1671*57766Selan    by the linker from the N_SETT's in input files will define __CTOR_LIST__
1672*57766Selan    and __DTOR_LIST__ rather than its being allocated as common storage
1673*57766Selan    by the definitions below.
1674*57766Selan 
1675*57766Selan    When using a linker that supports constructor and destructor segments,
1676*57766Selan    these definitions will not be used, since crtbegin.o and crtend.o
1677*57766Selan    (from crtstuff.c) will have already defined __CTOR_LIST__ and
1678*57766Selan     __DTOR_LIST__.  The crt*.o files are passed directly to the linker
1679*57766Selan    on its command line, by gcc.  */
1680*57766Selan 
1681*57766Selan /* The list needs two elements:  one is ignored (the old count); the
1682*57766Selan    second is the terminating zero.  Since both values are zero, this
1683*57766Selan    declaration is not initialized, and it becomes `common'.  */
1684*57766Selan 
1685*57766Selan #ifdef L_ctor_list
1686*57766Selan #include "gbl-ctors.h"
1687*57766Selan func_ptr __CTOR_LIST__[2];
1688*57766Selan #endif
1689*57766Selan 
1690*57766Selan #ifdef L_dtor_list
1691*57766Selan #include "gbl-ctors.h"
1692*57766Selan func_ptr __DTOR_LIST__[2];
1693*57766Selan #endif
1694