#include "tconfig.h"
#ifndef inhibit_libc
#include <stdlib.h>
#include <unistd.h>
#endif
#include "machmode.h"
#include "defaults.h"
#ifndef L_trampoline
#include <stddef.h>
#endif
#ifdef abort
#undef abort
#endif
#if (SUPPORTS_WEAK == 1) && (defined (ASM_OUTPUT_DEF) || defined (ASM_OUTPUT_WEAK_ALIAS))
#define WEAK_ALIAS
#endif
#if defined(CROSS_COMPILE) && !defined(inhibit_libc)
#define inhibit_libc
#endif
#ifndef LIBGCC2_WORDS_BIG_ENDIAN
#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
#endif
#ifndef PRIVATE_EXTERN
#define PRIVATE_EXTERN
#endif
#ifndef PRIVATE_EXTERN_ASM_OP
#define PRIVATE_EXTERN_ASM_OP ".global"
#endif
#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
#endif
typedef unsigned int UQItype __attribute__ ((mode (QI)));
typedef int SItype __attribute__ ((mode (SI)));
typedef unsigned int USItype __attribute__ ((mode (SI)));
typedef int DItype __attribute__ ((mode (DI)));
typedef unsigned int UDItype __attribute__ ((mode (DI)));
typedef float SFtype __attribute__ ((mode (SF)));
typedef float DFtype __attribute__ ((mode (DF)));
#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
typedef float XFtype __attribute__ ((mode (XF)));
#endif
#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
typedef float TFtype __attribute__ ((mode (TF)));
#endif
typedef int word_type __attribute__ ((mode (__word__)));
#define char bogus_type
#define short bogus_type
#define int bogus_type
#define long bogus_type
#define unsigned bogus_type
#define float bogus_type
#define double bogus_type
#define SI_TYPE_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#if LIBGCC2_WORDS_BIG_ENDIAN
struct DIstruct {SItype high, low;};
#else
struct DIstruct {SItype low, high;};
#endif
typedef union
{
struct DIstruct s;
DItype ll;
} DIunion;
#if (defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv)\
|| defined (L_divdi3) || defined (L_udivdi3) \
|| defined (L_moddi3) || defined (L_umoddi3))
#include "longlong.h"
#endif
extern DItype __fixunssfdi (SFtype a);
extern DItype __fixunsdfdi (DFtype a);
#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
extern DItype __fixunsxfdi (XFtype a);
#endif
#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
extern DItype __fixunstfdi (TFtype a);
#endif
#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
#if defined (L_divdi3) || defined (L_moddi3)
static inline
#endif
DItype
__negdi2 (DItype u)
{
DIunion w;
DIunion uu;
uu.ll = u;
w.s.low = -uu.s.low;
w.s.high = -uu.s.high - ((USItype) w.s.low > 0);
return w.ll;
}
#endif
#ifdef L_lshrdi3
DItype
__lshrdi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.high = 0;
w.s.low = (USItype)uu.s.high >> -bm;
}
else
{
USItype carries = (USItype)uu.s.high << bm;
w.s.high = (USItype)uu.s.high >> b;
w.s.low = ((USItype)uu.s.low >> b) | carries;
}
return w.ll;
}
#endif
#ifdef L_ashldi3
DItype
__ashldi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.low = 0;
w.s.high = (USItype)uu.s.low << -bm;
}
else
{
USItype carries = (USItype)uu.s.low >> bm;
w.s.low = (USItype)uu.s.low << b;
w.s.high = ((USItype)uu.s.high << b) | carries;
}
return w.ll;
}
#endif
#ifdef L_ashrdi3
DItype
__ashrdi3 (DItype u, word_type b)
{
DIunion w;
word_type bm;
DIunion uu;
if (b == 0)
return u;
uu.ll = u;
bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
if (bm <= 0)
{
w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
w.s.low = uu.s.high >> -bm;
}
else
{
USItype carries = (USItype)uu.s.high << bm;
w.s.high = uu.s.high >> b;
w.s.low = ((USItype)uu.s.low >> b) | carries;
}
return w.ll;
}
#endif
#ifdef L_ffsdi2
DItype
__ffsdi2 (DItype u)
{
DIunion uu, w;
uu.ll = u;
w.s.high = 0;
w.s.low = ffs (uu.s.low);
if (w.s.low != 0)
return w.ll;
w.s.low = ffs (uu.s.high);
if (w.s.low != 0)
{
w.s.low += BITS_PER_UNIT * sizeof (SItype);
return w.ll;
}
return w.ll;
}
#endif
#ifdef L_muldi3
DItype
__muldi3 (DItype u, DItype v)
{
DIunion w;
DIunion uu, vv;
uu.ll = u,
vv.ll = v;
w.ll = __umulsidi3 (uu.s.low, vv.s.low);
w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+ (USItype) uu.s.high * (USItype) vv.s.low);
return w.ll;
}
#endif
#ifdef L_udiv_w_sdiv
#if defined (sdiv_qrnnd)
USItype
__udiv_w_sdiv (USItype *rp, USItype a1, USItype a0, USItype d)
{
USItype q, r;
USItype c0, c1, b1;
if ((SItype) d >= 0)
{
if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1)))
{
sdiv_qrnnd (q, r, a1, a0, d);
}
else
{
sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1));
sdiv_qrnnd (q, r, c1, c0, d);
q += (USItype) 1 << (SI_TYPE_SIZE - 1);
}
}
else
{
b1 = d >> 1;
c1 = a1 >> 1;
c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1);
if (a1 < b1)
{
sdiv_qrnnd (q, r, c1, c0, b1);
r = 2*r + (a0 & 1);
if ((d & 1) != 0)
{
if (r >= q)
r = r - q;
else if (q - r <= d)
{
r = r - q + d;
q--;
}
else
{
r = r - q + 2*d;
q -= 2;
}
}
}
else if (c1 < b1)
{
c1 = (b1 - 1) - c1;
c0 = ~c0;
sdiv_qrnnd (q, r, c1, c0, b1);
q = ~q;
r = (b1 - 1) - r;
r = 2*r + (a0 & 1);
if ((d & 1) != 0)
{
if (r >= q)
r = r - q;
else if (q - r <= d)
{
r = r - q + d;
q--;
}
else
{
r = r - q + 2*d;
q -= 2;
}
}
}
else
{
if (a0 >= -d)
{
q = -1;
r = a0 + d;
}
else
{
q = -2;
r = a0 + 2*d;
}
}
}
*rp = r;
return q;
}
#else
USItype
__udiv_w_sdiv (USItype *rp __attribute__ ((__unused__)),
USItype a1 __attribute__ ((__unused__)),
USItype a0 __attribute__ ((__unused__)),
USItype d __attribute__ ((__unused__)))
{
return 0;
}
#endif
#endif
#if (defined (L_udivdi3) || defined (L_divdi3) || \
defined (L_umoddi3) || defined (L_moddi3))
#define L_udivmoddi4
#endif
#ifdef L_udivmoddi4
static const UQItype __clz_tab[] =
{
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,
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,
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,
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,
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,
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,
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,
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,
};
#if (defined (L_udivdi3) || defined (L_divdi3) || \
defined (L_umoddi3) || defined (L_moddi3))
static inline
#endif
UDItype
__udivmoddi4 (UDItype n, UDItype d, UDItype *rp)
{
DIunion ww;
DIunion nn, dd;
DIunion rr;
USItype d0, d1, n0, n1, n2;
USItype q0, q1;
USItype b, bm;
nn.ll = n;
dd.ll = d;
d0 = dd.s.low;
d1 = dd.s.high;
n0 = nn.s.low;
n1 = nn.s.high;
#if !UDIV_NEEDS_NORMALIZATION
if (d1 == 0)
{
if (d0 > n1)
{
udiv_qrnnd (q0, n0, n1, n0, d0);
q1 = 0;
}
else
{
if (d0 == 0)
d0 = 1 / d0;
udiv_qrnnd (q1, n1, 0, n1, d0);
udiv_qrnnd (q0, n0, n1, n0, d0);
}
if (rp != 0)
{
rr.s.low = n0;
rr.s.high = 0;
*rp = rr.ll;
}
}
#else
if (d1 == 0)
{
if (d0 > n1)
{
count_leading_zeros (bm, d0);
if (bm != 0)
{
d0 = d0 << bm;
n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
n0 = n0 << bm;
}
udiv_qrnnd (q0, n0, n1, n0, d0);
q1 = 0;
}
else
{
if (d0 == 0)
d0 = 1 / d0;
count_leading_zeros (bm, d0);
if (bm == 0)
{
n1 -= d0;
q1 = 1;
}
else
{
b = SI_TYPE_SIZE - bm;
d0 = d0 << bm;
n2 = n1 >> b;
n1 = (n1 << bm) | (n0 >> b);
n0 = n0 << bm;
udiv_qrnnd (q1, n1, n2, n1, d0);
}
udiv_qrnnd (q0, n0, n1, n0, d0);
}
if (rp != 0)
{
rr.s.low = n0 >> bm;
rr.s.high = 0;
*rp = rr.ll;
}
}
#endif
else
{
if (d1 > n1)
{
q0 = 0;
q1 = 0;
if (rp != 0)
{
rr.s.low = n0;
rr.s.high = n1;
*rp = rr.ll;
}
}
else
{
count_leading_zeros (bm, d1);
if (bm == 0)
{
if (n1 > d1 || n0 >= d0)
{
q0 = 1;
sub_ddmmss (n1, n0, n1, n0, d1, d0);
}
else
q0 = 0;
q1 = 0;
if (rp != 0)
{
rr.s.low = n0;
rr.s.high = n1;
*rp = rr.ll;
}
}
else
{
USItype m1, m0;
b = SI_TYPE_SIZE - bm;
d1 = (d1 << bm) | (d0 >> b);
d0 = d0 << bm;
n2 = n1 >> b;
n1 = (n1 << bm) | (n0 >> b);
n0 = n0 << bm;
udiv_qrnnd (q0, n1, n2, n1, d1);
umul_ppmm (m1, m0, q0, d0);
if (m1 > n1 || (m1 == n1 && m0 > n0))
{
q0--;
sub_ddmmss (m1, m0, m1, m0, d1, d0);
}
q1 = 0;
if (rp != 0)
{
sub_ddmmss (n1, n0, n1, n0, m1, m0);
rr.s.low = (n1 << b) | (n0 >> bm);
rr.s.high = n1 >> bm;
*rp = rr.ll;
}
}
}
}
ww.s.low = q0;
ww.s.high = q1;
return ww.ll;
}
#endif
#ifdef L_divdi3
UDItype __udivmoddi4 ();
DItype
__divdi3 (DItype u, DItype v)
{
word_type c = 0;
DIunion uu, vv;
DItype w;
uu.ll = u;
vv.ll = v;
if (uu.s.high < 0)
c = ~c,
uu.ll = __negdi2 (uu.ll);
if (vv.s.high < 0)
c = ~c,
vv.ll = __negdi2 (vv.ll);
w = __udivmoddi4 (uu.ll, vv.ll, (UDItype *) 0);
if (c)
w = __negdi2 (w);
return w;
}
#endif
#ifdef L_moddi3
UDItype __udivmoddi4 ();
DItype
__moddi3 (DItype u, DItype v)
{
word_type c = 0;
DIunion uu, vv;
DItype w;
uu.ll = u;
vv.ll = v;
if (uu.s.high < 0)
c = ~c,
uu.ll = __negdi2 (uu.ll);
if (vv.s.high < 0)
vv.ll = __negdi2 (vv.ll);
(void) __udivmoddi4 (uu.ll, vv.ll, &w);
if (c)
w = __negdi2 (w);
return w;
}
#endif
#ifdef L_umoddi3
UDItype __udivmoddi4 ();
UDItype
__umoddi3 (UDItype u, UDItype v)
{
UDItype w;
(void) __udivmoddi4 (u, v, &w);
return w;
}
#endif
#ifdef L_udivdi3
UDItype __udivmoddi4 ();
UDItype
__udivdi3 (UDItype n, UDItype d)
{
return __udivmoddi4 (n, d, (UDItype *) 0);
}
#endif
#ifdef L_cmpdi2
word_type
__cmpdi2 (DItype a, DItype b)
{
DIunion au, bu;
au.ll = a, bu.ll = b;
if (au.s.high < bu.s.high)
return 0;
else if (au.s.high > bu.s.high)
return 2;
if ((USItype) au.s.low < (USItype) bu.s.low)
return 0;
else if ((USItype) au.s.low > (USItype) bu.s.low)
return 2;
return 1;
}
#endif
#ifdef L_ucmpdi2
word_type
__ucmpdi2 (DItype a, DItype b)
{
DIunion au, bu;
au.ll = a, bu.ll = b;
if ((USItype) au.s.high < (USItype) bu.s.high)
return 0;
else if ((USItype) au.s.high > (USItype) bu.s.high)
return 2;
if ((USItype) au.s.low < (USItype) bu.s.low)
return 0;
else if ((USItype) au.s.low > (USItype) bu.s.low)
return 2;
return 1;
}
#endif
#if defined(L_fixunstfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DItype
__fixunstfdi (TFtype a)
{
TFtype b;
UDItype v;
if (a < 0)
return 0;
b = (a / HIGH_WORD_COEFF);
v = (USItype) b;
v <<= WORD_SIZE;
a -= (TFtype)v;
if (a < 0)
v -= (USItype) (- a);
else
v += (USItype) a;
return v;
}
#endif
#if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
DItype
__fixtfdi (TFtype a)
{
if (a < 0)
return - __fixunstfdi (-a);
return __fixunstfdi (a);
}
#endif
#if defined(L_fixunsxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DItype
__fixunsxfdi (XFtype a)
{
XFtype b;
UDItype v;
if (a < 0)
return 0;
b = (a / HIGH_WORD_COEFF);
v = (USItype) b;
v <<= WORD_SIZE;
a -= (XFtype)v;
if (a < 0)
v -= (USItype) (- a);
else
v += (USItype) a;
return v;
}
#endif
#if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
DItype
__fixxfdi (XFtype a)
{
if (a < 0)
return - __fixunsxfdi (-a);
return __fixunsxfdi (a);
}
#endif
#ifdef L_fixunsdfdi
#ifdef NEXT_SEMANTICS
#undef char
#undef short
#undef int
#undef long
#undef unsigned
#undef float
#undef double
#undef MIN
#undef MAX
#include <limits.h>
#endif
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DItype
__fixunsdfdi (DFtype a)
{
DFtype b;
UDItype v;
if (a < 0)
return 0;
#ifdef NEXT_SEMANTICS
else if (a > UQUAD_MAX)
return UQUAD_MAX;
else if (a <= UQUAD_MAX)
{
#endif
b = (a / HIGH_WORD_COEFF);
v = (USItype) b;
v <<= WORD_SIZE;
a -= (DFtype)v;
if (a < 0)
v -= (USItype) (- a);
else
v += (USItype) a;
return v;
#ifdef NEXT_SEMANTICS
}
else
return 0;
#endif
}
#endif
#ifdef L_fixdfdi
#ifdef NEXT_SEMANTICS
#undef char
#undef short
#undef int
#undef long
#undef unsigned
#undef float
#undef double
#undef MIN
#undef MAX
#include <limits.h>
#endif
DItype
__fixdfdi (DFtype a)
{
#ifdef NEXT_SEMANTICS
if (a > QUAD_MAX)
return QUAD_MAX;
else if (a < QUAD_MIN)
return QUAD_MIN;
#endif
if (a < 0)
return - __fixunsdfdi (-a);
#ifdef NEXT_SEMANTICS
else if (a > 0)
#endif
return __fixunsdfdi (a);
#ifdef NEXT_SEMANTICS
else
return 0;
#endif
}
#endif
#ifdef L_fixunssfdi
#ifdef NEXT_SEMANTICS
#undef char
#undef short
#undef int
#undef long
#undef unsigned
#undef float
#undef double
#undef MIN
#undef MAX
#include <limits.h>
#endif
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DItype
__fixunssfdi (SFtype original_a)
{
DFtype a = original_a;
DFtype b;
UDItype v;
if (a < 0)
return 0;
#ifdef NEXT_SEMANTICS
if (a > UQUAD_MAX)
return UQUAD_MAX;
#endif
b = (a / HIGH_WORD_COEFF);
v = (USItype) b;
v <<= WORD_SIZE;
a -= (DFtype)v;
if (a < 0)
v -= (USItype) (- a);
else
v += (USItype) a;
return v;
}
#endif
#ifdef L_fixsfdi
#ifdef NEXT_SEMANTICS
#undef char
#undef short
#undef int
#undef long
#undef unsigned
#undef float
#undef double
#undef MIN
#undef MAX
#include <limits.h>
#endif
DItype
__fixsfdi (SFtype a)
{
#ifdef NEXT_SEMANTICS
if (a > QUAD_MAX)
return QUAD_MAX;
else if (a < QUAD_MIN)
return QUAD_MIN;
#endif
if (a < 0)
return - __fixunssfdi (-a);
return __fixunssfdi (a);
}
#endif
#if defined(L_floatdixf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
XFtype
__floatdixf (DItype u)
{
XFtype d;
d = (SItype) (u >> WORD_SIZE);
d *= HIGH_HALFWORD_COEFF;
d *= HIGH_HALFWORD_COEFF;
d += (USItype) (u & (HIGH_WORD_COEFF - 1));
return d;
}
#endif
#if defined(L_floatditf) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
TFtype
__floatditf (DItype u)
{
TFtype d;
d = (SItype) (u >> WORD_SIZE);
d *= HIGH_HALFWORD_COEFF;
d *= HIGH_HALFWORD_COEFF;
d += (USItype) (u & (HIGH_WORD_COEFF - 1));
return d;
}
#endif
#ifdef L_floatdidf
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
DFtype
__floatdidf (DItype u)
{
DFtype d;
d = (SItype) (u >> WORD_SIZE);
d *= HIGH_HALFWORD_COEFF;
d *= HIGH_HALFWORD_COEFF;
d += (USItype) (u & (HIGH_WORD_COEFF - 1));
return d;
}
#endif
#ifdef L_floatdisf
#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDItype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE)
#define DI_SIZE (sizeof (DItype) * BITS_PER_UNIT)
#define UNKNOWN_FLOAT_FORMAT 0
#define IEEE_FLOAT_FORMAT 1
#define VAX_FLOAT_FORMAT 2
#define IBM_FLOAT_FORMAT 3
#ifndef HOST_FLOAT_FORMAT
#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
#endif
#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
#define DF_SIZE 53
#define SF_SIZE 24
#endif
#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
#define DF_SIZE 56
#define SF_SIZE 24
#endif
#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
#define DF_SIZE 56
#define SF_SIZE 24
#endif
SFtype
__floatdisf (DItype u)
{
DFtype f;
if (DF_SIZE < DI_SIZE
&& DF_SIZE > (DI_SIZE - DF_SIZE + SF_SIZE))
{
#define REP_BIT ((USItype) 1 << (DI_SIZE - DF_SIZE))
if (! (- ((DItype) 1 << DF_SIZE) < u
&& u < ((DItype) 1 << DF_SIZE)))
{
if ((USItype) u & (REP_BIT - 1))
u |= REP_BIT;
}
}
f = (SItype) (u >> WORD_SIZE);
f *= HIGH_HALFWORD_COEFF;
f *= HIGH_HALFWORD_COEFF;
f += (USItype) (u & (HIGH_WORD_COEFF - 1));
return (SFtype) f;
}
#endif
#if defined(L_fixunsxfsi) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96
#undef char
#undef short
#undef int
#undef long
#undef unsigned
#undef float
#undef double
#undef MIN
#undef MAX
#include <limits.h>
USItype
__fixunsxfsi (XFtype a)
{
if (a >= - (DFtype) LONG_MIN)
return (SItype) (a + LONG_MIN) - LONG_MIN;
return (SItype) a;
}
#endif
#ifdef L_fixunsdfsi
#undef char
#undef short
#undef int
#undef long
#undef unsigned
#undef float
#undef double
#undef MIN
#undef MAX
#include <limits.h>
USItype
__fixunsdfsi (DFtype a)
{
#ifdef NEXT_SEMANTICS
if (a > ULONG_MAX)
return ULONG_MAX;
else if (a < 0)
return 0;
#endif
if (a >= - (DFtype) LONG_MIN)
return (SItype) (a + LONG_MIN) - LONG_MIN;
return (SItype) a;
}
#endif
#ifdef L_fixunssfsi
#undef char
#undef short
#undef int
#undef long
#undef unsigned
#undef float
#undef double
#undef MIN
#undef MAX
#include <limits.h>
USItype
__fixunssfsi (SFtype a)
{
#ifdef NEXT_SEMANTICS
if (a > ULONG_MAX)
return ULONG_MAX;
else if (a < 0)
return 0;
#endif
if (a >= - (SFtype) LONG_MIN)
return (SItype) (a + LONG_MIN) - LONG_MIN;
return (SItype) a;
}
#endif
#define SItype bogus_type
#define USItype bogus_type
#define DItype bogus_type
#define UDItype bogus_type
#define SFtype bogus_type
#define DFtype bogus_type
#undef char
#undef short
#undef int
#undef long
#undef unsigned
#undef float
#undef double
#ifdef L__gcc_bcmp
int
__gcc_bcmp (unsigned char *s1, unsigned char *s2, size_t size)
{
while (size > 0)
{
unsigned char c1 = *s1++, c2 = *s2++;
if (c1 != c2)
return c1 - c2;
size--;
}
return 0;
}
#endif
#ifdef L__dummy
void
__dummy () {}
#endif
#ifdef L_varargs
#ifdef __i860__
#if defined(__svr4__) || defined(__alliant__)
asm (" .text");
asm (" .align 4");
asm (".globl __builtin_saveregs");
asm ("__builtin_saveregs:");
asm (".globl ___builtin_saveregs");
asm ("___builtin_saveregs:");
asm (" andnot 0x0f,%sp,%sp");
asm (" adds -96,%sp,%sp");
asm (" fst.q %f8, 0(%sp)");
asm (" fst.q %f12,16(%sp)");
asm (" st.l %r16,32(%sp)");
asm (" st.l %r17,36(%sp)");
asm (" st.l %r18,40(%sp)");
asm (" st.l %r19,44(%sp)");
asm (" st.l %r20,48(%sp)");
asm (" st.l %r21,52(%sp)");
asm (" st.l %r22,56(%sp)");
asm (" st.l %r23,60(%sp)");
asm (" st.l %r24,64(%sp)");
asm (" st.l %r25,68(%sp)");
asm (" st.l %r26,72(%sp)");
asm (" st.l %r27,76(%sp)");
asm (" adds 80,%sp,%r16");
asm (" st.l %r0, 0(%r16)");
asm (" st.l %r0, 4(%r16)");
asm (" st.l %sp, 8(%r16)");
asm (" bri %r1");
asm (" st.l %r28,12(%r16)");
#else
#if defined(__PARAGON__)
asm (" .text");
asm (" .align 4");
asm (".globl __builtin_saveregs");
asm ("__builtin_saveregs:");
asm (".globl ___builtin_saveregs");
asm ("___builtin_saveregs:");
asm (" andnot 0x0f,sp,sp");
asm (" adds -96,sp,sp");
asm (" fst.q f8, 0(sp)");
asm (" fst.q f12,16(sp)");
asm (" st.l r16,32(sp)");
asm (" st.l r17,36(sp)");
asm (" st.l r18,40(sp)");
asm (" st.l r19,44(sp)");
asm (" st.l r20,48(sp)");
asm (" st.l r21,52(sp)");
asm (" st.l r22,56(sp)");
asm (" st.l r23,60(sp)");
asm (" st.l r24,64(sp)");
asm (" st.l r25,68(sp)");
asm (" st.l r26,72(sp)");
asm (" st.l r27,76(sp)");
asm (" adds 80,sp,r16");
asm (" st.l r0, 0(r16)");
asm (" st.l r0, 4(r16)");
asm (" st.l sp, 8(r16)");
asm (" bri r1");
asm (" st.l r28,12(r16)");
#else
asm (" .text");
asm (" .align 4");
asm (".globl ___builtin_saveregs");
asm ("___builtin_saveregs:");
asm (" mov sp,r30");
asm (" andnot 0x0f,sp,sp");
asm (" adds -96,sp,sp");
asm (" st.l r16, 0(sp)");
asm (" st.l r17, 4(sp)");
asm (" st.l r18, 8(sp)");
asm (" st.l r19,12(sp)");
asm (" st.l r20,16(sp)");
asm (" st.l r21,20(sp)");
asm (" st.l r22,24(sp)");
asm (" st.l r23,28(sp)");
asm (" st.l r24,32(sp)");
asm (" st.l r25,36(sp)");
asm (" st.l r26,40(sp)");
asm (" st.l r27,44(sp)");
asm (" fst.q f8, 48(sp)");
asm (" fst.q f12,64(sp)");
asm (" st.l sp, 80(sp)");
asm (" st.l r28,84(sp)");
asm (" st.l r0, 88(sp)");
asm (" st.l r0, 92(sp)");
asm (" adds 80,sp,r16");
asm (" bri r1");
asm (" mov r30,sp");
#endif
#endif
#else
#ifdef __sparc__
#ifndef NEXT_SEMANTICS
asm (".global __builtin_saveregs");
asm ("__builtin_saveregs:");
#endif
asm (PRIVATE_EXTERN_ASM_OP " ___builtin_saveregs");
asm ("___builtin_saveregs:");
#ifdef NEED_PROC_COMMAND
asm (".proc 020");
#endif
asm ("st %i0,[%fp+68]");
asm ("st %i1,[%fp+72]");
asm ("st %i2,[%fp+76]");
asm ("st %i3,[%fp+80]");
asm ("st %i4,[%fp+84]");
asm ("retl");
asm ("st %i5,[%fp+88]");
#ifdef NEED_TYPE_COMMAND
#ifndef NEXT_SEMANTICS
asm (".type __builtin_saveregs,#function");
asm (".size __builtin_saveregs,.-__builtin_saveregs");
#endif
#endif
#else
#if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
asm (" .text");
#ifdef __mips16
asm (" .set nomips16");
#endif
asm (" .ent __builtin_saveregs");
asm (" .globl __builtin_saveregs");
asm ("__builtin_saveregs:");
asm (" sw $4,0($30)");
asm (" sw $5,4($30)");
asm (" sw $6,8($30)");
asm (" sw $7,12($30)");
asm (" j $31");
asm (" .end __builtin_saveregs");
#else
#ifndef ABORT
#define ABORT abort ()
#endif
void *
__builtin_saveregs ()
{
ABORT;
}
#endif
#endif
#endif
#endif
#ifdef L_eprintf
#ifndef inhibit_libc
#undef NULL
#include <stdio.h>
extern void __eprintf (const char *, const char *, unsigned int, const char *)
__attribute__ ((__noreturn__));
void
__eprintf (const char *string, const char *expression,
unsigned int line, const char *filename)
{
fprintf (stderr, string, expression, line, filename);
fflush (stderr);
abort ();
}
#endif
#endif
#ifdef L_bb
struct bb
{
long zero_word;
const char *filename;
long *counts;
long ncounts;
struct bb *next;
const unsigned long *addresses;
long nwords;
const char **functions;
const long *line_nums;
const char **filenames;
char *flags;
};
#ifdef BLOCK_PROFILER_CODE
BLOCK_PROFILER_CODE
#else
#ifndef inhibit_libc
#undef NULL
#include <stdio.h>
char *ctime ();
#include "gbl-ctors.h"
#include "gcov-io.h"
#include <string.h>
static struct bb *bb_head = NULL;
static int num_digits (long value, int base)
{
int minus = (value < 0 && base != 16);
unsigned long v = (minus) ? -value : value;
int ret = minus;
do
{
v /= base;
ret++;
}
while (v);
return ret;
}
void
__bb_exit_func (void)
{
FILE *da_file, *file;
long time_value;
int i;
if (bb_head == 0)
return;
i = strlen (bb_head->filename) - 3;
if (!strcmp (bb_head->filename+i, ".da"))
{
struct bb *ptr;
for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
{
if ((da_file = fopen (ptr->filename, "r")) != 0)
{
long n_counts = 0;
if (__read_long (&n_counts, da_file, 8) != 0)
{
fprintf (stderr, "arc profiling: Can't read output file %s.\n",
ptr->filename);
continue;
}
if (n_counts == ptr->ncounts)
{
int i;
for (i = 0; i < n_counts; i++)
{
long v = 0;
if (__read_long (&v, da_file, 8) != 0)
{
fprintf (stderr, "arc profiling: Can't read output file %s.\n",
ptr->filename);
break;
}
ptr->counts[i] += v;
}
}
if (fclose (da_file) == EOF)
fprintf (stderr, "arc profiling: Error closing output file %s.\n",
ptr->filename);
}
if ((da_file = fopen (ptr->filename, "w")) == 0)
{
fprintf (stderr, "arc profiling: Can't open output file %s.\n",
ptr->filename);
continue;
}
if (__write_long (ptr->ncounts, da_file, 8) != 0)
{
fprintf (stderr, "arc profiling: Error writing output file %s.\n",
ptr->filename);
}
else
{
int j;
long *count_ptr = ptr->counts;
int ret = 0;
for (j = ptr->ncounts; j > 0; j--)
{
if (__write_long (*count_ptr, da_file, 8) != 0)
{
ret=1;
break;
}
count_ptr++;
}
if (ret)
fprintf (stderr, "arc profiling: Error writing output file %s.\n",
ptr->filename);
}
if (fclose (da_file) == EOF)
fprintf (stderr, "arc profiling: Error closing output file %s.\n",
ptr->filename);
}
return;
}
file = fopen ("bb.out", "a");
if (!file)
perror ("bb.out");
else
{
struct bb *ptr;
time ((void *) &time_value);
fprintf (file, "Basic block profiling finished on %s\n", ctime ((void *) &time_value));
for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
{
int i;
int func_p = (ptr->nwords >= sizeof (struct bb)
&& ptr->nwords <= 1000
&& ptr->functions);
int line_p = (func_p && ptr->line_nums);
int file_p = (func_p && ptr->filenames);
int addr_p = (ptr->addresses != 0);
long ncounts = ptr->ncounts;
long cnt_max = 0;
long line_max = 0;
long addr_max = 0;
int file_len = 0;
int func_len = 0;
int blk_len = num_digits (ncounts, 10);
int cnt_len;
int line_len;
int addr_len;
fprintf (file, "File %s, %ld basic blocks \n\n",
ptr->filename, ncounts);
for (i = 0; i < ncounts; i++)
{
const char *p;
int len;
if (cnt_max < ptr->counts[i])
cnt_max = ptr->counts[i];
if (addr_p && addr_max < ptr->addresses[i])
addr_max = ptr->addresses[i];
if (line_p && line_max < ptr->line_nums[i])
line_max = ptr->line_nums[i];
if (func_p)
{
p = (ptr->functions[i]) ? (ptr->functions[i]) : "<none>";
len = strlen (p);
if (func_len < len)
func_len = len;
}
if (file_p)
{
p = (ptr->filenames[i]) ? (ptr->filenames[i]) : "<none>";
len = strlen (p);
if (file_len < len)
file_len = len;
}
}
addr_len = num_digits (addr_max, 16);
cnt_len = num_digits (cnt_max, 10);
line_len = num_digits (line_max, 10);
for (i = 0; i < ncounts; i++)
{
fprintf (file,
" Block #%*d: executed %*ld time(s)",
blk_len, i+1,
cnt_len, ptr->counts[i]);
if (addr_p)
fprintf (file, " address= 0x%.*lx", addr_len,
ptr->addresses[i]);
if (func_p)
fprintf (file, " function= %-*s", func_len,
(ptr->functions[i]) ? ptr->functions[i] : "<none>");
if (line_p)
fprintf (file, " line= %*ld", line_len, ptr->line_nums[i]);
if (file_p)
fprintf (file, " file= %s",
(ptr->filenames[i]) ? ptr->filenames[i] : "<none>");
fprintf (file, "\n");
}
fprintf (file, "\n");
fflush (file);
}
fprintf (file, "\n\n");
fclose (file);
}
}
void
__bb_init_func (struct bb *blocks)
{
if (blocks->zero_word)
return;
#ifdef ON_EXIT
if (!bb_head)
ON_EXIT (__bb_exit_func, 0);
#endif
blocks->zero_word = 1;
blocks->next = bb_head;
bb_head = blocks;
}
#ifndef MACHINE_STATE_SAVE
#define MACHINE_STATE_SAVE(ID)
#endif
#ifndef MACHINE_STATE_RESTORE
#define MACHINE_STATE_RESTORE(ID)
#endif
#define BB_BUCKETS 311
#define BBINBUFSIZE 500
#define BBINBUFSIZESTR "499"
struct bb_edge
{
struct bb_edge *next;
unsigned long src_addr;
unsigned long dst_addr;
unsigned long count;
};
enum bb_func_mode
{
TRACE_KEEP = 0, TRACE_ON = 1, TRACE_OFF = 2
};
struct bb_func
{
struct bb_func *next;
char *funcname;
char *filename;
enum bb_func_mode mode;
};
struct {
unsigned long blockno;
struct bb *blocks;
} __bb = {0, (struct bb *)0};
static unsigned long bb_src = 0;
static unsigned long bb_dst = 0;
static FILE *bb_tracefile = (FILE *) 0;
static struct bb_edge **bb_hashbuckets = (struct bb_edge **) 0;
static struct bb_func *bb_func_head = (struct bb_func *) 0;
static unsigned long bb_callcount = 0;
static int bb_mode = 0;
static unsigned long *bb_stack = (unsigned long *) 0;
static size_t bb_stacksize = 0;
static int reported = 0;
#ifdef HAVE_POPEN
#include <sys/stat.h>
#define GOPENDECOMPRESS "gzip -cd "
#define GOPENCOMPRESS "gzip -c >"
static FILE *
gopen (char *fn, char *mode)
{
int use_gzip;
char *p;
if (mode[1])
return (FILE *) 0;
if (mode[0] != 'r' && mode[0] != 'w')
return (FILE *) 0;
p = fn + strlen (fn)-1;
use_gzip = ((p[-1] == '.' && (p[0] == 'Z' || p[0] == 'z'))
|| (p[-2] == '.' && p[-1] == 'g' && p[0] == 'z'));
if (use_gzip)
{
if (mode[0]=='r')
{
FILE *f;
char *s = (char *) malloc (sizeof (char) * strlen (fn)
+ sizeof (GOPENDECOMPRESS));
strcpy (s, GOPENDECOMPRESS);
strcpy (s + (sizeof (GOPENDECOMPRESS)-1), fn);
f = popen (s, mode);
free (s);
return f;
}
else
{
FILE *f;
char *s = (char *) malloc (sizeof (char) * strlen (fn)
+ sizeof (GOPENCOMPRESS));
strcpy (s, GOPENCOMPRESS);
strcpy (s + (sizeof (GOPENCOMPRESS)-1), fn);
if (!(f = popen (s, mode)))
f = fopen (s, mode);
free (s);
return f;
}
}
else
return fopen (fn, mode);
}
static int
gclose (FILE *f)
{
struct stat buf;
if (f != 0)
{
if (!fstat (fileno (f), &buf) && S_ISFIFO (buf.st_mode))
return pclose (f);
return fclose (f);
}
return 0;
}
#endif
static void
__bb_exit_trace_func ()
{
FILE *file = fopen ("bb.out", "a");
struct bb_func *f;
struct bb *b;
if (!file)
perror ("bb.out");
if (bb_mode & 1)
{
if (!bb_tracefile)
perror ("bbtrace");
else
#ifdef HAVE_POPEN
gclose (bb_tracefile);
#else
fclose (bb_tracefile);
#endif
}
if (file)
{
long time_value;
const struct bb_func *p;
int printed_something = 0;
struct bb *ptr;
long blk;
time ((void *) &time_value);
for (p = bb_func_head; p != (struct bb_func *) 0; p = p->next)
{
for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
{
if (!ptr->filename || (p->filename != (char *) 0 && strcmp (p->filename, ptr->filename)))
continue;
for (blk = 0; blk < ptr->ncounts; blk++)
{
if (!strcmp (p->funcname, ptr->functions[blk]))
goto found;
}
}
if (!printed_something)
{
fprintf (file, "Functions in `bb.in' not executed during basic block profiling on %s\n", ctime ((void *) &time_value));
printed_something = 1;
}
fprintf (file, "\tFunction %s", p->funcname);
if (p->filename)
fprintf (file, " of file %s", p->filename);
fprintf (file, "\n" );
found: ;
}
if (printed_something)
fprintf (file, "\n");
}
if (bb_mode & 2)
{
if (!bb_hashbuckets)
{
if (!reported)
{
fprintf (stderr, "Profiler: out of memory\n");
reported = 1;
}
return;
}
else if (file)
{
long time_value;
int i;
unsigned long addr_max = 0;
unsigned long cnt_max = 0;
int cnt_len;
int addr_len;
time ((void *) &time_value);
fprintf (file, "Basic block jump tracing");
switch (bb_mode & 12)
{
case 0:
fprintf (file, " (with call)");
break;
case 4:
break;
case 8:
fprintf (file, " (with call & ret)");
break;
case 12:
fprintf (file, " (with ret)");
break;
}
fprintf (file, " finished on %s\n", ctime ((void *) &time_value));
for (i = 0; i < BB_BUCKETS; i++)
{
struct bb_edge *bucket = bb_hashbuckets[i];
for ( ; bucket; bucket = bucket->next )
{
if (addr_max < bucket->src_addr)
addr_max = bucket->src_addr;
if (addr_max < bucket->dst_addr)
addr_max = bucket->dst_addr;
if (cnt_max < bucket->count)
cnt_max = bucket->count;
}
}
addr_len = num_digits (addr_max, 16);
cnt_len = num_digits (cnt_max, 10);
for ( i = 0; i < BB_BUCKETS; i++)
{
struct bb_edge *bucket = bb_hashbuckets[i];
for ( ; bucket; bucket = bucket->next )
{
fprintf (file, "Jump from block 0x%.*lx to "
"block 0x%.*lx executed %*lu time(s)\n",
addr_len, bucket->src_addr,
addr_len, bucket->dst_addr,
cnt_len, bucket->count);
}
}
fprintf (file, "\n");
}
}
if (file)
fclose (file);
f = bb_func_head;
while (f)
{
struct bb_func *old = f;
f = f->next;
if (old->funcname) free (old->funcname);
if (old->filename) free (old->filename);
free (old);
}
if (bb_stack)
free (bb_stack);
if (bb_hashbuckets)
{
int i;
for (i = 0; i < BB_BUCKETS; i++)
{
struct bb_edge *old, *bucket = bb_hashbuckets[i];
while (bucket)
{
old = bucket;
bucket = bucket->next;
free (old);
}
}
free (bb_hashbuckets);
}
for (b = bb_head; b; b = b->next)
if (b->flags) free (b->flags);
}
static void
__bb_init_prg ()
{
FILE *file;
char buf[BBINBUFSIZE];
const char *p;
const char *pos;
enum bb_func_mode m;
#ifdef ON_EXIT
ON_EXIT (__bb_exit_func, 0);
#endif
if (!(file = fopen ("bb.in", "r")))
return;
while(fscanf (file, " %" BBINBUFSIZESTR "s ", buf) != EOF)
{
p = buf;
if (*p == '-')
{
m = TRACE_OFF;
p++;
}
else
{
m = TRACE_ON;
}
if (!strcmp (p, "__bb_trace__"))
bb_mode |= 1;
else if (!strcmp (p, "__bb_jumps__"))
bb_mode |= 2;
else if (!strcmp (p, "__bb_hidecall__"))
bb_mode |= 4;
else if (!strcmp (p, "__bb_showret__"))
bb_mode |= 8;
else
{
struct bb_func *f = (struct bb_func *) malloc (sizeof (struct bb_func));
if (f)
{
unsigned long l;
f->next = bb_func_head;
if ((pos = strchr (p, ':')))
{
if (!(f->funcname = (char *) malloc (strlen (pos+1)+1)))
continue;
strcpy (f->funcname, pos+1);
l = pos-p;
if ((f->filename = (char *) malloc (l+1)))
{
strncpy (f->filename, p, l);
f->filename[l] = '\0';
}
else
f->filename = (char *) 0;
}
else
{
if (!(f->funcname = (char *) malloc (strlen (p)+1)))
continue;
strcpy (f->funcname, p);
f->filename = (char *) 0;
}
f->mode = m;
bb_func_head = f;
}
}
}
fclose (file);
#ifdef HAVE_POPEN
if (bb_mode & 1)
bb_tracefile = gopen ("bbtrace.gz", "w");
#else
if (bb_mode & 1)
bb_tracefile = fopen ("bbtrace", "w");
#endif
if (bb_mode & 2)
{
bb_hashbuckets = (struct bb_edge **)
malloc (BB_BUCKETS * sizeof (struct bb_edge *));
if (bb_hashbuckets)
memset (bb_hashbuckets, 0, BB_BUCKETS * sizeof (struct bb_edge *));
}
if (bb_mode & 12)
{
bb_stacksize = 10;
bb_stack = (unsigned long *) malloc (bb_stacksize * sizeof (*bb_stack));
}
#ifdef ON_EXIT
ON_EXIT (__bb_exit_trace_func, 0);
#endif
}
void
__bb_trace_func ()
{
struct bb_edge *bucket;
MACHINE_STATE_SAVE("1")
if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
goto skip;
bb_dst = __bb.blocks->addresses[__bb.blockno];
__bb.blocks->counts[__bb.blockno]++;
if (bb_tracefile)
{
fwrite (&bb_dst, sizeof (unsigned long), 1, bb_tracefile);
}
if (bb_hashbuckets)
{
struct bb_edge **startbucket, **oldnext;
oldnext = startbucket
= & bb_hashbuckets[ (((int) bb_src*8) ^ (int) bb_dst) % BB_BUCKETS ];
bucket = *startbucket;
for (bucket = *startbucket; bucket;
oldnext = &(bucket->next), bucket = *oldnext)
{
if (bucket->src_addr == bb_src
&& bucket->dst_addr == bb_dst)
{
bucket->count++;
*oldnext = bucket->next;
bucket->next = *startbucket;
*startbucket = bucket;
goto ret;
}
}
bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
if (!bucket)
{
if (!reported)
{
fprintf (stderr, "Profiler: out of memory\n");
reported = 1;
}
}
else
{
bucket->src_addr = bb_src;
bucket->dst_addr = bb_dst;
bucket->next = *startbucket;
*startbucket = bucket;
bucket->count = 1;
}
}
ret:
bb_src = bb_dst;
skip:
;
MACHINE_STATE_RESTORE("1")
}
static void
__bb_trace_func_ret ()
{
struct bb_edge *bucket;
if (!bb_callcount || (__bb.blocks->flags && (__bb.blocks->flags[__bb.blockno] & TRACE_OFF)))
goto skip;
if (bb_hashbuckets)
{
struct bb_edge **startbucket, **oldnext;
oldnext = startbucket
= & bb_hashbuckets[ (((int) bb_dst * 8) ^ (int) bb_src) % BB_BUCKETS ];
bucket = *startbucket;
for (bucket = *startbucket; bucket;
oldnext = &(bucket->next), bucket = *oldnext)
{
if (bucket->src_addr == bb_dst
&& bucket->dst_addr == bb_src)
{
bucket->count++;
*oldnext = bucket->next;
bucket->next = *startbucket;
*startbucket = bucket;
goto ret;
}
}
bucket = (struct bb_edge *) malloc (sizeof (struct bb_edge));
if (!bucket)
{
if (!reported)
{
fprintf (stderr, "Profiler: out of memory\n");
reported = 1;
}
}
else
{
bucket->src_addr = bb_dst;
bucket->dst_addr = bb_src;
bucket->next = *startbucket;
*startbucket = bucket;
bucket->count = 1;
}
}
ret:
bb_dst = bb_src;
skip:
;
}
static void
__bb_init_file (struct bb *blocks)
{
const struct bb_func *p;
long blk, ncounts = blocks->ncounts;
const char **functions = blocks->functions;
blocks->zero_word = 1;
blocks->next = bb_head;
bb_head = blocks;
blocks->flags = 0;
if (!bb_func_head
|| !(blocks->flags = (char *) malloc (sizeof (char) * blocks->ncounts)))
return;
for (blk = 0; blk < ncounts; blk++)
blocks->flags[blk] = 0;
for (blk = 0; blk < ncounts; blk++)
{
for (p = bb_func_head; p; p = p->next)
{
if (!strcmp (p->funcname, functions[blk])
&& (!p->filename || !strcmp (p->filename, blocks->filename)))
{
blocks->flags[blk] |= p->mode;
}
}
}
}
void
__bb_trace_ret ()
{
MACHINE_STATE_SAVE("2")
if (bb_callcount)
{
if ((bb_mode & 12) && bb_stacksize > bb_callcount)
{
bb_src = bb_stack[bb_callcount];
if (bb_mode & 8)
__bb_trace_func_ret ();
}
bb_callcount -= 1;
}
MACHINE_STATE_RESTORE("2")
}
void
__bb_init_trace_func (struct bb *blocks, unsigned long blockno)
{
static int trace_init = 0;
MACHINE_STATE_SAVE("3")
if (!blocks->zero_word)
{
if (!trace_init)
{
trace_init = 1;
__bb_init_prg ();
}
__bb_init_file (blocks);
}
if (bb_callcount)
{
bb_callcount += 1;
if (bb_mode & 12)
{
if (bb_callcount >= bb_stacksize)
{
size_t newsize = bb_callcount + 100;
bb_stack = (unsigned long *) realloc (bb_stack, newsize);
if (! bb_stack)
{
if (!reported)
{
fprintf (stderr, "Profiler: out of memory\n");
reported = 1;
}
bb_stacksize = 0;
goto stack_overflow;
}
bb_stacksize = newsize;
}
bb_stack[bb_callcount] = bb_src;
if (bb_mode & 4)
bb_src = 0;
}
stack_overflow:;
}
else if (blocks->flags && (blocks->flags[blockno] & TRACE_ON))
{
bb_callcount = 1;
bb_src = 0;
if (bb_stack)
bb_stack[bb_callcount] = bb_src;
}
MACHINE_STATE_RESTORE("3")
}
#endif
#endif
#endif
#ifdef L_shtab
unsigned int __shtab[] = {
0x00000001, 0x00000002, 0x00000004, 0x00000008,
0x00000010, 0x00000020, 0x00000040, 0x00000080,
0x00000100, 0x00000200, 0x00000400, 0x00000800,
0x00001000, 0x00002000, 0x00004000, 0x00008000,
0x00010000, 0x00020000, 0x00040000, 0x00080000,
0x00100000, 0x00200000, 0x00400000, 0x00800000,
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000
};
#endif
#ifdef L_clear_cache
#define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
void
__clear_cache (char *beg, char *end)
{
#ifdef CLEAR_INSN_CACHE
CLEAR_INSN_CACHE (beg, end);
#else
#ifdef INSN_CACHE_SIZE
static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
static int initialized;
int offset;
void *start_addr
void *end_addr;
typedef (*function_ptr) ();
#if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
if (! initialized)
{
int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
& -INSN_CACHE_LINE_WIDTH);
int end_ptr = ptr + INSN_CACHE_SIZE;
while (ptr < end_ptr)
{
*(INSTRUCTION_TYPE *)ptr
= JUMP_AHEAD_INSTRUCTION + INSN_CACHE_LINE_WIDTH;
ptr += INSN_CACHE_LINE_WIDTH;
}
*(INSTRUCTION_TYPE *) (ptr - INSN_CACHE_LINE_WIDTH) = RETURN_INSTRUCTION;
initialized = 1;
}
(((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
& -INSN_CACHE_LINE_WIDTH))
());
#else
if (! initialized)
{
int ptr = (((int) array + INSN_CACHE_LINE_WIDTH - 1)
& -INSN_CACHE_LINE_WIDTH);
while (ptr < (int) array + sizeof array)
{
*(INSTRUCTION_TYPE *)ptr = RETURN_INSTRUCTION;
ptr += INSN_CACHE_LINE_WIDTH;
}
initialized = 1;
}
offset = ((int) beg & -INSN_CACHE_LINE_WIDTH) & (INSN_CACHE_PLANE_SIZE - 1);
start_addr = (((int) (array + INSN_CACHE_PLANE_SIZE - 1)
& -INSN_CACHE_PLANE_SIZE)
+ offset);
#if 0
if (end < beg + INSN_CACHE_PLANE_SIZE)
#endif
offset = (((int) (end + INSN_CACHE_LINE_WIDTH - 1)
& -INSN_CACHE_LINE_WIDTH)
& (INSN_CACHE_PLANE_SIZE - 1));
#if INSN_CACHE_DEPTH > 1
end_addr = (start_addr & -INSN_CACHE_PLANE_SIZE) + offset;
if (end_addr <= start_addr)
end_addr += INSN_CACHE_PLANE_SIZE;
for (plane = 0; plane < INSN_CACHE_DEPTH; plane++)
{
int addr = start_addr + plane * INSN_CACHE_PLANE_SIZE;
int stop = end_addr + plane * INSN_CACHE_PLANE_SIZE;
while (addr != stop)
{
((function_ptr) addr) ();
addr += INSN_CACHE_LINE_WIDTH;
}
}
#else
do
{
((function_ptr) start_addr) ();
start_addr += INSN_CACHE_LINE_WIDTH;
}
while ((start_addr % INSN_CACHE_SIZE) != offset);
#endif
#endif
#endif
#endif
}
#endif
#ifdef L_trampoline
#if defined(WINNT) && ! defined(__CYGWIN__) && ! defined (_UWIN)
#include <windows.h>
long getpagesize()
{
#ifdef _ALPHA_
return 8192;
#else
return 4096;
#endif
}
#ifdef i386
extern int VirtualProtect (char *, int, int, int *) __attribute__((stdcall));
#endif
int
mprotect (char *addr, int len, int prot)
{
int np, op;
if (prot == 7)
np = 0x40;
else if (prot == 5)
np = 0x20;
else if (prot == 4)
np = 0x10;
else if (prot == 3)
np = 0x04;
else if (prot == 1)
np = 0x02;
else if (prot == 0)
np = 0x01;
if (VirtualProtect (addr, len, np, &op))
return 0;
else
return -1;
}
#endif
#ifdef TRANSFER_FROM_TRAMPOLINE
TRANSFER_FROM_TRAMPOLINE
#endif
#if defined (NEXT_SEMANTICS) && defined (__MACH__)
#if !defined (__APPLE__) && (!defined (NS_TARGET_MAJOR) || NS_TARGET_MAJOR < 4)
#ifdef NeXTStep21
#include <mach.h>
#else
#include <mach/mach.h>
#endif
#endif
void
__enable_execute_stack (char *addr)
{
#if defined (NEXT_SEMANTICS) && defined (TARGET_V9)
#define TARGET_V9_SAVE TARGET_V9
#undef TARGET_V9
#define TARGET_V9 0
#endif
char *eaddr = addr + TRAMPOLINE_SIZE;
#if defined (NEXT_SEMANTICS) && defined (TARGET_V9)
#undef TARGET_V9
#define TARGET_V9 TARGET_V9_SAVE
#endif
#if !defined (__APPLE__) && (!defined (NS_TARGET_MAJOR) || NS_TARGET_MAJOR < 4)
kern_return_t r;
vm_address_t a = (vm_address_t) addr;
r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
if (r != KERN_SUCCESS)
{
mach_error("vm_protect VM_PROT_ALL", r);
exit(1);
}
#endif
#ifdef CLEAR_INSN_CACHE
CLEAR_INSN_CACHE (addr, eaddr);
#else
__clear_cache ((int) addr, (int) eaddr);
#endif
}
#endif
#ifdef __convex__
#include <sys/mman.h>
#include <sys/vmparam.h>
#include <machine/machparam.h>
void
__enable_execute_stack ()
{
int fp;
static unsigned lowest = USRSTACK;
unsigned current = (unsigned) &fp & -NBPG;
if (lowest > current)
{
unsigned len = lowest - current;
mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
lowest = current;
}
asm ("pich");
}
#endif
#ifdef __sysV88__
#include <sys/param.h>
#include <errno.h>
#include <sys/m88kbcs.h>
void
__enable_execute_stack ()
{
int save_errno;
static unsigned long lowest = USRSTACK;
unsigned long current = (unsigned long) &save_errno & -NBPC;
save_errno=errno;
if (lowest > current)
{
unsigned len=lowest-current;
memctl(current,len,MCT_TEXT);
lowest = current;
}
else
memctl(current,NBPC,MCT_TEXT);
errno=save_errno;
}
#endif
#ifdef __sysV68__
#include <sys/signal.h>
#include <errno.h>
#ifdef MCT_TEXT
asm("\n\
global memctl\n\
memctl:\n\
movq &75,%d0\n\
trap &0\n\
bcc.b noerror\n\
jmp cerror%\n\
noerror:\n\
movq &0,%d0\n\
rts");
#endif
void
__clear_insn_cache ()
{
#ifdef MCT_TEXT
int save_errno;
save_errno = errno;
memctl(0, 4096, MCT_TEXT);
errno = save_errno;
#endif
}
#endif
#ifdef __pyr__
#undef NULL
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/vmmac.h>
void
__enable_execute_stack ()
{
int fp;
if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
PROT_READ|PROT_WRITE|PROT_EXEC))
{
perror ("mprotect in __enable_execute_stack");
fflush (stderr);
abort ();
}
}
#endif
#if defined (sony_news) && defined (SYSTYPE_BSD)
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <syscall.h>
#include <machine/sysnews.h>
void
cacheflush (char *beg, int size, int flag)
{
if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
{
perror ("cache_flush");
fflush (stderr);
abort ();
}
}
#endif
#endif
#ifndef __CYGWIN__
#ifdef L__main
#include "gbl-ctors.h"
#ifndef NAME__MAIN
#define NAME__MAIN "__main"
#define SYMBOL__MAIN __main
#endif
#ifdef INIT_SECTION_ASM_OP
#undef HAS_INIT_SECTION
#define HAS_INIT_SECTION
#endif
#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF)
void
__do_global_dtors ()
{
#ifdef DO_GLOBAL_DTORS_BODY
DO_GLOBAL_DTORS_BODY;
#else
static func_ptr *p = __DTOR_LIST__ + 1;
while (*p)
{
p++;
(*(p-1)) ();
}
#endif
}
#endif
#ifndef HAS_INIT_SECTION
#ifndef ON_EXIT
#define ON_EXIT(a, b)
#elif !defined (NEXT_SEMANTICS)
extern int _exit_dummy_decl;
int *_exit_dummy_ref = &_exit_dummy_decl;
#endif
void
__do_global_ctors ()
{
DO_GLOBAL_CTORS_BODY;
ON_EXIT (__do_global_dtors, 0);
}
#endif
#ifdef NEXT_PDO
#ifdef __osf__
long int _objcInit_addr;
#else
int _objcInit_addr;
#endif
int __NXArgc;
char **__NXArgv;
#endif
#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main)
#if defined (_WIN32) && defined (NEXT_PDO)
#include <windows.h>
__declspec (dllimport) void _fpreset ();
#endif
#ifdef NEXT_EXTENSION
int __gnuc_argc;
const char **__gnuc_argv;
#endif
void
#if defined (NEXT_EXTENSION) || defined (NEXT_PDO)
SYMBOL__MAIN (int argc, const char **argv)
#else
SYMBOL__MAIN ()
#endif
{
static int initialized = 0;
#ifdef NEXT_PDO
#ifdef sparc
#define PRECIOUS_REGS "i0", "i1", "i2", "i3", "i4", "i5", \
"l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",\
"o0", "o1", "o2", "o3", "o4", "o5", "o7"
asm volatile("mov %%sp,%%g1": :);
asm volatile("restore": :);
asm volatile("st %%i0,%0": "=m" (__NXArgc): : PRECIOUS_REGS);
asm volatile("st %%i1,%0": "=m" (__NXArgv): : PRECIOUS_REGS);
asm volatile("save %%g0,0,%%g0": :);
asm volatile("mov %%g1,%%sp": :);
#endif/* def sparc */
#ifdef hpux
extern int __argc_value;
extern char **__argv_value;
__NXArgc = __argc_value;
__NXArgv = __argv_value;
#endif/* def hpux */
#if __alpha__ || __alpha
asm volatile("stq $16,%0": "=m" (__NXArgc));
asm volatile("stq $17,%0": "=m" (__NXArgv));
#endif
#ifdef _WIN32
extern int __argc;
extern char** __argv;
__NXArgc = __argc;
__NXArgv = __argv;
#endif _WIN32
#endif/* def NEXT_PDO */
#ifdef NEXT_EXTENSION
__gnuc_argc = argc;
__gnuc_argv = argv;
#endif
if (! initialized)
{
initialized = 1;
#if defined (NEXT_PDO) && defined (_WIN32)
_fpreset ();
_objcInit_addr = GetProcAddress (GetModuleHandle ("NEXTPDO.DLL"),
"_objcInit");
#endif
__do_global_ctors ();
#ifdef NEXT_PDO
if (_objcInit_addr)
((void (*)())_objcInit_addr)();
#endif
}
}
#endif
#endif
#endif
#ifdef L_ctors
#include "gbl-ctors.h"
#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY)
#if defined (ASM_OUTPUT_CONSTRUCTOR) || defined (USE_COLLECT2)
func_ptr __CTOR_LIST__[2] = {0, 0};
func_ptr __DTOR_LIST__[2] = {0, 0};
#else
func_ptr __CTOR_LIST__[2];
#if defined (_WIN32) && defined (NEXT_PDO)
int _ctor_dummy_decl = 0;
asm (".section\t.dtor$A");
func_ptr __DTOR_LIST__[1] = {0};
asm (".section\t.dtor$Z");
func_ptr __DTOR_END_OF_LIST__ = 0;
#else
func_ptr __DTOR_LIST__[2];
#endif
#endif
#endif
#endif
#ifdef L_exit
#include "gbl-ctors.h"
#ifdef NEED_ATEXIT
# ifdef ON_EXIT
# undef ON_EXIT
# endif
int _exit_dummy_decl = 0;
#endif
#ifndef ON_EXIT
#ifdef NEED_ATEXIT
# include <errno.h>
static func_ptr *atexit_chain = 0;
static long atexit_chain_length = 0;
static volatile long last_atexit_chain_slot = -1;
int atexit (func_ptr func)
{
if (++last_atexit_chain_slot == atexit_chain_length)
{
atexit_chain_length += 32;
if (atexit_chain)
atexit_chain = (func_ptr *) realloc (atexit_chain, atexit_chain_length
* sizeof (func_ptr));
else
atexit_chain = (func_ptr *) malloc (atexit_chain_length
* sizeof (func_ptr));
if (! atexit_chain)
{
atexit_chain_length = 0;
last_atexit_chain_slot = -1;
errno = ENOMEM;
return (-1);
}
}
atexit_chain[last_atexit_chain_slot] = func;
return (0);
}
#endif
extern void __do_global_dtors ();
extern void __bb_exit_func ();
extern void _cleanup ();
extern void _exit () __attribute__ ((noreturn));
void
exit (int status)
{
#if !defined (INIT_SECTION_ASM_OP) || !defined (OBJECT_FORMAT_ELF)
#ifdef NEED_ATEXIT
if (atexit_chain)
{
for ( ; last_atexit_chain_slot-- >= 0; )
{
(*atexit_chain[last_atexit_chain_slot + 1]) ();
atexit_chain[last_atexit_chain_slot + 1] = 0;
}
free (atexit_chain);
atexit_chain = 0;
}
#else
__do_global_dtors ();
#endif
#endif
#ifndef HAVE_ATEXIT
#ifndef inhibit_libc
__bb_exit_func ();
#endif
#endif
#ifdef EXIT_BODY
EXIT_BODY;
#else
_cleanup ();
#endif
_exit (status);
}
#else
int _exit_dummy_decl = 0;
# ifndef HAVE_ATEXIT
int atexit (func_ptr func)
{
return ON_EXIT (func, NULL);
}
# endif
#endif
#endif
#ifdef L_eh
#include "gthr.h"
#ifdef MACOSX
#include "apple/keymgr.h"
#else
extern void __default_terminate (void) __attribute__ ((__noreturn__));
void
__default_terminate ()
{
abort ();
}
void (*__terminate_func)() = __default_terminate;
#endif
void
__terminate ()
{
#ifdef MACOSX
void (*__terminate_func)() =
_keymgr_get_per_thread_data (KEYMGR_TERMINATE_HANDLER_KEY);
if (__terminate_func == NULL)
abort ();
else
#endif
(*__terminate_func)();
}
void *
__throw_type_match (void *catch_type, void *throw_type, void *obj)
{
#if 0
printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
catch_type, throw_type);
#endif
if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
return obj;
return 0;
}
void
__empty ()
{
}
#include "eh-common.h"
#ifndef inhibit_libc
#include <stdio.h>
#endif
extern void __throw ();
static void *
new_eh_context ()
{
struct eh_full_context {
struct eh_context c;
void *top_elt[2];
} *ehfc = (struct eh_full_context *) malloc (sizeof *ehfc);
if (! ehfc)
__terminate ();
memset (ehfc, 0, sizeof *ehfc);
ehfc->c.dynamic_handler_chain = (void **) ehfc->top_elt;
if ((void*)(&ehfc->c) != (void*)ehfc)
__terminate ();
return &ehfc->c;
}
#if __GTHREADS && !defined (MACOSX)
static __gthread_key_t eh_context_key;
static void
eh_context_free (void *ptr)
{
__gthread_key_dtor (eh_context_key, ptr);
if (ptr)
free (ptr);
}
#endif
static struct eh_context *eh_context_initialize ();
static struct eh_context *eh_context_static ();
#ifndef MACOSX
#if __GTHREADS
static struct eh_context *eh_context_specific ();
#endif
static struct eh_context *(*get_eh_context) () = &eh_context_initialize;
#else
static struct eh_context *eh_context_via_pthreads() ;
static struct eh_context *(*get_eh_context) () = &eh_context_via_pthreads ;
static struct eh_context *eh_context_via_pthreads() {
struct eh_context *eh ;
if ((eh =_keymgr_get_per_thread_data(KEYMGR_EH_CONTEXT_KEY)) == NULL) {
eh = new_eh_context() ;
_keymgr_set_per_thread_data(KEYMGR_EH_CONTEXT_KEY,eh) ;
}
return(eh) ;
}
#endif
void *
__get_eh_context ()
{
return (void *) (*get_eh_context) ();
}
void **
__get_eh_info ()
{
struct eh_context *eh = (*get_eh_context) ();
return &eh->info;
}
#ifndef MACOSX
#if __GTHREADS
static void
eh_threads_initialize ()
{
if (__gthread_key_create (&eh_context_key, &eh_context_free) == 0)
get_eh_context = &eh_context_specific;
else
get_eh_context = &eh_context_static;
}
#endif
static struct eh_context *
eh_context_initialize ()
{
#if __GTHREADS
static __gthread_once_t once = __GTHREAD_ONCE_INIT;
if (__gthread_once (&once, eh_threads_initialize) != 0
|| get_eh_context == &eh_context_initialize)
{
get_eh_context = &eh_context_static;
}
#else
get_eh_context = &eh_context_static;
#endif
return (*get_eh_context) ();
}
static struct eh_context *
eh_context_static ()
{
static struct eh_context eh;
static int initialized;
static void *top_elt[2];
if (! initialized)
{
initialized = 1;
memset (&eh, 0, sizeof eh);
eh.dynamic_handler_chain = top_elt;
}
return &eh;
}
#if __GTHREADS
static struct eh_context *
eh_context_specific ()
{
struct eh_context *eh;
eh = (struct eh_context *) __gthread_getspecific (eh_context_key);
if (! eh)
{
eh = new_eh_context ();
if (__gthread_setspecific (eh_context_key, (void *) eh) != 0)
__terminate ();
}
return eh;
}
#endif __GTHREADS
#endif
#ifdef DONT_USE_BUILTIN_SETJMP
#ifdef NEXT_SEMANTICS
#define setjmp _setjmp
#define longjmp _longjmp
#endif
extern void longjmp (void *, int);
#endif
void ***
__get_dynamic_handler_chain ()
{
struct eh_context *eh = (*get_eh_context) ();
return &eh->dynamic_handler_chain;
}
extern void __sjthrow (void) __attribute__ ((__noreturn__));
void
__sjthrow ()
{
struct eh_context *eh = (*get_eh_context) ();
void ***dhc = &eh->dynamic_handler_chain;
void *jmpbuf;
void (*func)(void *, int);
void *arg;
void ***cleanup;
cleanup = (void***)&(*dhc)[1];
if (cleanup[0])
{
double store[200];
void **buf = (void**)store;
buf[1] = 0;
buf[0] = (*dhc);
#ifdef DONT_USE_BUILTIN_SETJMP
if (! setjmp (&buf[2]))
#else
if (! __builtin_setjmp (&buf[2]))
#endif
{
*dhc = buf;
while (cleanup[0])
{
func = (void(*)(void*, int))cleanup[0][1];
arg = (void*)cleanup[0][2];
cleanup[0] = (void **)cleanup[0][0];
(*func)(arg, 2);
}
*dhc = buf[0];
}
else
{
__terminate ();
}
}
if (! eh->info || (*dhc)[0] == 0)
__terminate ();
jmpbuf = &(*dhc)[2];
*dhc = (void**)(*dhc)[0];
#ifdef DONT_USE_BUILTIN_SETJMP
longjmp (jmpbuf, 1);
#else
__builtin_longjmp (jmpbuf, 1);
#endif
}
extern void __sjpopnthrow (void) __attribute__ ((__noreturn__));
void
__sjpopnthrow ()
{
struct eh_context *eh = (*get_eh_context) ();
void ***dhc = &eh->dynamic_handler_chain;
void (*func)(void *, int);
void *arg;
void ***cleanup;
cleanup = (void***)&(*dhc)[1];
if (cleanup[0])
{
double store[200];
void **buf = (void**)store;
buf[1] = 0;
buf[0] = (*dhc);
#ifdef DONT_USE_BUILTIN_SETJMP
if (! setjmp (&buf[2]))
#else
if (! __builtin_setjmp (&buf[2]))
#endif
{
*dhc = buf;
while (cleanup[0])
{
func = (void(*)(void*, int))cleanup[0][1];
arg = (void*)cleanup[0][2];
cleanup[0] = (void **)cleanup[0][0];
(*func)(arg, 2);
}
*dhc = buf[0];
}
else
{
__terminate ();
}
}
*dhc = (void**)(*dhc)[0];
__sjthrow ();
}
int
__eh_rtime_match (void *rtime)
{
void *info;
__eh_matcher matcher;
void *ret;
info = *(__get_eh_info ());
matcher = ((__eh_info *)info)->match_function;
if (! matcher)
{
#ifndef inhibit_libc
fprintf (stderr, "Internal Compiler Bug: No runtime type matcher.");
#endif
return 0;
}
ret = (*matcher) (info, rtime, (void *)0);
return (ret != NULL);
}
#ifdef EH_TABLE_LOOKUP
EH_TABLE_LOOKUP
#else
#ifdef DWARF2_UNWIND_INFO
#ifndef GET_EXCEPTION_TABLE_ADDR_ENTRY
#define GET_EXCEPTION_TABLE_ADDR_ENTRY(ELEM) ELEM
#endif
#ifndef GET_EXCEPTION_TABLE_TYPE_ENTRY
#define GET_EXCEPTION_TABLE_TYPE_ENTRY(ELEM) ELEM
#endif
short
__get_eh_table_version (exception_descriptor *table)
{
return table->lang.version;
}
short
__get_eh_table_language (exception_descriptor *table)
{
return table->lang.language;
}
static void *
old_find_exception_handler (void *pc, old_exception_table *table)
{
if (table)
{
int pos;
int best = -1;
for (pos = 0; GET_EXCEPTION_TABLE_ADDR_ENTRY (table[pos].start_region) !=
(void *) -1; ++pos)
{
if (GET_EXCEPTION_TABLE_ADDR_ENTRY (table[pos].start_region) <= pc &&
GET_EXCEPTION_TABLE_ADDR_ENTRY (table[pos].end_region) > pc)
{
if (best == -1 || (GET_EXCEPTION_TABLE_ADDR_ENTRY (table[pos].end_region) <=
GET_EXCEPTION_TABLE_ADDR_ENTRY (table[best].end_region)
&& GET_EXCEPTION_TABLE_ADDR_ENTRY (table[pos].start_region) >=
GET_EXCEPTION_TABLE_ADDR_ENTRY (table[best].start_region)))
best = pos;
}
else if (best >= 0 &&
GET_EXCEPTION_TABLE_ADDR_ENTRY (table[pos].start_region) > pc)
break;
}
if (best != -1)
return GET_EXCEPTION_TABLE_ADDR_ENTRY (table[best].exception_handler);
}
return (void *) 0;
}
static void *
find_exception_handler (void *pc, exception_descriptor *table,
__eh_info *eh_info, int rethrow, int *cleanup)
{
void *retval = NULL;
*cleanup = 1;
if (table)
{
int pos = 0;
exception_table *tab = &(table->table[0]);
if (rethrow)
{
pos = ((exception_table *) pc) - tab;
pc = GET_EXCEPTION_TABLE_ADDR_ENTRY (((exception_table *) pc)->end_region) - 1;
if (GET_EXCEPTION_TABLE_ADDR_ENTRY (tab[pos].start_region) != (void *) -1)
pos++;
}
else
pc--;
for ( ; GET_EXCEPTION_TABLE_ADDR_ENTRY (tab[pos].start_region) != (void *) -1; pos++)
{
if (GET_EXCEPTION_TABLE_ADDR_ENTRY (tab[pos].start_region) <= pc
&& GET_EXCEPTION_TABLE_ADDR_ENTRY (tab[pos].end_region) > pc)
{
if (GET_EXCEPTION_TABLE_TYPE_ENTRY (tab[pos].match_info))
{
__eh_matcher matcher = eh_info->match_function;
if (matcher)
{
void *ret = (*matcher)((void *) eh_info,
GET_EXCEPTION_TABLE_TYPE_ENTRY (tab[pos].match_info), table);
if (ret)
{
if (retval == NULL)
retval = GET_EXCEPTION_TABLE_ADDR_ENTRY (tab[pos].exception_handler);
*cleanup = 0;
break;
}
}
}
else
{
if (retval == NULL)
retval = GET_EXCEPTION_TABLE_ADDR_ENTRY (tab[pos].exception_handler);
}
}
}
}
return retval;
}
#endif
#endif
#ifdef DWARF2_UNWIND_INFO
#include "frame.h"
typedef int ptr_type __attribute__ ((mode (pointer)));
#ifdef INCOMING_REGNO
#define target_flags 0
static int
in_reg_window (int reg, frame_state *udata)
{
if (udata->saved[reg] == REG_SAVED_REG)
return INCOMING_REGNO (reg) == reg;
if (udata->saved[reg] != REG_SAVED_OFFSET)
return 0;
#ifdef STACK_GROWS_DOWNWARD
return udata->reg_or_offset[reg] > 0;
#else
return udata->reg_or_offset[reg] < 0;
#endif
}
#else
static inline int in_reg_window (int reg, frame_state *udata) { return 0; }
#endif
static word_type *
get_reg_addr (unsigned reg, frame_state *udata, frame_state *sub_udata)
{
while (udata->saved[reg] == REG_SAVED_REG)
{
reg = udata->reg_or_offset[reg];
if (in_reg_window (reg, udata))
{
udata = sub_udata;
sub_udata = NULL;
}
}
if (udata->saved[reg] == REG_SAVED_OFFSET)
return (word_type *)(udata->cfa + udata->reg_or_offset[reg]);
else
abort ();
}
static inline void *
get_reg (unsigned reg, frame_state *udata, frame_state *sub_udata)
{
return (void *)(ptr_type) *get_reg_addr (reg, udata, sub_udata);
}
static inline void
put_reg (unsigned reg, void *val, frame_state *udata)
{
*get_reg_addr (reg, udata, NULL) = (word_type)(ptr_type) val;
}
static void
copy_reg (unsigned reg, frame_state *udata, frame_state *target_udata)
{
word_type *preg = get_reg_addr (reg, udata, NULL);
word_type *ptreg = get_reg_addr (reg, target_udata, NULL);
memcpy (ptreg, preg, __builtin_dwarf_reg_size (reg));
}
static inline void *
get_return_addr (frame_state *udata, frame_state *sub_udata)
{
return __builtin_extract_return_addr
(get_reg (udata->retaddr_column, udata, sub_udata));
}
static inline void
put_return_addr (void *val, frame_state *udata)
{
val = __builtin_frob_return_addr (val);
put_reg (udata->retaddr_column, val, udata);
}
static void *
next_stack_level (void *pc, frame_state *udata, frame_state *caller_udata)
{
caller_udata = __frame_state_for (pc, caller_udata);
if (! caller_udata)
return 0;
if (udata->saved[caller_udata->cfa_reg])
caller_udata->cfa = get_reg (caller_udata->cfa_reg, udata, 0);
else
caller_udata->cfa = udata->cfa;
caller_udata->cfa += caller_udata->cfa_offset;
return caller_udata;
}
void
__unwinding_cleanup ()
{
}
static void *
throw_helper (eh, pc, my_udata, offset_p)
struct eh_context *eh;
void *pc;
frame_state *my_udata;
long *offset_p;
{
frame_state ustruct2, *udata = &ustruct2;
frame_state ustruct;
frame_state *sub_udata = &ustruct;
void *saved_pc = pc;
void *handler;
void *handler_p;
void *pc_p;
frame_state saved_ustruct;
int new_eh_model;
int cleanup = 0;
int only_cleanup = 0;
int rethrow = 0;
int saved_state = 0;
long args_size;
__eh_info *eh_info = (__eh_info *)eh->info;
if (eh->table_index != (void *) 0)
rethrow = 1;
memcpy (udata, my_udata, sizeof (*udata));
handler = (void *) 0;
for (;;)
{
frame_state *p = udata;
udata = next_stack_level (pc, udata, sub_udata);
sub_udata = p;
if (! udata)
break;
if (udata->eh_ptr == NULL)
new_eh_model = 0;
else
new_eh_model = (((exception_descriptor *)(udata->eh_ptr))->
runtime_id_field == NEW_EH_RUNTIME);
if (rethrow)
{
rethrow = 0;
handler = find_exception_handler (eh->table_index, udata->eh_ptr,
eh_info, 1, &cleanup);
eh->table_index = (void *)0;
}
else
if (new_eh_model)
handler = find_exception_handler (pc, udata->eh_ptr, eh_info,
0, &cleanup);
else
handler = old_find_exception_handler (pc, udata->eh_ptr);
if (handler)
{
if (cleanup)
{
if (!saved_state)
{
saved_ustruct = *udata;
handler_p = handler;
pc_p = pc;
saved_state = 1;
only_cleanup = 1;
}
}
else
{
only_cleanup = 0;
break;
}
}
pc = get_return_addr (udata, sub_udata) - 1;
}
if (saved_state)
{
udata = &saved_ustruct;
handler = handler_p;
pc = pc_p;
if (only_cleanup)
__unwinding_cleanup ();
}
if (! handler)
__terminate();
eh->handler_label = handler;
args_size = udata->args_size;
if (pc == saved_pc)
udata = my_udata;
else
{
int i;
void *handler_pc = pc;
pc = saved_pc;
memcpy (udata, my_udata, sizeof (*udata));
while (pc != handler_pc)
{
frame_state *p = udata;
udata = next_stack_level (pc, udata, sub_udata);
sub_udata = p;
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
if (i != udata->retaddr_column && udata->saved[i])
{
#ifdef TARGET_EH_REG_SET_P
if (TARGET_EH_REG_SET_P (i))
{
DO_TARGET_EH_REG_SET (i, get_reg_addr (i, udata, 0));
continue;
}
#endif
if (in_reg_window (i, udata)
&& udata->saved[udata->retaddr_column] == REG_SAVED_REG
&& udata->reg_or_offset[udata->retaddr_column] == i)
continue;
copy_reg (i, udata, my_udata);
}
pc = get_return_addr (udata, sub_udata) - 1;
}
if (udata->saved[udata->retaddr_column] == REG_SAVED_REG)
{
i = udata->reg_or_offset[udata->retaddr_column];
if (in_reg_window (i, udata))
copy_reg (i, udata, my_udata);
}
}
#ifdef STACK_GROWS_DOWNWARD
*offset_p = udata->cfa - my_udata->cfa + args_size;
#else
*offset_p = my_udata->cfa - udata->cfa - args_size;
#endif
return handler;
}
void
__throw ()
{
struct eh_context *eh = (*get_eh_context) ();
void *pc, *handler;
long offset;
frame_state my_ustruct, *my_udata = &my_ustruct;
if (! eh->info)
__terminate ();
label:
my_udata = __frame_state_for (&&label, my_udata);
if (! my_udata)
__terminate ();
my_udata->cfa = __builtin_dwarf_cfa ();
__builtin_unwind_init ();
pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
handler = throw_helper (eh, pc, my_udata, &offset);
#ifdef TRACE_EXCEPTIONS
TRACE_EXCEPTIONS (TR_ALL, "eh_return: offset %d", offset);
TRACE_EXCEPTIONS (TR_ALL, " , handler 0x%08x\n", handler);
#endif
__builtin_eh_return ((void *)eh, offset, handler);
}
void
__rethrow (index)
void *index;
{
struct eh_context *eh = (*get_eh_context) ();
void *pc, *handler;
long offset;
frame_state my_ustruct, *my_udata = &my_ustruct;
if (! eh->info)
__terminate ();
eh->table_index = index;
label:
my_udata = __frame_state_for (&&label, my_udata);
if (! my_udata)
__terminate ();
my_udata->cfa = __builtin_dwarf_cfa ();
__builtin_unwind_init ();
pc = __builtin_extract_return_addr (__builtin_return_address (0)) - 1;
handler = throw_helper (eh, pc, my_udata, &offset);
__builtin_eh_return ((void *)eh, offset, handler);
}
#endif
#endif
#ifdef L_pure
#ifndef inhibit_libc
#undef NULL
#include <stdio.h>
#ifdef __GNU_LIBRARY__
#define write(fd, buf, n) __write((fd), (buf), (n))
#endif
#endif
#define MESSAGE "pure virtual method called\n"
#ifndef TERMINATE
#define TERMINATE __terminate ()
#endif
void
__pure_virtual ()
{
#ifndef inhibit_libc
write (2, MESSAGE, sizeof (MESSAGE) - 1);
#endif
TERMINATE;
}
#endif