[U-Boot] [PATCH] dm: mips: Import libgcc components from Linux

Import ashldr3, ashrdi3 and lshrdi3 to squash possible libgcc fp mismatch, resulting in the following warning:
mips-linux-gnu-ld: Warning: /usr/lib/gcc/mips-linux-gnu/4.7/libgcc.a(_lshrdi3.o) uses hard float, u-boot uses soft float mips-linux-gnu-ld: Warning: /usr/lib/gcc/mips-linux-gnu/4.7/libgcc.a(_ashldi3.o) uses hard float, u-boot uses soft float
Imported from Linux (linux-next 20120723) as of commit:
commit 72fbfb260197a52c2bc2583f3e8f15d261d0f924 Author: Ralf Baechle ralf@linux-mips.org Date: Wed Jun 7 13:25:37 2006 +0100
[MIPS] Fix optimization for size build.
It took a while longer than on other architectures but gcc has finally started to strike us as well ...
This also fixes the damage by 6edfba1b33c701108717f4e036320fc39abe1912.
Signed-off-by: Ralf Baechle ralf@linux-mips.org
Signed-off-by: Marek Vasut marex@denx.de Cc: Daniel Schwierzeck daniel.schwierzeck@googlemail.com --- arch/mips/lib/Makefile | 2 ++ arch/mips/lib/ashldi3.c | 25 +++++++++++++++++++++++++ arch/mips/lib/ashrdi3.c | 27 +++++++++++++++++++++++++++ arch/mips/lib/libgcc.h | 25 +++++++++++++++++++++++++ arch/mips/lib/lshrdi3.c | 25 +++++++++++++++++++++++++ 5 files changed, 104 insertions(+) create mode 100644 arch/mips/lib/ashldi3.c create mode 100644 arch/mips/lib/ashrdi3.c create mode 100644 arch/mips/lib/libgcc.h create mode 100644 arch/mips/lib/lshrdi3.c
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 9244f31..a469e30 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -34,6 +34,8 @@ else COBJS-y += bootm.o endif
+COBJS-y += ashldi3.o ashrdi3.o lshrdi3.o + SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c new file mode 100644 index 0000000..9b50d86 --- /dev/null +++ b/arch/mips/lib/ashldi3.c @@ -0,0 +1,25 @@ +#include "libgcc.h" + +long long __ashldi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.low = 0; + w.s.high = (unsigned int) uu.s.low << -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.low >> bm; + + w.s.low = (unsigned int) uu.s.low << b; + w.s.high = ((unsigned int) uu.s.high << b) | carries; + } + + return w.ll; +} diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c new file mode 100644 index 0000000..f30359b --- /dev/null +++ b/arch/mips/lib/ashrdi3.c @@ -0,0 +1,27 @@ +#include "libgcc.h" + +long long __ashrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = + uu.s.high >> 31; + w.s.low = uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +} diff --git a/arch/mips/lib/libgcc.h b/arch/mips/lib/libgcc.h new file mode 100644 index 0000000..05909d5 --- /dev/null +++ b/arch/mips/lib/libgcc.h @@ -0,0 +1,25 @@ +#ifndef __ASM_LIBGCC_H +#define __ASM_LIBGCC_H + +#include <asm/byteorder.h> + +typedef int word_type __attribute__ ((mode (__word__))); + +#ifdef __BIG_ENDIAN +struct DWstruct { + int high, low; +}; +#elif defined(__LITTLE_ENDIAN) +struct DWstruct { + int low, high; +}; +#else +#error I feel sick. +#endif + +typedef union { + struct DWstruct s; + long long ll; +} DWunion; + +#endif /* __ASM_LIBGCC_H */ diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c new file mode 100644 index 0000000..bb340ac --- /dev/null +++ b/arch/mips/lib/lshrdi3.c @@ -0,0 +1,25 @@ +#include "libgcc.h" + +long long __lshrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.high = 0; + w.s.low = (unsigned int) uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = (unsigned int) uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +}

Dear Mike Frysinger,
On Friday 27 July 2012 14:35:25 Marek Vasut wrote:
--- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -34,6 +34,8 @@ else
COBJS-y += bootm.o endif
+COBJS-y += ashldi3.o ashrdi3.o lshrdi3.o
pretty sure this belongs behind USE_PRIVATE_LIBGCC
Good point ... Mike, I was always wondering what this USE_PRIVATE_LIBGCC is, can you elaborate please (pour some of your knowledge on me ;-) ) ?
-mike
Best regards, Marek Vasut

On Friday 27 July 2012 15:10:00 Marek Vasut wrote:
Dear Mike Frysinger,
On Friday 27 July 2012 14:35:25 Marek Vasut wrote:
--- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -34,6 +34,8 @@ else
COBJS-y += bootm.o endif
+COBJS-y += ashldi3.o ashrdi3.o lshrdi3.o
pretty sure this belongs behind USE_PRIVATE_LIBGCC
Good point ... Mike, I was always wondering what this USE_PRIVATE_LIBGCC is, can you elaborate please (pour some of your knowledge on me ;-) ) ?
libgcc is a supplemental library that gcc provides that often times contains extended routines (usually written in assembly) for implementing math functions that the hardware does not provide itself in the form of dedicated instructions. most commonly, this takes the form of multiplication/divide routines. x86 tends to be "fat" and provide instructions like "mul" and "div", but embedded arches like arm/blackfin/mips/etc... tend to have simpler instructions so we have to implement these in software.
the problem comes in when the toolchain is built targeting an ABI/float model that differs from what we want in u-boot. Linux has long avoided this problem by always bundling the libgcc source files directly into its arch/ tree. it pulls in the bare min that it needs, and then never links with -lgcc.
u-boot has taken the opposite approach: it links against -lgcc for math routines rather than keeping a copy of its own. this leads to the problem you noticed with mips, but many of us have hit it with arm.
for the longest time, the party line was "use a different toolchain". but that's often impractical (if not almost impossible) for many users/devs, so the compromise has been the USE_PRIVATE_LIBGCC knob. now the ABI of the libgcc that comes with your toolchain does not matter because it isn't linked in -- we just compile (for the right ABI) local copies of the math routines, and then link against those.
personally, i wouldn't mind converting everyone to USE_PRIVATE_LIBGCC (and match exactly what Linux has been doing for ages), but i can live with the USE_PRIVATE_LIBGCC trade off. -mike

Import ashldr3, ashrdi3 and lshrdi3 to squash possible libgcc fp mismatch, resulting in the following warning:
mips-linux-gnu-ld: Warning: /usr/lib/gcc/mips-linux-gnu/4.7/libgcc.a(_lshrdi3.o) uses hard float, u-boot uses soft float mips-linux-gnu-ld: Warning: /usr/lib/gcc/mips-linux-gnu/4.7/libgcc.a(_ashldi3.o) uses hard float, u-boot uses soft float
Imported from Linux (linux-next 20120723) as of commit:
commit 72fbfb260197a52c2bc2583f3e8f15d261d0f924 Author: Ralf Baechle ralf@linux-mips.org Date: Wed Jun 7 13:25:37 2006 +0100
[MIPS] Fix optimization for size build.
It took a while longer than on other architectures but gcc has finally started to strike us as well ...
This also fixes the damage by 6edfba1b33c701108717f4e036320fc39abe1912.
Signed-off-by: Ralf Baechle ralf@linux-mips.org
Signed-off-by: Marek Vasut marex@denx.de Cc: Daniel Schwierzeck daniel.schwierzeck@googlemail.com --- arch/mips/config.mk | 2 ++ arch/mips/lib/Makefile | 20 ++++++++++++++++++++ arch/mips/lib/ashldi3.c | 25 +++++++++++++++++++++++++ arch/mips/lib/ashrdi3.c | 27 +++++++++++++++++++++++++++ arch/mips/lib/libgcc.h | 25 +++++++++++++++++++++++++ arch/mips/lib/lshrdi3.c | 25 +++++++++++++++++++++++++ 6 files changed, 124 insertions(+) create mode 100644 arch/mips/lib/ashldi3.c create mode 100644 arch/mips/lib/ashrdi3.c create mode 100644 arch/mips/lib/libgcc.h create mode 100644 arch/mips/lib/lshrdi3.c
V2: Wrap this into USE_PRIVATE_LIBGCC
diff --git a/arch/mips/config.mk b/arch/mips/config.mk index 6ab8acd..4dd1805 100644 --- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -52,3 +52,5 @@ PLATFORM_CPPFLAGS += -msoft-float PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections LDFLAGS_FINAL += --gc-sections + +USE_PRIVATE_LIBGCC = yes diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 9244f31..967e98a 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -25,6 +25,13 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(ARCH).o
+## Build a couple of necessary functions into a private libgcc +LIBGCC = $(obj)libgcc.o +GLSOBJS += ashldi3.o +GLSOBJS += ashrdi3.o +GLSOBJS += lshrdi3.o +LGOBJS := $(addprefix $(obj),$(GLSOBJS)) + SOBJS-y +=
COBJS-y += board.o @@ -37,9 +44,22 @@ endif SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+# Always build libmips.o +TARGETS := $(LIB) + +# Build private libgcc only when asked for +ifdef USE_PRIVATE_LIBGCC +TARGETS += $(LIBGCC) +endif + +all: $(TARGETS) + $(LIB): $(obj).depend $(OBJS) $(call cmd_link_o_target, $(OBJS))
+$(LIBGCC): $(obj).depend $(LGOBJS) + $(call cmd_link_o_target, $(LGOBJS)) + #########################################################################
# defines $(obj).depend target diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c new file mode 100644 index 0000000..9b50d86 --- /dev/null +++ b/arch/mips/lib/ashldi3.c @@ -0,0 +1,25 @@ +#include "libgcc.h" + +long long __ashldi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.low = 0; + w.s.high = (unsigned int) uu.s.low << -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.low >> bm; + + w.s.low = (unsigned int) uu.s.low << b; + w.s.high = ((unsigned int) uu.s.high << b) | carries; + } + + return w.ll; +} diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c new file mode 100644 index 0000000..f30359b --- /dev/null +++ b/arch/mips/lib/ashrdi3.c @@ -0,0 +1,27 @@ +#include "libgcc.h" + +long long __ashrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + /* w.s.high = 1..1 or 0..0 */ + w.s.high = + uu.s.high >> 31; + w.s.low = uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +} diff --git a/arch/mips/lib/libgcc.h b/arch/mips/lib/libgcc.h new file mode 100644 index 0000000..05909d5 --- /dev/null +++ b/arch/mips/lib/libgcc.h @@ -0,0 +1,25 @@ +#ifndef __ASM_LIBGCC_H +#define __ASM_LIBGCC_H + +#include <asm/byteorder.h> + +typedef int word_type __attribute__ ((mode (__word__))); + +#ifdef __BIG_ENDIAN +struct DWstruct { + int high, low; +}; +#elif defined(__LITTLE_ENDIAN) +struct DWstruct { + int low, high; +}; +#else +#error I feel sick. +#endif + +typedef union { + struct DWstruct s; + long long ll; +} DWunion; + +#endif /* __ASM_LIBGCC_H */ diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c new file mode 100644 index 0000000..bb340ac --- /dev/null +++ b/arch/mips/lib/lshrdi3.c @@ -0,0 +1,25 @@ +#include "libgcc.h" + +long long __lshrdi3(long long u, word_type b) +{ + DWunion uu, w; + word_type bm; + + if (b == 0) + return u; + + uu.ll = u; + bm = 32 - b; + + if (bm <= 0) { + w.s.high = 0; + w.s.low = (unsigned int) uu.s.high >> -bm; + } else { + const unsigned int carries = (unsigned int) uu.s.high << bm; + + w.s.high = (unsigned int) uu.s.high >> b; + w.s.low = ((unsigned int) uu.s.low >> b) | carries; + } + + return w.ll; +}

Dear Marek Vasut,
In message 1343417017-26346-1-git-send-email-marex@denx.de you wrote:
Import ashldr3, ashrdi3 and lshrdi3 to squash possible libgcc fp mismatch, resulting in the following warning:
...
--- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -52,3 +52,5 @@ PLATFORM_CPPFLAGS += -msoft-float PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections LDFLAGS_FINAL += --gc-sections
+USE_PRIVATE_LIBGCC = yes
NAK. It is always wrong to mandatorily set this!!
Best regards,
Wolfgang Denk

Dear Wolfgang Denk,
Dear Marek Vasut,
In message 1343417017-26346-1-git-send-email-marex@denx.de you wrote:
Import ashldr3, ashrdi3 and lshrdi3 to squash possible libgcc fp mismatch,
resulting in the following warning:
...
--- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -52,3 +52,5 @@ PLATFORM_CPPFLAGS += -msoft-float
PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections LDFLAGS_FINAL += --gc-sections
+USE_PRIVATE_LIBGCC = yes
NAK. It is always wrong to mandatorily set this!!
How is that a bug in the toolchain? The u-boot shall be completely self- contained, am I wrong?
Best regards,
Wolfgang Denk
Best regards, Marek Vasut

Hi Marek,
2012/7/27 Marek Vasut marex@denx.de:
Dear Wolfgang Denk,
Dear Marek Vasut,
In message 1343417017-26346-1-git-send-email-marex@denx.de you wrote:
Import ashldr3, ashrdi3 and lshrdi3 to squash possible libgcc fp mismatch,
resulting in the following warning:
...
--- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -52,3 +52,5 @@ PLATFORM_CPPFLAGS += -msoft-float
PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections LDFLAGS_FINAL += --gc-sections
+USE_PRIVATE_LIBGCC = yes
NAK. It is always wrong to mandatorily set this!!
How is that a bug in the toolchain? The u-boot shall be completely self- contained, am I wrong?
it's not a bug. You should try with a soft-float or multilib toolchain and not a hard-float one. The very few MIPS CPUs and SoCs we are currently supporting don't have a FPU at all.
Best regards, Daniel

Dear Daniel Schwierzeck,
In message CACUy__UytqvzKEt-ut5ubj5c-QSSxtMtP2RzDfuU9VvjEQtYqg@mail.gmail.com you wrote:
NAK. It is always wrong to mandatorily set this!!
How is that a bug in the toolchain? The u-boot shall be completely self- contained, am I wrong?
it's not a bug. You should try with a soft-float or multilib toolchain and not a hard-float one.
It is a bug. If we explicitly request -msoft-float (and we do that), then the compiler driver must not provide a hard-fp version of libgcc. If he has no soft-fp version, it should raise an error.
Best regards,
Wolfgang Denk

Dear Daniel Schwierzeck,
Hi Marek,
2012/7/27 Marek Vasut marex@denx.de:
Dear Wolfgang Denk,
Dear Marek Vasut,
In message 1343417017-26346-1-git-send-email-marex@denx.de you wrote:
Import ashldr3, ashrdi3 and lshrdi3 to squash possible libgcc fp mismatch,
resulting in the following warning:
...
--- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -52,3 +52,5 @@ PLATFORM_CPPFLAGS += -msoft-float
PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections LDFLAGS_FINAL += --gc-sections
+USE_PRIVATE_LIBGCC = yes
NAK. It is always wrong to mandatorily set this!!
How is that a bug in the toolchain? The u-boot shall be completely self- contained, am I wrong?
it's not a bug. You should try with a soft-float or multilib toolchain and not a hard-float one. The very few MIPS CPUs and SoCs we are currently supporting don't have a FPU at all.
All right, understood. Wolfgang also explained this to me so I know where the problem is. Please ignore this one.
Best regards, Daniel
Best regards, Marek Vasut

Dear Daniel Schwierzeck,
[...]
Urgh ... having this in my crosscompiler buildscripts and pondering why they're broken, that's something only I can do ...
export DEB_CROSS_NO_BIARCH=yes
Best regards, Marek Vasut

Dear Marek Vasut,
In message 201207272202.47977.marex@denx.de you wrote:
How is that a bug in the toolchain? The u-boot shall be completely self- contained, am I wrong?
Yes, you are wrong. U-Boot uses -msoft-float to tell the compiler we are using soft-fp, so the compiler is supposed to select a soft-fp version of libgcc. Yours doesn't.
Best regards,
Wolfgang Denk

2012/7/27 Marek Vasut marex@denx.de:
Import ashldr3, ashrdi3 and lshrdi3 to squash possible libgcc fp mismatch, resulting in the following warning:
mips-linux-gnu-ld: Warning: /usr/lib/gcc/mips-linux-gnu/4.7/libgcc.a(_lshrdi3.o) uses hard float, u-boot uses soft float mips-linux-gnu-ld: Warning: /usr/lib/gcc/mips-linux-gnu/4.7/libgcc.a(_ashldi3.o) uses hard float, u-boot uses soft float
Imported from Linux (linux-next 20120723) as of commit:
commit 72fbfb260197a52c2bc2583f3e8f15d261d0f924 Author: Ralf Baechle ralf@linux-mips.org Date: Wed Jun 7 13:25:37 2006 +0100
[MIPS] Fix optimization for size build. It took a while longer than on other architectures but gcc has finally started to strike us as well ... This also fixes the damage by 6edfba1b33c701108717f4e036320fc39abe1912. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Marek Vasut marex@denx.de Cc: Daniel Schwierzeck daniel.schwierzeck@googlemail.com
arch/mips/config.mk | 2 ++ arch/mips/lib/Makefile | 20 ++++++++++++++++++++ arch/mips/lib/ashldi3.c | 25 +++++++++++++++++++++++++ arch/mips/lib/ashrdi3.c | 27 +++++++++++++++++++++++++++ arch/mips/lib/libgcc.h | 25 +++++++++++++++++++++++++ arch/mips/lib/lshrdi3.c | 25 +++++++++++++++++++++++++ 6 files changed, 124 insertions(+) create mode 100644 arch/mips/lib/ashldi3.c create mode 100644 arch/mips/lib/ashrdi3.c create mode 100644 arch/mips/lib/libgcc.h create mode 100644 arch/mips/lib/lshrdi3.c
V2: Wrap this into USE_PRIVATE_LIBGCC
diff --git a/arch/mips/config.mk b/arch/mips/config.mk index 6ab8acd..4dd1805 100644 --- a/arch/mips/config.mk +++ b/arch/mips/config.mk @@ -52,3 +52,5 @@ PLATFORM_CPPFLAGS += -msoft-float PLATFORM_LDFLAGS += -G 0 -static -n -nostdlib PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections LDFLAGS_FINAL += --gc-sections
+USE_PRIVATE_LIBGCC = yes
I removed that last line as demanded by Wolfgang.
applied to u-boot-mips/master, thanks

Dear Marek Vasut,
In message 1343414125-23359-1-git-send-email-marex@denx.de you wrote:
Import ashldr3, ashrdi3 and lshrdi3 to squash possible libgcc fp mismatch, resulting in the following warning:
mips-linux-gnu-ld: Warning: /usr/lib/gcc/mips-linux-gnu/4.7/libgcc.a(_lshrdi3.o) uses hard float, u-boot uses soft float mips-linux-gnu-ld: Warning: /usr/lib/gcc/mips-linux-gnu/4.7/libgcc.a(_ashldi3.o) uses hard float, u-boot uses soft float
We consider this a bug in the tool chain. We provide a workarounf for such broken tool chains, but it has to be enabled explicitly by setting USE_PRIVATE_LIBGCC
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile index 9244f31..a469e30 100644 --- a/arch/mips/lib/Makefile +++ b/arch/mips/lib/Makefile @@ -34,6 +34,8 @@ else COBJS-y += bootm.o endif
+COBJS-y += ashldi3.o ashrdi3.o lshrdi3.o
Please make this dependent on USE_PRIVATE_LIBGCC being set.
Best regards,
Wolfgang Denk
participants (4)
-
Daniel Schwierzeck
-
Marek Vasut
-
Mike Frysinger
-
Wolfgang Denk