[U-Boot-Users] U-Boot with gcc-3.3.2 and ARM926EJS Targets fails due to __udiv0

Hi folks,
I'm currently porting U-Boot 1.0.0 to a NetSilicon NS9750 (ARM926EJS core). This port is partly derived from board/omap1610inn. The compiler is gcc-3.3.2, taken from the uClibc toolchain.
For my target the compiler is using his internal libgcc.a:__div0 routine which of course fails (it's an SWI instruction). But compiling U-Boot for an smdk2410 platform with the same compiler uses the correct U-Boot's own __div0 code. I can't see any relevant differences in both build lines.
Can anyone help me? And is it really necessary to include libgcc.a?
The build line for the NS9750: ======================== UNDEF_SYM=`arm-linux-objdump -x board/ns9750dev/libns9750dev.a cpu/arm926ejs/libarm926ejs.a lib_arm/libarm.a fs/jffs2/libjffs2.a fs/fdos/libfdos.a fs/fat/libfat.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/sk98lin/libsk98lin.a post/libpost.a post/cpu/libcpu.a common/libcommon.a lib_generic/libgeneric.a |sed -n -e 's/.*(__u_boot_cmd_.*)/-u\1/p'|sort|uniq`;\ arm-linux-ld -Bstatic -T /targets/ewp/LxMOD/build/apps/u-boot-1.0.0/board/ns9750dev/u-boot.lds -Ttext 0x00F80000 $UNDEF_SYM cpu/arm926ejs/start.o \ --start-group board/ns9750dev/libns9750dev.a cpu/arm926ejs/libarm926ejs.a lib_arm/libarm.a fs/jffs2/libjffs2.a fs/fdos/libfdos.a fs/fat/libfat.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/sk98lin/libsk98lin.a post/libpost.a post/cpu/libcpu.a common/libcommon.a lib_generic/libgeneric.a -L /usr/local/LxNETES-3/arm-linux/lib/gcc-lib/arm-linux/3.3.2 -lgcc --end-group \ -Map u-boot.map -o u-boot ========================
The relevant entry in u-boot.map for __div0:
=========================== /usr/local/LxNETES-3/arm-linux/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_udivsi3.o) drivers/libdrivers.a(serial_ns9750.o) (__udivsi3) / Compilation ============================
The build line for SMDK2410
=======================- UNDEF_SYM=`arm-linux-objdump -x board/smdk2410/libsmdk2410.a cpu/arm920t/libarm920t.a lib_arm/libarm.a fs/jffs2/libjffs2.a fs/fdos/libfdos.a fs/fat/libfat.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/sk98lin/libsk98lin.a post/libpost.a post/cpu/libcpu.a common/libcommon.a lib_generic/libgeneric.a |sed -n -e 's/.*(__u_boot_cmd_.*)/-u\1/p'|sort|uniq`;\ arm-linux-ld -Bstatic -T /targets/ewp/LxMOD/build/apps/u-boot.smdk/board/smdk2410/u-boot.lds -Ttext 0x33F80000 $UNDEF_SYM cpu/arm920t/start.o \ --start-group board/smdk2410/libsmdk2410.a cpu/arm920t/libarm920t.a lib_arm/libarm.a fs/jffs2/libjffs2.a fs/fdos/libfdos.a fs/fat/libfat.a net/libnet.a disk/libdisk.a rtc/librtc.a dtt/libdtt.a drivers/libdrivers.a drivers/sk98lin/libsk98lin.a post/libpost.a post/cpu/libcpu.a common/libcommon.a lib_generic/libgeneric.a -L /usr/local/LxNETES-3/arm-linux/lib/gcc-lib/arm-linux/3.3.2 -lgcc --end-group \ -Map u-boot.map -o u-boot ===================
The relevant entry in u-boot.map for __div0:
==================== lib_arm/libarm.a(_udivsi3.o) cpu/arm920t/libarm920t.a(speed.o) (__udivsi3)

Markus Pietrek maillist@fsforth.de schreibt:
For my target the compiler is using his internal libgcc.a:__div0 routine which of course fails (it's an SWI instruction). But compiling U-Boot for an smdk2410 platform with the same compiler uses the correct U-Boot's own __div0 code. I can't see any relevant differences in both build lines.
Hi,
your compiler wasn't built for a stand-alone target, otherwise it would have included a full implementation of __div0, __udivsi3 etc. However, there might be an easy solution to your problem, see below.
Can anyone help me? And is it really necessary to include libgcc.a?
The build line for the NS9750:
/usr/local/LxNETES-3/arm-linux/lib/gcc-lib/arm-linux/3.3.2/libgcc.a(_udivsi3.o) drivers/libdrivers.a(serial_ns9750.o) (__udivsi3)
The build line for SMDK2410
lib_arm/libarm.a(_udivsi3.o) cpu/arm920t/libarm920t.a(speed.o) (__udivsi3)
The reason for the difference is the link order: For SMDK2410, __udivsi3 is needed by a module linked before libarm.a (in this case, cpu/arm920t/speed.c), whereas for NS9750 no module before or in libarm.a needs it; drivers/libdrivers.a is linked after libarm.a, so the linker won't go back to get __udivsi3 there and falls back to using libgcc.a, which is linked last.
One solution could be to change the link order (link libarm.a last); another (dirty) solution to add some code to your board-specific code that needs __udivsi3. I'd prefer the former, of course.
Please try the attached quick patch and let us know if it solves the problem (or if it breaks thing). Caveat - I haven't tried it myself yet!
Cheers Anders

In message fc.004c4e48002071d73b9aca009ccdb13f.207378@rea.de you wrote:
your compiler wasn't built for a stand-alone target, otherwise
can you please explain what you mean with this statement? It's rather cryptic for me. I never built GCC "for a stand-alone target", and yet I always was able to use it without problems including for U-Boot.
The reason for the difference is the link order:
This is most definitely NOT the reason.
One solution could be to change the link order (link libarm.a last);
This makes no sense to me.
If you look carefully at the link statement you might notice that all the libraries are enclosed by a "--start-group ... --end-group" sequence.
Reading TFM:
The specified archives are searched repeatedly until no new undefined references are created. Normally, an archive is searched only once in the order that it is specified on the command line. If a symbol in that archive is needed to resolve an undefined symbol referred to by an object in an archive that appears later on the command line, the linker would not be able to resolve that reference. By grouping the archives, they all be searched repeatedly until all possible references are resolved.
Best regards,
Wolfgang Denk

Hello,
your compiler wasn't built for a stand-alone target, otherwise it would have included a full implementation of __div0, __udivsi3 etc. However, there might be an easy solution to your problem, see below.
There is a full set already available in the gcc? But anyway, it makes not much sense using two different gcc compilers. One for the bootloader, one for applications. And with which one has the linux kernel to be compiled?
The reason for the difference is the link order: For SMDK2410, __udivsi3 is needed by a module linked before libarm.a (in this case, cpu/arm920t/speed.c), whereas for NS9750 no module before or in libarm.a needs it; drivers/libdrivers.a is linked after libarm.a, so the linker won't go back to get __udivsi3 there and falls back to using libgcc.a, which is linked last.
Yes, of course. Now I see it. I'm needing the non-power 2 division only in the serial driver for calculation the baudrate divisior. And libdrivers has been after libarm :-(
Please try the attached quick patch and let us know if it solves the problem (or if it breaks thing). Caveat - I haven't tried it myself yet!
Thank you, it works fine. Therefore, in the near future a new board and CPU will be supported by U-Boot :-)
Bye,

Markus,
On Thu, Jan 29, 2004 at 09:37:25AM +0100, Markus Pietrek wrote:
There is a full set already available in the gcc? But anyway, it makes not much sense using two different gcc compilers. One for the bootloader, one for applications. And with which one has the linux kernel to be compiled?
It looks like I have fixed the problems with softfloat support in gcc-3.3.2 in PTXdist; they first came up when I tried to compile U-Boot and the linker claimed that libgcc wouldn't have softfloat support included. If you want to give it a try, download a snapshot from
http://www.pengutronix.de/software/ptxdist/ptxdist-20040201-1.tgz
and try it out with
make toolchain-arm-linux-3.3.2_config make world
Thank you, it works fine. Therefore, in the near future a new board and CPU will be supported by U-Boot :-)
The Atmel one? Which board are you working with?
Robert
participants (4)
-
Anders Larsen
-
Markus Pietrek
-
Robert Schwebel
-
Wolfgang Denk