On Sun, May 20, 2012 at 11:41 PM, Julius Baxter <[email protected]> wrote:
> On Fri, May 4, 2012 at 6:56 PM, R. Diez <[email protected]> wrote:
>> Hi all:
>>
>> I have this source line in my modified or1200 test suite:
>>
>> // Subtract a large negative from a large positive number. Should set
>> // both the overflow and carry flags.
>> TEST_INST_FF_I32_I32 0, SPR_SR_CY | SPR_SR_OV, l.sub, 0x7fffffff,
>> 0x80000000
>>
>> which translates into the following pseudo-instructions:
>>
>> set carry flag
>> set overflow flag
>> l.sub 0x7fffffff, 0x80000000
>>
>> When run against or1ksim, it generates the following results:
>>
>> 0xffffffff, carry flag set, overflow flag set
>>
>> However, it looks different when run against ORPSoC V2's or1200 RTL model
>> (simulated with Icarus Verilog):
>>
>> 0xffffffff, carry flag set, _NO_ overflow flag
>>
>> I'm having similar issues with the multiply instructions, many carry and
>> overflow flags are different. I wonder if I've made a mistake somewhere. Or
>> are we really so lucky that nobody has ever noticed?
>
> No, this could potentially be a genuine problem.
>
> The subtract test is far from exhaustive, and no doubt there's some holes
> there.
>
> I haven't investigated this one, but I suspect there's some overflow
> detection logic going awry (converting signed 0x80000000 into positive
> for the addition doesn't work correctly I suspect.
>
> I'll look into this though.
>
> What other suspect overflow results have you seen?
>
> Thanks
>
> Julius
The following patch appears to make OV work for this particular case
(test case SW patch also trailing):
Index: rtl/verilog/or1200/or1200_alu.v
===================================================================
--- rtl/verilog/or1200/or1200_alu.v (revision 798)
+++ rtl/verilog/or1200/or1200_alu.v (working copy)
@@ -169,6 +169,11 @@
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]) |
+`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) |
+`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;
Index: sw/tests/or1200/sim/or1200-ov.S
===================================================================
--- sw/tests/or1200/sim/or1200-ov.S (revision 798)
+++ sw/tests/or1200/sim/or1200-ov.S (working copy)
@@ -265,6 +265,16 @@
l.add r3, r0, r0 ;// Should clear overflow
l.nop 0x2
CHECK_OV_CLEAR
+
+ // Subtract the biggest negative number from the
+ // biggest positive number.
+ l.movhi r4,0x7fff
+ l.ori r4,r4,0xffff
+ l.movhi r5,0x8000
+ l.sub r3,r4,r5
+ l.nop 2
+ CHECK_OV_SET
+
#endif
l.movhi r4, 0x8000
_______________________________________________
OpenRISC mailing list
[email protected]
http://lists.openrisc.net/listinfo/openrisc