On Mon, Oct 1, 2012 at 6:56 AM, R. Diez <[email protected]> wrote:
> I didn't want to invest much time into this problem, so I thought I could use
> just one signed 33x33->66 bit multiplier for both signed and unsigned
> integers. For signed numbers, I could sign-extend 32-bit integers to 33 bits,
> for unsigned numbers, I could just prepend an extra zero bit. I could derive
> the Carry and Overflow flags from the 66-bit result. I could think harder
> about it and optimise further at a later point in time.
You only need one multiplier to do both signed and unsigned. 32x32 ->
64-bit multiplication is identical whether the operands are to
interpreted as signed or unsigned, as long as you interpret the result
the same way. So all you need to worry about is the CY and OV bits if
you use a full multiplier.
>I was also planning to add a Special Purpose Register and store the high-order
>32 bits from the final 64-bit result, as discussed in this Forum a few days
>ago. If I had to calculate the full 64 bits, I might as well make them all
>available to the software.
I wouldn't suggest this. I think we should leave the current opcodes
the way they are. Then I'd add another multiply opcode that drops
the result in the MACHI and MACLO registers. If you want the high
part you'd have to use a mfspr instruction. I also think we should
fix the MAC to do a 32x32-bit to 64-bit multiply, and use a full
64-bit add.
>
> However, I hit the following test case:
>
> l.mul -2 * -3 ( 0xfffffffe * 0xfffffffd )
>
> which yields 0x0000000000000006, but or1ksim wanted the Carry flag set in
> this case.
This is the code responsible:
/* We have 1's complement overflow, if, as an unsigned operation, the result
is greater than the largest possible 32-bit unsigned number. This is
probably quicker than unpicking the bits of the signed result. */
ultemp1 = (ULONGEST) temp1 & 0xffffffffULL;
ultemp2 = (ULONGEST) temp2 & 0xffffffffULL;
ultemp0 = ultemp1 * ultemp2;
if (ultemp0 > (ULONGEST) UINT32_MAX)
{
cpu_state.sprs[SPR_SR] |= SPR_SR_CY;
}
else
{
cpu_state.sprs[SPR_SR] &= ~SPR_SR_CY;
}
The comment indicates the Carry flag interprets the operands as
unsigned values. In this case, -2 and -3 are actually very large, and
multiply out to a number that's larger than what can be stored in 32
bits. So I think or1ksim is correct in this case.
-Pete
_______________________________________________
OpenRISC mailing list
[email protected]
http://lists.openrisc.net/listinfo/openrisc