/* More subroutines needed by GCC output code on some machines. */ /* Compile this one with gcc. */ /* Copyright (C) 1989, 1992 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 2, 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. */ #ifndef atarist /* It is incorrect to include config.h here, because this file is being compiled for the target, and hence definitions concerning only the host do not apply. */ #include "tconfig.h" #include "machmode.h" #ifndef L_trampoline #include "gstddef.h" #endif #else /* For the atari, include the relevant parts of config/m68k.h directly. */ #ifndef __mc68000__ #define __mc68000__ 1 #ifdef __M68020__ #define __mc68020__ 1 #endif #endif #if __GNUC__ < 2 #error This file is for GCC version 2 only. #endif #ifndef L_trampoline #include #endif /* Define this if most significant byte of a word is the lowest numbered. */ /* That is true on the 68000. */ #define BYTES_BIG_ENDIAN 1 /* Define this if most significant word of a multiword number is the lowest numbered. */ /* For 68000 we can decide arbitrarily since there are no machine instructions for them. So let's be consistent. */ #define WORDS_BIG_ENDIAN 1 /* number of bits in an addressable storage unit */ #define BITS_PER_UNIT 8 /* for this file this is always true, never compile anything in here with -mshort */ #define BITS_PER_WORD 32 /* This is the library routine that is used to transfer control from the trampoline to the actual nested function. */ /* A colon is used with no explicit operands to cause the template string to be scanned for %-constructs. */ /* The function name __transfer_from_trampoline is not actually used. The function definition just permits use of "asm with operands" (though the operand list is empty). */ #define TRANSFER_FROM_TRAMPOLINE \ void \ __transfer_from_trampoline () \ { \ register char *a0 asm ("%a0"); \ asm (".globl ___trampoline"); \ asm ("___trampoline:"); \ asm volatile ("move%.l %0,%@" : : "m" (a0[22])); \ asm volatile ("move%.l %1,%0" : "=a" (a0) : "m" (a0[18])); \ asm ("rts":); \ } #endif /* atarist */ /* In the first part of this file, we are interfacing to calls generated by the compiler itself. These calls pass values into these routines which have very specific modes (rather than very specific types), and these compiler-generated calls also expect any return values to have very specific modes (rather than very specific types). Thus, we need to avoid using regular C language type names in this part of the file because the sizes for those types can be configured to be anything. Instead we use the following special type names. */ 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 LONG_DOUBLE_TYPE_SIZE == 96 typedef float XFtype __attribute__ ((mode (XF))); #endif #if LONG_DOUBLE_TYPE_SIZE == 128 typedef float TFtype __attribute__ ((mode (TF))); #endif #if BITS_PER_WORD==16 typedef int word_type __attribute__ ((mode (HI))); #endif #if BITS_PER_WORD==32 typedef int word_type __attribute__ ((mode (SI))); #endif #if BITS_PER_WORD==64 typedef int word_type __attribute__ ((mode (DI))); #endif /* Make sure that we don't accidentally use any normal C language built-in type names in the first part of this file. Instead we want to use *only* the type names defined above. The following macro definitions insure that if we *do* accidentally use some normal C language built-in type name, we will get a syntax error. */ #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) /* DIstructs are pairs of SItype values in the order determined by WORDS_BIG_ENDIAN. */ #if WORDS_BIG_ENDIAN struct DIstruct {SItype high, low;}; #else struct DIstruct {SItype low, high;}; #endif /* We need this union to unpack/pack DImode values, since we don't have any arithmetic yet. Incoming DImode parameters are stored into the `ll' field, and the unpacked result is read from the struct `s'. */ typedef union { struct DIstruct s; DItype ll; } DIunion; #if defined (L_udivmoddi4) || defined (L_muldi3) || defined (L_udiv_w_sdiv) #include "longlong.h" #endif /* udiv or mul */ extern DItype __fixunssfdi (SFtype a); extern DItype __fixunsdfdi (DFtype a); #if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3) #if defined (L_divdi3) || defined (L_moddi3) static inline #endif DItype __negdi2 (u) 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_lshldi3 DItype __lshldi3 (u, b) DItype u; SItype b; { DIunion w; SItype 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_lshrdi3 DItype __lshrdi3 (u, b) DItype u; SItype b; { DIunion w; SItype 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 (u, b) DItype u; SItype b; { DIunion w; SItype 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 (u, b) DItype u; SItype b; { DIunion w; SItype bm; DIunion uu; if (b == 0) return u; uu.ll = u; bm = (sizeof (SItype) * BITS_PER_UNIT) - b; if (bm <= 0) { /* w.s.high = 1..1 or 0..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 (u) 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 (u, v) DItype u, 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 USItype __udiv_w_sdiv (rp, a1, a0, d) USItype *rp, a1, a0, d; { USItype q, r; USItype c0, c1, b1; if ((SItype) d >= 0) { if (a1 < d - a1 - (a0 >> (SI_TYPE_SIZE - 1))) { /* dividend, divisor, and quotient are nonnegative */ sdiv_qrnnd (q, r, a1, a0, d); } else { /* Compute c1*2^32 + c0 = a1*2^32 + a0 - 2^31*d */ sub_ddmmss (c1, c0, a1, a0, d >> 1, d << (SI_TYPE_SIZE - 1)); /* Divide (c1*2^32 + c0) by d */ sdiv_qrnnd (q, r, c1, c0, d); /* Add 2^31 to quotient */ q += (USItype) 1 << (SI_TYPE_SIZE - 1); } } else { b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ c1 = a1 >> 1; /* A/2 */ c0 = (a1 << (SI_TYPE_SIZE - 1)) + (a0 >> 1); if (a1 < b1) /* A < 2^32*b1, so A/2 < 2^31*b1 */ { sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ r = 2*r + (a0 & 1); /* Remainder from A/(2*b1) */ 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) /* So 2^31 <= (A/2)/b1 < 2^32 */ { c1 = (b1 - 1) - c1; c0 = ~c0; /* logical NOT */ sdiv_qrnnd (q, r, c1, c0, b1); /* (A/2) / (d/2) */ q = ~q; /* (A/2)/b1 */ r = (b1 - 1) - r; r = 2*r + (a0 & 1); /* A/(2*b1) */ 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 /* Implies c1 = b1 */ { /* Hence a1 = d - 1 = 2*b1 - 1 */ if (a0 >= -d) { q = -1; r = a0 + d; } else { q = -2; r = a0 + 2*d; } } } *rp = r; return q; } #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, }; UDItype __udivmoddi4 (n, d, rp) UDItype n, 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) { /* 0q = nn / 0D */ udiv_qrnnd (q0, n0, n1, n0, d0); q1 = 0; /* Remainder in n0. */ } else { /* qq = NN / 0d */ if (d0 == 0) d0 = 1 / d0; /* Divide intentionally by zero. */ udiv_qrnnd (q1, n1, 0, n1, d0); udiv_qrnnd (q0, n0, n1, n0, d0); /* Remainder in n0. */ } if (rp != 0) { rr.s.low = n0; rr.s.high = 0; *rp = rr.ll; } } #else /* UDIV_NEEDS_NORMALIZATION */ if (d1 == 0) { if (d0 > n1) { /* 0q = nn / 0D */ count_leading_zeros (bm, d0); if (bm != 0) { /* Normalize, i.e. make the most significant bit of the denominator set. */ d0 = d0 << bm; n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm)); n0 = n0 << bm; } udiv_qrnnd (q0, n0, n1, n0, d0); q1 = 0; /* Remainder in n0 >> bm. */ } else { /* qq = NN / 0d */ if (d0 == 0) d0 = 1 / d0; /* Divide intentionally by zero. */ count_leading_zeros (bm, d0); 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 SI_TYPE_SIZE are undefined.) */ n1 -= d0; q1 = 1; } else { /* Normalize. */ 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); } /* n1 != d0... */ udiv_qrnnd (q0, n0, n1, n0, d0); /* Remainder in n0 >> bm. */ } if (rp != 0) { rr.s.low = n0 >> bm; rr.s.high = 0; *rp = rr.ll; } } #endif /* UDIV_NEEDS_NORMALIZATION */ else { if (d1 > n1) { /* 00 = nn / DD */ q0 = 0; q1 = 0; /* Remainder in n1n0. */ if (rp != 0) { rr.s.low = n0; rr.s.high = n1; *rp = rr.ll; } } else { /* 0q = NN / dd */ count_leading_zeros (bm, d1); 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. */ /* The condition on the next line takes advantage of that n1 >= d1 (true due to program flow). */ 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; /* Normalize. */ 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; /* Remainder in (n1n0 - m1m0) >> bm. */ 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 (u, v) DItype u, v; { SItype 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 (u, v) DItype u, v; { SItype 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 (u, v) UDItype u, v; { DItype w; (void) __udivmoddi4 (u, v, &w); return w; } #endif #ifdef L_udivdi3 UDItype __udivmoddi4 (); UDItype __udivdi3 (n, d) UDItype n, d; { return __udivmoddi4 (n, d, (UDItype *) 0); } #endif #ifdef L_cmpdi2 word_type __cmpdi2 (a, b) DItype a, 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 (a, b) DItype a, 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) && (LONG_DOUBLE_TYPE_SIZE == 128) #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) DItype __fixunstfdi (a) TFtype a; { TFtype b; UDItype 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 DItype!), and shift it into the high word. */ v = (USItype) b; v <<= WORD_SIZE; /* Remove high part from the TFtype, leaving the low part as flonum. */ a -= (TFtype)v; /* Convert that to fixed (but not to DItype!) 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 -= (USItype) (- a); else v += (USItype) a; return v; } #endif #if defined(L_fixtfdi) && (LONG_DOUBLE_TYPE_SIZE == 128) DItype __fixtfdi (a) TFtype a; { if (a < 0) return - __fixunstfdi (-a); return __fixunstfdi (a); } #endif #if defined(L_fixunsxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96) #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) DItype __fixunsxfdi (a) XFtype a; { XFtype b; UDItype 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 DItype!), and shift it into the high word. */ v = (USItype) b; v <<= WORD_SIZE; /* Remove high part from the XFtype, leaving the low part as flonum. */ a -= (XFtype)v; /* Convert that to fixed (but not to DItype!) 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 -= (USItype) (- a); else v += (USItype) a; return v; } #endif #if defined(L_fixxfdi) && (LONG_DOUBLE_TYPE_SIZE == 96) DItype __fixxfdi (a) XFtype a; { if (a < 0) return - __fixunsxfdi (-a); return __fixunsxfdi (a); } #endif #ifdef L_fixunsdfdi #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) DItype __fixunsdfdi (a) DFtype a; { DFtype b; UDItype 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 DItype!), and shift it into the high word. */ v = (USItype) b; v <<= WORD_SIZE; /* Remove high part from the DFtype, leaving the low part as flonum. */ a -= (DFtype)v; /* Convert that to fixed (but not to DItype!) 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 -= (USItype) (- a); else v += (USItype) a; return v; } #endif #ifdef L_fixdfdi DItype __fixdfdi (a) DFtype a; { if (a < 0) return - __fixunsdfdi (-a); return __fixunsdfdi (a); } #endif #ifdef L_fixunssfdi #define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) #define HIGH_WORD_COEFF (((UDItype) 1) << WORD_SIZE) DItype __fixunssfdi (SFtype original_a) { /* Convert the SFtype to a DFtype, because that is surely not going to lose any bits. Some day someone else can write a faster version that avoids converting to DFtype, and verify it really works right. */ DFtype a = original_a; DFtype b; UDItype 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 DItype!), and shift it into the high word. */ v = (USItype) b; v <<= WORD_SIZE; /* Remove high part from the DFtype, leaving the low part as flonum. */ a -= (DFtype)v; /* Convert that to fixed (but not to DItype!) 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 -= (USItype) (- a); else v += (USItype) a; return v; } #endif #ifdef L_fixsfdi DItype __fixsfdi (SFtype a) { if (a < 0) return - __fixunssfdi (-a); return __fixunssfdi (a); } #endif #if defined(L_floatdixf) && (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 (u) DItype u; { XFtype d; SItype negate = 0; if (u < 0) u = -u, negate = 1; d = (USItype) (u >> WORD_SIZE); d *= HIGH_HALFWORD_COEFF; d *= HIGH_HALFWORD_COEFF; d += (USItype) (u & (HIGH_WORD_COEFF - 1)); return (negate ? -d : d); } #endif #if defined(L_floatditf) && (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 (u) DItype u; { TFtype d; SItype negate = 0; if (u < 0) u = -u, negate = 1; d = (USItype) (u >> WORD_SIZE); d *= HIGH_HALFWORD_COEFF; d *= HIGH_HALFWORD_COEFF; d += (USItype) (u & (HIGH_WORD_COEFF - 1)); return (negate ? -d : 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 (u) DItype u; { DFtype d; SItype negate = 0; if (u < 0) u = -u, negate = 1; d = (USItype) (u >> WORD_SIZE); d *= HIGH_HALFWORD_COEFF; d *= HIGH_HALFWORD_COEFF; d += (USItype) (u & (HIGH_WORD_COEFF - 1)); return (negate ? -d : 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) SFtype __floatdisf (u) DItype u; { /* Do the calculation in DFmode so that we don't lose any of the precision of the high word while multiplying it. */ DFtype f; SItype negate = 0; if (u < 0) u = -u, negate = 1; f = (USItype) (u >> WORD_SIZE); f *= HIGH_HALFWORD_COEFF; f *= HIGH_HALFWORD_COEFF; f += (USItype) (u & (HIGH_WORD_COEFF - 1)); return (SFtype) (negate ? -f : f); } #endif #if defined(L_fixunsxfsi) && LONG_DOUBLE_TYPE_SIZE == 96 #include "glimits.h" USItype __fixunsxfsi (a) XFtype a; { if (a >= - (DFtype) LONG_MIN) return (SItype) (a + LONG_MIN) - LONG_MIN; return (SItype) a; } #endif #ifdef L_fixunsdfsi #include USItype __fixunsdfsi (a) DFtype a; { if (a >= - (DFtype) LONG_MIN) return (SItype) (a + LONG_MIN) - LONG_MIN; return (SItype) a; } #endif #ifdef L_fixunssfsi #include USItype __fixunssfsi (SFtype a) { if (a >= - (SFtype) LONG_MIN) return (SItype) (a + LONG_MIN) - LONG_MIN; return (SItype) a; } #endif /* From here on down, the routines use normal data types. */ #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 /* frills for C++ */ #ifdef L_builtin_new #include typedef void (*vfp)(void); extern vfp __new_handler; void * __builtin_new (size_t sz) { void *p; /* malloc (0) is unpredictable; avoid it. */ if (sz == 0) sz = 1; p = (void *) malloc (sz); if (p == 0) (*__new_handler) (); return p; } #endif #ifdef L_caps_New /* Avoid forcing the library's meaning of `write' on the user program by using the "internal" name (for use within the library) */ #define write(fd, buf, n) _write((fd), (buf), (n)) typedef void (*vfp)(void); extern void *__builtin_new (size_t); static void default_new_handler (void); vfp __new_handler = default_new_handler; void * __builtin_vec_new (p, maxindex, size, ctor) void *p; size_t maxindex; size_t size; void (*ctor)(void *); { size_t i; size_t nelts = maxindex + 1; void *rval; if (p == 0) p = __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); } #define MESSAGE "Virtual memory exceeded in `new'\n" static void default_new_handler () { /* don't use fprintf (stderr, ...) because it may need to call malloc. */ /* This should really print the name of the program, but that is hard to do. We need a standard, clean way to get at the name. */ write (2, MESSAGE, sizeof (MESSAGE)); /* 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); void __builtin_delete (void *ptr) { if (ptr) free (ptr); } void __builtin_vec_delete (ptr, maxindex, size, dtor, auto_delete_vec, auto_delete) void *ptr; size_t maxindex; size_t size; void (*dtor)(void *, int); int auto_delete; { size_t i; size_t nelts = maxindex + 1; void *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_trampoline /* Jump to a trampoline, loading the static chain address. */ #ifdef TRANSFER_FROM_TRAMPOLINE TRANSFER_FROM_TRAMPOLINE #endif #endif /* L_trampoline */ #ifdef L__main #include "gbl-ctors.h" /* Run all the global destructors on exit from the program. */ void __do_global_dtors () { unsigned nptrs = (unsigned long) __DTOR_LIST__[0]; unsigned i; /* Some systems place the number of pointers in the first word of the table. On other systems, that word is -1. In all cases, the table is null-terminated. */ /* If the length is not recorded, count up to the null. */ if (nptrs == -1) for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++); /* GNU LD format. */ for (i = nptrs; i >= 1; i--) __DTOR_LIST__[i] (); } /* Run all the global constructors on entry to the program. */ void __do_global_ctors () { DO_GLOBAL_CTORS_BODY; } /* Subroutine called automatically by `main'. Compiling a global function named `main' produces an automatic call to this function at the beginning. For many systems, this routine calls __do_global_ctors. For systems which support a .init section we use the .init section to run __do_global_ctors, so we need not do anything here. */ void __main () { /* Support recursive calls to `main': run initializers just once. */ static int initialized = 0; if (! initialized) { initialized = 1; __do_global_ctors (); } } #endif /* L__main */ #ifdef L_ctor_list #include "gbl-ctors.h" const func_ptr __CTOR_LIST__[2] = {0, 0}; #endif /* L_ctor_list */ #ifdef L_dtor_list #include "gbl-ctors.h" const func_ptr __DTOR_LIST__[2] = {0, 0}; #endif /* L_ctor_list */