libgcc2.c revision 50600
1/* More subroutines needed by GCC output code on some machines.  */
2/* Compile this one with gcc.  */
3/* Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
4
5This file is part of GNU CC.
6
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING.  If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA.  */
21
22/* As a special exception, if you link this library with other files,
23   some of which are compiled with GCC, to produce an executable,
24   this library does not by itself cause the resulting executable
25   to be covered by the GNU General Public License.
26   This exception does not however invalidate any other reasons why
27   the executable file might be covered by the GNU General Public License.  */
28
29/* It is incorrect to include config.h here, because this file is being
30   compiled for the target, and hence definitions concerning only the host
31   do not apply.  */
32
33#include "tconfig.h"
34
35/* We disable this when inhibit_libc, so that gcc can still be built without
36   needing header files first.  */
37/* ??? This is not a good solution, since prototypes may be required in
38   some cases for correct code.  See also frame.c.  */
39#ifndef inhibit_libc
40/* fixproto guarantees these system headers exist. */
41#include <stdlib.h>
42#include <unistd.h>
43#endif
44
45#include "machmode.h"
46#include "defaults.h"
47#ifndef L_trampoline
48#include <stddef.h>
49#endif
50
51/* Don't use `fancy_abort' here even if config.h says to use it.  */
52#ifdef abort
53#undef abort
54#endif
55
56#if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS))
57#define WEAK_ALIAS
58#endif
59
60/* In a cross-compilation situation, default to inhibiting compilation
61   of routines that use libc.  */
62
63#if defined(CROSS_COMPILE) && !defined(inhibit_libc)
64#define inhibit_libc
65#endif
66
67/* Permit the tm.h file to select the endianness to use just for this
68   file.  This is used when the endianness is determined when the
69   compiler is run.  */
70
71#ifndef LIBGCC2_WORDS_BIG_ENDIAN
72#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
73#endif
74
75/* In the first part of this file, we are interfacing to calls generated
76   by the compiler itself.  These calls pass values into these routines
77   which have very specific modes (rather than very specific types), and
78   these compiler-generated calls also expect any return values to have
79   very specific modes (rather than very specific types).  Thus, we need
80   to avoid using regular C language type names in this part of the file
81   because the sizes for those types can be configured to be anything.
82   Instead we use the following special type names.  */
83
84typedef unsigned int UQItype	__attribute__ ((mode (QI)));
85typedef 	 int SItype	__attribute__ ((mode (SI)));
86typedef unsigned int USItype	__attribute__ ((mode (SI)));
87typedef		 int DItype	__attribute__ ((mode (DI)));
88typedef unsigned int UDItype	__attribute__ ((mode (DI)));
89
90typedef 	float SFtype	__attribute__ ((mode (SF)));
91typedef		float DFtype	__attribute__ ((mode (DF)));
92
93#if LONG_DOUBLE_TYPE_SIZE == 96
94typedef		float XFtype	__attribute__ ((mode (XF)));
95#endif
96#if LONG_DOUBLE_TYPE_SIZE == 128
97typedef		float TFtype	__attribute__ ((mode (TF)));
98#endif
99
100typedef int word_type __attribute__ ((mode (__word__)));
101
102/* Make sure that we don't accidentally use any normal C language built-in
103   type names in the first part of this file.  Instead we want to use *only*
104   the type names defined above.  The following macro definitions insure
105   that if we *do* accidentally use some normal C language built-in type name,
106   we will get a syntax error.  */
107
108#define char bogus_type
109#define short bogus_type
110#define int bogus_type
111#define long bogus_type
112#define unsigned bogus_type
113#define float bogus_type
114#define double bogus_type
115
116#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
117
118/* DIstructs are pairs of SItype values in the order determined by
119   LIBGCC2_WORDS_BIG_ENDIAN.  */
120
121#if LIBGCC2_WORDS_BIG_ENDIAN
122  struct DIstruct {SItype high, low;};
123#else
124  struct DIstruct {SItype low, high;};
125#endif
126
127/* We need this union to unpack/pack DImode values, since we don't have
128   any arithmetic yet.  Incoming DImode parameters are stored into the
129   `ll' field, and the unpacked result is read from the struct `s'.  */
130
131typedef union
132{
133  struct DIstruct s;
134  DItype ll;
135} DIunion;
136
137#if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\
138     || defined (L_divdi3) || defined (L_udivdi3) \
139     || defined (L_moddi3) || defined (L_umoddi3))
140
141#include "longlong.h"
142
143#endif /* udiv or mul */
144
145extern DItype __fixunssfdi (SFtype a);
146extern DItype __fixunsdfdi (DFtype a);
147#if LONG_DOUBLE_TYPE_SIZE == 96
148extern DItype __fixunsxfdi (XFtype a);
149#endif
150#if LONG_DOUBLE_TYPE_SIZE == 128
151extern DItype __fixunstfdi (TFtype a);
152#endif
153
154#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
155#if defined (L_divdi3) || defined (L_moddi3)
156static inline
157#endif
158DItype
159__negdi2 (DItype u)
160{
161  DIunion w;
162  DIunion uu;
163
164  uu.ll = u;
165
166  w.s.low = -uu.s.low;
167  w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
168
169  return w.ll;
170}
171#endif
172
173/* Unless shift functions are defined whith full ANSI prototypes,
174   parameter b will be promoted to int if word_type is smaller than an int.  */
175#ifdef L_lshrdi3
176DItype
177__lshrdi3 (DItype u, word_type b)
178{
179  DIunion w;
180  word_type bm;
181  DIunion uu;
182
183  if (b == 0)
184    return u;
185
186  uu.ll = u;
187
188  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
189  if (bm <= 0)
190    {
191      w.s.high = 0;
192      w.s.low = (USItype)uu.s.high >> -bm;
193    }
194  else
195    {
196      USItype carries = (USItype)uu.s.high << bm;
197      w.s.high = (USItype)uu.s.high >> b;
198      w.s.low = ((USItype)uu.s.low >> b) | carries;
199    }
200
201  return w.ll;
202}
203#endif
204
205#ifdef L_ashldi3
206DItype
207__ashldi3 (DItype u, word_type b)
208{
209  DIunion w;
210  word_type bm;
211  DIunion uu;
212
213  if (b == 0)
214    return u;
215
216  uu.ll = u;
217
218  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
219  if (bm <= 0)
220    {
221      w.s.low = 0;
222      w.s.high = (USItype)uu.s.low << -bm;
223    }
224  else
225    {
226      USItype carries = (USItype)uu.s.low >> bm;
227      w.s.low = (USItype)uu.s.low << b;
228      w.s.high = ((USItype)uu.s.high << b) | carries;
229    }
230
231  return w.ll;
232}
233#endif
234
235#ifdef L_ashrdi3
236DItype
237__ashrdi3 (DItype u, word_type b)
238{
239  DIunion w;
240  word_type bm;
241  DIunion uu;
242
243  if (b == 0)
244    return u;
245
246  uu.ll = u;
247
248  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
249  if (bm <= 0)
250    {
251      /* w.s.high = 1..1 or 0..0 */
252      w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
253      w.s.low = uu.s.high >> -bm;
254    }
255  else
256    {
257      USItype carries = (USItype)uu.s.high << bm;
258      w.s.high = uu.s.high >> b;
259      w.s.low = ((USItype)uu.s.low >> b) | carries;
260    }
261
262  return w.ll;
263}
264#endif
265
266#ifdef L_ffsdi2
267DItype
268__ffsdi2 (DItype u)
269{
270  DIunion uu, w;
271  uu.ll = u;
272  w.s.high = 0;
273  w.s.low = ffs (uu.s.low);
274  if (w.s.low != 0)
275    return w.ll;
276  w.s.low = ffs (uu.s.high);
277  if (w.s.low != 0)
278    {
279      w.s.low += BITS_PER_UNIT * sizeof (SItype);
280      return w.ll;
281    }
282  return w.ll;
283}
284#endif
285
286#ifdef L_muldi3
287DItype
288__muldi3 (DItype u, DItype v)
289{
290  DIunion w;
291  DIunion uu, vv;
292
293  uu.ll = u,
294  vv.ll = v;
295
296  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
297  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
298	       + (USItype) uu.s.high * (USItype) vv.s.low);
299
300  return w.ll;
301}
302#endif
303
304#ifdef L_udiv_w_sdiv
305#if defined (sdiv_qrnnd)
306USItype
307__udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
308{
309  USItype q, r;
310  USItype c0, c1, b1;
311
312  if ((SItype) d >= 0)
313    {
314      if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
315	{
316	  /* dividend, divisor, and quotient are nonnegative */
317	  sdiv_qrnnd (q, r, a1, a0, d);
318	}
319      else
320	{
321	  /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */
322	  sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
323	  /* Divide (c1*2^32 + c0) by d */
324	  sdiv_qrnnd (q, r, c1, c0, d);
325	  /* Add 2^31 to quotient */
326	  q += (USItype) 1 << (SI_TYPE_SIZE - 1);
327	}
328    }
329  else
330    {
331      b1 = d >> 1;			/* d/2, between 2^30 and 2^31 - 1 */
332      c1 = a1 >> 1;			/* A/2 */
333      c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
334
335      if (a1 < b1)			/* A < 2^32*b1, so A/2 < 2^31*b1 */
336	{
337	  sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
338
339	  r = 2*r + (a0 & 1);		/* Remainder from A/(2*b1) */
340	  if ((d & 1) != 0)
341	    {
342	      if (r >= q)
343		r = r - q;
344	      else if (q - r <= d)
345		{
346		  r = r - q + d;
347		  q--;
348		}
349	      else
350		{
351		  r = r - q + 2*d;
352		  q -= 2;
353		}
354	    }
355	}
356      else if (c1 < b1)			/* So 2^31 <= (A/2)/b1 < 2^32 */
357	{
358	  c1 = (b1 - 1) - c1;
359	  c0 = ~c0;			/* logical NOT */
360
361	  sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */
362
363	  q = ~q;			/* (A/2)/b1 */
364	  r = (b1 - 1) - r;
365
366	  r = 2*r + (a0 & 1);		/* A/(2*b1) */
367
368	  if ((d & 1) != 0)
369	    {
370	      if (r >= q)
371		r = r - q;
372	      else if (q - r <= d)
373		{
374		  r = r - q + d;
375		  q--;
376		}
377	      else
378		{
379		  r = r - q + 2*d;
380		  q -= 2;
381		}
382	    }
383	}
384      else				/* Implies c1 = b1 */
385	{				/* Hence a1 = d - 1 = 2*b1 - 1 */
386	  if (a0 >= -d)
387	    {
388	      q = -1;
389	      r = a0 + d;
390	    }
391	  else
392	    {
393	      q = -2;
394	      r = a0 + 2*d;
395	    }
396	}
397    }
398
399  *rp = r;
400  return q;
401}
402#else
403/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv.  */
404USItype
405__udiv_w_sdiv (USItype *rp __attribute__ ((__unused__)),
406	       USItype a1 __attribute__ ((__unused__)),
407	       USItype a0 __attribute__ ((__unused__)),
408	       USItype d __attribute__ ((__unused__)))
409{
410  return 0;
411}
412#endif
413#endif
414
415#if (defined (L_udivdi3) || defined (L_divdi3) || \
416     defined (L_umoddi3) || defined (L_moddi3))
417#define L_udivmoddi4
418#endif
419
420#ifdef L_udivmoddi4
421static const UQItype __clz_tab[] =
422{
423  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,
424  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,
425  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,
426  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,
427  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,
428  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,
429  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,
430  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,
431};
432
433#if (defined (L_udivdi3) || defined (L_divdi3) || \
434     defined (L_umoddi3) || defined (L_moddi3))
435static inline
436#endif
437UDItype
438__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
439{
440  DIunion ww;
441  DIunion nn, dd;
442  DIunion rr;
443  USItype d0, d1, n0, n1, n2;
444  USItype q0, q1;
445  USItype b, bm;
446
447  nn.ll = n;
448  dd.ll = d;
449
450  d0 = dd.s.low;
451  d1 = dd.s.high;
452  n0 = nn.s.low;
453  n1 = nn.s.high;
454
455#if !UDIV_NEEDS_NORMALIZATION
456  if (d1 == 0)
457    {
458      if (d0 > n1)
459	{
460	  /* 0q = nn / 0D */
461
462	  udiv_qrnnd (q0, n0, n1, n0, d0);
463	  q1 = 0;
464
465	  /* Remainder in n0.  */
466	}
467      else
468	{
469	  /* qq = NN / 0d */
470
471	  if (d0 == 0)
472	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
473
474	  udiv_qrnnd (q1, n1, 0, n1, d0);
475	  udiv_qrnnd (q0, n0, n1, n0, d0);
476
477	  /* Remainder in n0.  */
478	}
479
480      if (rp != 0)
481	{
482	  rr.s.low = n0;
483	  rr.s.high = 0;
484	  *rp = rr.ll;
485	}
486    }
487
488#else /* UDIV_NEEDS_NORMALIZATION */
489
490  if (d1 == 0)
491    {
492      if (d0 > n1)
493	{
494	  /* 0q = nn / 0D */
495
496	  count_leading_zeros (bm, d0);
497
498	  if (bm != 0)
499	    {
500	      /* Normalize, i.e. make the most significant bit of the
501		 denominator set.  */
502
503	      d0 = d0 << bm;
504	      n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
505	      n0 = n0 << bm;
506	    }
507
508	  udiv_qrnnd (q0, n0, n1, n0, d0);
509	  q1 = 0;
510
511	  /* Remainder in n0 >> bm.  */
512	}
513      else
514	{
515	  /* qq = NN / 0d */
516
517	  if (d0 == 0)
518	    d0 = 1 / d0;	/* Divide intentionally by zero.  */
519
520	  count_leading_zeros (bm, d0);
521
522	  if (bm == 0)
523	    {
524	      /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
525		 conclude (the most significant bit of n1 is set) /\ (the
526		 leading quotient digit q1 = 1).
527
528		 This special case is necessary, not an optimization.
529		 (Shifts counts of SI_TYPE_SIZE are undefined.)  */
530
531	      n1 -= d0;
532	      q1 = 1;
533	    }
534	  else
535	    {
536	      /* Normalize.  */
537
538	      b = SI_TYPE_SIZE - bm;
539
540	      d0 = d0 << bm;
541	      n2 = n1 >> b;
542	      n1 = (n1 << bm) | (n0 >> b);
543	      n0 = n0 << bm;
544
545	      udiv_qrnnd (q1, n1, n2, n1, d0);
546	    }
547
548	  /* n1 != d0...  */
549
550	  udiv_qrnnd (q0, n0, n1, n0, d0);
551
552	  /* Remainder in n0 >> bm.  */
553	}
554
555      if (rp != 0)
556	{
557	  rr.s.low = n0 >> bm;
558	  rr.s.high = 0;
559	  *rp = rr.ll;
560	}
561    }
562#endif /* UDIV_NEEDS_NORMALIZATION */
563
564  else
565    {
566      if (d1 > n1)
567	{
568	  /* 00 = nn / DD */
569
570	  q0 = 0;
571	  q1 = 0;
572
573	  /* Remainder in n1n0.  */
574	  if (rp != 0)
575	    {
576	      rr.s.low = n0;
577	      rr.s.high = n1;
578	      *rp = rr.ll;
579	    }
580	}
581      else
582	{
583	  /* 0q = NN / dd */
584
585	  count_leading_zeros (bm, d1);
586	  if (bm == 0)
587	    {
588	      /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
589		 conclude (the most significant bit of n1 is set) /\ (the
590		 quotient digit q0 = 0 or 1).
591
592		 This special case is necessary, not an optimization.  */
593
594	      /* The condition on the next line takes advantage of that
595		 n1 >= d1 (true due to program flow).  */
596	      if (n1 > d1 || n0 >= d0)
597		{
598		  q0 = 1;
599		  sub_ddmmss (n1, n0, n1, n0, d1, d0);
600		}
601	      else
602		q0 = 0;
603
604	      q1 = 0;
605
606	      if (rp != 0)
607		{
608		  rr.s.low = n0;
609		  rr.s.high = n1;
610		  *rp = rr.ll;
611		}
612	    }
613	  else
614	    {
615	      USItype m1, m0;
616	      /* Normalize.  */
617
618	      b = SI_TYPE_SIZE - bm;
619
620	      d1 = (d1 << bm) | (d0 >> b);
621	      d0 = d0 << bm;
622	      n2 = n1 >> b;
623	      n1 = (n1 << bm) | (n0 >> b);
624	      n0 = n0 << bm;
625
626	      udiv_qrnnd (q0, n1, n2, n1, d1);
627	      umul_ppmm (m1, m0, q0, d0);
628
629	      if (m1 > n1 || (m1 == n1 && m0 > n0))
630		{
631		  q0--;
632		  sub_ddmmss (m1, m0, m1, m0, d1, d0);
633		}
634
635	      q1 = 0;
636
637	      /* Remainder in (n1n0 - m1m0) >> bm.  */
638	      if (rp != 0)
639		{
640		  sub_ddmmss (n1, n0, n1, n0, m1, m0);
641		  rr.s.low = (n1 << b) | (n0 >> bm);
642		  rr.s.high = n1 >> bm;
643		  *rp = rr.ll;
644		}
645	    }
646	}
647    }
648
649  ww.s.low = q0;
650  ww.s.high = q1;
651  return ww.ll;
652}
653#endif
654
655#ifdef L_divdi3
656UDItype __udivmoddi4 ();
657
658DItype
659__divdi3 (DItype u, DItype v)
660{
661  word_type c = 0;
662  DIunion uu, vv;
663  DItype w;
664
665  uu.ll = u;
666  vv.ll = v;
667
668  if (uu.s.high < 0)
669    c = ~c,
670    uu.ll = __negdi2 (uu.ll);
671  if (vv.s.high < 0)
672    c = ~c,
673    vv.ll = __negdi2 (vv.ll);
674
675  w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
676  if (c)
677    w = __negdi2 (w);
678
679  return w;
680}
681#endif
682
683#ifdef L_moddi3
684UDItype __udivmoddi4 ();
685DItype
686__moddi3 (DItype u, DItype v)
687{
688  word_type c = 0;
689  DIunion uu, vv;
690  DItype w;
691
692  uu.ll = u;
693  vv.ll = v;
694
695  if (uu.s.high < 0)
696    c = ~c,
697    uu.ll = __negdi2 (uu.ll);
698  if (vv.s.high < 0)
699    vv.ll = __negdi2 (vv.ll);
700
701  (void) __udivmoddi4 (uu.ll, vv.ll, &w);
702  if (c)
703    w = __negdi2 (w);
704
705  return w;
706}
707#endif
708
709#ifdef L_umoddi3
710UDItype __udivmoddi4 ();
711UDItype
712__umoddi3 (UDItype u, UDItype v)
713{
714  UDItype w;
715
716  (void) __udivmoddi4 (u, v, &w);
717
718  return w;
719}
720#endif
721
722#ifdef L_udivdi3
723UDItype __udivmoddi4 ();
724UDItype
725__udivdi3 (UDItype n, UDItype d)
726{
727  return __udivmoddi4 (n, d, (UDItype *) 0);
728}
729#endif
730
731#ifdef L_cmpdi2
732word_type
733__cmpdi2 (DItype a, DItype b)
734{
735  DIunion au, bu;
736
737  au.ll = a, bu.ll = b;
738
739  if (au.s.high < bu.s.high)
740    return 0;
741  else if (au.s.high > bu.s.high)
742    return 2;
743  if ((USItype) au.s.low < (USItype) bu.s.low)
744    return 0;
745  else if ((USItype) au.s.low > (USItype) bu.s.low)
746    return 2;
747  return 1;
748}
749#endif
750
751#ifdef L_ucmpdi2
752word_type
753__ucmpdi2 (DItype a, DItype b)
754{
755  DIunion au, bu;
756
757  au.ll = a, bu.ll = b;
758
759  if ((USItype) au.s.high < (USItype) bu.s.high)
760    return 0;
761  else if ((USItype) au.s.high > (USItype) bu.s.high)
762    return 2;
763  if ((USItype) au.s.low < (USItype) bu.s.low)
764    return 0;
765  else if ((USItype) au.s.low > (USItype) bu.s.low)
766    return 2;
767  return 1;
768}
769#endif
770
771#if defined(L_fixunstfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
772#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
773#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
774
775DItype
776__fixunstfdi (TFtype a)
777{
778  TFtype b;
779  UDItype v;
780
781  if (a < 0)
782    return 0;
783
784  /* Compute high word of result, as a flonum.  */
785  b = (a / HIGH_WORD_COEFF);
786  /* Convert that to fixed (but not to DItype!),
787     and shift it into the high word.  */
788  v = (USItype) b;
789  v <<= WORD_SIZE;
790  /* Remove high part from the TFtype, leaving the low part as flonum.  */
791  a -= (TFtype)v;
792  /* Convert that to fixed (but not to DItype!) and add it in.
793     Sometimes A comes out negative.  This is significant, since
794     A has more bits than a long int does.  */
795  if (a < 0)
796    v -= (USItype) (- a);
797  else
798    v += (USItype) a;
799  return v;
800}
801#endif
802
803#if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128)
804DItype
805__fixtfdi (TFtype a)
806{
807  if (a < 0)
808    return - __fixunstfdi (-a);
809  return __fixunstfdi (a);
810}
811#endif
812
813#if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
814#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
815#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
816
817DItype
818__fixunsxfdi (XFtype a)
819{
820  XFtype b;
821  UDItype v;
822
823  if (a < 0)
824    return 0;
825
826  /* Compute high word of result, as a flonum.  */
827  b = (a / HIGH_WORD_COEFF);
828  /* Convert that to fixed (but not to DItype!),
829     and shift it into the high word.  */
830  v = (USItype) b;
831  v <<= WORD_SIZE;
832  /* Remove high part from the XFtype, leaving the low part as flonum.  */
833  a -= (XFtype)v;
834  /* Convert that to fixed (but not to DItype!) and add it in.
835     Sometimes A comes out negative.  This is significant, since
836     A has more bits than a long int does.  */
837  if (a < 0)
838    v -= (USItype) (- a);
839  else
840    v += (USItype) a;
841  return v;
842}
843#endif
844
845#if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96)
846DItype
847__fixxfdi (XFtype a)
848{
849  if (a < 0)
850    return - __fixunsxfdi (-a);
851  return __fixunsxfdi (a);
852}
853#endif
854
855#ifdef L_fixunsdfdi
856#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
857#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
858
859DItype
860__fixunsdfdi (DFtype a)
861{
862  DFtype b;
863  UDItype v;
864
865  if (a < 0)
866    return 0;
867
868  /* Compute high word of result, as a flonum.  */
869  b = (a / HIGH_WORD_COEFF);
870  /* Convert that to fixed (but not to DItype!),
871     and shift it into the high word.  */
872  v = (USItype) b;
873  v <<= WORD_SIZE;
874  /* Remove high part from the DFtype, leaving the low part as flonum.  */
875  a -= (DFtype)v;
876  /* Convert that to fixed (but not to DItype!) and add it in.
877     Sometimes A comes out negative.  This is significant, since
878     A has more bits than a long int does.  */
879  if (a < 0)
880    v -= (USItype) (- a);
881  else
882    v += (USItype) a;
883  return v;
884}
885#endif
886
887#ifdef L_fixdfdi
888DItype
889__fixdfdi (DFtype a)
890{
891  if (a < 0)
892    return - __fixunsdfdi (-a);
893  return __fixunsdfdi (a);
894}
895#endif
896
897#ifdef L_fixunssfdi
898#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
899#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
900
901DItype
902__fixunssfdi (SFtype original_a)
903{
904  /* Convert the SFtype to a DFtype, because that is surely not going
905     to lose any bits.  Some day someone else can write a faster version
906     that avoids converting to DFtype, and verify it really works right.  */
907  DFtype a = original_a;
908  DFtype b;
909  UDItype v;
910
911  if (a < 0)
912    return 0;
913
914  /* Compute high word of result, as a flonum.  */
915  b = (a / HIGH_WORD_COEFF);
916  /* Convert that to fixed (but not to DItype!),
917     and shift it into the high word.  */
918  v = (USItype) b;
919  v <<= WORD_SIZE;
920  /* Remove high part from the DFtype, leaving the low part as flonum.  */
921  a -= (DFtype)v;
922  /* Convert that to fixed (but not to DItype!) and add it in.
923     Sometimes A comes out negative.  This is significant, since
924     A has more bits than a long int does.  */
925  if (a < 0)
926    v -= (USItype) (- a);
927  else
928    v += (USItype) a;
929  return v;
930}
931#endif
932
933#ifdef L_fixsfdi
934DItype
935__fixsfdi (SFtype a)
936{
937  if (a < 0)
938    return - __fixunssfdi (-a);
939  return __fixunssfdi (a);
940}
941#endif
942
943#if defined(L_floatdixf) && (LONG_DOUBLE_TYPE_SIZE == 96)
944#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
945#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
946#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
947
948XFtype
949__floatdixf (DItype u)
950{
951  XFtype d;
952
953  d = (SItype) (u >> WORD_SIZE);
954  d *= HIGH_HALFWORD_COEFF;
955  d *= HIGH_HALFWORD_COEFF;
956  d += (USItype) (u & (HIGH_WORD_COEFF - 1));
957
958  return d;
959}
960#endif
961
962#if defined(L_floatditf) && (LONG_DOUBLE_TYPE_SIZE == 128)
963#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
964#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
965#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
966
967TFtype
968__floatditf (DItype u)
969{
970  TFtype d;
971
972  d = (SItype) (u >> WORD_SIZE);
973  d *= HIGH_HALFWORD_COEFF;
974  d *= HIGH_HALFWORD_COEFF;
975  d += (USItype) (u & (HIGH_WORD_COEFF - 1));
976
977  return d;
978}
979#endif
980
981#ifdef L_floatdidf
982#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
983#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
984#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
985
986DFtype
987__floatdidf (DItype u)
988{
989  DFtype d;
990
991  d = (SItype) (u >> WORD_SIZE);
992  d *= HIGH_HALFWORD_COEFF;
993  d *= HIGH_HALFWORD_COEFF;
994  d += (USItype) (u & (HIGH_WORD_COEFF - 1));
995
996  return d;
997}
998#endif
999
1000#ifdef L_floatdisf
1001#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
1002#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
1003#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
1004#define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
1005
1006/* Define codes for all the float formats that we know of.  Note
1007   that this is copied from real.h.  */
1008
1009#define UNKNOWN_FLOAT_FORMAT 0
1010#define IEEE_FLOAT_FORMAT 1
1011#define VAX_FLOAT_FORMAT 2
1012#define IBM_FLOAT_FORMAT 3
1013
1014/* Default to IEEE float if not specified.  Nearly all machines use it.  */
1015#ifndef HOST_FLOAT_FORMAT
1016#define	HOST_FLOAT_FORMAT	IEEE_FLOAT_FORMAT
1017#endif
1018
1019#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
1020#define DF_SIZE 53
1021#define SF_SIZE 24
1022#endif
1023
1024#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
1025#define DF_SIZE 56
1026#define SF_SIZE 24
1027#endif
1028
1029#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
1030#define DF_SIZE 56
1031#define SF_SIZE 24
1032#endif
1033
1034SFtype
1035__floatdisf (DItype u)
1036{
1037  /* Do the calculation in DFmode
1038     so that we don't lose any of the precision of the high word
1039     while multiplying it.  */
1040  DFtype f;
1041
1042  /* Protect against double-rounding error.
1043     Represent any low-order bits, that might be truncated in DFmode,
1044     by a bit that won't be lost.  The bit can go in anywhere below the
1045     rounding position of the SFmode.  A fixed mask and bit position
1046     handles all usual configurations.  It doesn't handle the case
1047     of 128-bit DImode, however.  */
1048  if (DF_SIZE < DI_SIZE
1049      && DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
1050    {
1051#define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
1052      if (! (- ((DItype) 1 << DF_SIZE) < u
1053	     && u < ((DItype) 1 << DF_SIZE)))
1054	{
1055	  if ((USItype) u & (REP_BIT - 1))
1056	    u |= REP_BIT;
1057	}
1058    }
1059  f = (SItype) (u >> WORD_SIZE);
1060  f *= HIGH_HALFWORD_COEFF;
1061  f *= HIGH_HALFWORD_COEFF;
1062  f += (USItype) (u & (HIGH_WORD_COEFF - 1));
1063
1064  return (SFtype) f;
1065}
1066#endif
1067
1068#if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96
1069/* Reenable the normal types, in case limits.h needs them.  */
1070#undef char
1071#undef short
1072#undef int
1073#undef long
1074#undef unsigned
1075#undef float
1076#undef double
1077#undef MIN
1078#undef MAX
1079#include <limits.h>
1080
1081USItype
1082__fixunsxfsi (XFtype a)
1083{
1084  if (a >= - (DFtype) LONG_MIN)
1085    return (SItype) (a + LONG_MIN) - LONG_MIN;
1086  return (SItype) a;
1087}
1088#endif
1089
1090#ifdef L_fixunsdfsi
1091/* Reenable the normal types, in case limits.h needs them.  */
1092#undef char
1093#undef short
1094#undef int
1095#undef long
1096#undef unsigned
1097#undef float
1098#undef double
1099#undef MIN
1100#undef MAX
1101#include <limits.h>
1102
1103USItype
1104__fixunsdfsi (DFtype a)
1105{
1106  if (a >= - (DFtype) LONG_MIN)
1107    return (SItype) (a + LONG_MIN) - LONG_MIN;
1108  return (SItype) a;
1109}
1110#endif
1111
1112#ifdef L_fixunssfsi
1113/* Reenable the normal types, in case limits.h needs them.  */
1114#undef char
1115#undef short
1116#undef int
1117#undef long
1118#undef unsigned
1119#undef float
1120#undef double
1121#undef MIN
1122#undef MAX
1123#include <limits.h>
1124
1125USItype
1126__fixunssfsi (SFtype a)
1127{
1128  if (a >= - (SFtype) LONG_MIN)
1129    return (SItype) (a + LONG_MIN) - LONG_MIN;
1130  return (SItype) a;
1131}
1132#endif
1133
1134/* From here on down, the routines use normal data types.  */
1135
1136#define SItype bogus_type
1137#define USItype bogus_type
1138#define DItype bogus_type
1139#define UDItype bogus_type
1140#define SFtype bogus_type
1141#define DFtype bogus_type
1142
1143#undef char
1144#undef short
1145#undef int
1146#undef long
1147#undef unsigned
1148#undef float
1149#undef double
1150
1151#ifdef L__gcc_bcmp
1152
1153/* Like bcmp except the sign is meaningful.
1154   Result is negative if S1 is less than S2,
1155   positive if S1 is greater, 0 if S1 and S2 are equal.  */
1156
1157int
1158__gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size)
1159{
1160  while (size > 0)
1161    {
1162      unsigned char c1 = *s1++, c2 = *s2++;
1163      if (c1 != c2)
1164	return c1 - c2;
1165      size--;
1166    }
1167  return 0;
1168}
1169
1170#endif
1171
1172#ifdef L__dummy
1173void
1174__dummy () {}
1175#endif
1176
1177#ifdef L_varargs
1178#ifdef __i860__
1179#if defined(__svr4__) || defined(__alliant__)
1180	asm ("	.text");
1181	asm ("	.align	4");
1182
1183/* The Alliant needs the added underscore.  */
1184	asm (".globl	__builtin_saveregs");
1185asm ("__builtin_saveregs:");
1186	asm (".globl	___builtin_saveregs");
1187asm ("___builtin_saveregs:");
1188
1189        asm ("	andnot	0x0f,%sp,%sp");	/* round down to 16-byte boundary */
1190	asm ("	adds	-96,%sp,%sp");  /* allocate stack space for reg save
1191					   area and also for a new va_list
1192					   structure */
1193	/* Save all argument registers in the arg reg save area.  The
1194	   arg reg save area must have the following layout (according
1195	   to the svr4 ABI):
1196
1197		struct {
1198		  union  {
1199		    float freg[8];
1200		    double dreg[4];
1201		  } float_regs;
1202		  long	ireg[12];
1203		};
1204	*/
1205
1206	asm ("	fst.q	%f8,  0(%sp)"); /* save floating regs (f8-f15)  */
1207	asm ("	fst.q	%f12,16(%sp)");
1208
1209	asm ("	st.l	%r16,32(%sp)"); /* save integer regs (r16-r27) */
1210	asm ("	st.l	%r17,36(%sp)");
1211	asm ("	st.l	%r18,40(%sp)");
1212	asm ("	st.l	%r19,44(%sp)");
1213	asm ("	st.l	%r20,48(%sp)");
1214	asm ("	st.l	%r21,52(%sp)");
1215	asm ("	st.l	%r22,56(%sp)");
1216	asm ("	st.l	%r23,60(%sp)");
1217	asm ("	st.l	%r24,64(%sp)");
1218	asm ("	st.l	%r25,68(%sp)");
1219	asm ("	st.l	%r26,72(%sp)");
1220	asm ("	st.l	%r27,76(%sp)");
1221
1222	asm ("	adds	80,%sp,%r16");  /* compute the address of the new
1223					   va_list structure.  Put in into
1224					   r16 so that it will be returned
1225					   to the caller.  */
1226
1227	/* Initialize all fields of the new va_list structure.  This
1228	   structure looks like:
1229
1230		typedef struct {
1231		    unsigned long	ireg_used;
1232		    unsigned long	freg_used;
1233		    long		*reg_base;
1234		    long		*mem_ptr;
1235		} va_list;
1236	*/
1237
1238	asm ("	st.l	%r0, 0(%r16)"); /* nfixed */
1239	asm ("	st.l	%r0, 4(%r16)"); /* nfloating */
1240	asm ("  st.l    %sp, 8(%r16)"); /* __va_ctl points to __va_struct.  */
1241	asm ("	bri	%r1");		/* delayed return */
1242	asm ("	st.l	%r28,12(%r16)"); /* pointer to overflow args */
1243
1244#else /* not __svr4__ */
1245#if defined(__PARAGON__)
1246	/*
1247	 *	we'll use SVR4-ish varargs but need SVR3.2 assembler syntax,
1248	 *	and we stand a better chance of hooking into libraries
1249	 *	compiled by PGI.  [andyp@ssd.intel.com]
1250	 */
1251	asm ("	.text");
1252	asm ("	.align	4");
1253	asm (".globl	__builtin_saveregs");
1254asm ("__builtin_saveregs:");
1255	asm (".globl	___builtin_saveregs");
1256asm ("___builtin_saveregs:");
1257
1258        asm ("	andnot	0x0f,sp,sp");	/* round down to 16-byte boundary */
1259	asm ("	adds	-96,sp,sp");	/* allocate stack space for reg save
1260					   area and also for a new va_list
1261					   structure */
1262	/* Save all argument registers in the arg reg save area.  The
1263	   arg reg save area must have the following layout (according
1264	   to the svr4 ABI):
1265
1266		struct {
1267		  union  {
1268		    float freg[8];
1269		    double dreg[4];
1270		  } float_regs;
1271		  long	ireg[12];
1272		};
1273	*/
1274
1275	asm ("	fst.q	f8,  0(sp)");
1276	asm ("	fst.q	f12,16(sp)");
1277	asm ("	st.l	r16,32(sp)");
1278	asm ("	st.l	r17,36(sp)");
1279	asm ("	st.l	r18,40(sp)");
1280	asm ("	st.l	r19,44(sp)");
1281	asm ("	st.l	r20,48(sp)");
1282	asm ("	st.l	r21,52(sp)");
1283	asm ("	st.l	r22,56(sp)");
1284	asm ("	st.l	r23,60(sp)");
1285	asm ("	st.l	r24,64(sp)");
1286	asm ("	st.l	r25,68(sp)");
1287	asm ("	st.l	r26,72(sp)");
1288	asm ("	st.l	r27,76(sp)");
1289
1290	asm ("	adds	80,sp,r16");  /* compute the address of the new
1291					   va_list structure.  Put in into
1292					   r16 so that it will be returned
1293					   to the caller.  */
1294
1295	/* Initialize all fields of the new va_list structure.  This
1296	   structure looks like:
1297
1298		typedef struct {
1299		    unsigned long	ireg_used;
1300		    unsigned long	freg_used;
1301		    long		*reg_base;
1302		    long		*mem_ptr;
1303		} va_list;
1304	*/
1305
1306	asm ("	st.l	r0, 0(r16)"); /* nfixed */
1307	asm ("	st.l	r0, 4(r16)"); /* nfloating */
1308	asm ("  st.l    sp, 8(r16)"); /* __va_ctl points to __va_struct.  */
1309	asm ("	bri	r1");		/* delayed return */
1310	asm ("	 st.l	r28,12(r16)"); /* pointer to overflow args */
1311#else /* not __PARAGON__ */
1312	asm ("	.text");
1313	asm ("	.align	4");
1314
1315	asm (".globl	___builtin_saveregs");
1316	asm ("___builtin_saveregs:");
1317	asm ("	mov	sp,r30");
1318	asm ("	andnot	0x0f,sp,sp");
1319	asm ("	adds	-96,sp,sp");  /* allocate sufficient space on the stack */
1320
1321/* Fill in the __va_struct.  */
1322	asm ("	st.l	r16, 0(sp)"); /* save integer regs (r16-r27) */
1323	asm ("	st.l	r17, 4(sp)"); /* int	fixed[12] */
1324	asm ("	st.l	r18, 8(sp)");
1325	asm ("	st.l	r19,12(sp)");
1326	asm ("	st.l	r20,16(sp)");
1327	asm ("	st.l	r21,20(sp)");
1328	asm ("	st.l	r22,24(sp)");
1329	asm ("	st.l	r23,28(sp)");
1330	asm ("	st.l	r24,32(sp)");
1331	asm ("	st.l	r25,36(sp)");
1332	asm ("	st.l	r26,40(sp)");
1333	asm ("	st.l	r27,44(sp)");
1334
1335	asm ("	fst.q	f8, 48(sp)"); /* save floating regs (f8-f15) */
1336	asm ("	fst.q	f12,64(sp)"); /* int floating[8] */
1337
1338/* Fill in the __va_ctl.  */
1339	asm ("  st.l    sp, 80(sp)"); /* __va_ctl points to __va_struct.  */
1340	asm ("	st.l	r28,84(sp)"); /* pointer to more args */
1341	asm ("	st.l	r0, 88(sp)"); /* nfixed */
1342	asm ("	st.l	r0, 92(sp)"); /* nfloating */
1343
1344	asm ("	adds	80,sp,r16");  /* return address of the __va_ctl.  */
1345	asm ("	bri	r1");
1346	asm ("	mov	r30,sp");
1347				/* recover stack and pass address to start
1348				   of data.  */
1349#endif /* not __PARAGON__ */
1350#endif /* not __svr4__ */
1351#else /* not __i860__ */
1352#ifdef __sparc__
1353	asm (".global __builtin_saveregs");
1354	asm ("__builtin_saveregs:");
1355	asm (".global ___builtin_saveregs");
1356	asm ("___builtin_saveregs:");
1357#ifdef NEED_PROC_COMMAND
1358	asm (".proc 020");
1359#endif
1360	asm ("st %i0,[%fp+68]");
1361	asm ("st %i1,[%fp+72]");
1362	asm ("st %i2,[%fp+76]");
1363	asm ("st %i3,[%fp+80]");
1364	asm ("st %i4,[%fp+84]");
1365	asm ("retl");
1366	asm ("st %i5,[%fp+88]");
1367#ifdef NEED_TYPE_COMMAND
1368	asm (".type __builtin_saveregs,#function");
1369	asm (".size __builtin_saveregs,.-__builtin_saveregs");
1370#endif
1371#else /* not __sparc__ */
1372#if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
1373
1374  asm ("	.text");
1375#ifdef __mips16
1376  asm ("	.set nomips16");
1377#endif
1378  asm ("	.ent __builtin_saveregs");
1379  asm ("	.globl __builtin_saveregs");
1380  asm ("__builtin_saveregs:");
1381  asm ("	sw	$4,0($30)");
1382  asm ("	sw	$5,4($30)");
1383  asm ("	sw	$6,8($30)");
1384  asm ("	sw	$7,12($30)");
1385  asm ("	j	$31");
1386  asm ("	.end __builtin_saveregs");
1387#else /* not __mips__, etc.  */
1388
1389void *
1390__builtin_saveregs ()
1391{
1392  abort ();
1393}
1394
1395#endif /* not __mips__ */
1396#endif /* not __sparc__ */
1397#endif /* not __i860__ */
1398#endif
1399
1400#ifdef L_eprintf
1401#ifndef inhibit_libc
1402
1403#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1404#include <stdio.h>
1405/* This is used by the `assert' macro.  */
1406void
1407__eprintf (const char *string, const char *expression,
1408	   unsigned int line, const char *filename)
1409{
1410  fprintf (stderr, string, expression, line, filename);
1411  fflush (stderr);
1412  abort ();
1413}
1414
1415#endif
1416#endif
1417
1418#ifdef L_bb
1419
1420/* Structure emitted by -a  */
1421struct bb
1422{
1423  long zero_word;
1424  const char *filename;
1425  long *counts;
1426  long ncounts;
1427  struct bb *next;
1428  const unsigned long *addresses;
1429
1430  /* Older GCC's did not emit these fields.  */
1431  long nwords;
1432  const char **functions;
1433  const long *line_nums;
1434  const char **filenames;
1435  char *flags;
1436};
1437
1438#ifdef BLOCK_PROFILER_CODE
1439BLOCK_PROFILER_CODE
1440#else
1441#ifndef inhibit_libc
1442
1443/* Simple minded basic block profiling output dumper for
1444   systems that don't provide tcov support.  At present,
1445   it requires atexit and stdio.  */
1446
1447#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
1448#include <stdio.h>
1449char *ctime ();
1450
1451#include "gbl-ctors.h"
1452#include "gcov-io.h"
1453#include <string.h>
1454
1455static struct bb *bb_head;
1456
1457/* Return the number of digits needed to print a value */
1458/* __inline__ */ static int num_digits (long value, int base)
1459{
1460  int minus = (value < 0 && base != 16);
1461  unsigned long v = (minus) ? -value : value;
1462  int ret = minus;
1463
1464  do
1465    {
1466      v /= base;
1467      ret++;
1468    }
1469  while (v);
1470
1471  return ret;
1472}
1473
1474void
1475__bb_exit_func (void)
1476{
1477  FILE *da_file, *file;
1478  long time_value;
1479  int i;
1480
1481  if (bb_head == 0)
1482    return;
1483
1484  i = strlen (bb_head->filename) - 3;
1485
1486  if (!strcmp (bb_head->filename+i, ".da"))
1487    {
1488      /* Must be -fprofile-arcs not -a.
1489	 Dump data in a form that gcov expects.  */
1490
1491      struct bb *ptr;
1492
1493      for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1494	{
1495	  /* If the file exists, and the number of counts in it is the same,
1496	     then merge them in.  */
1497
1498	  if ((da_file = fopen (ptr->filename, "r")) != 0)
1499	    {
1500	      long n_counts = 0;
1501
1502	      if (__read_long (&n_counts, da_file, 8) != 0)
1503		{
1504		  fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1505			   ptr->filename);
1506		  continue;
1507		}
1508
1509	      if (n_counts == ptr->ncounts)
1510		{
1511		  int i;
1512
1513		  for (i = 0; i < n_counts; i++)
1514		    {
1515		      long v = 0;
1516
1517		      if (__read_long (&v, da_file, 8) != 0)
1518			{
1519			  fprintf (stderr, "arc profiling: Can't read output file %s.\n",
1520				   ptr->filename);
1521			  break;
1522			}
1523		      ptr->counts[i] += v;
1524		    }
1525		}
1526
1527	      if (fclose (da_file) == EOF)
1528		fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1529			 ptr->filename);
1530	    }
1531	  if ((da_file = fopen (ptr->filename, "w")) == 0)
1532	    {
1533	      fprintf (stderr, "arc profiling: Can't open output file %s.\n",
1534		       ptr->filename);
1535	      continue;
1536	    }
1537
1538	  /* ??? Should first write a header to the file.  Preferably, a 4 byte
1539	     magic number, 4 bytes containing the time the program was
1540	     compiled, 4 bytes containing the last modification time of the
1541	     source file, and 4 bytes indicating the compiler options used.
1542
1543	     That way we can easily verify that the proper source/executable/
1544	     data file combination is being used from gcov.  */
1545
1546	  if (__write_long (ptr->ncounts, da_file, 8) != 0)
1547	    {
1548
1549	      fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1550		       ptr->filename);
1551	    }
1552	  else
1553	    {
1554	      int j;
1555	      long *count_ptr = ptr->counts;
1556	      int ret = 0;
1557	      for (j = ptr->ncounts; j > 0; j--)
1558		{
1559		  if (__write_long (*count_ptr, da_file, 8) != 0)
1560		    {
1561		      ret=1;
1562		      break;
1563		    }
1564		  count_ptr++;
1565		}
1566	      if (ret)
1567		fprintf (stderr, "arc profiling: Error writing output file %s.\n",
1568			 ptr->filename);
1569	    }
1570
1571	  if (fclose (da_file) == EOF)
1572	    fprintf (stderr, "arc profiling: Error closing output file %s.\n",
1573		     ptr->filename);
1574	}
1575
1576      return;
1577    }
1578
1579  /* Must be basic block profiling.  Emit a human readable output file.  */
1580
1581  file = fopen ("bb.out", "a");
1582
1583  if (!file)
1584    perror ("bb.out");
1585
1586  else
1587    {
1588      struct bb *ptr;
1589
1590      /* This is somewhat type incorrect, but it avoids worrying about
1591	 exactly where time.h is included from.  It should be ok unless
1592	 a void * differs from other pointer formats, or if sizeof (long)
1593	 is < sizeof (time_t).  It would be nice if we could assume the
1594	 use of rationale standards here.  */
1595
1596      time ((void *) &time_value);
1597      fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
1598
1599      /* We check the length field explicitly in order to allow compatibility
1600	 with older GCC's which did not provide it.  */
1601
1602      for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1603	{
1604	  int i;
1605	  int func_p	= (ptr->nwords >= sizeof (struct bb)
1606			   && ptr->nwords <= 1000
1607			   && ptr->functions);
1608	  int line_p	= (func_p && ptr->line_nums);
1609	  int file_p	= (func_p && ptr->filenames);
1610	  int addr_p	= (ptr->addresses != 0);
1611	  long ncounts	= ptr->ncounts;
1612	  long cnt_max  = 0;
1613	  long line_max = 0;
1614	  long addr_max = 0;
1615	  int file_len	= 0;
1616	  int func_len	= 0;
1617	  int blk_len	= num_digits (ncounts, 10);
1618	  int cnt_len;
1619	  int line_len;
1620	  int addr_len;
1621
1622	  fprintf (file, "File %s, %ld basic blocks \n\n",
1623		   ptr->filename, ncounts);
1624
1625	  /* Get max values for each field.  */
1626	  for (i = 0; i < ncounts; i++)
1627	    {
1628	      const char *p;
1629	      int len;
1630
1631	      if (cnt_max < ptr->counts[i])
1632		cnt_max = ptr->counts[i];
1633
1634	      if (addr_p && addr_max < ptr->addresses[i])
1635		addr_max = ptr->addresses[i];
1636
1637	      if (line_p && line_max < ptr->line_nums[i])
1638		line_max = ptr->line_nums[i];
1639
1640	      if (func_p)
1641		{
1642		  p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
1643		  len = strlen (p);
1644		  if (func_len < len)
1645		    func_len = len;
1646		}
1647
1648	      if (file_p)
1649		{
1650		  p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
1651		  len = strlen (p);
1652		  if (file_len < len)
1653		    file_len = len;
1654		}
1655	    }
1656
1657	  addr_len = num_digits (addr_max, 16);
1658	  cnt_len  = num_digits (cnt_max, 10);
1659	  line_len = num_digits (line_max, 10);
1660
1661	  /* Now print out the basic block information.  */
1662	  for (i = 0; i < ncounts; i++)
1663	    {
1664	      fprintf (file,
1665		       "    Block #%*d: executed %*ld time(s)",
1666		       blk_len, i+1,
1667		       cnt_len, ptr->counts[i]);
1668
1669	      if (addr_p)
1670		fprintf (file, " address= 0x%.*lx", addr_len,
1671			 ptr->addresses[i]);
1672
1673	      if (func_p)
1674		fprintf (file, " function= %-*s", func_len,
1675			 (ptr->functions[i]) ? ptr->functions[i] : "<none>");
1676
1677	      if (line_p)
1678		fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
1679
1680	      if (file_p)
1681		fprintf (file, " file= %s",
1682			 (ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
1683
1684	      fprintf (file, "\n");
1685	    }
1686
1687	  fprintf (file, "\n");
1688	  fflush (file);
1689	}
1690
1691      fprintf (file, "\n\n");
1692      fclose (file);
1693    }
1694}
1695
1696void
1697__bb_init_func (struct bb *blocks)
1698{
1699  /* User is supposed to check whether the first word is non-0,
1700     but just in case....  */
1701
1702  if (blocks->zero_word)
1703    return;
1704
1705#ifdef ON_EXIT
1706  /* Initialize destructor.  */
1707  if (!bb_head)
1708    ON_EXIT (__bb_exit_func, 0);
1709#endif
1710
1711  /* Set up linked list.  */
1712  blocks->zero_word = 1;
1713  blocks->next = bb_head;
1714  bb_head = blocks;
1715}
1716
1717#ifndef MACHINE_STATE_SAVE
1718#define MACHINE_STATE_SAVE(ID)
1719#endif
1720#ifndef MACHINE_STATE_RESTORE
1721#define MACHINE_STATE_RESTORE(ID)
1722#endif
1723
1724/* Number of buckets in hashtable of basic block addresses.  */
1725
1726#define BB_BUCKETS 311
1727
1728/* Maximum length of string in file bb.in.  */
1729
1730#define BBINBUFSIZE 500
1731
1732/* BBINBUFSIZE-1 with double quotes. We could use #BBINBUFSIZE or
1733   "BBINBUFSIZE" but want to avoid trouble with preprocessors.  */
1734
1735#define BBINBUFSIZESTR "499"
1736
1737struct bb_edge
1738{
1739  struct bb_edge *next;
1740  unsigned long src_addr;
1741  unsigned long dst_addr;
1742  unsigned long count;
1743};
1744
1745enum bb_func_mode
1746{
1747  TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
1748};
1749
1750struct bb_func
1751{
1752  struct bb_func *next;
1753  char *funcname;
1754  char *filename;
1755  enum bb_func_mode mode;
1756};
1757
1758/* This is the connection to the outside world.
1759   The BLOCK_PROFILER macro must set __bb.blocks
1760   and __bb.blockno.  */
1761
1762struct {
1763  unsigned long blockno;
1764  struct bb *blocks;
1765} __bb;
1766
1767/* Vars to store addrs of source and destination basic blocks
1768   of a jump.  */
1769
1770static unsigned long bb_src = 0;
1771static unsigned long bb_dst = 0;
1772
1773static FILE *bb_tracefile = (FILE *) 0;
1774static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
1775static struct bb_func *bb_func_head = (struct bb_func *) 0;
1776static unsigned long bb_callcount = 0;
1777static int bb_mode = 0;
1778
1779static unsigned long *bb_stack = (unsigned long *) 0;
1780static size_t bb_stacksize = 0;
1781
1782static int reported = 0;
1783
1784/* Trace modes:
1785Always             :   Print execution frequencies of basic blocks
1786                       to file bb.out.
1787bb_mode & 1 != 0   :   Dump trace of basic blocks to file bbtrace[.gz]
1788bb_mode & 2 != 0   :   Print jump frequencies to file bb.out.
1789bb_mode & 4 != 0   :   Cut call instructions from basic block flow.
1790bb_mode & 8 != 0   :   Insert return instructions in basic block flow.
1791*/
1792
1793#ifdef HAVE_POPEN
1794
1795/*#include <sys/types.h>*/
1796#include <sys/stat.h>
1797/*#include <malloc.h>*/
1798
1799/* Commands executed by gopen.  */
1800
1801#define GOPENDECOMPRESS "gzip -cd "
1802#define GOPENCOMPRESS "gzip -c >"
1803
1804/* Like fopen but pipes through gzip.  mode may only be "r" or "w".
1805   If it does not compile, simply replace gopen by fopen and delete
1806   '.gz' from any first parameter to gopen.  */
1807
1808static FILE *
1809gopen (char *fn, char *mode)
1810{
1811  int use_gzip;
1812  char *p;
1813
1814  if (mode[1])
1815    return (FILE *) 0;
1816
1817  if (mode[0] != 'r' && mode[0] != 'w')
1818    return (FILE *) 0;
1819
1820  p = fn + strlen (fn)-1;
1821  use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
1822	      || (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
1823
1824  if (use_gzip)
1825    {
1826      if (mode[0]=='r')
1827        {
1828          FILE *f;
1829          char *s = (char *) malloc (sizeof (char) * strlen (fn)
1830				     + sizeof (GOPENDECOMPRESS));
1831          strcpy (s, GOPENDECOMPRESS);
1832          strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
1833          f = popen (s, mode);
1834          free (s);
1835          return f;
1836        }
1837
1838      else
1839        {
1840          FILE *f;
1841          char *s = (char *) malloc (sizeof (char) * strlen (fn)
1842				     + sizeof (GOPENCOMPRESS));
1843          strcpy (s, GOPENCOMPRESS);
1844          strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
1845          if (!(f = popen (s, mode)))
1846            f = fopen (s, mode);
1847          free (s);
1848          return f;
1849        }
1850    }
1851
1852  else
1853    return fopen (fn, mode);
1854}
1855
1856static int
1857gclose (FILE *f)
1858{
1859  struct stat buf;
1860
1861  if (f != 0)
1862    {
1863      if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
1864        return pclose (f);
1865
1866      return fclose (f);
1867    }
1868  return 0;
1869}
1870
1871#endif /* HAVE_POPEN */
1872
1873/* Called once per program.  */
1874
1875static void
1876__bb_exit_trace_func ()
1877{
1878  FILE *file = fopen ("bb.out", "a");
1879  struct bb_func *f;
1880  struct bb *b;
1881
1882  if (!file)
1883    perror ("bb.out");
1884
1885  if (bb_mode & 1)
1886    {
1887      if (!bb_tracefile)
1888        perror ("bbtrace");
1889      else
1890#ifdef HAVE_POPEN
1891        gclose (bb_tracefile);
1892#else
1893        fclose (bb_tracefile);
1894#endif /* HAVE_POPEN */
1895    }
1896
1897  /* Check functions in `bb.in'.  */
1898
1899  if (file)
1900    {
1901      long time_value;
1902      const struct bb_func *p;
1903      int printed_something = 0;
1904      struct bb *ptr;
1905      long blk;
1906
1907      /* This is somewhat type incorrect.  */
1908      time ((void *) &time_value);
1909
1910      for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
1911        {
1912          for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
1913            {
1914              if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
1915                continue;
1916              for (blk = 0; blk < ptr->ncounts; blk++)
1917                {
1918                  if (!strcmp (p->funcname, ptr->functions[blk]))
1919                    goto found;
1920                }
1921            }
1922
1923          if (!printed_something)
1924            {
1925              fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
1926              printed_something = 1;
1927            }
1928
1929          fprintf (file, "\tFunction %s", p->funcname);
1930          if (p->filename)
1931              fprintf (file, " of file %s", p->filename);
1932          fprintf (file, "\n" );
1933
1934found:        ;
1935        }
1936
1937      if (printed_something)
1938       fprintf (file, "\n");
1939
1940    }
1941
1942  if (bb_mode & 2)
1943    {
1944      if (!bb_hashbuckets)
1945        {
1946          if (!reported)
1947            {
1948              fprintf (stderr, "Profiler: out of memory\n");
1949              reported = 1;
1950            }
1951          return;
1952        }
1953
1954      else if (file)
1955        {
1956          long time_value;
1957          int i;
1958          unsigned long addr_max = 0;
1959          unsigned long cnt_max  = 0;
1960          int cnt_len;
1961          int addr_len;
1962
1963          /* This is somewhat type incorrect, but it avoids worrying about
1964             exactly where time.h is included from.  It should be ok unless
1965             a void * differs from other pointer formats, or if sizeof (long)
1966             is < sizeof (time_t).  It would be nice if we could assume the
1967             use of rationale standards here.  */
1968
1969          time ((void *) &time_value);
1970          fprintf (file, "Basic block jump tracing");
1971
1972          switch (bb_mode & 12)
1973            {
1974              case 0:
1975                fprintf (file, " (with call)");
1976              break;
1977
1978              case 4:
1979		/* Print nothing.  */
1980              break;
1981
1982              case 8:
1983                fprintf (file, " (with call & ret)");
1984              break;
1985
1986              case 12:
1987                fprintf (file, " (with ret)");
1988              break;
1989            }
1990
1991          fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
1992
1993          for (i = 0; i < BB_BUCKETS; i++)
1994            {
1995               struct bb_edge *bucket = bb_hashbuckets[i];
1996               for ( ; bucket; bucket = bucket->next )
1997                 {
1998                   if (addr_max < bucket->src_addr)
1999                     addr_max = bucket->src_addr;
2000                   if (addr_max < bucket->dst_addr)
2001                     addr_max = bucket->dst_addr;
2002                   if (cnt_max < bucket->count)
2003                     cnt_max = bucket->count;
2004                 }
2005            }
2006          addr_len = num_digits (addr_max, 16);
2007          cnt_len  = num_digits (cnt_max, 10);
2008
2009          for ( i = 0; i < BB_BUCKETS; i++)
2010            {
2011               struct bb_edge *bucket = bb_hashbuckets[i];
2012               for ( ; bucket; bucket = bucket->next )
2013                 {
2014                   fprintf (file, "Jump from block 0x%.*lx to "
2015                                  "block 0x%.*lx executed %*lu time(s)\n",
2016                            addr_len, bucket->src_addr,
2017                            addr_len, bucket->dst_addr,
2018                            cnt_len, bucket->count);
2019                 }
2020            }
2021
2022          fprintf (file, "\n");
2023
2024        }
2025    }
2026
2027   if (file)
2028     fclose (file);
2029
2030   /* Free allocated memory.  */
2031
2032   f = bb_func_head;
2033   while (f)
2034     {
2035       struct bb_func *old = f;
2036
2037       f = f->next;
2038       if (old->funcname) free (old->funcname);
2039       if (old->filename) free (old->filename);
2040       free (old);
2041     }
2042
2043   if (bb_stack)
2044     free (bb_stack);
2045
2046   if (bb_hashbuckets)
2047     {
2048       int i;
2049
2050       for (i = 0; i < BB_BUCKETS; i++)
2051         {
2052           struct bb_edge *old, *bucket = bb_hashbuckets[i];
2053
2054           while (bucket)
2055             {
2056               old = bucket;
2057               bucket = bucket->next;
2058               free (old);
2059             }
2060         }
2061       free (bb_hashbuckets);
2062     }
2063
2064   for (b = bb_head; b; b = b->next)
2065     if (b->flags) free (b->flags);
2066}
2067
2068/* Called once per program.  */
2069
2070static void
2071__bb_init_prg ()
2072{
2073
2074  FILE *file;
2075  char buf[BBINBUFSIZE];
2076  const char *p;
2077  const char *pos;
2078  enum bb_func_mode m;
2079
2080#ifdef ON_EXIT
2081  /* Initialize destructor.  */
2082  ON_EXIT (__bb_exit_func, 0);
2083#endif
2084
2085  if (!(file = fopen ("bb.in", "r")))
2086    return;
2087
2088  while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
2089    {
2090      p = buf;
2091      if (*p == '-')
2092        {
2093          m = TRACE_OFF;
2094          p++;
2095        }
2096      else
2097        {
2098          m = TRACE_ON;
2099        }
2100      if (!strcmp (p, "__bb_trace__"))
2101        bb_mode |= 1;
2102      else if (!strcmp (p, "__bb_jumps__"))
2103        bb_mode |= 2;
2104      else if (!strcmp (p, "__bb_hidecall__"))
2105        bb_mode |= 4;
2106      else if (!strcmp (p, "__bb_showret__"))
2107        bb_mode |= 8;
2108      else
2109        {
2110          struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
2111          if (f)
2112            {
2113              unsigned long l;
2114              f->next = bb_func_head;
2115              if ((pos = strchr (p, ':')))
2116                {
2117                  if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
2118                    continue;
2119                  strcpy (f->funcname, pos+1);
2120                  l = pos-p;
2121                  if ((f->filename = (char *) malloc (l+1)))
2122                    {
2123                      strncpy (f->filename, p, l);
2124                      f->filename[l] = '\0';
2125                    }
2126                  else
2127                    f->filename = (char *) 0;
2128                }
2129              else
2130                {
2131                  if (!(f->funcname = (char *) malloc (strlen (p)+1)))
2132                    continue;
2133                  strcpy (f->funcname, p);
2134                  f->filename = (char *) 0;
2135                }
2136              f->mode = m;
2137              bb_func_head = f;
2138	    }
2139         }
2140    }
2141  fclose (file);
2142
2143#ifdef HAVE_POPEN
2144
2145  if (bb_mode & 1)
2146      bb_tracefile = gopen ("bbtrace.gz", "w");
2147
2148#else
2149
2150  if (bb_mode & 1)
2151      bb_tracefile = fopen ("bbtrace", "w");
2152
2153#endif /* HAVE_POPEN */
2154
2155  if (bb_mode & 2)
2156    {
2157      bb_hashbuckets = (struct bb_edge **)
2158                   malloc (BB_BUCKETS * sizeof (struct bb_edge *));
2159      if (bb_hashbuckets)
2160        memset (bb_hashbuckets, 0, BB_BUCKETS * sizeof (struct bb_edge *));
2161    }
2162
2163  if (bb_mode & 12)
2164    {
2165      bb_stacksize = 10;
2166      bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
2167    }
2168
2169#ifdef ON_EXIT
2170      /* Initialize destructor.  */
2171      ON_EXIT (__bb_exit_trace_func, 0);
2172#endif
2173
2174}
2175
2176/* Called upon entering a basic block.  */
2177
2178void
2179__bb_trace_func ()
2180{
2181  struct bb_edge *bucket;
2182
2183  MACHINE_STATE_SAVE("1")
2184
2185  if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2186    goto skip;
2187
2188  bb_dst = __bb.blocks->addresses[__bb.blockno];
2189  __bb.blocks->counts[__bb.blockno]++;
2190
2191  if (bb_tracefile)
2192    {
2193      fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
2194    }
2195
2196  if (bb_hashbuckets)
2197    {
2198      struct bb_edge **startbucket, **oldnext;
2199
2200      oldnext = startbucket
2201	= & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
2202      bucket = *startbucket;
2203
2204      for (bucket = *startbucket; bucket;
2205           oldnext = &(bucket->next), bucket = *oldnext)
2206        {
2207          if (bucket->src_addr == bb_src
2208	      && bucket->dst_addr == bb_dst)
2209            {
2210              bucket->count++;
2211              *oldnext = bucket->next;
2212              bucket->next = *startbucket;
2213              *startbucket = bucket;
2214              goto ret;
2215            }
2216        }
2217
2218      bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2219
2220      if (!bucket)
2221        {
2222          if (!reported)
2223            {
2224              fprintf (stderr, "Profiler: out of memory\n");
2225              reported = 1;
2226            }
2227        }
2228
2229      else
2230        {
2231          bucket->src_addr = bb_src;
2232          bucket->dst_addr = bb_dst;
2233          bucket->next = *startbucket;
2234          *startbucket = bucket;
2235          bucket->count = 1;
2236        }
2237    }
2238
2239ret:
2240  bb_src = bb_dst;
2241
2242skip:
2243  ;
2244
2245  MACHINE_STATE_RESTORE("1")
2246
2247}
2248
2249/* Called when returning from a function and `__bb_showret__' is set.  */
2250
2251static void
2252__bb_trace_func_ret ()
2253{
2254  struct bb_edge *bucket;
2255
2256  if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
2257    goto skip;
2258
2259  if (bb_hashbuckets)
2260    {
2261      struct bb_edge **startbucket, **oldnext;
2262
2263      oldnext = startbucket
2264	= & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
2265      bucket = *startbucket;
2266
2267      for (bucket = *startbucket; bucket;
2268           oldnext = &(bucket->next), bucket = *oldnext)
2269        {
2270          if (bucket->src_addr == bb_dst
2271	       && bucket->dst_addr == bb_src)
2272            {
2273              bucket->count++;
2274              *oldnext = bucket->next;
2275              bucket->next = *startbucket;
2276              *startbucket = bucket;
2277              goto ret;
2278            }
2279        }
2280
2281      bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
2282
2283      if (!bucket)
2284        {
2285          if (!reported)
2286            {
2287              fprintf (stderr, "Profiler: out of memory\n");
2288              reported = 1;
2289            }
2290        }
2291
2292      else
2293        {
2294          bucket->src_addr = bb_dst;
2295          bucket->dst_addr = bb_src;
2296          bucket->next = *startbucket;
2297          *startbucket = bucket;
2298          bucket->count = 1;
2299        }
2300    }
2301
2302ret:
2303  bb_dst = bb_src;
2304
2305skip:
2306  ;
2307
2308}
2309
2310/* Called upon entering the first function of a file.  */
2311
2312static void
2313__bb_init_file (struct bb *blocks)
2314{
2315
2316  const struct bb_func *p;
2317  long blk, ncounts = blocks->ncounts;
2318  const char **functions = blocks->functions;
2319
2320  /* Set up linked list.  */
2321  blocks->zero_word = 1;
2322  blocks->next = bb_head;
2323  bb_head = blocks;
2324
2325  blocks->flags = 0;
2326  if (!bb_func_head
2327      || !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
2328    return;
2329
2330  for (blk = 0; blk < ncounts; blk++)
2331    blocks->flags[blk] = 0;
2332
2333  for (blk = 0; blk < ncounts; blk++)
2334    {
2335      for (p = bb_func_head; p; p = p->next)
2336        {
2337          if (!strcmp (p->funcname, functions[blk])
2338	      && (!p->filename || !strcmp (p->filename, blocks->filename)))
2339            {
2340              blocks->flags[blk] |= p->mode;
2341            }
2342        }
2343    }
2344
2345}
2346
2347/* Called when exiting from a function.  */
2348
2349void
2350__bb_trace_ret ()
2351{
2352
2353  MACHINE_STATE_SAVE("2")
2354
2355  if (bb_callcount)
2356    {
2357      if ((bb_mode & 12) && bb_stacksize > bb_callcount)
2358        {
2359          bb_src = bb_stack[bb_callcount];
2360          if (bb_mode & 8)
2361            __bb_trace_func_ret ();
2362        }
2363
2364      bb_callcount -= 1;
2365    }
2366
2367  MACHINE_STATE_RESTORE("2")
2368
2369}
2370
2371/* Called when entering a function.  */
2372
2373void
2374__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
2375{
2376  static int trace_init = 0;
2377
2378  MACHINE_STATE_SAVE("3")
2379
2380  if (!blocks->zero_word)
2381    {
2382      if (!trace_init)
2383        {
2384          trace_init = 1;
2385          __bb_init_prg ();
2386        }
2387      __bb_init_file (blocks);
2388    }
2389
2390  if (bb_callcount)
2391    {
2392
2393      bb_callcount += 1;
2394
2395      if (bb_mode & 12)
2396        {
2397          if (bb_callcount >= bb_stacksize)
2398            {
2399              size_t newsize = bb_callcount + 100;
2400
2401              bb_stack = (unsigned long *) realloc (bb_stack, newsize);
2402              if (! bb_stack)
2403                {
2404                  if (!reported)
2405                    {
2406                      fprintf (stderr, "Profiler: out of memory\n");
2407                      reported = 1;
2408                    }
2409                  bb_stacksize = 0;
2410                  goto stack_overflow;
2411                }
2412	      bb_stacksize = newsize;
2413            }
2414          bb_stack[bb_callcount] = bb_src;
2415
2416          if (bb_mode & 4)
2417            bb_src = 0;
2418
2419        }
2420
2421stack_overflow:;
2422
2423    }
2424
2425  else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
2426    {
2427      bb_callcount = 1;
2428      bb_src = 0;
2429
2430      if (bb_stack)
2431          bb_stack[bb_callcount] = bb_src;
2432    }
2433
2434  MACHINE_STATE_RESTORE("3")
2435}
2436
2437#endif /* not inhibit_libc */
2438#endif /* not BLOCK_PROFILER_CODE */
2439#endif /* L_bb */
2440
2441#ifdef L_shtab
2442unsigned int __shtab[] = {
2443    0x00000001, 0x00000002, 0x00000004, 0x00000008,
2444    0x00000010, 0x00000020, 0x00000040, 0x00000080,
2445    0x00000100, 0x00000200, 0x00000400, 0x00000800,
2446    0x00001000, 0x00002000, 0x00004000, 0x00008000,
2447    0x00010000, 0x00020000, 0x00040000, 0x00080000,
2448    0x00100000, 0x00200000, 0x00400000, 0x00800000,
2449    0x01000000, 0x02000000, 0x04000000, 0x08000000,
2450    0x10000000, 0x20000000, 0x40000000, 0x80000000
2451  };
2452#endif
2453
2454#ifdef L_clear_cache
2455/* Clear part of an instruction cache.  */
2456
2457#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
2458
2459void
2460__clear_cache (char *beg, char *end)
2461{
2462#ifdef CLEAR_INSN_CACHE
2463  CLEAR_INSN_CACHE (beg, end);
2464#else
2465#ifdef INSN_CACHE_SIZE
2466  static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
2467  static int initialized;
2468  int offset;
2469  void *start_addr
2470  void *end_addr;
2471  typedef (*function_ptr) ();
2472
2473#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
2474  /* It's cheaper to clear the whole cache.
2475     Put in a series of jump instructions so that calling the beginning
2476     of the cache will clear the whole thing.  */
2477
2478  if (! initialized)
2479    {
2480      int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2481		 & -INSN_CACHE_LINE_WIDTH);
2482      int end_ptr = ptr + INSN_CACHE_SIZE;
2483
2484      while (ptr < end_ptr)
2485	{
2486	  *(INSTRUCTION_TYPE *)ptr
2487	    = JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
2488	  ptr += INSN_CACHE_LINE_WIDTH;
2489	}
2490      *(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
2491
2492      initialized = 1;
2493    }
2494
2495  /* Call the beginning of the sequence.  */
2496  (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2497		    & -INSN_CACHE_LINE_WIDTH))
2498   ());
2499
2500#else /* Cache is large.  */
2501
2502  if (! initialized)
2503    {
2504      int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
2505		 & -INSN_CACHE_LINE_WIDTH);
2506
2507      while (ptr < (int) array + sizeof array)
2508	{
2509	  *(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
2510	  ptr += INSN_CACHE_LINE_WIDTH;
2511	}
2512
2513      initialized = 1;
2514    }
2515
2516  /* Find the location in array that occupies the same cache line as BEG.  */
2517
2518  offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
2519  start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
2520		 & -INSN_CACHE_PLANE_SIZE)
2521		+ offset);
2522
2523  /* Compute the cache alignment of the place to stop clearing.  */
2524#if 0  /* This is not needed for gcc's purposes.  */
2525  /* If the block to clear is bigger than a cache plane,
2526     we clear the entire cache, and OFFSET is already correct.  */
2527  if (end < beg + INSN_CACHE_PLANE_SIZE)
2528#endif
2529    offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
2530	       & -INSN_CACHE_LINE_WIDTH)
2531	      & (INSN_CACHE_PLANE_SIZE - 1));
2532
2533#if INSN_CACHE_DEPTH > 1
2534  end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
2535  if (end_addr <= start_addr)
2536    end_addr += INSN_CACHE_PLANE_SIZE;
2537
2538  for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
2539    {
2540      int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
2541      int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
2542
2543      while (addr != stop)
2544	{
2545	  /* Call the return instruction at ADDR.  */
2546	  ((function_ptr) addr) ();
2547
2548	  addr += INSN_CACHE_LINE_WIDTH;
2549	}
2550    }
2551#else /* just one plane */
2552  do
2553    {
2554      /* Call the return instruction at START_ADDR.  */
2555      ((function_ptr) start_addr) ();
2556
2557      start_addr += INSN_CACHE_LINE_WIDTH;
2558    }
2559  while ((start_addr % INSN_CACHE_SIZE) != offset);
2560#endif /* just one plane */
2561#endif /* Cache is large */
2562#endif /* Cache exists */
2563#endif /* CLEAR_INSN_CACHE */
2564}
2565
2566#endif /* L_clear_cache */
2567
2568#ifdef L_trampoline
2569
2570/* Jump to a trampoline, loading the static chain address.  */
2571
2572#if defined(WINNT) && ! defined(__CYGWIN32__)
2573
2574long getpagesize()
2575{
2576#ifdef _ALPHA_
2577  return 8192;
2578#else
2579  return 4096;
2580#endif
2581}
2582
2583#ifdef i386
2584extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
2585#endif
2586
2587int
2588mprotect (char *addr, int len, int prot)
2589{
2590  int np, op;
2591
2592  if (prot == 7)
2593    np = 0x40;
2594  else if (prot == 5)
2595    np = 0x20;
2596  else if (prot == 4)
2597    np = 0x10;
2598  else if (prot == 3)
2599    np = 0x04;
2600  else if (prot == 1)
2601    np = 0x02;
2602  else if (prot == 0)
2603    np = 0x01;
2604
2605  if (VirtualProtect (addr, len, np, &op))
2606    return 0;
2607  else
2608    return -1;
2609}
2610
2611#endif
2612
2613#ifdef TRANSFER_FROM_TRAMPOLINE
2614TRANSFER_FROM_TRAMPOLINE
2615#endif
2616
2617#if defined (NeXT) && defined (__MACH__)
2618
2619/* Make stack executable so we can call trampolines on stack.
2620   This is called from INITIALIZE_TRAMPOLINE in next.h.  */
2621#ifdef NeXTStep21
2622 #include <mach.h>
2623#else
2624 #include <mach/mach.h>
2625#endif
2626
2627void
2628__enable_execute_stack (char *addr)
2629{
2630  kern_return_t r;
2631  char *eaddr = addr + TRAMPOLINE_SIZE;
2632  vm_address_t a = (vm_address_t) addr;
2633
2634  /* turn on execute access on stack */
2635  r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
2636  if (r != KERN_SUCCESS)
2637    {
2638      mach_error("vm_protect VM_PROT_ALL", r);
2639      exit(1);
2640    }
2641
2642  /* We inline the i-cache invalidation for speed */
2643
2644#ifdef CLEAR_INSN_CACHE
2645  CLEAR_INSN_CACHE (addr, eaddr);
2646#else
2647  __clear_cache ((int) addr, (int) eaddr);
2648#endif
2649}
2650
2651#endif /* defined (NeXT) && defined (__MACH__) */
2652
2653#ifdef __convex__
2654
2655/* Make stack executable so we can call trampolines on stack.
2656   This is called from INITIALIZE_TRAMPOLINE in convex.h.  */
2657
2658#include <sys/mman.h>
2659#include <sys/vmparam.h>
2660#include <machine/machparam.h>
2661
2662void
2663__enable_execute_stack ()
2664{
2665  int fp;
2666  static unsigned lowest = USRSTACK;
2667  unsigned current = (unsigned) &fp & -NBPG;
2668
2669  if (lowest > current)
2670    {
2671      unsigned len = lowest - current;
2672      mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
2673      lowest = current;
2674    }
2675
2676  /* Clear instruction cache in case an old trampoline is in it.  */
2677  asm ("pich");
2678}
2679#endif /* __convex__ */
2680
2681#ifdef __sysV88__
2682
2683/* Modified from the convex -code above.  */
2684
2685#include <sys/param.h>
2686#include <errno.h>
2687#include <sys/m88kbcs.h>
2688
2689void
2690__enable_execute_stack ()
2691{
2692  int save_errno;
2693  static unsigned long lowest = USRSTACK;
2694  unsigned long current = (unsigned long) &save_errno & -NBPC;
2695
2696  /* Ignore errno being set. memctl sets errno to EINVAL whenever the
2697     address is seen as 'negative'. That is the case with the stack.   */
2698
2699  save_errno=errno;
2700  if (lowest > current)
2701    {
2702      unsigned len=lowest-current;
2703      memctl(current,len,MCT_TEXT);
2704      lowest = current;
2705    }
2706  else
2707    memctl(current,NBPC,MCT_TEXT);
2708  errno=save_errno;
2709}
2710
2711#endif /* __sysV88__ */
2712
2713#ifdef __sysV68__
2714
2715#include <sys/signal.h>
2716#include <errno.h>
2717
2718/* Motorola forgot to put memctl.o in the libp version of libc881.a,
2719   so define it here, because we need it in __clear_insn_cache below */
2720/* On older versions of this OS, no memctl or MCT_TEXT are defined;
2721   hence we enable this stuff only if MCT_TEXT is #define'd.  */
2722
2723#ifdef MCT_TEXT
2724asm("\n\
2725	global memctl\n\
2726memctl:\n\
2727	movq &75,%d0\n\
2728	trap &0\n\
2729	bcc.b noerror\n\
2730	jmp cerror%\n\
2731noerror:\n\
2732	movq &0,%d0\n\
2733	rts");
2734#endif
2735
2736/* Clear instruction cache so we can call trampolines on stack.
2737   This is called from FINALIZE_TRAMPOLINE in mot3300.h.  */
2738
2739void
2740__clear_insn_cache ()
2741{
2742#ifdef MCT_TEXT
2743  int save_errno;
2744
2745  /* Preserve errno, because users would be surprised to have
2746  errno changing without explicitly calling any system-call. */
2747  save_errno = errno;
2748
2749  /* Keep it simple : memctl (MCT_TEXT) always fully clears the insn cache.
2750     No need to use an address derived from _start or %sp, as 0 works also. */
2751  memctl(0, 4096, MCT_TEXT);
2752  errno = save_errno;
2753#endif
2754}
2755
2756#endif /* __sysV68__ */
2757
2758#ifdef __pyr__
2759
2760#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
2761#include <stdio.h>
2762#include <sys/mman.h>
2763#include <sys/types.h>
2764#include <sys/param.h>
2765#include <sys/vmmac.h>
2766
2767/* Modified from the convex -code above.
2768   mremap promises to clear the i-cache.  */
2769
2770void
2771__enable_execute_stack ()
2772{
2773  int fp;
2774  if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
2775		PROT_READ|PROT_WRITE|PROT_EXEC))
2776    {
2777      perror ("mprotect in __enable_execute_stack");
2778      fflush (stderr);
2779      abort ();
2780    }
2781}
2782#endif /* __pyr__ */
2783
2784#if defined (sony_news) && defined (SYSTYPE_BSD)
2785
2786#include <stdio.h>
2787#include <sys/types.h>
2788#include <sys/param.h>
2789#include <syscall.h>
2790#include <machine/sysnews.h>
2791
2792/* cacheflush function for NEWS-OS 4.2.
2793   This function is called from trampoline-initialize code
2794   defined in config/mips/mips.h.  */
2795
2796void
2797cacheflush (char *beg, int size, int flag)
2798{
2799  if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
2800    {
2801      perror ("cache_flush");
2802      fflush (stderr);
2803      abort ();
2804    }
2805}
2806
2807#endif /* sony_news */
2808#endif /* L_trampoline */
2809
2810#ifndef __CYGWIN32__
2811#ifdef L__main
2812
2813#include "gbl-ctors.h"
2814/* Some systems use __main in a way incompatible with its use in gcc, in these
2815   cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
2816   give the same symbol without quotes for an alternative entry point.  You
2817   must define both, or neither.  */
2818#ifndef NAME__MAIN
2819#define NAME__MAIN "__main"
2820#define SYMBOL__MAIN __main
2821#endif
2822
2823#ifdef INIT_SECTION_ASM_OP
2824#undef HAS_INIT_SECTION
2825#define HAS_INIT_SECTION
2826#endif
2827
2828#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
2829/* Run all the global destructors on exit from the program.  */
2830
2831void
2832__do_global_dtors ()
2833{
2834#ifdef DO_GLOBAL_DTORS_BODY
2835  DO_GLOBAL_DTORS_BODY;
2836#else
2837  static func_ptr *p = __DTOR_LIST__ + 1;
2838  while (*p)
2839    {
2840      p++;
2841      (*(p-1)) ();
2842    }
2843#endif
2844}
2845#endif
2846
2847#ifndef HAS_INIT_SECTION
2848/* Run all the global constructors on entry to the program.  */
2849
2850#ifndef ON_EXIT
2851#define ON_EXIT(a, b)
2852#else
2853/* Make sure the exit routine is pulled in to define the globals as
2854   bss symbols, just in case the linker does not automatically pull
2855   bss definitions from the library.  */
2856
2857extern int _exit_dummy_decl;
2858int *_exit_dummy_ref = &_exit_dummy_decl;
2859#endif /* ON_EXIT */
2860
2861void
2862__do_global_ctors ()
2863{
2864  DO_GLOBAL_CTORS_BODY;
2865  ON_EXIT (__do_global_dtors, 0);
2866}
2867#endif /* no HAS_INIT_SECTION */
2868
2869#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
2870/* Subroutine called automatically by `main'.
2871   Compiling a global function named `main'
2872   produces an automatic call to this function at the beginning.
2873
2874   For many systems, this routine calls __do_global_ctors.
2875   For systems which support a .init section we use the .init section
2876   to run __do_global_ctors, so we need not do anything here.  */
2877
2878void
2879SYMBOL__MAIN ()
2880{
2881  /* Support recursive calls to `main': run initializers just once.  */
2882  static int initialized;
2883  if (! initialized)
2884    {
2885      initialized = 1;
2886      __do_global_ctors ();
2887    }
2888}
2889#endif /* no HAS_INIT_SECTION or INVOKE__main */
2890
2891#endif /* L__main */
2892#endif /* __CYGWIN32__ */
2893
2894#ifdef L_ctors
2895
2896#include "gbl-ctors.h"
2897
2898/* Provide default definitions for the lists of constructors and
2899   destructors, so that we don't get linker errors.  These symbols are
2900   intentionally bss symbols, so that gld and/or collect will provide
2901   the right values.  */
2902
2903/* We declare the lists here with two elements each,
2904   so that they are valid empty lists if no other definition is loaded.  */
2905#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
2906#if defined(__NeXT__) || defined(_AIX)
2907/* After 2.3, try this definition on all systems.  */
2908func_ptr __CTOR_LIST__[2] = {0, 0};
2909func_ptr __DTOR_LIST__[2] = {0, 0};
2910#else
2911func_ptr __CTOR_LIST__[2];
2912func_ptr __DTOR_LIST__[2];
2913#endif
2914#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */
2915#endif /* L_ctors */
2916
2917#ifdef L_exit
2918
2919#include "gbl-ctors.h"
2920
2921#ifdef NEED_ATEXIT
2922# ifdef ON_EXIT
2923#  undef ON_EXIT
2924# endif
2925int _exit_dummy_decl = 0;	/* prevent compiler & linker warnings */
2926#endif
2927
2928#ifndef ON_EXIT
2929
2930#ifdef NEED_ATEXIT
2931# include <errno.h>
2932
2933static func_ptr *atexit_chain = 0;
2934static long atexit_chain_length = 0;
2935static volatile long last_atexit_chain_slot = -1;
2936
2937int atexit (func_ptr func)
2938{
2939  if (++last_atexit_chain_slot == atexit_chain_length)
2940    {
2941      atexit_chain_length += 32;
2942      if (atexit_chain)
2943	atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
2944					     * sizeof (func_ptr));
2945      else
2946	atexit_chain = (func_ptr *) malloc (atexit_chain_length
2947					    * sizeof (func_ptr));
2948      if (! atexit_chain)
2949	{
2950	  atexit_chain_length = 0;
2951	  last_atexit_chain_slot = -1;
2952	  errno = ENOMEM;
2953	  return (-1);
2954	}
2955    }
2956  atexit_chain[last_atexit_chain_slot] = func;
2957  return (0);
2958}
2959#endif /* NEED_ATEXIT */
2960
2961/* If we have no known way of registering our own __do_global_dtors
2962   routine so that it will be invoked at program exit time, then we
2963   have to define our own exit routine which will get this to happen.  */
2964
2965extern void __do_global_dtors ();
2966extern void __bb_exit_func ();
2967extern void _cleanup ();
2968extern void _exit () __attribute__ ((noreturn));
2969
2970void
2971exit (int status)
2972{
2973#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
2974#ifdef NEED_ATEXIT
2975  if (atexit_chain)
2976    {
2977      for ( ; last_atexit_chain_slot-- >= 0; )
2978	{
2979	  (*atexit_chain[last_atexit_chain_slot + 1]) ();
2980	  atexit_chain[last_atexit_chain_slot + 1] = 0;
2981	}
2982      free (atexit_chain);
2983      atexit_chain = 0;
2984    }
2985#else /* No NEED_ATEXIT */
2986  __do_global_dtors ();
2987#endif /* No NEED_ATEXIT */
2988#endif /* !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF) */
2989/* In gbl-ctors.h, ON_EXIT is defined if HAVE_ATEXIT is defined.  In
2990   __bb_init_func and _bb_init_prg, __bb_exit_func is registered with
2991   ON_EXIT if ON_EXIT is defined.  Thus we must not call __bb_exit_func here
2992   if HAVE_ATEXIT is defined. */
2993#ifndef HAVE_ATEXIT
2994#ifndef inhibit_libc
2995  __bb_exit_func ();
2996#endif
2997#endif /* !HAVE_ATEXIT */
2998#ifdef EXIT_BODY
2999  EXIT_BODY;
3000#else
3001  _cleanup ();
3002#endif
3003  _exit (status);
3004}
3005
3006#else /* ON_EXIT defined */
3007int _exit_dummy_decl = 0;	/* prevent compiler & linker warnings */
3008
3009# ifndef HAVE_ATEXIT
3010/* Provide a fake for atexit() using ON_EXIT.  */
3011int atexit (func_ptr func)
3012{
3013  return ON_EXIT (func, NULL);
3014}
3015# endif /* HAVE_ATEXIT */
3016#endif /* ON_EXIT defined */
3017
3018#endif /* L_exit */
3019
3020#ifdef L_eh
3021
3022#include "gthr.h"
3023
3024/* Shared exception handling support routines.  */
3025
3026void
3027__default_terminate ()
3028{
3029  abort ();
3030}
3031
3032void (*__terminate_func)() = __default_terminate;
3033
3034void
3035__terminate ()
3036{
3037  (*__terminate_func)();
3038}
3039
3040void *
3041__throw_type_match (void *catch_type, void *throw_type, void *obj)
3042{
3043#if 0
3044 printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
3045	 catch_type, throw_type);
3046#endif
3047 if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
3048   return obj;
3049 return 0;
3050}
3051
3052void
3053__empty ()
3054{
3055}
3056
3057
3058/* Include definitions of EH context and table layout */
3059
3060#include "eh-common.h"
3061
3062/* Allocate and return a new EH context structure. */
3063
3064extern void __throw ();
3065
3066static void *
3067new_eh_context ()
3068{
3069  struct eh_full_context {
3070    struct eh_context c;
3071    void *top_elt[2];
3072  } *ehfc = (struct eh_full_context *) malloc (sizeof *ehfc);
3073
3074  if (! ehfc)
3075    __terminate ();
3076
3077  memset (ehfc, 0, sizeof *ehfc);
3078
3079  ehfc->c.dynamic_handler_chain = (void **) ehfc->top_elt;
3080
3081  /* This should optimize out entirely.  This should always be true,
3082     but just in case it ever isn't, don't allow bogus code to be
3083     generated.  */
3084
3085  if ((void*)(&ehfc->c) != (void*)ehfc)
3086    __terminate ();
3087
3088  return &ehfc->c;
3089}
3090
3091#if __GTHREADS
3092static __gthread_key_t eh_context_key;
3093
3094/* Destructor for struct eh_context. */
3095static void
3096eh_context_free (void *ptr)
3097{
3098  __gthread_key_dtor (eh_context_key, ptr);
3099  if (ptr)
3100    free (ptr);
3101}
3102#endif
3103
3104/* Pointer to function to return EH context. */
3105
3106static struct eh_context *eh_context_initialize ();
3107static struct eh_context *eh_context_static ();
3108#if __GTHREADS
3109static struct eh_context *eh_context_specific ();
3110#endif
3111
3112static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
3113
3114/* Routine to get EH context.
3115   This one will simply call the function pointer. */
3116
3117void *
3118__get_eh_context ()
3119{
3120  return (void *) (*get_eh_context) ();
3121}
3122
3123/* Get and set the language specific info pointer. */
3124
3125void **
3126__get_eh_info ()
3127{
3128  struct eh_context *eh = (*get_eh_context) ();
3129  return &eh->info;
3130}
3131
3132#if __GTHREADS
3133static void
3134eh_threads_initialize ()
3135{
3136  /* Try to create the key.  If it fails, revert to static method,
3137     otherwise start using thread specific EH contexts. */
3138  if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
3139    get_eh_context = &eh_context_specific;
3140  else
3141    get_eh_context = &eh_context_static;
3142}
3143#endif /* no __GTHREADS */
3144
3145/* Initialize EH context.
3146   This will be called only once, since we change GET_EH_CONTEXT
3147   pointer to another routine. */
3148
3149static struct eh_context *
3150eh_context_initialize ()
3151{
3152#if __GTHREADS
3153
3154  static __gthread_once_t once = __GTHREAD_ONCE_INIT;
3155  /* Make sure that get_eh_context does not point to us anymore.
3156     Some systems have dummy thread routines in their libc that
3157     return a success (Solaris 2.6 for example). */
3158  if (__gthread_once (&once, eh_threads_initialize) != 0
3159      || get_eh_context == &eh_context_initialize)
3160    {
3161      /* Use static version of EH context. */
3162      get_eh_context = &eh_context_static;
3163    }
3164
3165#else /* no __GTHREADS */
3166
3167  /* Use static version of EH context. */
3168  get_eh_context = &eh_context_static;
3169
3170#endif /* no __GTHREADS */
3171
3172  return (*get_eh_context) ();
3173}
3174
3175/* Return a static EH context. */
3176
3177static struct eh_context *
3178eh_context_static ()
3179{
3180  static struct eh_context *eh;
3181  if (! eh)
3182    eh = new_eh_context ();
3183  return eh;
3184}
3185
3186#if __GTHREADS
3187/* Return a thread specific EH context. */
3188
3189static struct eh_context *
3190eh_context_specific ()
3191{
3192  struct eh_context *eh;
3193  eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
3194  if (! eh)
3195    {
3196      eh = new_eh_context ();
3197      if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
3198	__terminate ();
3199    }
3200
3201  return eh;
3202}
3203#endif __GTHREADS
3204
3205/* Support routines for setjmp/longjmp exception handling.  */
3206
3207/* Calls to __sjthrow are generated by the compiler when an exception
3208   is raised when using the setjmp/longjmp exception handling codegen
3209   method.  */
3210
3211#ifdef DONT_USE_BUILTIN_SETJMP
3212extern void longjmp (void *, int);
3213#endif
3214
3215/* Routine to get the head of the current thread's dynamic handler chain
3216   use for exception handling. */
3217
3218void ***
3219__get_dynamic_handler_chain ()
3220{
3221  struct eh_context *eh = (*get_eh_context) ();
3222  return &eh->dynamic_handler_chain;
3223}
3224
3225/* This is used to throw an exception when the setjmp/longjmp codegen
3226   method is used for exception handling.
3227
3228   We call __terminate if there are no handlers left.  Otherwise we run the
3229   cleanup actions off the dynamic cleanup stack, and pop the top of the
3230   dynamic handler chain, and use longjmp to transfer back to the associated
3231   handler.  */
3232
3233void
3234__sjthrow ()
3235{
3236  struct eh_context *eh = (*get_eh_context) ();
3237  void ***dhc = &eh->dynamic_handler_chain;
3238  void *jmpbuf;
3239  void (*func)(void *, int);
3240  void *arg;
3241  void ***cleanup;
3242
3243  /* The cleanup chain is one word into the buffer.  Get the cleanup
3244     chain.  */
3245  cleanup = (void***)&(*dhc)[1];
3246
3247  /* If there are any cleanups in the chain, run them now.  */
3248  if (cleanup[0])
3249    {
3250      double store[200];
3251      void **buf = (void**)store;
3252      buf[1] = 0;
3253      buf[0] = (*dhc);
3254
3255      /* try { */
3256#ifdef DONT_USE_BUILTIN_SETJMP
3257      if (! setjmp (&buf[2]))
3258#else
3259      if (! __builtin_setjmp (&buf[2]))
3260#endif
3261	{
3262	  *dhc = buf;
3263	  while (cleanup[0])
3264	    {
3265	      func = (void(*)(void*, int))cleanup[0][1];
3266	      arg = (void*)cleanup[0][2];
3267
3268	      /* Update this before running the cleanup.  */
3269	      cleanup[0] = (void **)cleanup[0][0];
3270
3271	      (*func)(arg, 2);
3272	    }
3273	  *dhc = buf[0];
3274	}
3275      /* catch (...) */
3276      else
3277	{
3278	  __terminate ();
3279	}
3280    }
3281
3282  /* We must call terminate if we try and rethrow an exception, when
3283     there is no exception currently active and when there are no
3284     handlers left.  */
3285  if (! eh->info || (*dhc)[0] == 0)
3286    __terminate ();
3287
3288  /* Find the jmpbuf associated with the top element of the dynamic
3289     handler chain.  The jumpbuf starts two words into the buffer.  */
3290  jmpbuf = &(*dhc)[2];
3291
3292  /* Then we pop the top element off the dynamic handler chain.  */
3293  *dhc = (void**)(*dhc)[0];
3294
3295  /* And then we jump to the handler.  */
3296
3297#ifdef DONT_USE_BUILTIN_SETJMP
3298  longjmp (jmpbuf, 1);
3299#else
3300  __builtin_longjmp (jmpbuf, 1);
3301#endif
3302}
3303
3304/* Run cleanups on the dynamic cleanup stack for the current dynamic
3305   handler, then pop the handler off the dynamic handler stack, and
3306   then throw.  This is used to skip the first handler, and transfer
3307   control to the next handler in the dynamic handler stack.  */
3308
3309void
3310__sjpopnthrow ()
3311{
3312  struct eh_context *eh = (*get_eh_context) ();
3313  void ***dhc = &eh->dynamic_handler_chain;
3314  void (*func)(void *, int);
3315  void *arg;
3316  void ***cleanup;
3317
3318  /* The cleanup chain is one word into the buffer.  Get the cleanup
3319     chain.  */
3320  cleanup = (void***)&(*dhc)[1];
3321
3322  /* If there are any cleanups in the chain, run them now.  */
3323  if (cleanup[0])
3324    {
3325      double store[200];
3326      void **buf = (void**)store;
3327      buf[1] = 0;
3328      buf[0] = (*dhc);
3329
3330      /* try { */
3331#ifdef DONT_USE_BUILTIN_SETJMP
3332      if (! setjmp (&buf[2]))
3333#else
3334      if (! __builtin_setjmp (&buf[2]))
3335#endif
3336	{
3337	  *dhc = buf;
3338	  while (cleanup[0])
3339	    {
3340	      func = (void(*)(void*, int))cleanup[0][1];
3341	      arg = (void*)cleanup[0][2];
3342
3343	      /* Update this before running the cleanup.  */
3344	      cleanup[0] = (void **)cleanup[0][0];
3345
3346	      (*func)(arg, 2);
3347	    }
3348	  *dhc = buf[0];
3349	}
3350      /* catch (...) */
3351      else
3352	{
3353	  __terminate ();
3354	}
3355    }
3356
3357  /* Then we pop the top element off the dynamic handler chain.  */
3358  *dhc = (void**)(*dhc)[0];
3359
3360  __sjthrow ();
3361}
3362
3363/* Support code for all exception region-based exception handling.  */
3364
3365/* This value identifies the place from which an exception is being
3366   thrown.  */
3367
3368#ifdef EH_TABLE_LOOKUP
3369
3370EH_TABLE_LOOKUP
3371
3372#else
3373
3374#ifdef DWARF2_UNWIND_INFO
3375
3376
3377/* Return the table version of an exception descriptor */
3378
3379short
3380__get_eh_table_version (exception_descriptor *table)
3381{
3382  return table->lang.version;
3383}
3384
3385/* Return the originating table language of an exception descriptor */
3386
3387short
3388__get_eh_table_language (exception_descriptor *table)
3389{
3390  return table->lang.language;
3391}
3392
3393/* This routine takes a PC and a pointer to the exception region TABLE for
3394   its translation unit, and returns the address of the exception handler
3395   associated with the closest exception table handler entry associated
3396   with that PC, or 0 if there are no table entries the PC fits in.
3397
3398   In the advent of a tie, we have to give the last entry, as it represents
3399   an inner block.  */
3400
3401static void *
3402old_find_exception_handler (void *pc, old_exception_table *table)
3403{
3404  if (table)
3405    {
3406      int pos;
3407      int best = -1;
3408
3409      /* We can't do a binary search because the table isn't guaranteed
3410         to be sorted from function to function.  */
3411      for (pos = 0; table[pos].start_region != (void *) -1; ++pos)
3412        {
3413          if (table[pos].start_region <= pc && table[pos].end_region > pc)
3414            {
3415              /* This can apply.  Make sure it is at least as small as
3416                 the previous best.  */
3417              if (best == -1 || (table[pos].end_region <= table[best].end_region
3418                        && table[pos].start_region >= table[best].start_region))
3419                best = pos;
3420            }
3421          /* But it is sorted by starting PC within a function.  */
3422          else if (best >= 0 && table[pos].start_region > pc)
3423            break;
3424        }
3425      if (best != -1)
3426        return table[best].exception_handler;
3427    }
3428
3429  return (void *) 0;
3430}
3431
3432static void *
3433find_exception_handler (void *pc, exception_descriptor *table, void *eh_info)
3434{
3435  if (table)
3436    {
3437      /* The new model assumed the table is sorted inner-most out so the
3438         first region we find which matches is the correct one */
3439
3440      int pos;
3441      void *ret;
3442      exception_table *tab = &(table->table[0]);
3443
3444      /* Subtract 1 from the PC to avoid hitting the next region */
3445      pc--;
3446
3447      /* We can't do a binary search because the table is in inner-most
3448         to outermost address ranges within functions */
3449      for (pos = 0; tab[pos].start_region != (void *) -1; pos++)
3450        {
3451          if (tab[pos].start_region <= pc && tab[pos].end_region > pc)
3452            {
3453              if (tab[pos].match_info)
3454                {
3455                  __eh_matcher matcher = ((__eh_info *)eh_info)->match_function;
3456                  /* match info but no matcher is NOT a match */
3457                  if (matcher)
3458                    {
3459                      ret = (*matcher)(eh_info, tab[pos].match_info, table);
3460                      if (ret)
3461                        return tab[pos].exception_handler;
3462                    }
3463                }
3464              else
3465                return tab[pos].exception_handler;
3466            }
3467        }
3468    }
3469
3470  return (void *) 0;
3471}
3472#endif /* DWARF2_UNWIND_INFO */
3473#endif /* EH_TABLE_LOOKUP */
3474
3475#ifdef DWARF2_UNWIND_INFO
3476/* Support code for exception handling using static unwind information.  */
3477
3478#include "frame.h"
3479
3480/* This type is used in get_reg and put_reg to deal with ABIs where a void*
3481   is smaller than a word, such as the Irix 6 n32 ABI.  We cast twice to
3482   avoid a warning about casting between int and pointer of different
3483   sizes.  */
3484
3485typedef int ptr_type __attribute__ ((mode (pointer)));
3486
3487/* Get the value of register REG as saved in UDATA, where SUB_UDATA is a
3488   frame called by UDATA or 0.  */
3489
3490static void*
3491get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
3492{
3493  if (udata->saved[reg] == REG_SAVED_OFFSET)
3494    return (void *)(ptr_type)
3495      *(word_type *)(udata->cfa + udata->reg_or_offset[reg]);
3496  else if (udata->saved[reg] == REG_SAVED_REG && sub_udata)
3497    return get_reg (udata->reg_or_offset[reg], sub_udata, 0);
3498  else
3499    abort ();
3500}
3501
3502/* Overwrite the saved value for register REG in frame UDATA with VAL.  */
3503
3504static void
3505put_reg (unsigned reg, void *val, frame_state *udata)
3506{
3507  if (udata->saved[reg] == REG_SAVED_OFFSET)
3508    *(word_type *)(udata->cfa + udata->reg_or_offset[reg])
3509      = (word_type)(ptr_type) val;
3510  else
3511    abort ();
3512}
3513
3514/* Copy the saved value for register REG from frame UDATA to frame
3515   TARGET_UDATA.  Unlike the previous two functions, this can handle
3516   registers that are not one word large.  */
3517
3518static void
3519copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
3520{
3521  if (udata->saved[reg] == REG_SAVED_OFFSET
3522      && target_udata->saved[reg] == REG_SAVED_OFFSET)
3523    memcpy (target_udata->cfa + target_udata->reg_or_offset[reg],
3524	    udata->cfa + udata->reg_or_offset[reg],
3525	    __builtin_dwarf_reg_size (reg));
3526  else
3527    abort ();
3528}
3529
3530/* Retrieve the return address for frame UDATA, where SUB_UDATA is a
3531   frame called by UDATA or 0.  */
3532
3533static inline void *
3534get_return_addr (frame_state *udata, frame_state *sub_udata)
3535{
3536  return __builtin_extract_return_addr
3537    (get_reg (udata->retaddr_column, udata, sub_udata));
3538}
3539
3540/* Overwrite the return address for frame UDATA with VAL.  */
3541
3542static inline void
3543put_return_addr (void *val, frame_state *udata)
3544{
3545  val = __builtin_frob_return_addr (val);
3546  put_reg (udata->retaddr_column, val, udata);
3547}
3548
3549/* Given the current frame UDATA and its return address PC, return the
3550   information about the calling frame in CALLER_UDATA.  */
3551
3552static void *
3553next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
3554{
3555  caller_udata = __frame_state_for (pc, caller_udata);
3556  if (! caller_udata)
3557    return 0;
3558
3559  /* Now go back to our caller's stack frame.  If our caller's CFA register
3560     was saved in our stack frame, restore it; otherwise, assume the CFA
3561     register is SP and restore it to our CFA value.  */
3562  if (udata->saved[caller_udata->cfa_reg])
3563    caller_udata->cfa = get_reg (caller_udata->cfa_reg, udata, 0);
3564  else
3565    caller_udata->cfa = udata->cfa;
3566  caller_udata->cfa += caller_udata->cfa_offset;
3567
3568  return caller_udata;
3569}
3570
3571#ifdef INCOMING_REGNO
3572/* Is the saved value for register REG in frame UDATA stored in a register
3573   window in the previous frame?  */
3574
3575static int
3576in_reg_window (int reg, frame_state *udata)
3577{
3578  if (udata->saved[reg] != REG_SAVED_OFFSET)
3579    return 0;
3580
3581#ifdef STACK_GROWS_DOWNWARD
3582  return udata->reg_or_offset[reg] > 0;
3583#else
3584  return udata->reg_or_offset[reg] < 0;
3585#endif
3586}
3587#endif /* INCOMING_REGNO */
3588
3589/* We first search for an exception handler, and if we don't find
3590   it, we call __terminate on the current stack frame so that we may
3591   use the debugger to walk the stack and understand why no handler
3592   was found.
3593
3594   If we find one, then we unwind the frames down to the one that
3595   has the handler and transfer control into the handler.  */
3596
3597void
3598__throw ()
3599{
3600  struct eh_context *eh = (*get_eh_context) ();
3601  void *saved_pc, *pc, *handler, *retaddr;
3602  frame_state ustruct, ustruct2;
3603  frame_state *udata = &ustruct;
3604  frame_state *sub_udata = &ustruct2;
3605  frame_state my_ustruct, *my_udata = &my_ustruct;
3606  long args_size;
3607  int new_exception_model;
3608
3609  /* This is required for C++ semantics.  We must call terminate if we
3610     try and rethrow an exception, when there is no exception currently
3611     active.  */
3612  if (! eh->info)
3613    __terminate ();
3614
3615  /* Start at our stack frame.  */
3616label:
3617  udata = __frame_state_for (&&label, udata);
3618  if (! udata)
3619    __terminate ();
3620
3621  /* We need to get the value from the CFA register.  At this point in
3622     compiling __throw we don't know whether or not we will use the frame
3623     pointer register for the CFA, so we check our unwind info.  */
3624  if (udata->cfa_reg == __builtin_dwarf_fp_regnum ())
3625    udata->cfa = __builtin_fp ();
3626  else
3627    udata->cfa = __builtin_sp ();
3628  udata->cfa += udata->cfa_offset;
3629
3630  memcpy (my_udata, udata, sizeof (*udata));
3631
3632  /* Do any necessary initialization to access arbitrary stack frames.
3633     On the SPARC, this means flushing the register windows.  */
3634  __builtin_unwind_init ();
3635
3636  /* Now reset pc to the right throw point.  */
3637  pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
3638  saved_pc = pc;
3639
3640  handler = 0;
3641  for (;;)
3642    {
3643      frame_state *p = udata;
3644      udata = next_stack_level (pc, udata, sub_udata);
3645      sub_udata = p;
3646
3647      /* If we couldn't find the next frame, we lose.  */
3648      if (! udata)
3649	break;
3650
3651      if (udata->eh_ptr == NULL)
3652        new_exception_model = 0;
3653      else
3654        new_exception_model = (((exception_descriptor *)(udata->eh_ptr))->
3655                                          runtime_id_field == NEW_EH_RUNTIME);
3656
3657      if (new_exception_model)
3658        handler = find_exception_handler (pc, udata->eh_ptr, eh->info);
3659      else
3660        handler = old_find_exception_handler (pc, udata->eh_ptr);
3661
3662      /* If we found one, we can stop searching.  */
3663      if (handler)
3664	{
3665	  args_size = udata->args_size;
3666	  break;
3667	}
3668
3669      /* Otherwise, we continue searching.  We subtract 1 from PC to avoid
3670	 hitting the beginning of the next region.  */
3671      pc = get_return_addr (udata, sub_udata) - 1;
3672    }
3673
3674  /* If we haven't found a handler by now, this is an unhandled
3675     exception.  */
3676  if (! handler)
3677    __terminate ();
3678
3679  eh->handler_label = handler;
3680
3681  if (pc == saved_pc)
3682    /* We found a handler in the throw context, no need to unwind.  */
3683    udata = my_udata;
3684  else
3685    {
3686      int i;
3687
3688      /* Unwind all the frames between this one and the handler by copying
3689	 their saved register values into our register save slots.  */
3690
3691      /* Remember the PC where we found the handler.  */
3692      void *handler_pc = pc;
3693
3694      /* Start from the throw context again.  */
3695      pc = saved_pc;
3696      memcpy (udata, my_udata, sizeof (*udata));
3697
3698      while (pc != handler_pc)
3699	{
3700	  frame_state *p = udata;
3701	  udata = next_stack_level (pc, udata, sub_udata);
3702	  sub_udata = p;
3703
3704	  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
3705	    if (i != udata->retaddr_column && udata->saved[i])
3706	      {
3707#ifdef INCOMING_REGNO
3708		/* If you modify the saved value of the return address
3709		   register on the SPARC, you modify the return address for
3710		   your caller's frame.  Don't do that here, as it will
3711		   confuse get_return_addr.  */
3712		if (in_reg_window (i, udata)
3713		    && udata->saved[udata->retaddr_column] == REG_SAVED_REG
3714		    && udata->reg_or_offset[udata->retaddr_column] == i)
3715		  continue;
3716#endif
3717		copy_reg (i, udata, my_udata);
3718	      }
3719
3720	  pc = get_return_addr (udata, sub_udata) - 1;
3721	}
3722
3723#ifdef INCOMING_REGNO
3724      /* But we do need to update the saved return address register from
3725	 the last frame we unwind, or the handler frame will have the wrong
3726	 return address.  */
3727      if (udata->saved[udata->retaddr_column] == REG_SAVED_REG)
3728	{
3729	  i = udata->reg_or_offset[udata->retaddr_column];
3730	  if (in_reg_window (i, udata))
3731	    copy_reg (i, udata, my_udata);
3732	}
3733#endif
3734    }
3735  /* udata now refers to the frame called by the handler frame.  */
3736
3737  /* Emit the stub to adjust sp and jump to the handler.  */
3738  if (new_exception_model)
3739    retaddr = __builtin_eh_stub ();
3740  else
3741    retaddr =  __builtin_eh_stub_old ();
3742
3743  /* And then set our return address to point to the stub.  */
3744  if (my_udata->saved[my_udata->retaddr_column] == REG_SAVED_OFFSET)
3745    put_return_addr (retaddr, my_udata);
3746  else
3747    __builtin_set_return_addr_reg (retaddr);
3748
3749  /* Set up the registers we use to communicate with the stub.
3750     We check STACK_GROWS_DOWNWARD so the stub can use adjust_stack.  */
3751
3752  if (new_exception_model)
3753    __builtin_set_eh_regs ((void *)eh,
3754#ifdef STACK_GROWS_DOWNWARD
3755			 udata->cfa - my_udata->cfa
3756#else
3757			 my_udata->cfa - udata->cfa
3758#endif
3759			 + args_size);
3760  else
3761    __builtin_set_eh_regs (handler,
3762
3763#ifdef STACK_GROWS_DOWNWARD
3764			 udata->cfa - my_udata->cfa
3765#else
3766			 my_udata->cfa - udata->cfa
3767#endif
3768			 + args_size);
3769
3770  /* Epilogue:  restore the handler frame's register values and return
3771     to the stub.  */
3772}
3773#endif /* DWARF2_UNWIND_INFO */
3774
3775#endif /* L_eh */
3776
3777#ifdef L_pure
3778#ifndef inhibit_libc
3779/* This gets us __GNU_LIBRARY__.  */
3780#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch.  */
3781#include <stdio.h>
3782
3783#ifdef __GNU_LIBRARY__
3784  /* Avoid forcing the library's meaning of `write' on the user program
3785     by using the "internal" name (for use within the library)  */
3786#define write(fd, buf, n)	__write((fd), (buf), (n))
3787#endif
3788#endif /* inhibit_libc */
3789
3790#define MESSAGE "pure virtual method called\n"
3791
3792void
3793__pure_virtual ()
3794{
3795#ifndef inhibit_libc
3796  write (2, MESSAGE, sizeof (MESSAGE) - 1);
3797#endif
3798  _exit (-1);
3799}
3800#endif
3801