On Sat, Jan 12, 2013 at 2:18 PM, Segher Boessenkool segher@kernel.crashing.org wrote:
Actually this got me thinking, since you're right in that integer division should require a manual trap. This took me into OpenBIOS's bundled version of libgcc and __udivmoddi4.c:
__uint128_t __udivmodti4(__uint128_t num, __uint128_t den, __uint128_t *rem_p) { __uint128_t quot = 0, qbit = 1;
if ( den == 0 ) { __divide_error(); return 0; /* If trap returns... */ }
[It seems you showed __udivmodti4 instead -- but the code is much the same].
That's not libgcc code: it is x86 Linux kernel code or klibc or something like that. Libgcc forces a single-precision divide by zero when the double- precision routine divides by zero, so there can be no problem there.
Some software archeology follows.
The function __udivmoddi4() was added by me in r4 as arch/sparc32/libgcc/__udivmoddi4.c in 2006. Then I moved the file with r61 to its current location in ./libgcc, with R62 copied this to __udivmodti4.c and changed 64 bit types to 128 bits.
This and files __divdi3.c, __udivdi3.c and __umoddi3.c seem to originate from klibc indeed. With 2f6cd4633e623c29bbcb793eff76c8c08c2c0f9c H. Peter Anvin added the files to klibc/arch/i386/libgcc/ in 2002, they have been moved since to usr/klibc/libgcc/ and reformatted. Before reformatting to kernel style, the files were identical to our version except for a header change.
Some klibc files like these are also used by Syslinux, iPXE and gPXE, but they may actually be newer than OpenBIOS r4. So I think I used klibc directly.
As specified by usr/klibc/LICENSE, klibc is a mix of GPLv2only, BSD and MIT licensed files, the default being MIT unless files originate from BSD or Linux. I think these files are therefore MIT licensed. GPLv2only and BSD would be OK for OpenBIOS too.
Files ashldi3.c and ashrdi3.c are from GCC 2.95.2 libgcc which was GPLv2+ at that time (way before GPLv3 switch). GPLv2+ is also fine for OpenBIOS.
The license situation could be clarified by copying the LICENSE from klibc to OpenBIOS.
A quick grep of the source shows that __divide_error() is manually set to the unexpected exception trap handler in start.S:
_GLOBAL(__divide_error): trap_error: mflr r3 LOAD_REG_FUNC(r4, unexpected_excep) mtctr r4 bctr
Heh. So actually all we need to do is provide an empty function for __divide_error() and we magically get the behaviour we want. Revised patch to follow shortly.
Or not have a __divide_error at all, which makes it clearer the intent is to have the double precision divide have the same behaviour as single precision on whatever hardware it runs on. Your patch should work though :-)
Segher
-- OpenBIOS http://openbios.org/ Mailinglist: http://lists.openbios.org/mailman/listinfo Free your System - May the Forth be with you