From 8aa77c9ee63146dff6afcd0971edd9a4e04bc41b Mon Sep 17 00:00:00 2001 From: James Benton Date: Wed, 8 Jun 2016 01:24:37 +0100 Subject: [PATCH] Add a part of libgcc to get 64 bit integer division function __udivdi3. We cannot link with devkitPPC libgcc because it includes __eabi which we do not want, as that sets up r2 and r13 SDA registers from elf file symbols but that is done by the RPL FileInfo read by CafeOS for the Wii U. In future we should probably fork devkitPPC to build without powerpc eabi in order to match what we expect for the Wii U. --- crt/libgcc2.c | 2247 ++++++++++++++++++++++++++++++++++++++++++++++++ crt/libgcc2.h | 529 ++++++++++++ crt/longlong.h | 1693 ++++++++++++++++++++++++++++++++++++ crt/tconfig.h | 8 + rules/rpl.mk | 2 +- 5 files changed, 4478 insertions(+), 1 deletion(-) create mode 100644 crt/libgcc2.c create mode 100644 crt/libgcc2.h create mode 100644 crt/longlong.h create mode 100644 crt/tconfig.h diff --git a/crt/libgcc2.c b/crt/libgcc2.c new file mode 100644 index 00000000..d3c77909 --- /dev/null +++ b/crt/libgcc2.c @@ -0,0 +1,2247 @@ +/* More subroutines needed by GCC output code on some machines. */ +/* Compile this one with gcc. */ +/* Copyright (C) 1989-2013 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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 3, or (at your option) any later +version. + +GCC 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#include "tconfig.h" + +#ifdef HAVE_GAS_HIDDEN +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) +#else +#define ATTRIBUTE_HIDDEN +#endif + +/* Work out the largest "word" size that we can deal with on this target. */ +#if MIN_UNITS_PER_WORD > 4 +# define LIBGCC2_MAX_UNITS_PER_WORD 8 +#elif (MIN_UNITS_PER_WORD > 2 \ + || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4)) +# define LIBGCC2_MAX_UNITS_PER_WORD 4 +#else +# define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD +#endif + +/* Work out what word size we are using for this compilation. + The value can be set on the command line. */ +#ifndef LIBGCC2_UNITS_PER_WORD +#define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD +#endif + +#if LIBGCC2_UNITS_PER_WORD <= LIBGCC2_MAX_UNITS_PER_WORD + +#include "libgcc2.h" + +#ifdef DECLARE_LIBRARY_RENAMES + DECLARE_LIBRARY_RENAMES +#endif + +#if defined (L_negdi2) +DWtype +__negdi2 (DWtype u) +{ + const DWunion uu = {.ll = u}; + const DWunion w = { {.low = -uu.s.low, + .high = -uu.s.high - ((UWtype) -uu.s.low > 0) } }; + + return w.ll; +} +#endif + +#ifdef L_addvsi3 +Wtype +__addvSI3 (Wtype a, Wtype b) +{ + const Wtype w = (UWtype) a + (UWtype) b; + + if (b >= 0 ? w < a : w > a) + abort (); + + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__addvsi3 (SItype a, SItype b) +{ + const SItype w = (USItype) a + (USItype) b; + + if (b >= 0 ? w < a : w > a) + abort (); + + return w; +} +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ +#endif + +#ifdef L_addvdi3 +DWtype +__addvDI3 (DWtype a, DWtype b) +{ + const DWtype w = (UDWtype) a + (UDWtype) b; + + if (b >= 0 ? w < a : w > a) + abort (); + + return w; +} +#endif + +#ifdef L_subvsi3 +Wtype +__subvSI3 (Wtype a, Wtype b) +{ + const Wtype w = (UWtype) a - (UWtype) b; + + if (b >= 0 ? w > a : w < a) + abort (); + + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__subvsi3 (SItype a, SItype b) +{ + const SItype w = (USItype) a - (USItype) b; + + if (b >= 0 ? w > a : w < a) + abort (); + + return w; +} +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ +#endif + +#ifdef L_subvdi3 +DWtype +__subvDI3 (DWtype a, DWtype b) +{ + const DWtype w = (UDWtype) a - (UDWtype) b; + + if (b >= 0 ? w > a : w < a) + abort (); + + return w; +} +#endif + +#ifdef L_mulvsi3 +Wtype +__mulvSI3 (Wtype a, Wtype b) +{ + const DWtype w = (DWtype) a * (DWtype) b; + + if ((Wtype) (w >> W_TYPE_SIZE) != (Wtype) w >> (W_TYPE_SIZE - 1)) + abort (); + + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +#undef WORD_SIZE +#define WORD_SIZE (sizeof (SItype) * BITS_PER_UNIT) +SItype +__mulvsi3 (SItype a, SItype b) +{ + const DItype w = (DItype) a * (DItype) b; + + if ((SItype) (w >> WORD_SIZE) != (SItype) w >> (WORD_SIZE-1)) + abort (); + + return w; +} +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ +#endif + +#ifdef L_negvsi2 +Wtype +__negvSI2 (Wtype a) +{ + const Wtype w = -(UWtype) a; + + if (a >= 0 ? w > 0 : w < 0) + abort (); + + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__negvsi2 (SItype a) +{ + const SItype w = -(USItype) a; + + if (a >= 0 ? w > 0 : w < 0) + abort (); + + return w; +} +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ +#endif + +#ifdef L_negvdi2 +DWtype +__negvDI2 (DWtype a) +{ + const DWtype w = -(UDWtype) a; + + if (a >= 0 ? w > 0 : w < 0) + abort (); + + return w; +} +#endif + +#ifdef L_absvsi2 +Wtype +__absvSI2 (Wtype a) +{ + Wtype w = a; + + if (a < 0) +#ifdef L_negvsi2 + w = __negvSI2 (a); +#else + w = -(UWtype) a; + + if (w < 0) + abort (); +#endif + + return w; +} +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +SItype +__absvsi2 (SItype a) +{ + SItype w = a; + + if (a < 0) +#ifdef L_negvsi2 + w = __negvsi2 (a); +#else + w = -(USItype) a; + + if (w < 0) + abort (); +#endif + + return w; +} +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ +#endif + +#ifdef L_absvdi2 +DWtype +__absvDI2 (DWtype a) +{ + DWtype w = a; + + if (a < 0) +#ifdef L_negvdi2 + w = __negvDI2 (a); +#else + w = -(UDWtype) a; + + if (w < 0) + abort (); +#endif + + return w; +} +#endif + +#ifdef L_mulvdi3 +DWtype +__mulvDI3 (DWtype u, DWtype v) +{ + /* The unchecked multiplication needs 3 Wtype x Wtype multiplications, + but the checked multiplication needs only two. */ + const DWunion uu = {.ll = u}; + const DWunion vv = {.ll = v}; + + if (__builtin_expect (uu.s.high == uu.s.low >> (W_TYPE_SIZE - 1), 1)) + { + /* u fits in a single Wtype. */ + if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1)) + { + /* v fits in a single Wtype as well. */ + /* A single multiplication. No overflow risk. */ + return (DWtype) uu.s.low * (DWtype) vv.s.low; + } + else + { + /* Two multiplications. */ + DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low}; + DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.high}; + + if (vv.s.high < 0) + w1.s.high -= uu.s.low; + if (uu.s.low < 0) + w1.ll -= vv.ll; + w1.ll += (UWtype) w0.s.high; + if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1)) + { + w0.s.high = w1.s.low; + return w0.ll; + } + } + } + else + { + if (__builtin_expect (vv.s.high == vv.s.low >> (W_TYPE_SIZE - 1), 1)) + { + /* v fits into a single Wtype. */ + /* Two multiplications. */ + DWunion w0 = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low}; + DWunion w1 = {.ll = (UDWtype) (UWtype) uu.s.high + * (UDWtype) (UWtype) vv.s.low}; + + if (uu.s.high < 0) + w1.s.high -= vv.s.low; + if (vv.s.low < 0) + w1.ll -= uu.ll; + w1.ll += (UWtype) w0.s.high; + if (__builtin_expect (w1.s.high == w1.s.low >> (W_TYPE_SIZE - 1), 1)) + { + w0.s.high = w1.s.low; + return w0.ll; + } + } + else + { + /* A few sign checks and a single multiplication. */ + if (uu.s.high >= 0) + { + if (vv.s.high >= 0) + { + if (uu.s.high == 0 && vv.s.high == 0) + { + const DWtype w = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low; + if (__builtin_expect (w >= 0, 1)) + return w; + } + } + else + { + if (uu.s.high == 0 && vv.s.high == (Wtype) -1) + { + DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low}; + + ww.s.high -= uu.s.low; + if (__builtin_expect (ww.s.high < 0, 1)) + return ww.ll; + } + } + } + else + { + if (vv.s.high >= 0) + { + if (uu.s.high == (Wtype) -1 && vv.s.high == 0) + { + DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low}; + + ww.s.high -= vv.s.low; + if (__builtin_expect (ww.s.high < 0, 1)) + return ww.ll; + } + } + else + { + if (uu.s.high == (Wtype) -1 && vv.s.high == (Wtype) - 1) + { + DWunion ww = {.ll = (UDWtype) (UWtype) uu.s.low + * (UDWtype) (UWtype) vv.s.low}; + + ww.s.high -= uu.s.low; + ww.s.high -= vv.s.low; + if (__builtin_expect (ww.s.high >= 0, 1)) + return ww.ll; + } + } + } + } + } + + /* Overflow. */ + abort (); +} +#endif + + +/* Unless shift functions are defined with full ANSI prototypes, + parameter b will be promoted to int if shift_count_type is smaller than an int. */ +#ifdef L_lshrdi3 +DWtype +__lshrdi3 (DWtype u, shift_count_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const shift_count_type bm = W_TYPE_SIZE - b; + DWunion w; + + if (bm <= 0) + { + w.s.high = 0; + w.s.low = (UWtype) uu.s.high >> -bm; + } + else + { + const UWtype carries = (UWtype) uu.s.high << bm; + + w.s.high = (UWtype) uu.s.high >> b; + w.s.low = ((UWtype) uu.s.low >> b) | carries; + } + + return w.ll; +} +#endif + +#ifdef L_ashldi3 +DWtype +__ashldi3 (DWtype u, shift_count_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const shift_count_type bm = W_TYPE_SIZE - b; + DWunion w; + + if (bm <= 0) + { + w.s.low = 0; + w.s.high = (UWtype) uu.s.low << -bm; + } + else + { + const UWtype carries = (UWtype) uu.s.low >> bm; + + w.s.low = (UWtype) uu.s.low << b; + w.s.high = ((UWtype) uu.s.high << b) | carries; + } + + return w.ll; +} +#endif + +#ifdef L_ashrdi3 +DWtype +__ashrdi3 (DWtype u, shift_count_type b) +{ + if (b == 0) + return u; + + const DWunion uu = {.ll = u}; + const shift_count_type bm = W_TYPE_SIZE - b; + DWunion w; + + if (bm <= 0) + { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = uu.s.high >> (W_TYPE_SIZE - 1); + w.s.low = uu.s.high >> -bm; + } + else + { + const UWtype carries = (UWtype) uu.s.high << bm; + + w.s.high = uu.s.high >> b; + w.s.low = ((UWtype) uu.s.low >> b) | carries; + } + + return w.ll; +} +#endif + +#ifdef L_bswapsi2 +SItype +__bswapsi2 (SItype u) +{ + return ((((u) & 0xff000000) >> 24) + | (((u) & 0x00ff0000) >> 8) + | (((u) & 0x0000ff00) << 8) + | (((u) & 0x000000ff) << 24)); +} +#endif +#ifdef L_bswapdi2 +DItype +__bswapdi2 (DItype u) +{ + return ((((u) & 0xff00000000000000ull) >> 56) + | (((u) & 0x00ff000000000000ull) >> 40) + | (((u) & 0x0000ff0000000000ull) >> 24) + | (((u) & 0x000000ff00000000ull) >> 8) + | (((u) & 0x00000000ff000000ull) << 8) + | (((u) & 0x0000000000ff0000ull) << 24) + | (((u) & 0x000000000000ff00ull) << 40) + | (((u) & 0x00000000000000ffull) << 56)); +} +#endif +#ifdef L_ffssi2 +#undef int +int +__ffsSI2 (UWtype u) +{ + UWtype count; + + if (u == 0) + return 0; + + count_trailing_zeros (count, u); + return count + 1; +} +#endif + +#ifdef L_ffsdi2 +#undef int +int +__ffsDI2 (DWtype u) +{ + const DWunion uu = {.ll = u}; + UWtype word, count, add; + + if (uu.s.low != 0) + word = uu.s.low, add = 0; + else if (uu.s.high != 0) + word = uu.s.high, add = W_TYPE_SIZE; + else + return 0; + + count_trailing_zeros (count, word); + return count + add + 1; +} +#endif + +#ifdef L_muldi3 +DWtype +__muldi3 (DWtype u, DWtype v) +{ + const DWunion uu = {.ll = u}; + const DWunion vv = {.ll = v}; + DWunion w = {.ll = __umulsidi3 (uu.s.low, vv.s.low)}; + + w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high + + (UWtype) uu.s.high * (UWtype) vv.s.low); + + return w.ll; +} +#endif + +#if (defined (L_udivdi3) || defined (L_divdi3) || \ + defined (L_umoddi3) || defined (L_moddi3)) +#if defined (sdiv_qrnnd) +#define L_udiv_w_sdiv +#endif +#endif + +#ifdef L_udiv_w_sdiv +#if defined (sdiv_qrnnd) +#if (defined (L_udivdi3) || defined (L_divdi3) || \ + defined (L_umoddi3) || defined (L_moddi3)) +static inline __attribute__ ((__always_inline__)) +#endif +UWtype +__udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d) +{ + UWtype q, r; + UWtype c0, c1, b1; + + if ((Wtype) d >= 0) + { + if (a1 < d - a1 - (a0 >> (W_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 << (W_TYPE_SIZE - 1)); + /* Divide (c1*2^32 + c0) by d. */ + sdiv_qrnnd (q, r, c1, c0, d); + /* Add 2^31 to quotient. */ + q += (UWtype) 1 << (W_TYPE_SIZE - 1); + } + } + else + { + b1 = d >> 1; /* d/2, between 2^30 and 2^31 - 1 */ + c1 = a1 >> 1; /* A/2 */ + c0 = (a1 << (W_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; +} +#else +/* If sdiv_qrnnd doesn't exist, define dummy __udiv_w_sdiv. */ +UWtype +__udiv_w_sdiv (UWtype *rp __attribute__ ((__unused__)), + UWtype a1 __attribute__ ((__unused__)), + UWtype a0 __attribute__ ((__unused__)), + UWtype 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_clz +const UQItype __clz_tab[256] = +{ + 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 +}; +#endif + +#ifdef L_clzsi2 +#undef int +int +__clzSI2 (UWtype x) +{ + Wtype ret; + + count_leading_zeros (ret, x); + + return ret; +} +#endif + +#ifdef L_clzdi2 +#undef int +int +__clzDI2 (UDWtype x) +{ + const DWunion uu = {.ll = x}; + UWtype word; + Wtype ret, add; + + if (uu.s.high) + word = uu.s.high, add = 0; + else + word = uu.s.low, add = W_TYPE_SIZE; + + count_leading_zeros (ret, word); + return ret + add; +} +#endif + +#ifdef L_ctzsi2 +#undef int +int +__ctzSI2 (UWtype x) +{ + Wtype ret; + + count_trailing_zeros (ret, x); + + return ret; +} +#endif + +#ifdef L_ctzdi2 +#undef int +int +__ctzDI2 (UDWtype x) +{ + const DWunion uu = {.ll = x}; + UWtype word; + Wtype ret, add; + + if (uu.s.low) + word = uu.s.low, add = 0; + else + word = uu.s.high, add = W_TYPE_SIZE; + + count_trailing_zeros (ret, word); + return ret + add; +} +#endif + +#ifdef L_clrsbsi2 +#undef int +int +__clrsbSI2 (Wtype x) +{ + Wtype ret; + + if (x < 0) + x = ~x; + if (x == 0) + return W_TYPE_SIZE - 1; + count_leading_zeros (ret, x); + return ret - 1; +} +#endif + +#ifdef L_clrsbdi2 +#undef int +int +__clrsbDI2 (DWtype x) +{ + const DWunion uu = {.ll = x}; + UWtype word; + Wtype ret, add; + + if (uu.s.high == 0) + word = uu.s.low, add = W_TYPE_SIZE; + else if (uu.s.high == -1) + word = ~uu.s.low, add = W_TYPE_SIZE; + else if (uu.s.high >= 0) + word = uu.s.high, add = 0; + else + word = ~uu.s.high, add = 0; + + if (word == 0) + ret = W_TYPE_SIZE; + else + count_leading_zeros (ret, word); + + return ret + add - 1; +} +#endif + +#ifdef L_popcount_tab +const UQItype __popcount_tab[256] = +{ + 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, + 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 +}; +#endif + +#ifdef L_popcountsi2 +#undef int +int +__popcountSI2 (UWtype x) +{ + int i, ret = 0; + + for (i = 0; i < W_TYPE_SIZE; i += 8) + ret += __popcount_tab[(x >> i) & 0xff]; + + return ret; +} +#endif + +#ifdef L_popcountdi2 +#undef int +int +__popcountDI2 (UDWtype x) +{ + int i, ret = 0; + + for (i = 0; i < 2*W_TYPE_SIZE; i += 8) + ret += __popcount_tab[(x >> i) & 0xff]; + + return ret; +} +#endif + +#ifdef L_paritysi2 +#undef int +int +__paritySI2 (UWtype x) +{ +#if W_TYPE_SIZE > 64 +# error "fill out the table" +#endif +#if W_TYPE_SIZE > 32 + x ^= x >> 32; +#endif +#if W_TYPE_SIZE > 16 + x ^= x >> 16; +#endif + x ^= x >> 8; + x ^= x >> 4; + x &= 0xf; + return (0x6996 >> x) & 1; +} +#endif + +#ifdef L_paritydi2 +#undef int +int +__parityDI2 (UDWtype x) +{ + const DWunion uu = {.ll = x}; + UWtype nx = uu.s.low ^ uu.s.high; + +#if W_TYPE_SIZE > 64 +# error "fill out the table" +#endif +#if W_TYPE_SIZE > 32 + nx ^= nx >> 32; +#endif +#if W_TYPE_SIZE > 16 + nx ^= nx >> 16; +#endif + nx ^= nx >> 8; + nx ^= nx >> 4; + nx &= 0xf; + return (0x6996 >> nx) & 1; +} +#endif + +#ifdef L_udivmoddi4 + +#if (defined (L_udivdi3) || defined (L_divdi3) || \ + defined (L_umoddi3) || defined (L_moddi3)) +static inline __attribute__ ((__always_inline__)) +#endif +UDWtype +__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) +{ + const DWunion nn = {.ll = n}; + const DWunion dd = {.ll = d}; + DWunion rr; + UWtype d0, d1, n0, n1, n2; + UWtype q0, q1; + UWtype b, bm; + + 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 >> (W_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 W_TYPE_SIZE are undefined.) */ + + n1 -= d0; + q1 = 1; + } + else + { + /* Normalize. */ + + b = W_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 + { + UWtype m1, m0; + /* Normalize. */ + + b = W_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; + } + } + } + } + + const DWunion ww = {{.low = q0, .high = q1}}; + return ww.ll; +} +#endif + +#ifdef L_divdi3 +DWtype +__divdi3 (DWtype u, DWtype v) +{ + Wtype c = 0; + DWunion uu = {.ll = u}; + DWunion vv = {.ll = v}; + DWtype w; + + if (uu.s.high < 0) + c = ~c, + uu.ll = -uu.ll; + if (vv.s.high < 0) + c = ~c, + vv.ll = -vv.ll; + + w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0); + if (c) + w = -w; + + return w; +} +#endif + +#ifdef L_moddi3 +DWtype +__moddi3 (DWtype u, DWtype v) +{ + Wtype c = 0; + DWunion uu = {.ll = u}; + DWunion vv = {.ll = v}; + DWtype w; + + if (uu.s.high < 0) + c = ~c, + uu.ll = -uu.ll; + if (vv.s.high < 0) + vv.ll = -vv.ll; + + (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w); + if (c) + w = -w; + + return w; +} +#endif + +#ifdef L_umoddi3 +UDWtype +__umoddi3 (UDWtype u, UDWtype v) +{ + UDWtype w; + + (void) __udivmoddi4 (u, v, &w); + + return w; +} +#endif + +#ifdef L_udivdi3 +UDWtype +__udivdi3 (UDWtype n, UDWtype d) +{ + return __udivmoddi4 (n, d, (UDWtype *) 0); +} +#endif + +#ifdef L_cmpdi2 +cmp_return_type +__cmpdi2 (DWtype a, DWtype b) +{ + const DWunion au = {.ll = a}; + const DWunion bu = {.ll = b}; + + if (au.s.high < bu.s.high) + return 0; + else if (au.s.high > bu.s.high) + return 2; + if ((UWtype) au.s.low < (UWtype) bu.s.low) + return 0; + else if ((UWtype) au.s.low > (UWtype) bu.s.low) + return 2; + return 1; +} +#endif + +#ifdef L_ucmpdi2 +cmp_return_type +__ucmpdi2 (DWtype a, DWtype b) +{ + const DWunion au = {.ll = a}; + const DWunion bu = {.ll = b}; + + if ((UWtype) au.s.high < (UWtype) bu.s.high) + return 0; + else if ((UWtype) au.s.high > (UWtype) bu.s.high) + return 2; + if ((UWtype) au.s.low < (UWtype) bu.s.low) + return 0; + else if ((UWtype) au.s.low > (UWtype) bu.s.low) + return 2; + return 1; +} +#endif + +#if defined(L_fixunstfdi) && LIBGCC2_HAS_TF_MODE +UDWtype +__fixunstfDI (TFtype a) +{ + if (a < 0) + return 0; + + /* Compute high word of result, as a flonum. */ + const TFtype b = (a / Wtype_MAXp1_F); + /* Convert that to fixed (but not to DWtype!), + and shift it into the high word. */ + UDWtype v = (UWtype) b; + v <<= W_TYPE_SIZE; + /* Remove high part from the TFtype, leaving the low part as flonum. */ + a -= (TFtype)v; + /* Convert that to fixed (but not to DWtype!) 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 -= (UWtype) (- a); + else + v += (UWtype) a; + return v; +} +#endif + +#if defined(L_fixtfdi) && LIBGCC2_HAS_TF_MODE +DWtype +__fixtfdi (TFtype a) +{ + if (a < 0) + return - __fixunstfDI (-a); + return __fixunstfDI (a); +} +#endif + +#if defined(L_fixunsxfdi) && LIBGCC2_HAS_XF_MODE +UDWtype +__fixunsxfDI (XFtype a) +{ + if (a < 0) + return 0; + + /* Compute high word of result, as a flonum. */ + const XFtype b = (a / Wtype_MAXp1_F); + /* Convert that to fixed (but not to DWtype!), + and shift it into the high word. */ + UDWtype v = (UWtype) b; + v <<= W_TYPE_SIZE; + /* Remove high part from the XFtype, leaving the low part as flonum. */ + a -= (XFtype)v; + /* Convert that to fixed (but not to DWtype!) 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 -= (UWtype) (- a); + else + v += (UWtype) a; + return v; +} +#endif + +#if defined(L_fixxfdi) && LIBGCC2_HAS_XF_MODE +DWtype +__fixxfdi (XFtype a) +{ + if (a < 0) + return - __fixunsxfDI (-a); + return __fixunsxfDI (a); +} +#endif + +#if defined(L_fixunsdfdi) && LIBGCC2_HAS_DF_MODE +UDWtype +__fixunsdfDI (DFtype a) +{ + /* Get high part of result. The division here will just moves the radix + point and will not cause any rounding. Then the conversion to integral + type chops result as desired. */ + const UWtype hi = a / Wtype_MAXp1_F; + + /* Get low part of result. Convert `hi' to floating type and scale it back, + then subtract this from the number being converted. This leaves the low + part. Convert that to integral type. */ + const UWtype lo = a - (DFtype) hi * Wtype_MAXp1_F; + + /* Assemble result from the two parts. */ + return ((UDWtype) hi << W_TYPE_SIZE) | lo; +} +#endif + +#if defined(L_fixdfdi) && LIBGCC2_HAS_DF_MODE +DWtype +__fixdfdi (DFtype a) +{ + if (a < 0) + return - __fixunsdfDI (-a); + return __fixunsdfDI (a); +} +#endif + +#if defined(L_fixunssfdi) && LIBGCC2_HAS_SF_MODE +UDWtype +__fixunssfDI (SFtype a) +{ +#if LIBGCC2_HAS_DF_MODE + /* 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. */ + const DFtype dfa = a; + + /* Get high part of result. The division here will just moves the radix + point and will not cause any rounding. Then the conversion to integral + type chops result as desired. */ + const UWtype hi = dfa / Wtype_MAXp1_F; + + /* Get low part of result. Convert `hi' to floating type and scale it back, + then subtract this from the number being converted. This leaves the low + part. Convert that to integral type. */ + const UWtype lo = dfa - (DFtype) hi * Wtype_MAXp1_F; + + /* Assemble result from the two parts. */ + return ((UDWtype) hi << W_TYPE_SIZE) | lo; +#elif FLT_MANT_DIG < W_TYPE_SIZE + if (a < 1) + return 0; + if (a < Wtype_MAXp1_F) + return (UWtype)a; + if (a < Wtype_MAXp1_F * Wtype_MAXp1_F) + { + /* Since we know that there are fewer significant bits in the SFmode + quantity than in a word, we know that we can convert out all the + significant bits in one step, and thus avoid losing bits. */ + + /* ??? This following loop essentially performs frexpf. If we could + use the real libm function, or poke at the actual bits of the fp + format, it would be significantly faster. */ + + UWtype shift = 0, counter; + SFtype msb; + + a /= Wtype_MAXp1_F; + for (counter = W_TYPE_SIZE / 2; counter != 0; counter >>= 1) + { + SFtype counterf = (UWtype)1 << counter; + if (a >= counterf) + { + shift |= counter; + a /= counterf; + } + } + + /* Rescale into the range of one word, extract the bits of that + one word, and shift the result into position. */ + a *= Wtype_MAXp1_F; + counter = a; + return (DWtype)counter << shift; + } + return -1; +#else +# error +#endif +} +#endif + +#if defined(L_fixsfdi) && LIBGCC2_HAS_SF_MODE +DWtype +__fixsfdi (SFtype a) +{ + if (a < 0) + return - __fixunssfDI (-a); + return __fixunssfDI (a); +} +#endif + +#if defined(L_floatdixf) && LIBGCC2_HAS_XF_MODE +XFtype +__floatdixf (DWtype u) +{ +#if W_TYPE_SIZE > XF_SIZE +# error +#endif + XFtype d = (Wtype) (u >> W_TYPE_SIZE); + d *= Wtype_MAXp1_F; + d += (UWtype)u; + return d; +} +#endif + +#if defined(L_floatundixf) && LIBGCC2_HAS_XF_MODE +XFtype +__floatundixf (UDWtype u) +{ +#if W_TYPE_SIZE > XF_SIZE +# error +#endif + XFtype d = (UWtype) (u >> W_TYPE_SIZE); + d *= Wtype_MAXp1_F; + d += (UWtype)u; + return d; +} +#endif + +#if defined(L_floatditf) && LIBGCC2_HAS_TF_MODE +TFtype +__floatditf (DWtype u) +{ +#if W_TYPE_SIZE > TF_SIZE +# error +#endif + TFtype d = (Wtype) (u >> W_TYPE_SIZE); + d *= Wtype_MAXp1_F; + d += (UWtype)u; + return d; +} +#endif + +#if defined(L_floatunditf) && LIBGCC2_HAS_TF_MODE +TFtype +__floatunditf (UDWtype u) +{ +#if W_TYPE_SIZE > TF_SIZE +# error +#endif + TFtype d = (UWtype) (u >> W_TYPE_SIZE); + d *= Wtype_MAXp1_F; + d += (UWtype)u; + return d; +} +#endif + +#if (defined(L_floatdisf) && LIBGCC2_HAS_SF_MODE) \ + || (defined(L_floatdidf) && LIBGCC2_HAS_DF_MODE) +#define DI_SIZE (W_TYPE_SIZE * 2) +#define F_MODE_OK(SIZE) \ + (SIZE < DI_SIZE \ + && SIZE > (DI_SIZE - SIZE + FSSIZE) \ + && !AVOID_FP_TYPE_CONVERSION(SIZE)) +#if defined(L_floatdisf) +#define FUNC __floatdisf +#define FSTYPE SFtype +#define FSSIZE SF_SIZE +#else +#define FUNC __floatdidf +#define FSTYPE DFtype +#define FSSIZE DF_SIZE +#endif + +FSTYPE +FUNC (DWtype u) +{ +#if FSSIZE >= W_TYPE_SIZE + /* When the word size is small, we never get any rounding error. */ + FSTYPE f = (Wtype) (u >> W_TYPE_SIZE); + f *= Wtype_MAXp1_F; + f += (UWtype)u; + return f; +#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \ + || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \ + || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) + +#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) +# define FSIZE DF_SIZE +# define FTYPE DFtype +#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) +# define FSIZE XF_SIZE +# define FTYPE XFtype +#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) +# define FSIZE TF_SIZE +# define FTYPE TFtype +#else +# error +#endif + +#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE)) + + /* Protect against double-rounding error. + Represent any low-order bits, that might be truncated by a bit that + won't be lost. The bit can go in anywhere below the rounding position + of the FSTYPE. A fixed mask and bit position handles all usual + configurations. */ + if (! (- ((DWtype) 1 << FSIZE) < u + && u < ((DWtype) 1 << FSIZE))) + { + if ((UDWtype) u & (REP_BIT - 1)) + { + u &= ~ (REP_BIT - 1); + u |= REP_BIT; + } + } + + /* Do the calculation in a wider type so that we don't lose any of + the precision of the high word while multiplying it. */ + FTYPE f = (Wtype) (u >> W_TYPE_SIZE); + f *= Wtype_MAXp1_F; + f += (UWtype)u; + return (FSTYPE) f; +#else +#if FSSIZE >= W_TYPE_SIZE - 2 +# error +#endif + /* Finally, the word size is larger than the number of bits in the + required FSTYPE, and we've got no suitable wider type. The only + way to avoid double rounding is to special case the + extraction. */ + + /* If there are no high bits set, fall back to one conversion. */ + if ((Wtype)u == u) + return (FSTYPE)(Wtype)u; + + /* Otherwise, find the power of two. */ + Wtype hi = u >> W_TYPE_SIZE; + if (hi < 0) + hi = -hi; + + UWtype count, shift; + count_leading_zeros (count, hi); + + /* No leading bits means u == minimum. */ + if (count == 0) + return -(Wtype_MAXp1_F * (Wtype_MAXp1_F / 2)); + + shift = 1 + W_TYPE_SIZE - count; + + /* Shift down the most significant bits. */ + hi = u >> shift; + + /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */ + if ((UWtype)u << (W_TYPE_SIZE - shift)) + hi |= 1; + + /* Convert the one word of data, and rescale. */ + FSTYPE f = hi, e; + if (shift == W_TYPE_SIZE) + e = Wtype_MAXp1_F; + /* The following two cases could be merged if we knew that the target + supported a native unsigned->float conversion. More often, we only + have a signed conversion, and have to add extra fixup code. */ + else if (shift == W_TYPE_SIZE - 1) + e = Wtype_MAXp1_F / 2; + else + e = (Wtype)1 << shift; + return f * e; +#endif +} +#endif + +#if (defined(L_floatundisf) && LIBGCC2_HAS_SF_MODE) \ + || (defined(L_floatundidf) && LIBGCC2_HAS_DF_MODE) +#define DI_SIZE (W_TYPE_SIZE * 2) +#define F_MODE_OK(SIZE) \ + (SIZE < DI_SIZE \ + && SIZE > (DI_SIZE - SIZE + FSSIZE) \ + && !AVOID_FP_TYPE_CONVERSION(SIZE)) +#if defined(L_floatundisf) +#define FUNC __floatundisf +#define FSTYPE SFtype +#define FSSIZE SF_SIZE +#else +#define FUNC __floatundidf +#define FSTYPE DFtype +#define FSSIZE DF_SIZE +#endif + +FSTYPE +FUNC (UDWtype u) +{ +#if FSSIZE >= W_TYPE_SIZE + /* When the word size is small, we never get any rounding error. */ + FSTYPE f = (UWtype) (u >> W_TYPE_SIZE); + f *= Wtype_MAXp1_F; + f += (UWtype)u; + return f; +#elif (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) \ + || (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) \ + || (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) + +#if (LIBGCC2_HAS_DF_MODE && F_MODE_OK (DF_SIZE)) +# define FSIZE DF_SIZE +# define FTYPE DFtype +#elif (LIBGCC2_HAS_XF_MODE && F_MODE_OK (XF_SIZE)) +# define FSIZE XF_SIZE +# define FTYPE XFtype +#elif (LIBGCC2_HAS_TF_MODE && F_MODE_OK (TF_SIZE)) +# define FSIZE TF_SIZE +# define FTYPE TFtype +#else +# error +#endif + +#define REP_BIT ((UDWtype) 1 << (DI_SIZE - FSIZE)) + + /* Protect against double-rounding error. + Represent any low-order bits, that might be truncated by a bit that + won't be lost. The bit can go in anywhere below the rounding position + of the FSTYPE. A fixed mask and bit position handles all usual + configurations. */ + if (u >= ((UDWtype) 1 << FSIZE)) + { + if ((UDWtype) u & (REP_BIT - 1)) + { + u &= ~ (REP_BIT - 1); + u |= REP_BIT; + } + } + + /* Do the calculation in a wider type so that we don't lose any of + the precision of the high word while multiplying it. */ + FTYPE f = (UWtype) (u >> W_TYPE_SIZE); + f *= Wtype_MAXp1_F; + f += (UWtype)u; + return (FSTYPE) f; +#else +#if FSSIZE == W_TYPE_SIZE - 1 +# error +#endif + /* Finally, the word size is larger than the number of bits in the + required FSTYPE, and we've got no suitable wider type. The only + way to avoid double rounding is to special case the + extraction. */ + + /* If there are no high bits set, fall back to one conversion. */ + if ((UWtype)u == u) + return (FSTYPE)(UWtype)u; + + /* Otherwise, find the power of two. */ + UWtype hi = u >> W_TYPE_SIZE; + + UWtype count, shift; + count_leading_zeros (count, hi); + + shift = W_TYPE_SIZE - count; + + /* Shift down the most significant bits. */ + hi = u >> shift; + + /* If we lost any nonzero bits, set the lsb to ensure correct rounding. */ + if ((UWtype)u << (W_TYPE_SIZE - shift)) + hi |= 1; + + /* Convert the one word of data, and rescale. */ + FSTYPE f = hi, e; + if (shift == W_TYPE_SIZE) + e = Wtype_MAXp1_F; + /* The following two cases could be merged if we knew that the target + supported a native unsigned->float conversion. More often, we only + have a signed conversion, and have to add extra fixup code. */ + else if (shift == W_TYPE_SIZE - 1) + e = Wtype_MAXp1_F / 2; + else + e = (Wtype)1 << shift; + return f * e; +#endif +} +#endif + +#if defined(L_fixunsxfsi) && LIBGCC2_HAS_XF_MODE +/* Reenable the normal types, in case limits.h needs them. */ +#undef char +#undef short +#undef int +#undef long +#undef unsigned +#undef float +#undef double +#undef MIN +#undef MAX +#include + +UWtype +__fixunsxfSI (XFtype a) +{ + if (a >= - (DFtype) Wtype_MIN) + return (Wtype) (a + Wtype_MIN) - Wtype_MIN; + return (Wtype) a; +} +#endif + +#if defined(L_fixunsdfsi) && LIBGCC2_HAS_DF_MODE +/* Reenable the normal types, in case limits.h needs them. */ +#undef char +#undef short +#undef int +#undef long +#undef unsigned +#undef float +#undef double +#undef MIN +#undef MAX +#include + +UWtype +__fixunsdfSI (DFtype a) +{ + if (a >= - (DFtype) Wtype_MIN) + return (Wtype) (a + Wtype_MIN) - Wtype_MIN; + return (Wtype) a; +} +#endif + +#if defined(L_fixunssfsi) && LIBGCC2_HAS_SF_MODE +/* Reenable the normal types, in case limits.h needs them. */ +#undef char +#undef short +#undef int +#undef long +#undef unsigned +#undef float +#undef double +#undef MIN +#undef MAX +#include + +UWtype +__fixunssfSI (SFtype a) +{ + if (a >= - (SFtype) Wtype_MIN) + return (Wtype) (a + Wtype_MIN) - Wtype_MIN; + return (Wtype) a; +} +#endif + +/* Integer power helper used from __builtin_powi for non-constant + exponents. */ + +#if (defined(L_powisf2) && LIBGCC2_HAS_SF_MODE) \ + || (defined(L_powidf2) && LIBGCC2_HAS_DF_MODE) \ + || (defined(L_powixf2) && LIBGCC2_HAS_XF_MODE) \ + || (defined(L_powitf2) && LIBGCC2_HAS_TF_MODE) +# if defined(L_powisf2) +# define TYPE SFtype +# define NAME __powisf2 +# elif defined(L_powidf2) +# define TYPE DFtype +# define NAME __powidf2 +# elif defined(L_powixf2) +# define TYPE XFtype +# define NAME __powixf2 +# elif defined(L_powitf2) +# define TYPE TFtype +# define NAME __powitf2 +# endif + +#undef int +#undef unsigned +TYPE +NAME (TYPE x, int m) +{ + unsigned int n = m < 0 ? -m : m; + TYPE y = n % 2 ? x : 1; + while (n >>= 1) + { + x = x * x; + if (n % 2) + y = y * x; + } + return m < 0 ? 1/y : y; +} + +#endif + +#if ((defined(L_mulsc3) || defined(L_divsc3)) && LIBGCC2_HAS_SF_MODE) \ + || ((defined(L_muldc3) || defined(L_divdc3)) && LIBGCC2_HAS_DF_MODE) \ + || ((defined(L_mulxc3) || defined(L_divxc3)) && LIBGCC2_HAS_XF_MODE) \ + || ((defined(L_multc3) || defined(L_divtc3)) && LIBGCC2_HAS_TF_MODE) + +#undef float +#undef double +#undef long + +#if defined(L_mulsc3) || defined(L_divsc3) +# define MTYPE SFtype +# define CTYPE SCtype +# define MODE sc +# define CEXT f +# define NOTRUNC __FLT_EVAL_METHOD__ == 0 +#elif defined(L_muldc3) || defined(L_divdc3) +# define MTYPE DFtype +# define CTYPE DCtype +# define MODE dc +# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64 +# define CEXT l +# define NOTRUNC 1 +# else +# define CEXT +# define NOTRUNC __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1 +# endif +#elif defined(L_mulxc3) || defined(L_divxc3) +# define MTYPE XFtype +# define CTYPE XCtype +# define MODE xc +# define CEXT l +# define NOTRUNC 1 +#elif defined(L_multc3) || defined(L_divtc3) +# define MTYPE TFtype +# define CTYPE TCtype +# define MODE tc +# if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 +# define CEXT l +# else +# define CEXT LIBGCC2_TF_CEXT +# endif +# define NOTRUNC 1 +#else +# error +#endif + +#define CONCAT3(A,B,C) _CONCAT3(A,B,C) +#define _CONCAT3(A,B,C) A##B##C + +#define CONCAT2(A,B) _CONCAT2(A,B) +#define _CONCAT2(A,B) A##B + +/* All of these would be present in a full C99 implementation of + and . Our problem is that only a few systems have such full + implementations. Further, libgcc_s.so isn't currently linked against + libm.so, and even for systems that do provide full C99, the extra overhead + of all programs using libgcc having to link against libm. So avoid it. */ + +#define isnan(x) __builtin_expect ((x) != (x), 0) +#define isfinite(x) __builtin_expect (!isnan((x) - (x)), 1) +#define isinf(x) __builtin_expect (!isnan(x) & !isfinite(x), 0) + +#define INFINITY CONCAT2(__builtin_huge_val, CEXT) () +#define I 1i + +/* Helpers to make the following code slightly less gross. */ +#define COPYSIGN CONCAT2(__builtin_copysign, CEXT) +#define FABS CONCAT2(__builtin_fabs, CEXT) + +/* Verify that MTYPE matches up with CEXT. */ +extern void *compile_type_assert[sizeof(INFINITY) == sizeof(MTYPE) ? 1 : -1]; + +/* Ensure that we've lost any extra precision. */ +#if NOTRUNC +# define TRUNC(x) +#else +# define TRUNC(x) __asm__ ("" : "=m"(x) : "m"(x)) +#endif + +#if defined(L_mulsc3) || defined(L_muldc3) \ + || defined(L_mulxc3) || defined(L_multc3) + +CTYPE +CONCAT3(__mul,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d) +{ + MTYPE ac, bd, ad, bc, x, y; + CTYPE res; + + ac = a * c; + bd = b * d; + ad = a * d; + bc = b * c; + + TRUNC (ac); + TRUNC (bd); + TRUNC (ad); + TRUNC (bc); + + x = ac - bd; + y = ad + bc; + + if (isnan (x) && isnan (y)) + { + /* Recover infinities that computed as NaN + iNaN. */ + _Bool recalc = 0; + if (isinf (a) || isinf (b)) + { + /* z is infinite. "Box" the infinity and change NaNs in + the other factor to 0. */ + a = COPYSIGN (isinf (a) ? 1 : 0, a); + b = COPYSIGN (isinf (b) ? 1 : 0, b); + if (isnan (c)) c = COPYSIGN (0, c); + if (isnan (d)) d = COPYSIGN (0, d); + recalc = 1; + } + if (isinf (c) || isinf (d)) + { + /* w is infinite. "Box" the infinity and change NaNs in + the other factor to 0. */ + c = COPYSIGN (isinf (c) ? 1 : 0, c); + d = COPYSIGN (isinf (d) ? 1 : 0, d); + if (isnan (a)) a = COPYSIGN (0, a); + if (isnan (b)) b = COPYSIGN (0, b); + recalc = 1; + } + if (!recalc + && (isinf (ac) || isinf (bd) + || isinf (ad) || isinf (bc))) + { + /* Recover infinities from overflow by changing NaNs to 0. */ + if (isnan (a)) a = COPYSIGN (0, a); + if (isnan (b)) b = COPYSIGN (0, b); + if (isnan (c)) c = COPYSIGN (0, c); + if (isnan (d)) d = COPYSIGN (0, d); + recalc = 1; + } + if (recalc) + { + x = INFINITY * (a * c - b * d); + y = INFINITY * (a * d + b * c); + } + } + + __real__ res = x; + __imag__ res = y; + return res; +} +#endif /* complex multiply */ + +#if defined(L_divsc3) || defined(L_divdc3) \ + || defined(L_divxc3) || defined(L_divtc3) + +CTYPE +CONCAT3(__div,MODE,3) (MTYPE a, MTYPE b, MTYPE c, MTYPE d) +{ + MTYPE denom, ratio, x, y; + CTYPE res; + + /* ??? We can get better behavior from logarithmic scaling instead of + the division. But that would mean starting to link libgcc against + libm. We could implement something akin to ldexp/frexp as gcc builtins + fairly easily... */ + if (FABS (c) < FABS (d)) + { + ratio = c / d; + denom = (c * ratio) + d; + x = ((a * ratio) + b) / denom; + y = ((b * ratio) - a) / denom; + } + else + { + ratio = d / c; + denom = (d * ratio) + c; + x = ((b * ratio) + a) / denom; + y = (b - (a * ratio)) / denom; + } + + /* Recover infinities and zeros that computed as NaN+iNaN; the only cases + are nonzero/zero, infinite/finite, and finite/infinite. */ + if (isnan (x) && isnan (y)) + { + if (c == 0.0 && d == 0.0 && (!isnan (a) || !isnan (b))) + { + x = COPYSIGN (INFINITY, c) * a; + y = COPYSIGN (INFINITY, c) * b; + } + else if ((isinf (a) || isinf (b)) && isfinite (c) && isfinite (d)) + { + a = COPYSIGN (isinf (a) ? 1 : 0, a); + b = COPYSIGN (isinf (b) ? 1 : 0, b); + x = INFINITY * (a * c + b * d); + y = INFINITY * (b * c - a * d); + } + else if ((isinf (c) || isinf (d)) && isfinite (a) && isfinite (b)) + { + c = COPYSIGN (isinf (c) ? 1 : 0, c); + d = COPYSIGN (isinf (d) ? 1 : 0, d); + x = 0.0 * (a * c + b * d); + y = 0.0 * (b * c - a * d); + } + } + + __real__ res = x; + __imag__ res = y; + return res; +} +#endif /* complex divide */ + +#endif /* all complex float routines */ + +/* 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 Wtype +#undef UWtype +#undef HWtype +#undef UHWtype +#undef DWtype +#undef UDWtype + +#undef char +#undef short +#undef int +#undef long +#undef unsigned +#undef float +#undef double + +#ifdef L__gcc_bcmp + +/* Like bcmp except the sign is meaningful. + Result is negative if S1 is less than S2, + positive if S1 is greater, 0 if S1 and S2 are equal. */ + +int +__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, size_t size) +{ + while (size > 0) + { + const unsigned char c1 = *s1++, c2 = *s2++; + if (c1 != c2) + return c1 - c2; + size--; + } + return 0; +} + +#endif + +/* __eprintf used to be used by GCC's private version of . + We no longer provide that header, but this routine remains in libgcc.a + for binary backward compatibility. Note that it is not included in + the shared version of libgcc. */ +#ifdef L_eprintf +#ifndef inhibit_libc + +#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ +#include + +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_clear_cache +/* Clear part of an instruction cache. */ + +void +__clear_cache (char *beg __attribute__((__unused__)), + char *end __attribute__((__unused__))) +{ +#ifdef CLEAR_INSN_CACHE + CLEAR_INSN_CACHE (beg, end); +#endif /* CLEAR_INSN_CACHE */ +} + +#endif /* L_clear_cache */ + +#ifdef L_trampoline + +/* Jump to a trampoline, loading the static chain address. */ + +#if defined(WINNT) && ! defined(__CYGWIN__) +#include +int getpagesize (void); +int mprotect (char *,int, int); + +int +getpagesize (void) +{ +#ifdef _ALPHA_ + return 8192; +#else + return 4096; +#endif +} + +int +mprotect (char *addr, int len, int prot) +{ + DWORD 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; + else + return -1; + + if (VirtualProtect (addr, len, np, &op)) + return 0; + else + return -1; +} + +#endif /* WINNT && ! __CYGWIN__ */ + +#ifdef TRANSFER_FROM_TRAMPOLINE +TRANSFER_FROM_TRAMPOLINE +#endif +#endif /* L_trampoline */ + +#ifndef __CYGWIN__ +#ifdef L__main + +#include "gbl-ctors.h" + +/* Some systems use __main in a way incompatible with its use in gcc, in these + cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to + give the same symbol without quotes for an alternative entry point. You + must define both, or neither. */ +#ifndef NAME__MAIN +#define NAME__MAIN "__main" +#define SYMBOL__MAIN __main +#endif + +#if defined (INIT_SECTION_ASM_OP) || defined (INIT_ARRAY_SECTION_ASM_OP) +#undef HAS_INIT_SECTION +#define HAS_INIT_SECTION +#endif + +#if !defined (HAS_INIT_SECTION) || !defined (OBJECT_FORMAT_ELF) + +/* Some ELF crosses use crtstuff.c to provide __CTOR_LIST__, but use this + code to run constructors. In that case, we need to handle EH here, too. */ + +#ifdef EH_FRAME_SECTION_NAME +#include "unwind-dw2-fde.h" +extern unsigned char __EH_FRAME_BEGIN__[]; +#endif + +/* Run all the global destructors on exit from the program. */ + +void +__do_global_dtors (void) +{ +#ifdef DO_GLOBAL_DTORS_BODY + DO_GLOBAL_DTORS_BODY; +#else + static func_ptr *p = __DTOR_LIST__ + 1; + while (*p) + { + p++; + (*(p-1)) (); + } +#endif +#if defined (EH_FRAME_SECTION_NAME) && !defined (HAS_INIT_SECTION) + { + static int completed = 0; + if (! completed) + { + completed = 1; + __deregister_frame_info (__EH_FRAME_BEGIN__); + } + } +#endif +} +#endif + +#ifndef HAS_INIT_SECTION +/* Run all the global constructors on entry to the program. */ + +void +__do_global_ctors (void) +{ +#ifdef EH_FRAME_SECTION_NAME + { + static struct object object; + __register_frame_info (__EH_FRAME_BEGIN__, &object); + } +#endif + DO_GLOBAL_CTORS_BODY; + atexit (__do_global_dtors); +} +#endif /* no HAS_INIT_SECTION */ + +#if !defined (HAS_INIT_SECTION) || defined (INVOKE__main) +/* 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. */ + +extern void SYMBOL__MAIN (void); +void +SYMBOL__MAIN (void) +{ + /* Support recursive calls to `main': run initializers just once. */ + static int initialized; + if (! initialized) + { + initialized = 1; + __do_global_ctors (); + } +} +#endif /* no HAS_INIT_SECTION or INVOKE__main */ + +#endif /* L__main */ +#endif /* __CYGWIN__ */ + +#ifdef L_ctors + +#include "gbl-ctors.h" + +/* Provide default definitions for the lists of constructors and + destructors, so that we don't get linker errors. These symbols are + intentionally bss symbols, so that gld and/or collect will provide + the right values. */ + +/* We declare the lists here with two elements each, + so that they are valid empty lists if no other definition is loaded. + + If we are using the old "set" extensions to have the gnu linker + collect ctors and dtors, then we __CTOR_LIST__ and __DTOR_LIST__ + must be in the bss/common section. + + Long term no port should use those extensions. But many still do. */ +#if !defined(INIT_SECTION_ASM_OP) && !defined(CTOR_LISTS_DEFINED_EXTERNALLY) +#if defined (TARGET_ASM_CONSTRUCTOR) || defined (USE_COLLECT2) +func_ptr __CTOR_LIST__[2] = {0, 0}; +func_ptr __DTOR_LIST__[2] = {0, 0}; +#else +func_ptr __CTOR_LIST__[2]; +func_ptr __DTOR_LIST__[2]; +#endif +#endif /* no INIT_SECTION_ASM_OP and not CTOR_LISTS_DEFINED_EXTERNALLY */ +#endif /* L_ctors */ +#endif /* LIBGCC2_UNITS_PER_WORD <= MIN_UNITS_PER_WORD */ diff --git a/crt/libgcc2.h b/crt/libgcc2.h new file mode 100644 index 00000000..ee136d98 --- /dev/null +++ b/crt/libgcc2.h @@ -0,0 +1,529 @@ +/* Header file for libgcc2.c. */ +/* Copyright (C) 2000-2013 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC 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 3, or (at your option) any later +version. + +GCC 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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifndef GCC_LIBGCC2_H +#define GCC_LIBGCC2_H + +#ifndef HIDE_EXPORTS +#pragma GCC visibility push(default) +#endif + +extern int __gcc_bcmp (const unsigned char *, const unsigned char *, size_t); +extern void __clear_cache (char *, char *); +extern void __eprintf (const char *, const char *, unsigned int, const char *) + __attribute__ ((__noreturn__)); + +#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE +#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE +#endif + +#ifndef LIBGCC2_HAS_SF_MODE +#define LIBGCC2_HAS_SF_MODE (BITS_PER_UNIT == 8) +#endif + +#ifndef LIBGCC2_HAS_DF_MODE +#define LIBGCC2_HAS_DF_MODE \ + (BITS_PER_UNIT == 8 \ + && (__SIZEOF_DOUBLE__ * __CHAR_BIT__ == 64 \ + || LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64)) +#endif + +#ifndef LIBGCC2_HAS_XF_MODE +#define LIBGCC2_HAS_XF_MODE \ + (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) +#endif + +#ifndef LIBGCC2_HAS_TF_MODE +#define LIBGCC2_HAS_TF_MODE \ + (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128) +#endif + +#ifndef SF_SIZE +#if LIBGCC2_HAS_SF_MODE +#define SF_SIZE FLT_MANT_DIG +#else +#define SF_SIZE 0 +#endif +#endif + +#ifndef DF_SIZE +#if LIBGCC2_HAS_DF_MODE +#if __SIZEOF_DOUBLE__ * __CHAR_BIT__ == 64 +#define DF_SIZE DBL_MANT_DIG +#elif LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 64 +#define DF_SIZE LDBL_MANT_DIG +#else +#define DF_SIZE 0 +#endif +#else +#define DF_SIZE 0 +#endif +#endif + +#ifndef XF_SIZE +#if LIBGCC2_HAS_XF_MODE +#define XF_SIZE LDBL_MANT_DIG +#else +#define XF_SIZE 0 +#endif +#endif + +#ifndef TF_SIZE +#if LIBGCC2_HAS_TF_MODE +#define TF_SIZE LDBL_MANT_DIG +#else +#define TF_SIZE 0 +#endif +#endif + +/* FIXME: This #ifdef probably should be removed, ie. enable the test + for mips too. */ +/* Don't use IBM Extended Double TFmode for TI->SF calculations. + The conversion from long double to float suffers from double + rounding, because we convert via double. In other cases, going + through the software fp routines is much slower than the fallback. */ +#ifdef __powerpc__ +#define AVOID_FP_TYPE_CONVERSION(SIZE) (SIZE == 106) +#elif defined(WIDEST_HARDWARE_FP_SIZE) +#define AVOID_FP_TYPE_CONVERSION(SIZE) (SIZE > WIDEST_HARDWARE_FP_SIZE) +#else +#define AVOID_FP_TYPE_CONVERSION(SIZE) 0 +#endif + +/* 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 int QItype __attribute__ ((mode (QI))); +typedef unsigned int UQItype __attribute__ ((mode (QI))); +typedef int HItype __attribute__ ((mode (HI))); +typedef unsigned int UHItype __attribute__ ((mode (HI))); +#if MIN_UNITS_PER_WORD > 1 +/* These typedefs are usually forbidden on dsp's with UNITS_PER_WORD 1. */ +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +#if __SIZEOF_LONG_LONG__ > 4 +/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 2. */ +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +#if MIN_UNITS_PER_WORD > 4 +/* These typedefs are usually forbidden on archs with UNITS_PER_WORD 4. */ +typedef int TItype __attribute__ ((mode (TI))); +typedef unsigned int UTItype __attribute__ ((mode (TI))); +#endif +#endif +#endif + +#if LIBGCC2_HAS_SF_MODE +typedef float SFtype __attribute__ ((mode (SF))); +typedef _Complex float SCtype __attribute__ ((mode (SC))); +#endif +#if LIBGCC2_HAS_DF_MODE +typedef float DFtype __attribute__ ((mode (DF))); +typedef _Complex float DCtype __attribute__ ((mode (DC))); +#endif +#if LIBGCC2_HAS_XF_MODE +typedef float XFtype __attribute__ ((mode (XF))); +typedef _Complex float XCtype __attribute__ ((mode (XC))); +#endif +#if LIBGCC2_HAS_TF_MODE +typedef float TFtype __attribute__ ((mode (TF))); +typedef _Complex float TCtype __attribute__ ((mode (TC))); +#endif + +typedef int cmp_return_type __attribute__((mode (__libgcc_cmp_return__))); +typedef int shift_count_type __attribute__((mode (__libgcc_shift_count__))); + +/* 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 + +/* Versions prior to 3.4.4 were not taking into account the word size for + the 5 trapping arithmetic functions absv, addv, subv, mulv and negv. As + a consequence, the si and di variants were always and the only ones emitted. + To maintain backward compatibility, COMPAT_SIMODE_TRAPPING_ARITHMETIC is + defined on platforms where it makes sense to still have the si variants + emitted. As a bonus, their implementation is now correct. Note that the + same mechanism should have been implemented for the di variants, but it + turns out that no platform would define COMPAT_DIMODE_TRAPPING_ARITHMETIC + if it existed. */ + +#if LIBGCC2_UNITS_PER_WORD == 8 +#define W_TYPE_SIZE (8 * BITS_PER_UNIT) +#define Wtype DItype +#define UWtype UDItype +#define HWtype DItype +#define UHWtype UDItype +#define DWtype TItype +#define UDWtype UTItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## di ## b +#define __NDW(a,b) __gnu_ ## a ## ti ## b +#else +#define __NW(a,b) __ ## a ## di ## b +#define __NDW(a,b) __ ## a ## ti ## b +#endif +#define COMPAT_SIMODE_TRAPPING_ARITHMETIC +#elif LIBGCC2_UNITS_PER_WORD == 4 +#define W_TYPE_SIZE (4 * BITS_PER_UNIT) +#define Wtype SItype +#define UWtype USItype +#define HWtype SItype +#define UHWtype USItype +#define DWtype DItype +#define UDWtype UDItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## si ## b +#define __NDW(a,b) __gnu_ ## a ## di ## b +#else +#define __NW(a,b) __ ## a ## si ## b +#define __NDW(a,b) __ ## a ## di ## b +#endif +#elif LIBGCC2_UNITS_PER_WORD == 2 +#define W_TYPE_SIZE (2 * BITS_PER_UNIT) +#define Wtype HItype +#define UWtype UHItype +#define HWtype HItype +#define UHWtype UHItype +#define DWtype SItype +#define UDWtype USItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## hi ## b +#define __NDW(a,b) __gnu_ ## a ## si ## b +#else +#define __NW(a,b) __ ## a ## hi ## b +#define __NDW(a,b) __ ## a ## si ## b +#endif +#else +#define W_TYPE_SIZE BITS_PER_UNIT +#define Wtype QItype +#define UWtype UQItype +#define HWtype QItype +#define UHWtype UQItype +#define DWtype HItype +#define UDWtype UHItype +#ifdef LIBGCC2_GNU_PREFIX +#define __NW(a,b) __gnu_ ## a ## qi ## b +#define __NDW(a,b) __gnu_ ## a ## hi ## b +#else +#define __NW(a,b) __ ## a ## qi ## b +#define __NDW(a,b) __ ## a ## hi ## b +#endif +#endif + +#ifdef LIBGCC2_GNU_PREFIX +#define __N(a) __gnu_ ## a +#else +#define __N(a) __ ## a +#endif +#define Wtype_MAX ((Wtype)(((UWtype)1 << (W_TYPE_SIZE - 1)) - 1)) +#define Wtype_MIN (- Wtype_MAX - 1) + +#if W_TYPE_SIZE == 8 +# define Wtype_MAXp1_F 0x1p8f +#elif W_TYPE_SIZE == 16 +# define Wtype_MAXp1_F 0x1p16f +#elif W_TYPE_SIZE == 32 +# define Wtype_MAXp1_F 0x1p32f +#elif W_TYPE_SIZE == 64 +# define Wtype_MAXp1_F 0x1p64f +#else +# error "expand the table" +#endif + +#define __muldi3 __NDW(mul,3) +#define __divdi3 __NDW(div,3) +#define __udivdi3 __NDW(udiv,3) +#define __moddi3 __NDW(mod,3) +#define __umoddi3 __NDW(umod,3) +#define __negdi2 __NDW(neg,2) +#define __lshrdi3 __NDW(lshr,3) +#define __ashldi3 __NDW(ashl,3) +#define __ashrdi3 __NDW(ashr,3) +#define __cmpdi2 __NDW(cmp,2) +#define __ucmpdi2 __NDW(ucmp,2) +#define __udivmoddi4 __NDW(udivmod,4) +#define __fixunstfDI __NDW(fixunstf,) +#define __fixtfdi __NDW(fixtf,) +#define __fixunsxfDI __NDW(fixunsxf,) +#define __fixxfdi __NDW(fixxf,) +#define __fixunsdfDI __NDW(fixunsdf,) +#define __fixdfdi __NDW(fixdf,) +#define __fixunssfDI __NDW(fixunssf,) +#define __fixsfdi __NDW(fixsf,) +#define __floatdixf __NDW(float,xf) +#define __floatditf __NDW(float,tf) +#define __floatdidf __NDW(float,df) +#define __floatdisf __NDW(float,sf) +#define __floatundixf __NDW(floatun,xf) +#define __floatunditf __NDW(floatun,tf) +#define __floatundidf __NDW(floatun,df) +#define __floatundisf __NDW(floatun,sf) +#define __fixunsxfSI __NW(fixunsxf,) +#define __fixunstfSI __NW(fixunstf,) +#define __fixunsdfSI __NW(fixunsdf,) +#define __fixunssfSI __NW(fixunssf,) + +#define __absvSI2 __NW(absv,2) +#define __addvSI3 __NW(addv,3) +#define __subvSI3 __NW(subv,3) +#define __mulvSI3 __NW(mulv,3) +#define __negvSI2 __NW(negv,2) +#define __absvDI2 __NDW(absv,2) +#define __addvDI3 __NDW(addv,3) +#define __subvDI3 __NDW(subv,3) +#define __mulvDI3 __NDW(mulv,3) +#define __negvDI2 __NDW(negv,2) + +#define __ffsSI2 __NW(ffs,2) +#define __clzSI2 __NW(clz,2) +#define __ctzSI2 __NW(ctz,2) +#define __clrsbSI2 __NW(clrsb,2) +#define __popcountSI2 __NW(popcount,2) +#define __paritySI2 __NW(parity,2) +#define __ffsDI2 __NDW(ffs,2) +#define __clzDI2 __NDW(clz,2) +#define __ctzDI2 __NDW(ctz,2) +#define __clrsbDI2 __NDW(clrsb,2) +#define __popcountDI2 __NDW(popcount,2) +#define __parityDI2 __NDW(parity,2) + +#define __clz_tab __N(clz_tab) +#define __bswapsi2 __N(bswapsi2) +#define __bswapdi2 __N(bswapdi2) +#define __udiv_w_sdiv __N(udiv_w_sdiv) +#define __clear_cache __N(clear_cache) +#define __enable_execute_stack __N(enable_execute_stack) + +#ifndef __powisf2 +#define __powisf2 __N(powisf2) +#endif +#ifndef __powidf2 +#define __powidf2 __N(powidf2) +#endif +#ifndef __powitf2 +#define __powitf2 __N(powitf2) +#endif +#ifndef __powixf2 +#define __powixf2 __N(powixf2) +#endif +#ifndef __mulsc3 +#define __mulsc3 __N(mulsc3) +#endif +#ifndef __muldc3 +#define __muldc3 __N(muldc3) +#endif +#ifndef __mulxc3 +#define __mulxc3 __N(mulxc3) +#endif +#ifndef __multc3 +#define __multc3 __N(multc3) +#endif +#ifndef __divsc3 +#define __divsc3 __N(divsc3) +#endif +#ifndef __divdc3 +#define __divdc3 __N(divdc3) +#endif +#ifndef __divxc3 +#define __divxc3 __N(divxc3) +#endif +#ifndef __divtc3 +#define __divtc3 __N(divtc3) +#endif + +extern DWtype __muldi3 (DWtype, DWtype); +extern DWtype __divdi3 (DWtype, DWtype); +extern UDWtype __udivdi3 (UDWtype, UDWtype); +extern UDWtype __umoddi3 (UDWtype, UDWtype); +extern DWtype __moddi3 (DWtype, DWtype); + +/* __udivmoddi4 is static inline when building other libgcc2 portions. */ +#if (!defined (L_udivdi3) && !defined (L_divdi3) && \ + !defined (L_umoddi3) && !defined (L_moddi3)) +extern UDWtype __udivmoddi4 (UDWtype, UDWtype, UDWtype *); +#endif + +/* __negdi2 is static inline when building other libgcc2 portions. */ +#if !defined(L_divdi3) && !defined(L_moddi3) +extern DWtype __negdi2 (DWtype); +#endif + +extern DWtype __lshrdi3 (DWtype, shift_count_type); +extern DWtype __ashldi3 (DWtype, shift_count_type); +extern DWtype __ashrdi3 (DWtype, shift_count_type); + +/* __udiv_w_sdiv is static inline when building other libgcc2 portions. */ +#if (!defined(L_udivdi3) && !defined(L_divdi3) && \ + !defined(L_umoddi3) && !defined(L_moddi3)) +extern UWtype __udiv_w_sdiv (UWtype *, UWtype, UWtype, UWtype); +#endif + +extern cmp_return_type __cmpdi2 (DWtype, DWtype); +extern cmp_return_type __ucmpdi2 (DWtype, DWtype); + +#if MIN_UNITS_PER_WORD > 1 +extern SItype __bswapsi2 (SItype); +#endif +#if __SIZEOF_LONG_LONG__ > 4 +extern DItype __bswapdi2 (DItype); +#endif + +extern Wtype __absvSI2 (Wtype); +extern Wtype __addvSI3 (Wtype, Wtype); +extern Wtype __subvSI3 (Wtype, Wtype); +extern Wtype __mulvSI3 (Wtype, Wtype); +extern Wtype __negvSI2 (Wtype); +extern DWtype __absvDI2 (DWtype); +extern DWtype __addvDI3 (DWtype, DWtype); +extern DWtype __subvDI3 (DWtype, DWtype); +extern DWtype __mulvDI3 (DWtype, DWtype); +extern DWtype __negvDI2 (DWtype); + +#ifdef COMPAT_SIMODE_TRAPPING_ARITHMETIC +#define __absvsi2 __N(absvsi2) +#define __negvsi2 __N(negvsi2) +#define __addvsi3 __N(addvsi3) +#define __subvsi3 __N(subvsi3) +#define __mulvsi3 __N(mulvsi3) + +extern SItype __absvsi2 (SItype); +extern SItype __addvsi3 (SItype, SItype); +extern SItype __subvsi3 (SItype, SItype); +extern SItype __mulvsi3 (SItype, SItype); +extern SItype __negvsi2 (SItype); +#endif /* COMPAT_SIMODE_TRAPPING_ARITHMETIC */ + +#undef int +#if LIBGCC2_HAS_SF_MODE +extern DWtype __fixsfdi (SFtype); +extern SFtype __floatdisf (DWtype); +extern SFtype __floatundisf (UDWtype); +extern UWtype __fixunssfSI (SFtype); +extern UDWtype __fixunssfDI (SFtype); +extern SFtype __powisf2 (SFtype, int); +extern SCtype __divsc3 (SFtype, SFtype, SFtype, SFtype); +extern SCtype __mulsc3 (SFtype, SFtype, SFtype, SFtype); +#endif +#if LIBGCC2_HAS_DF_MODE +extern DWtype __fixdfdi (DFtype); +extern DFtype __floatdidf (DWtype); +extern DFtype __floatundidf (UDWtype); +extern UWtype __fixunsdfSI (DFtype); +extern UDWtype __fixunsdfDI (DFtype); +extern DFtype __powidf2 (DFtype, int); +extern DCtype __divdc3 (DFtype, DFtype, DFtype, DFtype); +extern DCtype __muldc3 (DFtype, DFtype, DFtype, DFtype); +#endif + +#if LIBGCC2_HAS_XF_MODE +extern DWtype __fixxfdi (XFtype); +extern UDWtype __fixunsxfDI (XFtype); +extern XFtype __floatdixf (DWtype); +extern XFtype __floatundixf (UDWtype); +extern UWtype __fixunsxfSI (XFtype); +extern XFtype __powixf2 (XFtype, int); +extern XCtype __divxc3 (XFtype, XFtype, XFtype, XFtype); +extern XCtype __mulxc3 (XFtype, XFtype, XFtype, XFtype); +#endif + +#if LIBGCC2_HAS_TF_MODE +extern UDWtype __fixunstfDI (TFtype); +extern DWtype __fixtfdi (TFtype); +extern TFtype __floatditf (DWtype); +extern TFtype __floatunditf (UDWtype); +extern TFtype __powitf2 (TFtype, int); +extern TCtype __divtc3 (TFtype, TFtype, TFtype, TFtype); +extern TCtype __multc3 (TFtype, TFtype, TFtype, TFtype); +#endif +#define int bogus_type + +/* DWstructs are pairs of Wtype values in the order determined by + __BYTE_ORDER__. */ + +#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ + struct DWstruct {Wtype high, low;}; +#else + struct DWstruct {Wtype 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 DWstruct s; + DWtype ll; +} DWunion; + +/* Defined for L_popcount_tab. Exported here because some targets may + want to use it for their own versions of the __popcount builtins. */ +extern const UQItype __popcount_tab[256]; + +/* Defined for L_clz. Exported here because some targets may want to use + it for their own versions of the __clz builtins. It contains the bit + position of the first set bit for the numbers 0 - 255. This avoids the + need for a separate table for the __ctz builtins. */ +extern const UQItype __clz_tab[256]; + +#include "longlong.h" + +#undef int +extern int __clzDI2 (UDWtype); +extern int __clzSI2 (UWtype); +extern int __ctzSI2 (UWtype); +extern int __ctzDI2 (UDWtype); +extern int __clrsbSI2 (Wtype); +extern int __clrsbDI2 (DWtype); +extern int __ffsSI2 (UWtype); +extern int __ffsDI2 (DWtype); +extern int __popcountSI2 (UWtype); +extern int __popcountDI2 (UDWtype); +extern int __paritySI2 (UWtype); +extern int __parityDI2 (UDWtype); +#define int bogus_type + +extern void __enable_execute_stack (void *); + +#ifndef HIDE_EXPORTS +#pragma GCC visibility pop +#endif + +#endif /* ! GCC_LIBGCC2_H */ diff --git a/crt/longlong.h b/crt/longlong.h new file mode 100644 index 00000000..c4b1b97b --- /dev/null +++ b/crt/longlong.h @@ -0,0 +1,1693 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Copyright (C) 1991-2013 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + UQItype -- Unsigned 8 bit type. + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. */ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +#ifndef W_TYPE_SIZE +#define W_TYPE_SIZE 32 +#define UWtype USItype +#define UHWtype USItype +#define UDWtype UDItype +#endif + +/* Used in glibc only. */ +#ifndef attribute_hidden +#define attribute_hidden +#endif + +extern const UQItype __clz_tab[256] attribute_hidden; + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two + UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first nonzero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! + (E.g. WE32100, IBM360.) */ + +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + +#if defined (__alpha) && W_TYPE_SIZE == 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + (ph) = __builtin_alpha_umulh (__m0, __m1); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#ifdef __alpha_cix__ +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clzl (X)) +#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctzl (X)) +#define COUNT_LEADING_ZEROS_0 64 +#else +#define count_leading_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __t = __builtin_alpha_cmpbge (0, __xr); \ + __a = __clz_tab[__t ^ 0xff] - 1; \ + __t = __builtin_alpha_extbl (__xr, __a); \ + (COUNT) = 64 - (__clz_tab[__t] + __a*8); \ + } while (0) +#define count_trailing_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __t = __builtin_alpha_cmpbge (0, __xr); \ + __t = ~__t & -~__t; \ + __a = ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + __t = __builtin_alpha_extbl (__xr, __a); \ + __a <<= 3; \ + __t &= -__t; \ + __a += ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + (COUNT) = __a; \ + } while (0) +#endif /* __alpha_cix__ */ +#endif /* __alpha */ + +#if defined (__arc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +/* Call libgcc routine. */ +#define umul_ppmm(w1, w0, u, v) \ +do { \ + DWunion __w; \ + __w.ll = __umulsidi3 (u, v); \ + w1 = __w.s.high; \ + w0 = __w.s.low; \ +} while (0) +#define __umulsidi3 __umulsidi3 +UDItype __umulsidi3 (USItype, USItype); +#endif + +#if defined (__arm__) && (defined (__thumb2__) || !defined (__thumb__)) \ + && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rI" ((USItype) (bl)) __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rI" ((USItype) (bl)) __CLOBBER_CC) +# if defined(__ARM_ARCH_2__) || defined(__ARM_ARCH_2A__) \ + || defined(__ARM_ARCH_3__) +# define umul_ppmm(xh, xl, a, b) \ + do { \ + register USItype __t0, __t1, __t2; \ + __asm__ ("%@ Inlined umul_ppmm\n" \ + " mov %2, %5, lsr #16\n" \ + " mov %0, %6, lsr #16\n" \ + " bic %3, %5, %2, lsl #16\n" \ + " bic %4, %6, %0, lsl #16\n" \ + " mul %1, %3, %4\n" \ + " mul %4, %2, %4\n" \ + " mul %3, %0, %3\n" \ + " mul %0, %2, %0\n" \ + " adds %3, %4, %3\n" \ + " addcs %0, %0, #65536\n" \ + " adds %1, %1, %3, lsl #16\n" \ + " adc %0, %0, %3, lsr #16" \ + : "=&r" ((USItype) (xh)), \ + "=r" ((USItype) (xl)), \ + "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ + : "r" ((USItype) (a)), \ + "r" ((USItype) (b)) __CLOBBER_CC ); \ + } while (0) +# define UMUL_TIME 20 +# else +# define umul_ppmm(xh, xl, a, b) \ + do { \ + /* Generate umull, under compiler control. */ \ + register UDItype __t0 = (UDItype)(USItype)(a) * (USItype)(b); \ + (xl) = (USItype)__t0; \ + (xh) = (USItype)(__t0 >> 32); \ + } while (0) +# define UMUL_TIME 3 +# endif +# define UDIV_TIME 100 +#endif /* __arm__ */ + +#if defined(__arm__) +/* Let gcc decide how best to implement count_leading_zeros. */ +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clz (X)) +#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctz (X)) +#define COUNT_LEADING_ZEROS_0 32 +#endif + +#if defined (__AVR__) + +#if W_TYPE_SIZE == 16 +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clz (X)) +#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctz (X)) +#define COUNT_LEADING_ZEROS_0 16 +#endif /* W_TYPE_SIZE == 16 */ + +#if W_TYPE_SIZE == 32 +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clzl (X)) +#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctzl (X)) +#define COUNT_LEADING_ZEROS_0 32 +#endif /* W_TYPE_SIZE == 32 */ + +#if W_TYPE_SIZE == 64 +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clzll (X)) +#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctzll (X)) +#define COUNT_LEADING_ZEROS_0 64 +#endif /* W_TYPE_SIZE == 64 */ + +#endif /* defined (__AVR__) */ + +#if defined (__CRIS__) && __CRIS_arch_version >= 3 +#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clz (X)) +#if __CRIS_arch_version >= 8 +#define count_trailing_zeros(COUNT, X) ((COUNT) = __builtin_ctz (X)) +#endif +#endif /* __CRIS__ */ + +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rM" ((USItype) (ah)), \ + "rM" ((USItype) (bh)), \ + "%rM" ((USItype) (al)), \ + "rM" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rM" ((USItype) (ah)), \ + "rM" ((USItype) (bh)), \ + "rM" ((USItype) (al)), \ + "rM" ((USItype) (bl))) +#if defined (_PA_RISC1_1) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + union \ + { \ + UDItype __f; \ + struct {USItype __w1, __w0;} __w1w0; \ + } __t; \ + __asm__ ("xmpyu %1,%2,%0" \ + : "=x" (__t.__f) \ + : "x" ((USItype) (u)), \ + "x" ((USItype) (v))); \ + (w1) = __t.__w1w0.__w1; \ + (w0) = __t.__w1w0.__w0; \ + } while (0) +#define UMUL_TIME 8 +#else +#define UMUL_TIME 30 +#endif +#define UDIV_TIME 40 +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + "ldi 1,%0\n" \ +" extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ +" extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n"\ +" ldo 16(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ +" extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n"\ +" ldo 8(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ +" extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n"\ +" ldo 4(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ +" extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n"\ +" ldo 2(%0),%0 ; Yes. Perform add.\n" \ +" extru %1,30,1,%1 ; Extract bit 1.\n" \ +" sub %0,%1,%0 ; Subtract it.\n" \ + : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif + +#if (defined (__i370__) || defined (__s390__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#if !defined (__zarch__) +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("lr %N0,%1\n\tmr %0,%2" \ + : "=&r" (__x.__ll) \ + : "r" (m0), "r" (m1)); \ + (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __x.__i.__h = n1; __x.__i.__l = n0; \ + __asm__ ("dr %0,%2" \ + : "=r" (__x.__ll) \ + : "0" (__x.__ll), "r" (d)); \ + (q) = __x.__i.__l; (r) = __x.__i.__h; \ + } while (0) +#else +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + register SItype __r0 __asm__ ("0"); \ + register SItype __r1 __asm__ ("1") = (m0); \ + \ + __asm__ ("mr\t%%r0,%3" \ + : "=r" (__r0), "=r" (__r1) \ + : "r" (__r1), "r" (m1)); \ + (xh) = __r0; (xl) = __r1; \ + } while (0) + +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + register SItype __r0 __asm__ ("0") = (n1); \ + register SItype __r1 __asm__ ("1") = (n0); \ + \ + __asm__ ("dr\t%%r0,%4" \ + : "=r" (__r0), "=r" (__r1) \ + : "r" (__r0), "r" (__r1), "r" (d)); \ + (q) = __r1; (r) = __r0; \ + } while (0) +#endif /* __zarch__ */ +#endif + +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add{l} {%5,%1|%1,%5}\n\tadc{l} {%3,%0|%0,%3}" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub{l} {%5,%1|%1,%5}\n\tsbb{l} {%3,%0|%0,%3}" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mul{l} %3" \ + : "=a" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "rm" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, dv) \ + __asm__ ("div{l} %4" \ + : "=a" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "rm" ((USItype) (dv))) +#define count_leading_zeros(count, x) ((count) = __builtin_clz (x)) +#define count_trailing_zeros(count, x) ((count) = __builtin_ctz (x)) +#define UMUL_TIME 40 +#define UDIV_TIME 40 +#endif /* 80x86 */ + +#if (defined (__x86_64__) || defined (__i386__)) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add{q} {%5,%1|%1,%5}\n\tadc{q} {%3,%0|%0,%3}" \ + : "=r" ((UDItype) (sh)), \ + "=&r" ((UDItype) (sl)) \ + : "%0" ((UDItype) (ah)), \ + "rme" ((UDItype) (bh)), \ + "%1" ((UDItype) (al)), \ + "rme" ((UDItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub{q} {%5,%1|%1,%5}\n\tsbb{q} {%3,%0|%0,%3}" \ + : "=r" ((UDItype) (sh)), \ + "=&r" ((UDItype) (sl)) \ + : "0" ((UDItype) (ah)), \ + "rme" ((UDItype) (bh)), \ + "1" ((UDItype) (al)), \ + "rme" ((UDItype) (bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mul{q} %3" \ + : "=a" ((UDItype) (w0)), \ + "=d" ((UDItype) (w1)) \ + : "%0" ((UDItype) (u)), \ + "rm" ((UDItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, dv) \ + __asm__ ("div{q} %4" \ + : "=a" ((UDItype) (q)), \ + "=d" ((UDItype) (r)) \ + : "0" ((UDItype) (n0)), \ + "1" ((UDItype) (n1)), \ + "rm" ((UDItype) (dv))) +#define count_leading_zeros(count, x) ((count) = __builtin_clzll (x)) +#define count_trailing_zeros(count, x) ((count) = __builtin_ctzll (x)) +#define UMUL_TIME 40 +#define UDIV_TIME 40 +#endif /* x86_64 */ + +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((USItype) (u)), \ + "dI" ((USItype) (v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__w) \ + : "%dI" ((USItype) (u)), \ + "dI" ((USItype) (v))); \ + __w; }) +#endif /* __i960__ */ + +#if defined (__ia64) && W_TYPE_SIZE == 64 +/* This form encourages gcc (pre-release 3.4 at least) to emit predicated + "sub r=r,r" and "sub r=r,r,1", giving a 2 cycle latency. The generic + code using "al>= _c; \ + if (_x >= 1 << 4) \ + _x >>= 4, _c += 4; \ + if (_x >= 1 << 2) \ + _x >>= 2, _c += 2; \ + _c += _x >> 1; \ + (count) = W_TYPE_SIZE - 1 - _c; \ + } while (0) +/* similar to what gcc does for __builtin_ffs, but 0 based rather than 1 + based, and we don't need a special case for x==0 here */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + __asm__ ("popcnt %0 = %1" \ + : "=r" (count) \ + : "r" ((__ctz_x-1) & ~__ctz_x)); \ + } while (0) +#define UMUL_TIME 14 +#endif + +#if defined (__M32R__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + /* The cmp clears the condition bit. */ \ + __asm__ ("cmp %0,%0\n\taddx %1,%5\n\taddx %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl)) \ + : "cbit") +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + /* The cmp clears the condition bit. */ \ + __asm__ ("cmp %0,%0\n\tsubx %1,%5\n\tsubx %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl)) \ + : "cbit") +#endif /* __M32R__ */ + +#if defined (__mc68000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \ + : "=d" ((USItype) (sh)), \ + "=&d" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "d" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \ + : "=d" ((USItype) (sh)), \ + "=&d" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "d" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) + +/* The '020, '030, '040, '060 and CPU32 have 32x32->64 and 64/32->32q-32r. */ +#if (defined (__mc68020__) && !defined (__mc68060__)) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "dmi" ((USItype) (v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "dmi" ((USItype) (d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "dmi" ((USItype) (d))) + +#elif defined (__mcoldfire__) /* not mc68020 */ + +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("| Inlined umul_ppmm\n" \ + " move%.l %2,%/d0\n" \ + " move%.l %3,%/d1\n" \ + " move%.l %/d0,%/d2\n" \ + " swap %/d0\n" \ + " move%.l %/d1,%/d3\n" \ + " swap %/d1\n" \ + " move%.w %/d2,%/d4\n" \ + " mulu %/d3,%/d4\n" \ + " mulu %/d1,%/d2\n" \ + " mulu %/d0,%/d3\n" \ + " mulu %/d0,%/d1\n" \ + " move%.l %/d4,%/d0\n" \ + " clr%.w %/d0\n" \ + " swap %/d0\n" \ + " add%.l %/d0,%/d2\n" \ + " add%.l %/d3,%/d2\n" \ + " jcc 1f\n" \ + " add%.l %#65536,%/d1\n" \ + "1: swap %/d2\n" \ + " moveq %#0,%/d0\n" \ + " move%.w %/d2,%/d0\n" \ + " move%.w %/d4,%/d2\n" \ + " move%.l %/d2,%1\n" \ + " add%.l %/d1,%/d0\n" \ + " move%.l %/d0,%0" \ + : "=g" ((USItype) (xh)), \ + "=g" ((USItype) (xl)) \ + : "g" ((USItype) (a)), \ + "g" ((USItype) (b)) \ + : "d0", "d1", "d2", "d3", "d4") +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#else /* not ColdFire */ +/* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX. */ +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("| Inlined umul_ppmm\n" \ + " move%.l %2,%/d0\n" \ + " move%.l %3,%/d1\n" \ + " move%.l %/d0,%/d2\n" \ + " swap %/d0\n" \ + " move%.l %/d1,%/d3\n" \ + " swap %/d1\n" \ + " move%.w %/d2,%/d4\n" \ + " mulu %/d3,%/d4\n" \ + " mulu %/d1,%/d2\n" \ + " mulu %/d0,%/d3\n" \ + " mulu %/d0,%/d1\n" \ + " move%.l %/d4,%/d0\n" \ + " eor%.w %/d0,%/d0\n" \ + " swap %/d0\n" \ + " add%.l %/d0,%/d2\n" \ + " add%.l %/d3,%/d2\n" \ + " jcc 1f\n" \ + " add%.l %#65536,%/d1\n" \ + "1: swap %/d2\n" \ + " moveq %#0,%/d0\n" \ + " move%.w %/d2,%/d0\n" \ + " move%.w %/d4,%/d2\n" \ + " move%.l %/d2,%1\n" \ + " add%.l %/d1,%/d0\n" \ + " move%.l %/d0,%0" \ + : "=g" ((USItype) (xh)), \ + "=g" ((USItype) (xl)) \ + : "g" ((USItype) (a)), \ + "g" ((USItype) (b)) \ + : "d0", "d1", "d2", "d3", "d4") +#define UMUL_TIME 100 +#define UDIV_TIME 400 + +#endif /* not mc68020 */ + +/* The '020, '030, '040 and '060 have bitfield insns. + cpu32 disguises as a 68020, but lacks them. */ +#if defined (__mc68020__) && !defined (__mcpu32__) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((USItype) (count)) \ + : "od" ((USItype) (x)), "n" (0)) +/* Some ColdFire architectures have a ff1 instruction supported via + __builtin_clz. */ +#elif defined (__mcfisaaplus__) || defined (__mcfisac__) +#define count_leading_zeros(count,x) ((count) = __builtin_clz (x)) +#define COUNT_LEADING_ZEROS_0 32 +#endif +#endif /* mc68000 */ + +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rJ" ((USItype) (ah)), \ + "rJ" ((USItype) (bh)), \ + "%rJ" ((USItype) (al)), \ + "rJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rJ" ((USItype) (ah)), \ + "rJ" ((USItype) (bh)), \ + "rJ" ((USItype) (al)), \ + "rJ" ((USItype) (bl))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((USItype) (x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__mc88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mulu.d %0,%1,%2" \ + : "=r" (__xx.__ll) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __q; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q) \ + : "r" (__xx.__ll), \ + "r" ((USItype) (d))); \ + (r) = (n0) - __q * (d); (q) = __q; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __mc88110__ */ +#endif /* __m88000__ */ + +#if defined (__mn10300__) +# if defined (__AM33__) +# define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clz (X)) +# define umul_ppmm(w1, w0, u, v) \ + asm("mulu %3,%2,%1,%0" : "=r"(w0), "=r"(w1) : "r"(u), "r"(v)) +# define smul_ppmm(w1, w0, u, v) \ + asm("mul %3,%2,%1,%0" : "=r"(w0), "=r"(w1) : "r"(u), "r"(v)) +# else +# define umul_ppmm(w1, w0, u, v) \ + asm("nop; nop; mulu %3,%0" : "=d"(w0), "=z"(w1) : "%0"(u), "d"(v)) +# define smul_ppmm(w1, w0, u, v) \ + asm("nop; nop; mul %3,%0" : "=d"(w0), "=z"(w1) : "%0"(u), "d"(v)) +# endif +# define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + DWunion __s, __a, __b; \ + __a.s.low = (al); __a.s.high = (ah); \ + __b.s.low = (bl); __b.s.high = (bh); \ + __s.ll = __a.ll + __b.ll; \ + (sl) = __s.s.low; (sh) = __s.s.high; \ + } while (0) +# define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + DWunion __s, __a, __b; \ + __a.s.low = (al); __a.s.high = (ah); \ + __b.s.low = (bl); __b.s.high = (bh); \ + __s.ll = __a.ll - __b.ll; \ + (sl) = __s.s.low; (sh) = __s.s.high; \ + } while (0) +# define udiv_qrnnd(q, r, nh, nl, d) \ + asm("divu %2,%0" : "=D"(q), "=z"(r) : "D"(d), "0"(nl), "1"(nh)) +# define sdiv_qrnnd(q, r, nh, nl, d) \ + asm("div %2,%0" : "=D"(q), "=z"(r) : "D"(d), "0"(nl), "1"(nh)) +# define UMUL_TIME 3 +# define UDIV_TIME 38 +#endif + +#if defined (__mips__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UDItype __x = (UDItype) (USItype) (u) * (USItype) (v); \ + (w1) = (USItype) (__x >> 32); \ + (w0) = (USItype) (__x); \ + } while (0) +#define UMUL_TIME 10 +#define UDIV_TIME 100 + +#if (__mips == 32 || __mips == 64) && ! __mips16 +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clz (X)) +#define COUNT_LEADING_ZEROS_0 32 +#endif +#endif /* __mips__ */ + +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((USItype) (u)), \ + "g" ((USItype) (v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype) (u)), \ + "g" ((USItype) (v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__xx.__ll) \ + : "0" (__xx.__ll), \ + "g" ((USItype) (d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { \ + __asm__ ("ffsd %2,%0" \ + : "=r" ((USItype) (count)) \ + : "0" ((USItype) 0), \ + "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + +/* FIXME: We should test _IBMR2 here when we add assembly support for the + system vendor compilers. + FIXME: What's needed for gcc PowerPC VxWorks? __vxworks__ is not good + enough, since that hits ARM and m68k too. */ +#if (defined (_ARCH_PPC) /* AIX */ \ + || defined (__powerpc__) /* gcc */ \ + || defined (__POWERPC__) /* BEOS */ \ + || defined (__ppc__) /* Darwin */ \ + || (defined (PPC) && ! defined (CPU_FAMILY)) /* gcc 2.7.x GNU&SysV */ \ + || (defined (PPC) && defined (CPU_FAMILY) /* VxWorks */ \ + && CPU_FAMILY == PPC) \ + ) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("add%I4c %1,%3,%4\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("add%I4c %1,%3,%4\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("add%I5c %1,%4,%5\n\tadde %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\tsubfze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\tsubfme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("subf%I4c %1,%5,%4\n\tsubfe %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("cntlzw %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 32 +#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \ + || defined (__ppc__) \ + || (defined (PPC) && ! defined (CPU_FAMILY)) /* gcc 2.7.x GNU&SysV */ \ + || (defined (PPC) && defined (CPU_FAMILY) /* VxWorks */ \ + && CPU_FAMILY == PPC) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#endif +#endif /* 32-bit POWER architecture variants. */ + +/* We should test _IBMR2 here when we add assembly support for the system + vendor compilers. */ +#if (defined (_ARCH_PPC64) || defined (__powerpc64__)) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("add%I4c %1,%3,%4\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("add%I4c %1,%3,%4\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("add%I5c %1,%4,%5\n\tadde %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\tsubfze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\tsubfme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\taddme %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("subf%I3c %1,%4,%3\n\taddze %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("subf%I4c %1,%5,%4\n\tsubfe %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + DItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 /* ??? */ +#define UDIV_TIME 120 /* ??? */ +#endif /* 64-bit PowerPC. */ + +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5\n\tae %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "r" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5\n\tse %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2\n" \ +" mts r10,%2\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" cas %0,r2,r0\n" \ +" mfs r10,%1" \ + : "=r" ((USItype) (ph)), \ + "=r" ((USItype) (pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x))); \ + (count) += 16; \ + } \ + } while (0) +#endif + +#if defined(__sh__) && !__SHMEDIA__ && W_TYPE_SIZE == 32 +#ifndef __sh1__ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3\n\tsts%M1 macl,%1\n\tsts%M0 mach,%0" \ + : "=r<" ((USItype)(w1)), \ + "=r<" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "macl", "mach") +#define UMUL_TIME 5 +#endif + +/* This is the same algorithm as __udiv_qrnnd_c. */ +#define UDIV_NEEDS_NORMALIZATION 1 + +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + extern UWtype __udiv_qrnnd_16 (UWtype, UWtype) \ + __attribute__ ((visibility ("hidden"))); \ + /* r0: rn r1: qn */ /* r0: n1 r4: n0 r5: d r6: d1 */ /* r2: __m */ \ + __asm__ ( \ + "mov%M4 %4,r5\n" \ +" swap.w %3,r4\n" \ +" swap.w r5,r6\n" \ +" jsr @%5\n" \ +" shll16 r6\n" \ +" swap.w r4,r4\n" \ +" jsr @%5\n" \ +" swap.w r1,%0\n" \ +" or r1,%0" \ + : "=r" (q), "=&z" (r) \ + : "1" (n1), "r" (n0), "rm" (d), "r" (&__udiv_qrnnd_16) \ + : "r1", "r2", "r4", "r5", "r6", "pr", "t"); \ + } while (0) + +#define UDIV_TIME 80 + +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("clrt;subc %5,%1; subc %4,%0" \ + : "=r" (sh), "=r" (sl) \ + : "0" (ah), "1" (al), "r" (bh), "r" (bl) : "t") + +#endif /* __sh__ */ + +#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32 +#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v) +#define count_leading_zeros(count, x) \ + do \ + { \ + UDItype x_ = (USItype)(x); \ + SItype c_; \ + \ + __asm__ ("nsb %1, %0" : "=r" (c_) : "r" (x_)); \ + (count) = c_ - 31; \ + } \ + while (0) +#define COUNT_LEADING_ZEROS_0 32 +#endif + +#if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \ + && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rJ" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "%rJ" ((USItype) (al)), \ + "rI" ((USItype) (bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rJ" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "rJ" ((USItype) (al)), \ + "rI" ((USItype) (bl)) \ + __CLOBBER_CC) +#if defined (__sparc_v9__) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + register USItype __g1 asm ("g1"); \ + __asm__ ("umul\t%2,%3,%1\n\t" \ + "srlx\t%1, 32, %0" \ + : "=r" ((USItype) (w1)), \ + "=r" (__g1) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))); \ + (w0) = __g1; \ + } while (0) +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("mov\t%2,%%y\n\t" \ + "udiv\t%3,%4,%0\n\t" \ + "umul\t%0,%4,%1\n\t" \ + "sub\t%3,%1,%1" \ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__n1)), \ + "r" ((USItype) (__n0)), \ + "r" ((USItype) (__d))) +#else +#if defined (__sparc_v8__) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))) +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__n1)), \ + "r" ((USItype) (__n0)), \ + "r" ((USItype) (__d))) +#else +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" wr %%g0,%2,%%y ! Not a delayed write for sparclite\n" \ +" tst %%g0\n" \ +" divscc %3,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%0\n" \ +" rd %%y,%1\n" \ +" bl,a 1f\n" \ +" add %1,%4,%1\n" \ +"1: ! End of inline udiv_qrnnd" \ + : "=r" ((USItype) (q)), \ + "=r" ((USItype) (r)) \ + : "r" ((USItype) (n1)), \ + "r" ((USItype) (n0)), \ + "rI" ((USItype) (d)) \ + : "g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + do { \ + __asm__ ("scan %1,1,%0" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x))); \ + } while (0) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#else +/* SPARC without integer multiplication and divide instructions. + (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm\n" \ +" wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n"\ +" sra %3,31,%%o5 ! Don't move this insn\n" \ +" and %2,%%o5,%%o5 ! Don't move this insn\n" \ +" andcc %%g0,0,%%g1 ! Don't move this insn\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,0,%%g1\n" \ +" add %%g1,%%o5,%0\n" \ +" rd %%y,%1" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "%rI" ((USItype) (u)), \ + "r" ((USItype) (v)) \ + : "g1", "o5" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +/* It's quite necessary to add this much assembler for the sparc. + The default udiv_qrnnd (in C) is more than 10 times slower! */ +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" mov 32,%%g1\n" \ +" subcc %1,%2,%%g0\n" \ +"1: bcs 5f\n" \ +" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \ +" sub %1,%2,%1 ! this kills msb of n\n" \ +" addx %1,%1,%1 ! so this can't give carry\n" \ +" subcc %%g1,1,%%g1\n" \ +"2: bne 1b\n" \ +" subcc %1,%2,%%g0\n" \ +" bcs 3f\n" \ +" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \ +" b 3f\n" \ +" sub %1,%2,%1 ! this kills msb of n\n" \ +"4: sub %1,%2,%1\n" \ +"5: addxcc %1,%1,%1\n" \ +" bcc 2b\n" \ +" subcc %%g1,1,%%g1\n" \ +"! Got carry from n. Subtract next step to cancel this carry.\n" \ +" bne 4b\n" \ +" addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n" \ +" sub %1,%2,%1\n" \ +"3: xnor %0,0,%0\n" \ +" ! End of inline udiv_qrnnd" \ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__d)), \ + "1" ((USItype) (__n1)), \ + "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC) +#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +#endif /* __sparc_v9__ */ +#endif /* sparc32 */ + +#if ((defined (__sparc__) && defined (__arch64__)) || defined (__sparcv9)) \ + && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UDItype __carry = 0; \ + __asm__ ("addcc\t%r5,%6,%1\n\t" \ + "add\t%r3,%4,%0\n\t" \ + "movcs\t%%xcc, 1, %2\n\t" \ + "add\t%0, %2, %0" \ + : "=r" ((UDItype)(sh)), \ + "=&r" ((UDItype)(sl)), \ + "+r" (__carry) \ + : "%rJ" ((UDItype)(ah)), \ + "rI" ((UDItype)(bh)), \ + "%rJ" ((UDItype)(al)), \ + "rI" ((UDItype)(bl)) \ + __CLOBBER_CC); \ + } while (0) + +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UDItype __carry = 0; \ + __asm__ ("subcc\t%r5,%6,%1\n\t" \ + "sub\t%r3,%4,%0\n\t" \ + "movcs\t%%xcc, 1, %2\n\t" \ + "sub\t%0, %2, %0" \ + : "=r" ((UDItype)(sh)), \ + "=&r" ((UDItype)(sl)), \ + "+r" (__carry) \ + : "%rJ" ((UDItype)(ah)), \ + "rI" ((UDItype)(bh)), \ + "%rJ" ((UDItype)(al)), \ + "rI" ((UDItype)(bl)) \ + __CLOBBER_CC); \ + } while (0) + +#define umul_ppmm(wh, wl, u, v) \ + do { \ + UDItype tmp1, tmp2, tmp3, tmp4; \ + __asm__ __volatile__ ( \ + "srl %7,0,%3\n\t" \ + "mulx %3,%6,%1\n\t" \ + "srlx %6,32,%2\n\t" \ + "mulx %2,%3,%4\n\t" \ + "sllx %4,32,%5\n\t" \ + "srl %6,0,%3\n\t" \ + "sub %1,%5,%5\n\t" \ + "srlx %5,32,%5\n\t" \ + "addcc %4,%5,%4\n\t" \ + "srlx %7,32,%5\n\t" \ + "mulx %3,%5,%3\n\t" \ + "mulx %2,%5,%5\n\t" \ + "sethi %%hi(0x80000000),%2\n\t" \ + "addcc %4,%3,%4\n\t" \ + "srlx %4,32,%4\n\t" \ + "add %2,%2,%2\n\t" \ + "movcc %%xcc,%%g0,%2\n\t" \ + "addcc %5,%4,%5\n\t" \ + "sllx %3,32,%3\n\t" \ + "add %1,%3,%1\n\t" \ + "add %5,%2,%0" \ + : "=r" ((UDItype)(wh)), \ + "=&r" ((UDItype)(wl)), \ + "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \ + : "r" ((UDItype)(u)), \ + "r" ((UDItype)(v)) \ + __CLOBBER_CC); \ + } while (0) +#define UMUL_TIME 96 +#define UDIV_TIME 230 +#endif /* sparc64 */ + +#if defined (__vax__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \ + : "=g" ((USItype) (sh)), \ + "=&g" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \ + : "=g" ((USItype) (sh)), \ + "=&g" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union { \ + UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=r" (__xx.__ll) \ + : "g" (__m0), \ + "g" (__m1)); \ + (xh) = __xx.__i.__h; \ + (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) \ + : "g" (__xx.__ll), "g" (d)); \ + } while (0) +#endif /* __vax__ */ + +#ifdef _TMS320C6X +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do \ + { \ + UDItype __ll; \ + __asm__ ("addu .l1 %1, %2, %0" \ + : "=a" (__ll) : "a" (al), "a" (bl)); \ + (sl) = (USItype)__ll; \ + (sh) = ((USItype)(__ll >> 32)) + (ah) + (bh); \ + } \ + while (0) + +#ifdef _TMS320C6400_PLUS +#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UDItype __x = (UDItype) (USItype) (u) * (USItype) (v); \ + (w1) = (USItype) (__x >> 32); \ + (w0) = (USItype) (__x); \ + } while (0) +#endif /* _TMS320C6400_PLUS */ + +#define count_leading_zeros(count, x) ((count) = __builtin_clz (x)) +#ifdef _TMS320C6400 +#define count_trailing_zeros(count, x) ((count) = __builtin_ctz (x)) +#endif +#define UMUL_TIME 4 +#define UDIV_TIME 40 +#endif /* _TMS320C6X */ + +#if defined (__xtensa__) && W_TYPE_SIZE == 32 +/* This code is not Xtensa-configuration-specific, so rely on the compiler + to expand builtin functions depending on what configuration features + are available. This avoids library calls when the operation can be + performed in-line. */ +#define umul_ppmm(w1, w0, u, v) \ + do { \ + DWunion __w; \ + __w.ll = __builtin_umulsidi3 (u, v); \ + w1 = __w.s.high; \ + w0 = __w.s.low; \ + } while (0) +#define __umulsidi3(u, v) __builtin_umulsidi3 (u, v) +#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clz (X)) +#define count_trailing_zeros(COUNT, X) ((COUNT) = __builtin_ctz (X)) +#endif /* __xtensa__ */ + +#if defined xstormy16 +extern UHItype __stormy16_count_leading_zeros (UHItype); +#define count_leading_zeros(count, x) \ + do \ + { \ + UHItype size; \ + \ + /* We assume that W_TYPE_SIZE is a multiple of 16... */ \ + for ((count) = 0, size = W_TYPE_SIZE; size; size -= 16) \ + { \ + UHItype c; \ + \ + c = __clzhi2 ((x) >> (size - 16)); \ + (count) += c; \ + if (c != 16) \ + break; \ + } \ + } \ + while (0) +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "%0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __xx; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "rQR" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +/* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of + smul_ppmm. */ +#if !defined (umul_ppmm) && defined (smul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __xm0 = (u), __xm1 = (v); \ + smul_ppmm (__w1, w0, __xm0, __xm1); \ + (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1) \ + + (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0); \ + } while (0) +#endif + +/* If we still don't have umul_ppmm, define it using plain C. */ +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({DWunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0; \ + UWtype __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + USItype __r; \ + (q) = __udiv_w_sdiv (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype)1<<2*__BITS4) \ + ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif diff --git a/crt/tconfig.h b/crt/tconfig.h new file mode 100644 index 00000000..a3075fac --- /dev/null +++ b/crt/tconfig.h @@ -0,0 +1,8 @@ +// Defines needed to compile libgcc2.c +#define BITS_PER_UNIT 8 +#define LONG_DOUBLE_TYPE_SIZE 64 +#define MIN_UNITS_PER_WORD 4 +typedef unsigned int size_t; + +// Unsigned 64 bit division: +#define L_udivdi3 diff --git a/rules/rpl.mk b/rules/rpl.mk index 16b5889d..8046e73a 100644 --- a/rules/rpl.mk +++ b/rules/rpl.mk @@ -1,7 +1,7 @@ LIBPATHS := -L$(WUT_ROOT)/lib CFLAGS := -I$(WUT_ROOT)/include -fno-builtin -ffreestanding CXXFLAGS := $(CFLAGS) -LDFLAGS := -nostdlib -nostartfiles $(WUT_ROOT)/lib/crt0.o -T $(WUT_ROOT)/rules/rpl.ld -pie -fPIE -z common-page-size=64 -z max-page-size=64 -lcoreinit +LDFLAGS := -nostdlib -nostartfiles $(WUT_ROOT)/lib/crt0.o $(WUT_ROOT)/lib/libgcc2.o -T $(WUT_ROOT)/rules/rpl.ld -pie -fPIE -z common-page-size=64 -z max-page-size=64 -lcoreinit ELF2RPL := $(WUT_ROOT)/bin/elf2rpl include $(WUT_ROOT)/rules/base.mk