On 11/01/13 18:22, Segher Boessenkool wrote:
So, how to implement this. Firstly, we should have the same behaviour for *all* divide insns (/ u/ mod umod /mod u/mod um/mod mu/mod sm/rem fm/mod and whatever I forgot), not just um/mod and those words derived from it. Secondly, we get what we want if we just use the machine's (or C's) divide operator. So it seems the actual problem (if there is one at all) is that OpenBIOS' mu/mod does not behave as the hardware would. Related, / and the other single-precision division words do not need to call mu/mod (which is very expensive), they can much cheaper be implemented as C words (cheaper in execution time that is -- it costs more code :-) )
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... */ }
.. .. }
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.
ATB,
Mark.