From: Scott McNutt <smcnutt@psyent.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] nios2: fix div64 issue for gcc4
Date: Tue, 25 May 2010 16:58:34 -0400 [thread overview]
Message-ID: <4BFC39FA.1080802@psyent.com> (raw)
In-Reply-To: <1273874405-15545-2-git-send-email-thomas@wytron.com.tw>
Applied to:
git://git.denx.de/u-boot-nios.git next
Thanks,
--Scott
Thomas Chou wrote:
> This patch fixes the run-time error on div64 when built with
> gcc4, which was reported by jhwu0625 on nios forum. It merges
> math support from libgcc of gcc4. This patch is copied from
> nios2-linux.
>
> It works with both gcc3 and gcc4. The old mult.c, divmod.c and
> math.h are removed.
>
> Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
> ---
> arch/nios2/lib/Makefile | 3 +-
> arch/nios2/lib/divmod.c | 101 --------
> arch/nios2/lib/libgcc.c | 592 +++++++++++++++++++++++++++++++++++++++++++++
> arch/nios2/lib/longlong.h | 263 ++++++++++++++++++++
> arch/nios2/lib/math.h | 16 --
> arch/nios2/lib/mult.c | 56 -----
> 6 files changed, 856 insertions(+), 175 deletions(-)
> delete mode 100644 arch/nios2/lib/divmod.c
> create mode 100644 arch/nios2/lib/libgcc.c
> create mode 100644 arch/nios2/lib/longlong.h
> delete mode 100644 arch/nios2/lib/math.h
> delete mode 100644 arch/nios2/lib/mult.c
>
> diff --git a/arch/nios2/lib/Makefile b/arch/nios2/lib/Makefile
> index b69bc38..92320c5 100644
> --- a/arch/nios2/lib/Makefile
> +++ b/arch/nios2/lib/Makefile
> @@ -29,8 +29,7 @@ SOBJS-y += cache.o
>
> COBJS-y += board.o
> COBJS-y += bootm.o
> -COBJS-y += divmod.o
> -COBJS-y += mult.o
> +COBJS-y += libgcc.o
> COBJS-y += time.o
>
> SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
> diff --git a/arch/nios2/lib/divmod.c b/arch/nios2/lib/divmod.c
> deleted file mode 100644
> index 3c7e71e..0000000
> --- a/arch/nios2/lib/divmod.c
> +++ /dev/null
> @@ -1,101 +0,0 @@
> -/*
> - * This file is part of GNU CC.
> - *
> - * GNU CC is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published
> - * by the Free Software Foundation; either version 2, or (at your
> - * option) any later version.
> - *
> - * GNU CC is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public
> - * License along with GNU CC; see the file COPYING. If not, write
> - * to the Free Software Foundation, 59 Temple Place - Suite 330,
> - * Boston, MA 02111-1307, USA.
> - */
> -
> -
> -#include "math.h"
> -
> -USItype udivmodsi4 (USItype num, USItype den, word_type modwanted)
> -{
> - USItype bit = 1;
> - USItype res = 0;
> -
> - while (den < num && bit && !(den & (1L << 31))) {
> - den <<= 1;
> - bit <<= 1;
> - }
> - while (bit) {
> - if (num >= den) {
> - num -= den;
> - res |= bit;
> - }
> - bit >>= 1;
> - den >>= 1;
> - }
> - if (modwanted)
> - return num;
> - return res;
> -}
> -
> -
> -SItype __divsi3 (SItype a, SItype b)
> -{
> - word_type neg = 0;
> - SItype res;
> -
> - if (a < 0) {
> - a = -a;
> - neg = !neg;
> - }
> -
> - if (b < 0) {
> - b = -b;
> - neg = !neg;
> - }
> -
> - res = udivmodsi4 (a, b, 0);
> -
> - if (neg)
> - res = -res;
> -
> - return res;
> -}
> -
> -
> -SItype __modsi3 (SItype a, SItype b)
> -{
> - word_type neg = 0;
> - SItype res;
> -
> - if (a < 0) {
> - a = -a;
> - neg = 1;
> - }
> -
> - if (b < 0)
> - b = -b;
> -
> - res = udivmodsi4 (a, b, 1);
> -
> - if (neg)
> - res = -res;
> -
> - return res;
> -}
> -
> -
> -SItype __udivsi3 (SItype a, SItype b)
> -{
> - return udivmodsi4 (a, b, 0);
> -}
> -
> -
> -SItype __umodsi3 (SItype a, SItype b)
> -{
> - return udivmodsi4 (a, b, 1);
> -}
> diff --git a/arch/nios2/lib/libgcc.c b/arch/nios2/lib/libgcc.c
> new file mode 100644
> index 0000000..dc05627
> --- /dev/null
> +++ b/arch/nios2/lib/libgcc.c
> @@ -0,0 +1,592 @@
> +/*
> + * This file is part of GNU CC.
> + *
> + * GNU CC is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published
> + * by the Free Software Foundation; either version 2, or (at your
> + * option) any later version.
> + *
> + * GNU CC is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public
> + * License along with GNU CC; see the file COPYING. If not, write
> + * to the Free Software Foundation, 59 Temple Place - Suite 330,
> + * Boston, MA 02111-1307, USA.
> + */
> +
> +typedef unsigned int UWtype;
> +typedef unsigned int UHWtype;
> +typedef unsigned long long UDWtype;
> +#define W_TYPE_SIZE 32
> +
> +typedef unsigned char UQItype;
> +typedef long SItype;
> +typedef unsigned long USItype;
> +typedef long long DItype;
> +typedef unsigned long long DSItype;
> +
> +#include "longlong.h"
> +
> +
> +typedef int word_type;
> +typedef long Wtype;
> +typedef long long DWtype;
> +
> +struct DWstruct { Wtype low, high;};
> +
> +typedef union
> +{
> + struct DWstruct s;
> + DWtype ll;
> +} DWunion;
> +
> +#define BITS_PER_UNIT 8
> +
> +UDWtype
> +__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp);
> +
> +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
> +};
> +
> +
> +DWtype
> +__ashldi3 (DWtype u, word_type b)
> +{
> + if (b == 0)
> + return u;
> +
> + const DWunion uu = {.ll = u};
> + const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - 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;
> +}
> +
> +DWtype
> +__ashrdi3 (DWtype u, word_type b)
> +{
> + if (b == 0)
> + return u;
> +
> + const DWunion uu = {.ll = u};
> + const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b;
> + DWunion w;
> +
> + if (bm <= 0)
> + {
> + /* w.s.high = 1..1 or 0..0 */
> + w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 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;
> +}
> +
> +DWtype
> +__lshrdi3 (DWtype u, word_type b)
> +{
> + if (b == 0)
> + return u;
> +
> + const DWunion uu = {.ll = u};
> + const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - 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;
> +}
> +
> +word_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;
> +}
> +
> +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;
> +}
> +
> +DWtype
> +__divdi3 (DWtype u, DWtype v)
> +{
> + word_type 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;
> +}
> +
> +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;
> +}
> +
> +
> +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;
> +}
> +
> +DWtype
> +__moddi3 (DWtype u, DWtype v)
> +{
> + word_type 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;
> +}
> +
> +word_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;
> +}
> +
> +
> +UDWtype
> +__udivdi3 (UDWtype n, UDWtype d)
> +{
> + return __udivmoddi4 (n, d, (UDWtype *) 0);
> +}
> +
> +UDWtype
> +__umoddi3 (UDWtype u, UDWtype v)
> +{
> + UDWtype w;
> + (void) __udivmoddi4 (u, v, &w);
> +
> + return w;
> +}
> +
> +static USItype
> +udivmodsi4(USItype num, USItype den, word_type modwanted)
> +{
> + USItype bit = 1;
> + USItype res = 0;
> +
> + while (den < num && bit && !(den & (1L<<31)))
> + {
> + den <<=1;
> + bit <<=1;
> + }
> + while (bit)
> + {
> + if (num >= den)
> + {
> + num -= den;
> + res |= bit;
> + }
> + bit >>=1;
> + den >>=1;
> + }
> + if (modwanted) return num;
> + return res;
> +}
> +
> +SItype
> +__divsi3 (SItype a, SItype b)
> +{
> + word_type neg = 0;
> + SItype res;
> +
> + if (a < 0)
> + {
> + a = -a;
> + neg = !neg;
> + }
> +
> + if (b < 0)
> + {
> + b = -b;
> + neg = !neg;
> + }
> +
> + res = udivmodsi4 (a, b, 0);
> +
> + if (neg)
> + res = -res;
> +
> + return res;
> +}
> +
> +
> +SItype
> +__udivsi3 (SItype a, SItype b)
> +{
> + return udivmodsi4 (a, b, 0);
> +}
> +
> +
> +SItype
> +__modsi3 (SItype a, SItype b)
> +{
> + word_type neg = 0;
> + SItype res;
> +
> + if (a < 0)
> + {
> + a = -a;
> + neg = 1;
> + }
> +
> + if (b < 0)
> + b = -b;
> +
> + res = udivmodsi4 (a, b, 1);
> +
> + if (neg)
> + res = -res;
> +
> + return res;
> +}
> +
> +SItype
> +__mulsi3 (SItype a, SItype b)
> +{
> + SItype res = 0;
> + USItype cnt = a;
> +
> + while (cnt)
> + {
> + if (cnt & 1)
> + {
> + res += b;
> + }
> + b <<= 1;
> + cnt >>= 1;
> + }
> +
> + return res;
> +}
> +
> +SItype
> +__umodsi3 (SItype a, SItype b)
> +
> +{
> + return udivmodsi4 (a, b, 1);
> +}
> +
> +int
> +__gcc_bcmp (const unsigned char *s1, const unsigned char *s2, unsigned long size)
> +{
> + while (size > 0)
> + {
> + const unsigned char c1 = *s1++, c2 = *s2++;
> + if (c1 != c2)
> + return c1 - c2;
> + size--;
> + }
> + return 0;
> +}
> diff --git a/arch/nios2/lib/longlong.h b/arch/nios2/lib/longlong.h
> new file mode 100644
> index 0000000..392f7e7
> --- /dev/null
> +++ b/arch/nios2/lib/longlong.h
> @@ -0,0 +1,263 @@
> +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic.
> + Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2004,
> + 2005 Free Software Foundation, Inc.
> +
> + This definition file is free software; you can redistribute it
> + and/or modify it under the terms of the GNU General Public
> + License as published by the Free Software Foundation; either
> + version 2, or (at your option) any later version.
> +
> + This definition file is distributed in the hope that it will be
> + useful, but WITHOUT ANY WARRANTY; without even the implied
> + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
> + See the GNU General Public License for more details.
> +
> + You should have received a copy of the GNU General Public License
> + along with this program; if not, write to the Free Software
> + Foundation, Inc., 51 Franklin Street, Fifth Floor,
> + Boston, MA 02110-1301, USA. */
> +
> +/* 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
> +
> +extern const UQItype __clz_tab[256];
> +
> +/* 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.) */
> +
> +/* Snipped per CPU support */
> +
> +/* 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/arch/nios2/lib/math.h b/arch/nios2/lib/math.h
> deleted file mode 100644
> index f0aed8e..0000000
> --- a/arch/nios2/lib/math.h
> +++ /dev/null
> @@ -1,16 +0,0 @@
> -#define BITS_PER_UNIT 8
> -
> -typedef int HItype __attribute__ ((mode (HI)));
> -typedef unsigned int UHItype __attribute__ ((mode (HI)));
> -
> -typedef int SItype __attribute__ ((mode (SI)));
> -typedef unsigned int USItype __attribute__ ((mode (SI)));
> -
> -typedef int word_type __attribute__ ((mode (__word__)));
> -
> -struct SIstruct {HItype low, high;};
> -
> -typedef union {
> - struct SIstruct s;
> - SItype ll;
> -} SIunion;
> diff --git a/arch/nios2/lib/mult.c b/arch/nios2/lib/mult.c
> deleted file mode 100644
> index ec8139e..0000000
> --- a/arch/nios2/lib/mult.c
> +++ /dev/null
> @@ -1,56 +0,0 @@
> -/*
> - * This file is part of GNU CC.
> - *
> - * GNU CC is free software; you can redistribute it and/or modify
> - * it under the terms of the GNU General Public License as published
> - * by the Free Software Foundation; either version 2, or (at your
> - * option) any later version.
> - *
> - * GNU CC is distributed in the hope that it will be useful,
> - * but WITHOUT ANY WARRANTY; without even the implied warranty of
> - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> - * GNU General Public License for more details.
> - *
> - * You should have received a copy of the GNU General Public
> - * License along with GNU CC; see the file COPYING. If not, write
> - * to the Free Software Foundation, 59 Temple Place - Suite 330,
> - * Boston, MA 02111-1307, USA.
> - */
> -
> -
> -#include <common.h>
> -
> -#if !defined(CONFIG_SYS_NIOS_MULT_HW) && !defined(CONFIG_SYS_NIOS_MULT_MSTEP)
> -
> -#include "math.h"
> -
> -USItype __mulsi3 (USItype a, USItype b)
> -{
> - USItype c = 0;
> -
> - while (a != 0) {
> - if (a & 1)
> - c += b;
> - a >>= 1;
> - b <<= 1;
> - }
> -
> - return c;
> -}
> -
> -
> -UHItype __mulhi3 (UHItype a, UHItype b)
> -{
> - UHItype c = 0;
> -
> - while (a != 0) {
> - if (a & 1)
> - c += b;
> - a >>= 1;
> - b <<= 1;
> - }
> -
> - return c;
> -}
> -
> -#endif /*!defined(CONFIG_SYS_NIOS_MULT_HW) && !defined(CONFIG_SYS_NIOS_MULT_MSTEP) */
next prev parent reply other threads:[~2010-05-25 20:58 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-14 22:00 [U-Boot] [PATCH] nios2: fix r15 issue for gcc4 Thomas Chou
2010-05-14 22:00 ` [U-Boot] [PATCH] nios2: fix div64 " Thomas Chou
2010-05-25 20:58 ` Scott McNutt [this message]
2010-05-19 23:11 ` [U-Boot] [PATCH] nios2: fix r15 " Mike Frysinger
2010-05-20 1:32 ` Thomas Chou
2010-05-21 3:08 ` [U-Boot] [PATCH] nios2: allow STANDALONE_LOAD_ADDR overriding Thomas Chou
2010-05-25 20:58 ` Scott McNutt
2010-05-21 3:08 ` [U-Boot] [PATCH v2] nios2: fix r15 issue for gcc4 Thomas Chou
2010-05-25 20:57 ` Scott McNutt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4BFC39FA.1080802@psyent.com \
--to=smcnutt@psyent.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.