Subject: toolchain/22452: programs broken b/c libgcc1 functions are in libc, not libgcc
To: None <gnats-bugs@gnats.NetBSD.org>
From: None <uwe@netbsd.org>
List: netbsd-bugs
Date: 08/12/2003 12:46:48
>Number:         22452
>Category:       toolchain
>Synopsis:       programs broken b/c libgcc1 functions are in libc, not libgcc
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    toolchain-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Aug 12 12:47:00 UTC 2003
>Closed-Date:
>Last-Modified:
>Originator:     Valeriy E. Ushakov
>Release:        1.6W
>Organization:
>Environment:
NetBSD nada 1.6W NetBSD 1.6W (NADA) #15: Fri Aug  8 04:21:34 MSD 2003  uwe@sampo:/export/netbsd/cvs/src/sys/arch/hpcsh/compile/NADA hpcsh
>Description:
With gcc-2.95.3 sh3 ports were limited to static world.  Now that
gcc-3.3.1 is in the tree, sh3 ports can be compiled to use shared
libraries, however the resulting world has many important binaries
broken (fsck_ffs, ksh, mv, sshd - to name a few).  I used to run
dynamic sh3 words before, built with gcc-3.3 as EXTERNAL_TOOLCHAIN and
it worked fine.

The problem is caused by the fact that in NetBSD platform's libgcc1
functions are part of libc, not libgcc.

In my case i traced the lossage down to __udivsi3 function (or
pseudo-instruction, if you will).

__udivsi3_i1 instruction is not treated as a normal function call that
clobbers all the scratch registers.  In sh.md it is defined to clobber
only a couple of registers.

However, since in NetBSD this function is in libc, when the shared
libc.so is used, the call to __udivsi3 (in libc.so) will clobber the
scratch registers because it has to go through the dynamic linker.  In
other words, a call to __udivsi3 in a shared library doesn't really
satisfy the constraints of sh.md.

In a stock gcc distribution, this function is in libgcc.a, so the code
is correct and the dynamic world built in such way worked fine.  But
when the __udivsi3 is in the libc.so - the code generated by the gcc
is simply not correct (keeps values in scratch registers across a
function call).

I'd say that this is our fault that we put __udivsi3 (and other
libgcc1 functions) into libc.  We should move it back to libgcc where
it belongs, because the code generated by the gcc depends on it.

>How-To-Repeat:
Build world for a sh3 platform using gcc-3.3.1 by specifying USE_TOOLS_TOOLCHAIN=no

Make sure that NOPIC is not defined by bsd.own.mk. Setting HAVE_GCC3
might be ok though I'm not sure if it has other effect.  I simply
commented that piece of bsd.own.mk out for my builds.

Try to run the produced binaries.  Observe some of them fail
in misterious ways.  E.g.

$ mv a b
mv: out of memory!


>Fix:
Functions like __udivsi3 should be moved to libgcc.a.
Manually adding relevant .o files from libc.a to libgcc.a and
relinking the failing binaries made them work.

libgcc1 functions are in lib/libc/arch/${MACHINE}/gen/
For sh3 those are (if i haven't missed some): 

ashiftrt.S
ashlsi3.S
ashrsi3.S
lshrsi3.S
movstr.S
movstrSI.S
movstr_i4.S
mulsi3.S
sdivsi3.S
udivsi3.S

>Release-Note:
>Audit-Trail:
>Unformatted: