* [U-Boot] [PATCH] nios2: fix r15 issue for gcc4
@ 2010-05-14 22:00 Thomas Chou
2010-05-14 22:00 ` [U-Boot] [PATCH] nios2: fix div64 " Thomas Chou
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Thomas Chou @ 2010-05-14 22:00 UTC (permalink / raw)
To: u-boot
The "-ffixed-r15" option doesn't work well for gcc4. Since we
don't use gp for small data with option "-G0", we can use gp
as global data pointer. This allows compiler to use r15. It
is necessary for gcc4 to work properly.
Signed-off-by: Thomas Chou <thomas@wytron.com.tw>
---
arch/nios2/config.mk | 2 +-
arch/nios2/cpu/start.S | 7 -------
arch/nios2/include/asm/global_data.h | 2 +-
3 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/arch/nios2/config.mk b/arch/nios2/config.mk
index 8e5d6ef..6789038 100644
--- a/arch/nios2/config.mk
+++ b/arch/nios2/config.mk
@@ -27,6 +27,6 @@ CROSS_COMPILE ?= nios2-elf-
STANDALONE_LOAD_ADDR = 0x02000000 -L $(gcclibdir)
PLATFORM_CPPFLAGS += -DCONFIG_NIOS2 -D__NIOS2__
-PLATFORM_CPPFLAGS += -ffixed-r15 -G0
+PLATFORM_CPPFLAGS += -G0
LDSCRIPT ?= $(SRCTREE)/$(CPUDIR)/u-boot.lds
diff --git a/arch/nios2/cpu/start.S b/arch/nios2/cpu/start.S
index d1016ea..76d3b52 100644
--- a/arch/nios2/cpu/start.S
+++ b/arch/nios2/cpu/start.S
@@ -113,13 +113,6 @@ _cur: movhi r5, %hi(_cur - _start)
bne r5, r6, 4b
5:
- /* GLOBAL POINTER -- the global pointer is used to reference
- * "small data" (see -G switch). The linker script must
- * provide the gp address.
- */
- movhi gp, %hi(_gp)
- ori gp, gp, %lo(_gp)
-
/* JUMP TO RELOC ADDR */
movhi r4, %hi(_reloc)
ori r4, r4, %lo(_reloc)
diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h
index 34aa962..f1b3482 100644
--- a/arch/nios2/include/asm/global_data.h
+++ b/arch/nios2/include/asm/global_data.h
@@ -48,6 +48,6 @@ typedef struct global_data {
#define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */
#define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */
-#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("r15")
+#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("gp")
#endif /* __ASM_NIOS2_GLOBALDATA_H_ */
--
1.5.5.6
^ permalink raw reply related [flat|nested] 9+ messages in thread* [U-Boot] [PATCH] nios2: fix div64 issue for gcc4 2010-05-14 22:00 [U-Boot] [PATCH] nios2: fix r15 issue for gcc4 Thomas Chou @ 2010-05-14 22:00 ` Thomas Chou 2010-05-25 20:58 ` Scott McNutt 2010-05-19 23:11 ` [U-Boot] [PATCH] nios2: fix r15 " Mike Frysinger ` (2 subsequent siblings) 3 siblings, 1 reply; 9+ messages in thread From: Thomas Chou @ 2010-05-14 22:00 UTC (permalink / raw) To: u-boot 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) */ -- 1.5.5.6 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [U-Boot] [PATCH] nios2: fix div64 issue for gcc4 2010-05-14 22:00 ` [U-Boot] [PATCH] nios2: fix div64 " Thomas Chou @ 2010-05-25 20:58 ` Scott McNutt 0 siblings, 0 replies; 9+ messages in thread From: Scott McNutt @ 2010-05-25 20:58 UTC (permalink / raw) To: u-boot 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) */ ^ permalink raw reply [flat|nested] 9+ messages in thread
* [U-Boot] [PATCH] nios2: fix r15 issue for gcc4 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-19 23:11 ` 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-21 3:08 ` [U-Boot] [PATCH v2] nios2: fix r15 issue for gcc4 Thomas Chou 3 siblings, 1 reply; 9+ messages in thread From: Mike Frysinger @ 2010-05-19 23:11 UTC (permalink / raw) To: u-boot On Friday 14 May 2010 18:00:04 Thomas Chou wrote: > The "-ffixed-r15" option doesn't work well for gcc4. Since we > don't use gp for small data with option "-G0", we can use gp > as global data pointer. This allows compiler to use r15. It > is necessary for gcc4 to work properly. > > Signed-off-by: Thomas Chou <thomas@wytron.com.tw> > --- > arch/nios2/config.mk | 2 +- > arch/nios2/cpu/start.S | 7 ------- > arch/nios2/include/asm/global_data.h | 2 +- > 3 files changed, 2 insertions(+), 9 deletions(-) i think you also need to update examples/standalone/stubs.c maybe also document things in README and doc/README.standalone ? -mike -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 836 bytes Desc: This is a digitally signed message part. Url : http://lists.denx.de/pipermail/u-boot/attachments/20100519/11d0b8b8/attachment.pgp ^ permalink raw reply [flat|nested] 9+ messages in thread
* [U-Boot] [PATCH] nios2: fix r15 issue for gcc4 2010-05-19 23:11 ` [U-Boot] [PATCH] nios2: fix r15 " Mike Frysinger @ 2010-05-20 1:32 ` Thomas Chou 0 siblings, 0 replies; 9+ messages in thread From: Thomas Chou @ 2010-05-20 1:32 UTC (permalink / raw) To: u-boot Mike Frysinger wrote: > On Friday 14 May 2010 18:00:04 Thomas Chou wrote: >> The "-ffixed-r15" option doesn't work well for gcc4. Since we >> don't use gp for small data with option "-G0", we can use gp >> as global data pointer. This allows compiler to use r15. It >> is necessary for gcc4 to work properly. >> >> Signed-off-by: Thomas Chou <thomas@wytron.com.tw> >> --- >> arch/nios2/config.mk | 2 +- >> arch/nios2/cpu/start.S | 7 ------- >> arch/nios2/include/asm/global_data.h | 2 +- >> 3 files changed, 2 insertions(+), 9 deletions(-) > > i think you also need to update examples/standalone/stubs.c > > maybe also document things in README and doc/README.standalone ? > -mike Dear Mike, Thank you very mcuh. The nios2 gd usage was not documented. I will add it to README and doc/README.standalone. I will update examples/standalone/stubs.c, too. Best regards, Thomas ^ permalink raw reply [flat|nested] 9+ messages in thread
* [U-Boot] [PATCH] nios2: allow STANDALONE_LOAD_ADDR overriding 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-19 23:11 ` [U-Boot] [PATCH] nios2: fix r15 " Mike Frysinger @ 2010-05-21 3:08 ` 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 3 siblings, 1 reply; 9+ messages in thread From: Thomas Chou @ 2010-05-21 3:08 UTC (permalink / raw) To: u-boot This patch allows users to override default STANDALONE_LOAD_ADDR. The gcclibdir path was duplicated in the standalone Makefile and can be removed. Signed-off-by: Thomas Chou <thomas@wytron.com.tw> --- arch/nios2/config.mk | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/arch/nios2/config.mk b/arch/nios2/config.mk index 6789038..793cc43 100644 --- a/arch/nios2/config.mk +++ b/arch/nios2/config.mk @@ -24,7 +24,7 @@ CROSS_COMPILE ?= nios2-elf- -STANDALONE_LOAD_ADDR = 0x02000000 -L $(gcclibdir) +STANDALONE_LOAD_ADDR ?= 0x02000000 PLATFORM_CPPFLAGS += -DCONFIG_NIOS2 -D__NIOS2__ PLATFORM_CPPFLAGS += -G0 -- 1.7.1.86.g0e460 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [U-Boot] [PATCH] nios2: allow STANDALONE_LOAD_ADDR overriding 2010-05-21 3:08 ` [U-Boot] [PATCH] nios2: allow STANDALONE_LOAD_ADDR overriding Thomas Chou @ 2010-05-25 20:58 ` Scott McNutt 0 siblings, 0 replies; 9+ messages in thread From: Scott McNutt @ 2010-05-25 20:58 UTC (permalink / raw) To: u-boot Applied to: git://git.denx.de/u-boot-nios.git next Thanks, --Scott Thomas Chou wrote: > This patch allows users to override default STANDALONE_LOAD_ADDR. > The gcclibdir path was duplicated in the standalone Makefile and > can be removed. > > Signed-off-by: Thomas Chou <thomas@wytron.com.tw> > --- > arch/nios2/config.mk | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/arch/nios2/config.mk b/arch/nios2/config.mk > index 6789038..793cc43 100644 > --- a/arch/nios2/config.mk > +++ b/arch/nios2/config.mk > @@ -24,7 +24,7 @@ > > CROSS_COMPILE ?= nios2-elf- > > -STANDALONE_LOAD_ADDR = 0x02000000 -L $(gcclibdir) > +STANDALONE_LOAD_ADDR ?= 0x02000000 > > PLATFORM_CPPFLAGS += -DCONFIG_NIOS2 -D__NIOS2__ > PLATFORM_CPPFLAGS += -G0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [U-Boot] [PATCH v2] nios2: fix r15 issue for gcc4 2010-05-14 22:00 [U-Boot] [PATCH] nios2: fix r15 issue for gcc4 Thomas Chou ` (2 preceding siblings ...) 2010-05-21 3:08 ` [U-Boot] [PATCH] nios2: allow STANDALONE_LOAD_ADDR overriding Thomas Chou @ 2010-05-21 3:08 ` Thomas Chou 2010-05-25 20:57 ` Scott McNutt 3 siblings, 1 reply; 9+ messages in thread From: Thomas Chou @ 2010-05-21 3:08 UTC (permalink / raw) To: u-boot The "-ffixed-r15" option doesn't work well for gcc4. Since we don't use gp for small data with option "-G0", we can use gp as global data pointer. This allows compiler to use r15. It is necessary for gcc4 to work properly. Signed-off-by: Thomas Chou <thomas@wytron.com.tw> --- v2: update standalone stubs and doc. README | 8 ++++++++ arch/nios2/config.mk | 2 +- arch/nios2/cpu/start.S | 7 ------- arch/nios2/include/asm/global_data.h | 2 +- doc/README.standalone | 13 +++++++------ examples/standalone/stubs.c | 6 +++--- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/README b/README index 81692c0..acb3308 100644 --- a/README +++ b/README @@ -4023,6 +4023,14 @@ On ARM, the following registers are used: ==> U-Boot will use R8 to hold a pointer to the global data +On Nios II, the ABI is documented here: + http://www.altera.com/literature/hb/nios2/n2cpu_nii51016.pdf + + ==> U-Boot will use gp to hold a pointer to the global data + + Note: on Nios II, we give "-G0" option to gcc and don't use gp + to access small data sections, so gp is free. + NOTE: DECLARE_GLOBAL_DATA_PTR must be used with file-global scope, or current versions of GCC may "optimize" the code too much. diff --git a/arch/nios2/config.mk b/arch/nios2/config.mk index 8e5d6ef..6789038 100644 --- a/arch/nios2/config.mk +++ b/arch/nios2/config.mk @@ -27,6 +27,6 @@ CROSS_COMPILE ?= nios2-elf- STANDALONE_LOAD_ADDR = 0x02000000 -L $(gcclibdir) PLATFORM_CPPFLAGS += -DCONFIG_NIOS2 -D__NIOS2__ -PLATFORM_CPPFLAGS += -ffixed-r15 -G0 +PLATFORM_CPPFLAGS += -G0 LDSCRIPT ?= $(SRCTREE)/$(CPUDIR)/u-boot.lds diff --git a/arch/nios2/cpu/start.S b/arch/nios2/cpu/start.S index d1016ea..76d3b52 100644 --- a/arch/nios2/cpu/start.S +++ b/arch/nios2/cpu/start.S @@ -113,13 +113,6 @@ _cur: movhi r5, %hi(_cur - _start) bne r5, r6, 4b 5: - /* GLOBAL POINTER -- the global pointer is used to reference - * "small data" (see -G switch). The linker script must - * provide the gp address. - */ - movhi gp, %hi(_gp) - ori gp, gp, %lo(_gp) - /* JUMP TO RELOC ADDR */ movhi r4, %hi(_reloc) ori r4, r4, %lo(_reloc) diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h index 34aa962..f1b3482 100644 --- a/arch/nios2/include/asm/global_data.h +++ b/arch/nios2/include/asm/global_data.h @@ -48,6 +48,6 @@ typedef struct global_data { #define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ #define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ -#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("r15") +#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("gp") #endif /* __ASM_NIOS2_GLOBALDATA_H_ */ diff --git a/doc/README.standalone b/doc/README.standalone index 885c92f..6381087 100644 --- a/doc/README.standalone +++ b/doc/README.standalone @@ -19,12 +19,12 @@ Design Notes on Exporting U-Boot Functions to Standalone Applications: thus the compiler cannot perform type checks on these assignments. 2. The pointer to the jump table is passed to the application in a - machine-dependent way. PowerPC, ARM, MIPS and Blackfin architectures - use a dedicated register to hold the pointer to the 'global_data' - structure: r2 on PowerPC, r8 on ARM, k0 on MIPS, and P3 on Blackfin. - The x86 architecture does not use such a register; instead, the - pointer to the 'global_data' structure is passed as 'argv[-1]' - pointer. + machine-dependent way. PowerPC, ARM, MIPS, Blackfin and Nios II + architectures use a dedicated register to hold the pointer to the + 'global_data' structure: r2 on PowerPC, r8 on ARM, k0 on MIPS, + P3 on Blackfin and gp on Nios II. The x86 architecture does not + use such a register; instead, the pointer to the 'global_data' + structure is passed as 'argv[-1]' pointer. The application can access the 'global_data' structure in the same way as U-Boot does: @@ -56,6 +56,7 @@ Design Notes on Exporting U-Boot Functions to Standalone Applications: ARM 0x0c100000 0x0c100000 MIPS 0x80200000 0x80200000 Blackfin 0x00001000 0x00001000 + Nios II 0x02000000 0x02000000 For example, the "hello world" application may be loaded and executed on a PowerPC board with the following commands: diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c index ce3371d..0187708 100644 --- a/examples/standalone/stubs.c +++ b/examples/standalone/stubs.c @@ -84,7 +84,7 @@ gd_t *global_data; : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x) : "r0"); #elif defined(CONFIG_NIOS2) /* - * r15 holds the pointer to the global_data, r8 is call-clobbered + * gp holds the pointer to the global_data, r8 is call-clobbered */ #define EXPORT_FUNC(x) \ asm volatile ( \ @@ -92,11 +92,11 @@ gd_t *global_data; #x ":\n" \ " movhi r8, %%hi(%0)\n" \ " ori r8, r0, %%lo(%0)\n" \ -" add r8, r8, r15\n" \ +" add r8, r8, gp\n" \ " ldw r8, 0(r8)\n" \ " ldw r8, %1(r8)\n" \ " jmp r8\n" \ - : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r15"); + : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "gp"); #elif defined(CONFIG_M68K) /* * d7 holds the pointer to the global_data, a0 is a call-clobbered -- 1.7.1.86.g0e460 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [U-Boot] [PATCH v2] nios2: fix r15 issue for gcc4 2010-05-21 3:08 ` [U-Boot] [PATCH v2] nios2: fix r15 issue for gcc4 Thomas Chou @ 2010-05-25 20:57 ` Scott McNutt 0 siblings, 0 replies; 9+ messages in thread From: Scott McNutt @ 2010-05-25 20:57 UTC (permalink / raw) To: u-boot Applied to: git://git.denx.de/u-boot-nios.git next Thanks, --Scott Thomas Chou wrote: > The "-ffixed-r15" option doesn't work well for gcc4. Since we > don't use gp for small data with option "-G0", we can use gp > as global data pointer. This allows compiler to use r15. It > is necessary for gcc4 to work properly. > > Signed-off-by: Thomas Chou <thomas@wytron.com.tw> > --- > v2: update standalone stubs and doc. > > README | 8 ++++++++ > arch/nios2/config.mk | 2 +- > arch/nios2/cpu/start.S | 7 ------- > arch/nios2/include/asm/global_data.h | 2 +- > doc/README.standalone | 13 +++++++------ > examples/standalone/stubs.c | 6 +++--- > 6 files changed, 20 insertions(+), 18 deletions(-) > > diff --git a/README b/README > index 81692c0..acb3308 100644 > --- a/README > +++ b/README > @@ -4023,6 +4023,14 @@ On ARM, the following registers are used: > > ==> U-Boot will use R8 to hold a pointer to the global data > > +On Nios II, the ABI is documented here: > + http://www.altera.com/literature/hb/nios2/n2cpu_nii51016.pdf > + > + ==> U-Boot will use gp to hold a pointer to the global data > + > + Note: on Nios II, we give "-G0" option to gcc and don't use gp > + to access small data sections, so gp is free. > + > NOTE: DECLARE_GLOBAL_DATA_PTR must be used with file-global scope, > or current versions of GCC may "optimize" the code too much. > > diff --git a/arch/nios2/config.mk b/arch/nios2/config.mk > index 8e5d6ef..6789038 100644 > --- a/arch/nios2/config.mk > +++ b/arch/nios2/config.mk > @@ -27,6 +27,6 @@ CROSS_COMPILE ?= nios2-elf- > STANDALONE_LOAD_ADDR = 0x02000000 -L $(gcclibdir) > > PLATFORM_CPPFLAGS += -DCONFIG_NIOS2 -D__NIOS2__ > -PLATFORM_CPPFLAGS += -ffixed-r15 -G0 > +PLATFORM_CPPFLAGS += -G0 > > LDSCRIPT ?= $(SRCTREE)/$(CPUDIR)/u-boot.lds > diff --git a/arch/nios2/cpu/start.S b/arch/nios2/cpu/start.S > index d1016ea..76d3b52 100644 > --- a/arch/nios2/cpu/start.S > +++ b/arch/nios2/cpu/start.S > @@ -113,13 +113,6 @@ _cur: movhi r5, %hi(_cur - _start) > bne r5, r6, 4b > 5: > > - /* GLOBAL POINTER -- the global pointer is used to reference > - * "small data" (see -G switch). The linker script must > - * provide the gp address. > - */ > - movhi gp, %hi(_gp) > - ori gp, gp, %lo(_gp) > - > /* JUMP TO RELOC ADDR */ > movhi r4, %hi(_reloc) > ori r4, r4, %lo(_reloc) > diff --git a/arch/nios2/include/asm/global_data.h b/arch/nios2/include/asm/global_data.h > index 34aa962..f1b3482 100644 > --- a/arch/nios2/include/asm/global_data.h > +++ b/arch/nios2/include/asm/global_data.h > @@ -48,6 +48,6 @@ typedef struct global_data { > #define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */ > #define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */ > > -#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("r15") > +#define DECLARE_GLOBAL_DATA_PTR register gd_t *gd asm ("gp") > > #endif /* __ASM_NIOS2_GLOBALDATA_H_ */ > diff --git a/doc/README.standalone b/doc/README.standalone > index 885c92f..6381087 100644 > --- a/doc/README.standalone > +++ b/doc/README.standalone > @@ -19,12 +19,12 @@ Design Notes on Exporting U-Boot Functions to Standalone Applications: > thus the compiler cannot perform type checks on these assignments. > > 2. The pointer to the jump table is passed to the application in a > - machine-dependent way. PowerPC, ARM, MIPS and Blackfin architectures > - use a dedicated register to hold the pointer to the 'global_data' > - structure: r2 on PowerPC, r8 on ARM, k0 on MIPS, and P3 on Blackfin. > - The x86 architecture does not use such a register; instead, the > - pointer to the 'global_data' structure is passed as 'argv[-1]' > - pointer. > + machine-dependent way. PowerPC, ARM, MIPS, Blackfin and Nios II > + architectures use a dedicated register to hold the pointer to the > + 'global_data' structure: r2 on PowerPC, r8 on ARM, k0 on MIPS, > + P3 on Blackfin and gp on Nios II. The x86 architecture does not > + use such a register; instead, the pointer to the 'global_data' > + structure is passed as 'argv[-1]' pointer. > > The application can access the 'global_data' structure in the same > way as U-Boot does: > @@ -56,6 +56,7 @@ Design Notes on Exporting U-Boot Functions to Standalone Applications: > ARM 0x0c100000 0x0c100000 > MIPS 0x80200000 0x80200000 > Blackfin 0x00001000 0x00001000 > + Nios II 0x02000000 0x02000000 > > For example, the "hello world" application may be loaded and > executed on a PowerPC board with the following commands: > diff --git a/examples/standalone/stubs.c b/examples/standalone/stubs.c > index ce3371d..0187708 100644 > --- a/examples/standalone/stubs.c > +++ b/examples/standalone/stubs.c > @@ -84,7 +84,7 @@ gd_t *global_data; > : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x) : "r0"); > #elif defined(CONFIG_NIOS2) > /* > - * r15 holds the pointer to the global_data, r8 is call-clobbered > + * gp holds the pointer to the global_data, r8 is call-clobbered > */ > #define EXPORT_FUNC(x) \ > asm volatile ( \ > @@ -92,11 +92,11 @@ gd_t *global_data; > #x ":\n" \ > " movhi r8, %%hi(%0)\n" \ > " ori r8, r0, %%lo(%0)\n" \ > -" add r8, r8, r15\n" \ > +" add r8, r8, gp\n" \ > " ldw r8, 0(r8)\n" \ > " ldw r8, %1(r8)\n" \ > " jmp r8\n" \ > - : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "r15"); > + : : "i"(offsetof(gd_t, jt)), "i"(XF_ ## x * sizeof(void *)) : "gp"); > #elif defined(CONFIG_M68K) > /* > * d7 holds the pointer to the global_data, a0 is a call-clobbered ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-05-25 20:58 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 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 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
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox