On Sat, Jun 2, 2012 at 4:35 PM, Julius Baxter <[email protected]> wrote:
> On Tue, May 29, 2012 at 7:02 PM, R. Diez <[email protected]> wrote:
>> Hallo Julius:
>>
>>> [...]
>>
>>> I created a bug and applied these fixes:
>>> http://bugzilla.opencores.org/bugzilla4/show_bug.cgi?id=91
>>
>>
>>
>> I have re-run my modified test suite once more against the patched ORPSoC
>> V2, and a different test fails now. That test used to succeed before the
>> patch. It's the second test in asm-sub.S :
>>
>> // Subtract two small positive numbers. Sets the carry, but never the
>> overflow if the result is negative.
>>
>> OK    -> TEST_INST_FF_I32_I32 0, SPR_SR_CY | SPR_SR_OV, l.sub, 0x00000003,
>> 0x00000002
>>
>> fails -> TEST_INST_FF_I32_I32 0, SPR_SR_CY | SPR_SR_OV, l.sub, 0x00000001,
>> 0x00000002
>>
>>
>> According to the test case (and to or1ksim's results), the overflow flag
>> should _not_ be set in the case, but it is with the new ORPSoC V2.
>
> OK, I've looked into this. I certainly think that last fix was not sufficient.
>
> I have expanded the ORPSoC overflow flag testsuite and got a better fix.
>
> I've marked the bug as open again, too.
>
> If I submit an RTL patch, are you happy to test it against your suite
> before I check this in?
>
> Thanks,
>
> Julius

OK, I think I have identified all of the cases where we should get
overflow, and tested them and made the RTL behave appropriately.

I think the cases for add and subtract are:

a) both numbers positive, result is two's complement negative (bit 31 set)
b) both numbers are two's complement negative and the result is
positive (bit 31 clear)

in for subtract, it's:

a) subtract positive from negative and result is positive (bit 31 clear)
b) subtract the largest 32-bit two's complement negative number from 0
(unable to represent that as a positive two's complement number)

The following patch should fix this in the OR1200:

Index: rtl/verilog/or1200/or1200_alu.v
===================================================================
--- rtl/verilog/or1200/or1200_alu.v     (revision 809)
+++ rtl/verilog/or1200/or1200_alu.v     (working copy)
@@ -167,15 +167,22 @@
 `endif
 `endif                 
 assign {cy_sum, result_sum} = (a + b_mux) + carry_in;
-// Numbers either both +ve and bit 31 of result set
-assign ov_sum = ((!a[width-1] & !b_mux[width-1]) & result_sum[width-1]) |
+
+assign ov_sum =
+               // When adding, numbers both +ve and result is negative,
+               // or, both -ve and  bit 31 of result clear
+               ((a[width-1] == b[width-1]) &
+                (a[width-1] ^ result_sum[width-1]) &
+                alu_op==`OR1200_ALUOP_ADD)
 `ifdef OR1200_IMPL_SUB
-               // Subtract larger negative from smaller positive
-               ((!a[width-1] & b_mux[width-1]) & result_sum[width-1] &
-                alu_op==`OR1200_ALUOP_SUB) |
+               // Subtract positive from a negative and got positive result
+               | ((((a[width-1] & !b[width-1]) & !result_sum[width-1]) |
+                   // Or, annoying case of subtracting -INT_MAX from zero
+                   (!(|a) & (b[width-1] & !(|b[width-2:0])))) &
+                  alu_op==`OR1200_ALUOP_SUB)
 `endif
-// or both -ve and bit 31 of result clear
-               ((a[width-1] & b_mux[width-1]) & !result_sum[width-1]);
+               ;
+
 assign result_and = a & b;

 //
_______________________________________________
OpenRISC mailing list
[email protected]
http://lists.openrisc.net/listinfo/openrisc

Reply via email to