home *** CD-ROM | disk | FTP | other *** search
- /* More subroutines needed by GCC output code on some machines. */
- /* Compile this one with gcc. */
- /* Copyright (C) 1989, 1990 Free Software Foundation, Inc.
-
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* As a special exception, if you link this library with files
- compiled with GCC to produce an executable, this does not cause
- the resulting executable to be covered by the GNU General Public License.
- This exception does not however invalidate any other reasons why
- the executable file might be covered by the GNU General Public License. */
-
- #include "types.h"
- #include <stddef.h>
-
- /* In case config.h defined it. */
- #undef abort
-
- #ifndef LONG_TYPE_SIZE
- #define LONG_TYPE_SIZE (sizeof (long) * BITS_PER_UNIT)
- #endif
-
- #ifndef SItype
- #define SItype long int
- #endif
-
- /* long long ints are pairs of long ints in the order determined by
- WORDS_BIG_ENDIAN. */
-
- #if WORDS_BIG_ENDIAN
- struct longlong {long high, low;};
- #else
- struct longlong {long low, high;};
- #endif
-
- /* We need this union to unpack/pack longlongs, since we don't have
- any arithmetic yet. Incoming long long parameters are stored
- into the `ll' field, and the unpacked result is read from the struct
- longlong. */
-
- typedef union
- {
- struct longlong s;
- long long ll;
- } long_long;
-
- /* Internally, long long ints are strings of unsigned shorts in the
- order determined by BYTES_BIG_ENDIAN. */
-
- #define B (1 << (LONG_TYPE_SIZE / 2))
- #define lowpart(t) ((unsigned long) (t) % B)
- #define highpart(t) ((unsigned long) (t) / B)
-
-
- /* Define auxilliary functions for multiplication and division.
- 1) __umulsidi3(a,b) multiplies two unsigned long integers A and B,
- and returns a long long product.
- 2) div_qrnnd(q,r,n1,n0,d) divides a long long integer, composed by the
- long integers N1 and N0, by D and places the quotient in Q and the
- remainder in R. If N1 >= D the quotient cannot be represented, and
- the result is undefined.
-
- There's a simple machine instruction for these operations on almost
- all CPUs. Use them! */
-
- #if defined (L_udivdi3) || defined (L_muldi3)
-
- #if defined (__mc68020__)
- #define __umulsidi3(u, v) \
- ({long_long __w; \
- asm ("mulul %3,%1:%0" : "=d" (__w.s.low), "=d" (__w.s.high) \
- : "%0" (u), "dmsK" (v)); \
- __w.ll; \
- })
- #define div_qrnnd(q, r, n1, n0, d) \
- asm ("divul %4,%1:%0" : "=d" (q), "=d" (r) : "0" (n0), "1" (n1), "dmsK" (d))
-
- #elif defined (sparc)
- unsigned long long __umulsidi3 () asm (".umul");
-
- #elif defined (ns32000)
- /* Try:
- #define __umulsidi3(u, v) \
- ({long long __w; \
- asm ("meid %2,%0" : "=g" (__w) : "%0" (u), "g" (v)); __w; \
- })
- */
- #define __umulsidi3(u, v) \
- ({long_long __w; \
- asm ("movd %2,r0; meid %3,r0; movd r0,%0; movd r1,%1" \
- : "=g" (__w.s.low), "=g" (__w.s.high) \
- : "g" (u), "g" (v) \
- : "r0", "r1"); __w.ll; \
- })
- #define div_qrnnd(q, r, n1, n0, d) \
- ({ \
- asm ("movd %1,r0; movd %2,r1; deid %3,r0; movd r1,%0" \
- : "=g" (q) : "g" (n0), "g" (n1), "g" (d) : "r0", "r1"); \
- asm ("movd %1,r0; movd %2,r1; deid %3,r0; movd r0,%0" \
- : "=g" (r) : "g" (n0), "g" (n1), "g" (d) : "r0", "r1"); \
- })
-
- #elif defined (__i386__)
- #define __umulsidi3(u, v) \
- ({long_long __w; \
- asm ("mull %3" : "=a" (__w.s.low), "=d" (__w.s.high) \
- : "%0" (u), "rm" (v)); __w.ll; \
- })
- #define div_qrnnd(quo, rem, n1, n0, den) \
- asm ("divl %4" : "=a" (quo), "=d" (rem) : "0" (n0), "1" (n1), "rm" (den))
-
- #endif
-
- /* If this machine has no inline assembler, use the C function. */
- #if !defined (__umulsidi3)
- static inline unsigned long long
- __umulsidi3 (u, v)
- unsigned long u, v;
- {
- unsigned long x0, x1, x2, x3;
- unsigned long ulow, vlow, uhigh, vhigh;
- long_long w;
-
- ulow = lowpart (u);
- uhigh = highpart (u);
- vlow = lowpart (v);
- vhigh = highpart (v);
-
- x0 = ulow * vlow;
- x1 = ulow * vhigh + highpart (x0);
- x2 = uhigh * vlow;
- x3 = uhigh * vhigh;
-
- x1 += x2;
- if (x1 < x2)
- x3 += B;
-
- w.s.high = x3 + highpart (x1);
- w.s.low = lowpart (x1) * B + lowpart (x0);
-
- return w.ll;
- }
- #endif
-
- #if !defined (div_qrnnd)
-
- /* Defined as a macro because of the two output parameters. */
- #define div_qrnnd(q, r, n1, n0, d) \
- ({ \
- unsigned int __d1, __d0, __q1, __q0; \
- unsigned long __r1, __r0, __m; \
- __d1 = highpart (d); \
- __d0 = lowpart (d); \
- __r1 = (n1) % __d1; \
- __q1 = (n1) / __d1; \
- __m = (unsigned long) __q1 * __d0; \
- __r1 = __r1 * B | highpart (n0); \
- while (__r1 < __m) \
- __q1--, __r1 += (d); \
- __r0 = __r1 % __d1; \
- __q0 = __r1 / __d1; \
- __m = (unsigned long) __q0 * __d0; \
- __r0 = __r0 * B | lowpart (n0); \
- while (__r0 < __m) \
- __q0--, __r0 += (d); \
- (q) = (unsigned long) __q1 * B | __q0; \
- (r) = __r0; \
- })
- #endif
- #endif /* udiv or mul */
-
- #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
- #if defined (L_divdi3) || defined (L_moddi3)
- static inline
- #endif
- long long
- __negdi2 (u)
- long long u;
- {
- long_long w;
- long_long uu;
-
- uu.ll = u;
-
- w.s.low = -uu.s.low;
- w.s.high = w.s.low == 0 ? -uu.s.high : ~uu.s.high;
-
- return w.ll;
- }
- #endif
-
- #ifdef L_anddi3
- long long
- __anddi3 (u, v)
- long long u, v;
- {
- long_long w;
- long_long uu, vv;
-
- uu.ll = u;
- vv.ll = v;
-
- w.s.high = uu.s.high & vv.s.high;
- w.s.low = uu.s.low & vv.s.low;
-
- return w.ll;
- }
- #endif
-
- #ifdef L_iordi3
- long long
- __iordi3 (u, v)
- long long u, v;
- {
- long_long w;
- long_long uu, vv;
-
- uu.ll = u;
- vv.ll = v;
-
- w.s.high = uu.s.high | vv.s.high;
- w.s.low = uu.s.low | vv.s.low;
-
- return w.ll;
- }
- #endif
-
- #ifdef L_xordi3
- long long
- __xordi3 (u, v)
- long long u, v;
- {
- long_long w;
- long_long uu, vv;
-
- uu.ll = u;
- vv.ll = v;
-
- w.s.high = uu.s.high ^ vv.s.high;
- w.s.low = uu.s.low ^ vv.s.low;
-
- return w.ll;
- }
- #endif
-
- #ifdef L_one_cmpldi2
- long long
- __one_cmpldi2 (u)
- long long u;
- {
- long_long w;
- long_long uu;
-
- uu.ll = u;
-
- w.s.high = ~uu.s.high;
- w.s.low = ~uu.s.low;
-
- return w.ll;
- }
- #endif
-
- #ifdef L_lshldi3
- long long
- __lshldi3 (u, b1)
- long long u;
- long long b1;
- {
- long_long w;
- long bm;
- long_long uu;
- int b = b1;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (long) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.low = 0;
- w.s.high = (unsigned long)uu.s.low << -bm;
- }
- else
- {
- unsigned long carries = (unsigned long)uu.s.low >> bm;
- w.s.low = (unsigned long)uu.s.low << b;
- w.s.high = ((unsigned long)uu.s.high << b) | carries;
- }
-
- return w.ll;
- }
- #endif
-
- #ifdef L_lshrdi3
- long long
- __lshrdi3 (u, b1)
- long long u;
- long long b1;
- {
- long_long w;
- long bm;
- long_long uu;
- int b = b1;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (long) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.high = 0;
- w.s.low = (unsigned long)uu.s.high >> -bm;
- }
- else
- {
- unsigned long carries = (unsigned long)uu.s.high << bm;
- w.s.high = (unsigned long)uu.s.high >> b;
- w.s.low = ((unsigned long)uu.s.low >> b) | carries;
- }
-
- return w.ll;
- }
- #endif
-
- #ifdef L_ashldi3
- long long
- __ashldi3 (u, b1)
- long long u;
- long long b1;
- {
- long_long w;
- long bm;
- long_long uu;
- int b = b1;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (long) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.low = 0;
- w.s.high = (unsigned long)uu.s.low << -bm;
- }
- else
- {
- unsigned long carries = (unsigned long)uu.s.low >> bm;
- w.s.low = (unsigned long)uu.s.low << b;
- w.s.high = ((unsigned long)uu.s.high << b) | carries;
- }
-
- return w.ll;
- }
- #endif
-
- #ifdef L_ashrdi3
- long long
- __ashrdi3 (u, b1)
- long long u;
- long long b1;
- {
- long_long w;
- long bm;
- long_long uu;
- int b = b1;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
-
- bm = (sizeof (long) * BITS_PER_UNIT) - b;
- if (bm <= 0)
- {
- w.s.high = uu.s.high >> 31; /* just to make w.s.high 1..1 or 0..0 */
- w.s.low = uu.s.high >> -bm;
- }
- else
- {
- unsigned long carries = (unsigned long)uu.s.high << bm;
- w.s.high = uu.s.high >> b;
- w.s.low = ((unsigned long)uu.s.low >> b) | carries;
- }
-
- return w.ll;
- }
- #endif
-
- #ifdef L_adddi3
- long long
- __adddi3 (u, v)
- long long u, v;
- {
- long_long w;
- long_long uu, vv;
-
- uu.ll = u;
- vv.ll = v;
-
- w.s.low = uu.s.low + vv.s.low;
- w.s.high = uu.s.high + vv.s.high + ((unsigned long) w.s.low < uu.s.low);
-
- return w.ll;
- }
- #endif
-
- #ifdef L_subdi3
- long long
- __subdi3 (u, v)
- long long u, v;
- {
- long_long w;
- long_long uu, vv;
-
- uu.ll = u;
- vv.ll = v;
-
- w.s.low = uu.s.low - vv.s.low;
- w.s.high = uu.s.high - vv.s.high - ((unsigned long) w.s.low > uu.s.low);
-
- return w.ll;
- }
- #endif
-
- #ifdef L_divdi3
- long long
- __divdi3 (u, v)
- long long u, v;
- {
- int c = 0;
- long_long uu, vv;
- long_long 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.ll = (unsigned long long) uu.ll / vv.ll;
- if (c)
- w.ll = __negdi2 (uu.ll);
-
- return w.ll;
- }
- #endif
-
- #ifdef L_moddi3
- long long
- __moddi3 (u, v)
- long long u, v;
- {
- int c = 0;
- long_long uu, vv;
- long_long 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.ll = (unsigned long long) uu.ll % vv.ll;
- if (c)
- w.ll = __negdi2 (w.ll);
-
- return w.ll;
- }
- #endif
-
- #ifdef L_umoddi3
- unsigned long long
- __umoddi3 (u, v)
- unsigned long long u, v;
- {
- /* This ought to be done better. The division calculates the remainder,
- so we should not make a multiplication here. */
- return u - (u / v) * v;
- }
- #endif
-
- #ifdef L_muldi3
- long long
- __muldi3 (u, v)
- long long u, v;
- {
- long_long w;
- long_long uu, vv;
-
- uu.ll = u, vv.ll = v;
-
- w.ll = __umulsidi3 (uu.s.low, vv.s.low);
- w.s.high += uu.s.low * vv.s.high + uu.s.high * vv.s.low;
-
- return w.ll;
- }
- #endif
-
- #ifdef L_udivdi3
-
- /* Compute the index of the most significant non-zero bit in X. Range
- 0,1,...,32 for 0,1,0x80000000.
- This is for 32 bits machines max. In my opinion, this function should
- be a __builtin and a standard md code generation name, since it's
- useful even for floating point normalization. */
-
- static inline unsigned long
- bits (x)
- unsigned long x;
- {
- static unsigned char t[] =
- {
- 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
- };
- unsigned a;
-
- a = x <= 0xffff ? (x <= 0xff ? 0 : 8) : (x <= 0xffffff ? 16 : 24);
-
- return t[x >> a] + a;
- }
-
- unsigned long long
- __udivdi3 (n, d)
- unsigned long long n, d;
- {
- long_long ww;
- long_long nn, dd;
- unsigned long d0, d1, n0, n1, n2;
- unsigned long q0, q1;
- unsigned b, bm;
- long_long mm;
-
- nn.ll = n;
- dd.ll = d;
-
- d0 = dd.s.low;
- d1 = dd.s.high;
- n0 = nn.s.low;
- n1 = nn.s.high;
-
- if (d1 == 0)
- {
- if (d0 > n1)
- {
- /* 0q = nn / 0D */
-
- b = bits (d0);
-
- bm = LONG_TYPE_SIZE - b;
- if (bm != 0)
- {
- /* Normalize, i.e. make the most significant bit of the
- denominator set. */
-
- d0 = d0 << bm;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
- }
- div_qrnnd (q0, n0, n1, n0, d0);
- q1 = 0;
-
- /* Remainder in n0 >> bm. */
- }
- else
- {
- /* qq = NN / 0d */
-
- b = bits (d0);
-
- if (b == 0)
- b = 1/d0; /* Divide intentionally by zero. */
-
- bm = LONG_TYPE_SIZE - b;
- if (bm == 0)
- {
- /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
- conclude (the most significant bit of n1 is set) /\ (the
- leading quotient digit q1 = 1).
-
- This special case is necessary, not an optimization.
- (Shifts counts of LONG_TYPE_SIZE are undefined.) */
-
- n1 -= d0;
- q1 = 1;
- }
- else
- {
- /* Normalize. */
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- div_qrnnd (q1, n1, n2, n1, d0);
- }
-
- /* n1 != d0... */
-
- div_qrnnd (q0, n0, n1, n0, d0);
-
- /* Remainder in n0. */
- }
- }
- else
- {
- if (d1 > n1)
- {
- /* 00 = nn / DD */
-
- q0 = 0;
- q1 = 0;
-
- /* Remainder in n1n0. */
- }
- else
- {
- /* 0q = NN / dd */
-
- b = bits (d1);
- bm = LONG_TYPE_SIZE - b;
- if (bm == 0)
- {
- /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
- conclude (the most significant bit of n1 is set) /\ (the
- quotient digit q0 = 0 or 1).
-
- This special case is necessary, not an optimization. */
-
- q0 = (n1 > d1) | (n1 == d1 && n0 >= d0);
- q1 = 0;
- }
- else
- {
- /* Normalize. */
- d1 = (d1 << bm) | (d0 >> b);
- d0 = d0 << bm;
- n2 = n1 >> b;
- n1 = (n1 << bm) | (n0 >> b);
- n0 = n0 << bm;
-
- div_qrnnd (q0, n1, n2, n1, d1);
-
- mm.ll = __umulsidi3 (q0, d0);
-
- if (mm.s.high > n1 || (mm.s.high == n1 && mm.s.low > n0))
- q0--;
-
- q1 = 0;
-
- /* Remainder in mm - n1n0 (but if q0 was decremented?). */
- }
- }
- }
-
- ww.s.low = q0;
- ww.s.high = q1;
- return ww.ll;
- }
- #endif
-
- #ifdef L_cmpdi2
- SItype
- __cmpdi2 (a, b)
- long long a, b;
- {
- long_long 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 ((unsigned) au.s.low < (unsigned) bu.s.low)
- return 0;
- else if ((unsigned) au.s.low > (unsigned) bu.s.low)
- return 2;
- return 1;
- }
- #endif
-
- #ifdef L_ucmpdi2
- SItype
- __ucmpdi2 (a, b)
- long long a, b;
- {
- long_long au, bu;
-
- au.ll = a, bu.ll = b;
-
- if ((unsigned) au.s.high < (unsigned) bu.s.high)
- return 0;
- else if ((unsigned) au.s.high > (unsigned) bu.s.high)
- return 2;
- if ((unsigned) au.s.low < (unsigned) bu.s.low)
- return 0;
- else if ((unsigned) au.s.low > (unsigned) bu.s.low)
- return 2;
- return 1;
- }
- #endif
-
- #ifdef L_fixunsdfdi
- #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
- #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
-
- long long
- __fixunsdfdi (a)
- double a;
- {
- double b;
- unsigned long long v;
-
- if (a < 0)
- return 0;
-
- /* Compute high word of result, as a flonum. */
- b = (a / HIGH_WORD_COEFF);
- /* Convert that to fixed (but not to long long!),
- and shift it into the high word. */
- v = (unsigned long int) b;
- v <<= WORD_SIZE;
- /* Remove high part from the double, leaving the low part as flonum. */
- a -= (double)v;
- /* Convert that to fixed (but not to long long!) and add it in.
- Sometimes A comes out negative. This is significant, since
- A has more bits than a long int does. */
- if (a < 0)
- v -= (unsigned long int) (- a);
- else
- v += (unsigned long int) a;
- return v;
- }
- #endif
-
- #ifdef L_fixdfdi
- long long
- __fixdfdi (a)
- double a;
- {
- long long __fixunsdfdi (double a);
-
- if (a < 0)
- return - __fixunsdfdi (-a);
- return __fixunsdfdi (a);
- }
- #endif
-
- #ifdef L_fixunssfdi
- #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
- #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
-
- long long
- __fixunssfdi (float original_a)
- {
- /* Convert the float to a double, because that is surely not going
- to lose any bits. Some day someone else can write a faster version
- that avoids converting to double, and verify it really works right. */
- double a = original_a;
- double b;
- unsigned long long v;
-
- if (a < 0)
- return 0;
-
- /* Compute high word of result, as a flonum. */
- b = (a / HIGH_WORD_COEFF);
- /* Convert that to fixed (but not to long long!),
- and shift it into the high word. */
- v = (unsigned long int) b;
- v <<= WORD_SIZE;
- /* Remove high part from the double, leaving the low part as flonum. */
- a -= (double)v;
- /* Convert that to fixed (but not to long long!) and add it in.
- Sometimes A comes out negative. This is significant, since
- A has more bits than a long int does. */
- if (a < 0)
- v -= (unsigned long int) (- a);
- else
- v += (unsigned long int) a;
- return v;
- }
- #endif
-
- #ifdef L_fixsfdi
- long long
- __fixsfdi (float a)
- {
- long long __fixunssfdi (float a);
-
- if (a < 0)
- return - __fixunssfdi (-a);
- return __fixunssfdi (a);
- }
- #endif
-
- #ifdef L_floatdidf
- #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
- #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2))
- #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
-
- double
- __floatdidf (u)
- long long u;
- {
- double d;
- int negate = 0;
-
- if (u < 0)
- u = -u, negate = 1;
-
- d = (unsigned int) (u >> WORD_SIZE);
- d *= HIGH_HALFWORD_COEFF;
- d *= HIGH_HALFWORD_COEFF;
- d += (unsigned int) (u & (HIGH_WORD_COEFF - 1));
-
- return (negate ? -d : d);
- }
- #endif
-
- #ifdef L_floatdisf
- #define WORD_SIZE (sizeof (long) * BITS_PER_UNIT)
- #define HIGH_HALFWORD_COEFF (((long long) 1) << (WORD_SIZE / 2))
- #define HIGH_WORD_COEFF (((long long) 1) << WORD_SIZE)
-
- float
- __floatdisf (u)
- long long u;
- {
- float f;
- int negate = 0;
-
- if (u < 0)
- u = -u, negate = 1;
-
- f = (unsigned int) (u >> WORD_SIZE);
- f *= HIGH_HALFWORD_COEFF;
- f *= HIGH_HALFWORD_COEFF;
- f += (unsigned int) (u & (HIGH_WORD_COEFF - 1));
-
- return (negate ? -f : f);
- }
- #endif
-
- #ifdef L_fixunsdfsi
- #include "limits.h"
-
- unsigned SItype
- __fixunsdfsi (a)
- double a;
- {
- if (a >= - (double) LONG_MIN)
- return (SItype) (a + LONG_MIN) - LONG_MIN;
- return (SItype) a;
- }
- #endif
-
- #ifdef L_fixunssfsi
- #include "limits.h"
-
- unsigned SItype
- __fixunssfsi (float a)
- {
- if (a >= - (float) LONG_MIN)
- return (SItype) (a + LONG_MIN) - LONG_MIN;
- return (SItype) a;
- }
- #endif
-
- #ifdef L_varargs
- #ifdef i860
- asm (" .text");
- asm (" .align 4");
-
- asm ("___builtin_saveregs::");
- asm (" mov sp,r30");
- asm (" andnot 0x0f,sp,sp");
- asm (" adds -96,sp,sp"); /* allocate sufficient space on the stack */
-
- asm (" st.l r16, 0(sp)"); /* save integer regs (r16-r27) */
- asm (" st.l r17, 4(sp)"); /* int fixed[12] */
- 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)"); /* save floating regs (f8-f15) */
- asm (" fst.q f12,64(sp)"); /* int floating[8] */
-
- asm (" st.l r28,80(sp)"); /* pointer to more args */
- asm (" st.l r0, 84(sp)"); /* nfixed */
- asm (" st.l r0, 88(sp)"); /* nfloating */
- asm (" st.l r0, 92(sp)"); /* pad */
-
- asm (" mov sp,r16");
- asm (" bri r1");
- asm (" mov r30,sp");
- /* recover stack and pass address to start
- of data. */
- #endif
- #ifdef __sparc__
- asm (".global ___builtin_saveregs");
- asm ("___builtin_saveregs:");
- 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]");
- #else /* not __sparc__ */
- #if defined(__MIPSEL__) | defined(__R3000__) | defined(__R2000__) | defined(__mips__)
-
- 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 /* not mips */
- __builtin_saveregs ()
- {
- abort ();
- }
- #endif /* not mips */
- #endif /* not __sparc__ */
- #endif
-
- #ifdef L_eprintf
- #include <stdio.h>
- /* This is used by the `assert' macro. */
- void
- __eprintf (string, expression, line, filename)
- char *string;
- char *expression;
- int line;
- char *filename;
- {
- fprintf (stderr, string, expression, line, filename);
- fflush (stderr);
- abort ();
- }
- #endif
-
- #ifdef L_bb
- /* Avoid warning from ranlib about empty object file. */
- __bb_avoid_warning ()
- {}
-
- #if defined (sun) && defined (mc68000)
- struct bb
- {
- int initialized;
- char *filename;
- int *counts;
- int ncounts;
- int zero_word;
- int *addresses;
- };
-
- __bb_init_func (blocks)
- struct bb *blocks;
- {
- extern int ___tcov_init;
-
- if (! ___tcov_init)
- ___tcov_init_func ();
-
- ___bb_link (blocks->filename, blocks->counts, blocks->ncounts);
- }
-
- #endif
- #endif
-
- /* frills for C++ */
-
- #ifdef L_builtin_new
- typedef void (*vfp)();
-
- extern vfp __new_handler;
-
- char *
- __builtin_new (sz)
- long sz;
- {
- char *p;
-
- p = (char *)malloc (sz);
- if (p == 0)
- (*__new_handler) ();
- return p;
- }
- #endif
-
- #ifdef L_builtin_New
- typedef void (*vfp)();
-
- static void
- default_new_handler ();
-
- vfp __new_handler = default_new_handler;
-
- char *
- __builtin_vec_new (p, maxindex, size, ctor)
- char *p;
- int maxindex, size;
- void (*ctor)();
- {
- int i, nelts = maxindex + 1;
- char *rval;
-
- if (p == 0)
- p = (char *)__builtin_new (nelts * size);
-
- rval = p;
-
- for (i = 0; i < nelts; i++)
- {
- (*ctor) (p);
- p += size;
- }
-
- return rval;
- }
-
- vfp
- __set_new_handler (handler)
- vfp handler;
- {
- vfp prev_handler;
-
- prev_handler = __new_handler;
- if (handler == 0) handler = default_new_handler;
- __new_handler = handler;
- return prev_handler;
- }
-
- vfp
- set_new_handler (handler)
- vfp handler;
- {
- return __set_new_handler (handler);
- }
-
- static void
- default_new_handler ()
- {
- /* don't use fprintf (stderr, ...) because it may need to call malloc. */
- write (2, "default_new_handler: out of memory... aaaiiiiiieeeeeeeeeeeeee!\n", 65);
- /* don't call exit () because that may call global destructors which
- may cause a loop. */
- _exit (-1);
- }
- #endif
-
- #ifdef L_builtin_del
- typedef void (*vfp)();
-
- void
- __builtin_delete (ptr)
- char *ptr;
- {
- if (ptr)
- free (ptr);
- }
-
- void
- __builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete)
- char *ptr;
- int maxindex, size;
- void (*dtor)();
- int auto_delete;
- {
- int i, nelts = maxindex + 1;
- char *p = ptr;
-
- ptr += nelts * size;
-
- for (i = 0; i < nelts; i++)
- {
- ptr -= size;
- (*dtor) (ptr, auto_delete);
- }
-
- if (auto_delete_vec)
- __builtin_delete (p);
- }
-
- #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
- /* Clear part of an instruction cache. */
-
- #define INSN_CACHE_PLANE_SIZE (INSN_CACHE_SIZE / INSN_CACHE_DEPTH)
-
- void
- __clear_cache (beg, end)
- char *beg, *end;
- {
- #ifdef INSN_CACHE_SIZE
- static char array[INSN_CACHE_SIZE + INSN_CACHE_PLANE_SIZE + INSN_CACHE_LINE_WIDTH];
- static int initialized = 0;
- int offset;
- unsigned int start_addr, end_addr;
- typedef (*function_ptr) ();
-
- #if (INSN_CACHE_SIZE / INSN_CACHE_LINE_WIDTH) < 16
- /* It's cheaper to clear the whole cache.
- Put in a series of jump instructions so that calling the beginning
- of the cache will clear the whole thing. */
-
- 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;
- }
-
- /* Call the beginning of the sequence. */
- (((function_ptr) (((int) array + INSN_CACHE_LINE_WIDTH - 1)
- & -INSN_CACHE_LINE_WIDTH))
- ());
-
- #else /* Cache is large. */
-
- 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;
- }
-
- /* Find the location in array that occupies the same cache line as BEG. */
-
- 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);
-
- /* Compute the cache alignment of the place to stop clearing. */
- #if 0 /* This is not needed for gcc's purposes. */
- /* If the block to clear is bigger than a cache plane,
- we clear the entire cache, and OFFSET is already correct. */
- 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)
- {
- /* Call the return instruction at ADDR. */
- ((function_ptr) addr) ();
-
- addr += INSN_CACHE_LINE_WIDTH;
- }
- }
- #else /* just one plane */
- do
- {
- /* Call the return instruction at START_ADDR. */
- ((function_ptr) start_addr) ();
-
- start_addr += INSN_CACHE_LINE_WIDTH;
- }
- while ((start_addr % INSN_CACHE_SIZE) != offset);
- #endif /* just one plane */
- #endif /* Cache is large */
- #endif /* Cache exists */
- }
-
- #endif /* L_clear_cache */
-
- #ifdef L_trampoline
-
- /* Jump to a trampoline, loading the static chain address. */
-
- #ifdef TRANSFER_FROM_TRAMPOLINE
-
- /* asm with operands is permitted only within a function. */
- static dummy ()
- {
- TRANSFER_FROM_TRAMPOLINE
- }
- #endif
-
- #endif
-