def elaborate(self, platform):
m = Module()
comb = m.d.comb
- carry_out, o = self.o.carry_out, self.o.o
+ carry_out, o = self.o.xer_co, self.o.o
# check if op is 32-bit, and get sign bit from operand a
is_32bit = Signal(reset_less=True)
with m.Case(InternalOp.OP_ADD):
# bit 0 is not part of the result, top bit is the carry-out
comb += o.eq(add_output[1:-1])
- comb += carry_out.eq(add_output[-1])
+ comb += carry_out.data[0].eq(add_output[-1]) # XER.CO
+
+ # XXX no! wrongggg, see microwatt OP_ADD code
+ # https://bugs.libre-soc.org/show_bug.cgi?id=319#c5
+ comb += carry_out.data[1].eq(add_output[-1]) # XER.CO32
#### exts (sign-extend) ####
with m.Case(InternalOp.OP_EXTS):
###### sticky overflow and context, both pass-through #####
- comb += self.o.so.eq(self.i.so)
+ comb += self.o.xer_so.data.eq(self.i.so)
comb += self.o.ctx.eq(self.i.ctx)
return m
comb += target.eq(o)
# Handle carry_out
- with m.If(self.i.ctx.op.output_carry):
- comb += self.o.carry_out.eq(self.i.carry_out)
+ comb += self.o.xer_co.data.eq(self.i.xer_co.data)
+ comb += self.o.xer_co.ok.eq(op.output_carry)
# create condition register cr0 and sticky-overflow
is_zero = Signal(reset_less=True)
is_negative = Signal(reset_less=True)
msb_test = Signal(reset_less=True) # set equal to MSB, invert if OP=CMP
is_cmp = Signal(reset_less=True) # true if OP=CMP
- so = Signal(reset_less=True)
+ so = Signal(1, reset_less=True)
+ ov = Signal(2, reset_less=True) # OV, OV32
+ cr0 = Signal(4, reset_less=True)
# TODO: if o[63] is XORed with "operand == OP_CMP"
# that can be used as a test
comb += is_zero.eq(target == 0)
comb += is_positive.eq(~is_zero & ~msb_test)
comb += is_negative.eq(~is_zero & msb_test)
- comb += so.eq(self.i.so | self.i.ov)
+ # XXX see https://bugs.libre-soc.org/show_bug.cgi?id=319#c5
+ comb += ov[0].eq(self.i.xer_so.data | self.i.xer_ov.data[0]) # OV
+ comb += ov[1].eq(self.i.xer_so.data | self.i.xer_ov.data[1]) # OV32 XXX!
+ comb += so.eq(self.i.xer_so.data | self.i.xer_ov.data[0]) # OV
with m.If(op.insn_type != InternalOp.OP_CMPEQB):
- comb += self.o.cr0.eq(Cat(so, is_zero, is_positive, is_negative))
+ comb += cr0.eq(Cat(so, is_zero, is_positive, is_negative))
with m.Else():
- comb += self.o.cr0.eq(self.i.cr0)
+ comb += cr0.eq(self.i.cr0)
- # copy [inverted] output, sticky-overflow and context out
+ # copy [inverted] cr0, output, sticky-overflow and context out
comb += self.o.o.eq(o)
- comb += self.o.so.eq(so)
+ comb += self.o.cr0.data.eq(cr0)
+ comb += self.o.cr0.ok.eq(op.rc.rc & op.rc.rc_ok) # CR0 to be set
+ comb += self.o.xer_so.data.eq(so)
+ comb += self.o.xer_so.ok.eq(op.oe.oe & op.oe.oe_ok) # SO is to be set
+ comb += self.o.xer_ov.data.eq(ov)
+ comb += self.o.xer_ov.ok.eq(op.oe.oe & op.oe.oe_ok) # OV/32 is to be set
comb += self.o.ctx.eq(self.i.ctx)
return m
from nmutil.dynamicpipe import SimpleHandshakeRedir
from soc.fu.alu.alu_input_record import CompALUOpSubset
from ieee754.fpcommon.getop import FPPipeContext
-
+from soc.decoder.power_decoder2 import Data
class IntegerData:
def __init__(self, pspec):
super().__init__(pspec)
self.o = Signal(64, reset_less=True, name="stage_o")
- self.carry_out = Signal(reset_less=True)
- self.carry_out32 = Signal(reset_less=True)
- self.cr0 = Signal(4, reset_less=True)
- self.ov = Signal(reset_less=True)
- self.ov32 = Signal(reset_less=True)
- self.so = Signal(reset_less=True)
+ self.cr0 = Data(4, name="cr0")
+ self.xer_co = Data(2, name="xer_co") # bit0: co, bit1: co32
+ self.xer_ov = Data(2, name="xer_ov") # bit0: ov, bit1: ov32
+ self.xer_so = Data(1, name="xer_so")
def __iter__(self):
yield from super().__iter__()
yield self.o
- yield self.carry_out
- yield self.carry_out32
+ yield self.xer_co
yield self.cr0
- yield self.ov
- yield self.ov32
- yield self.so
+ yield self.xer_ov
+ yield self.xer_so
def eq(self, i):
lst = super().eq(i)
return lst + [self.o.eq(i.o),
- self.carry_out.eq(i.carry_out),
- self.carry_out32.eq(i.carry_out32),
- self.cr0.eq(i.cr0), self.ov.eq(i.ov),
- self.ov32.eq(i.ov32), self.so.eq(i.so)]
+ self.xer_co.eq(i.xer_co),
+ self.cr0.eq(i.cr0),
+ self.xer_ov.eq(i.xer_ov), self.xer_so.eq(i.xer_so)]
class IntPipeSpec:
rc = yield dec2.e.rc.data
if rc:
cr_expected = sim.crl[0].get_range().value
- cr_actual = yield alu.n.data_o.cr0
+ cr_actual = yield alu.n.data_o.cr0.data
self.assertEqual(cr_expected, cr_actual, code)
op = yield dec2.e.insn_type
if op == InternalOp.OP_CMP.value or \
op == InternalOp.OP_CMPEQB.value:
bf = yield dec2.dec.BF
- cr_actual = yield alu.n.data_o.cr0
+ cr_actual = yield alu.n.data_o.cr0.data
cr_expected = sim.crl[bf].get_range().value
self.assertEqual(cr_expected, cr_actual, code)
cry_out = yield dec2.e.output_carry
if cry_out:
expected_carry = 1 if sim.spr['XER'][XER_bits['CA']] else 0
- real_carry = yield alu.n.data_o.carry_out
- self.assertEqual(expected_carry, real_carry)
+ real_carry = yield alu.n.data_o.xer_co.data[0] # XXX CO not CO32
+ self.assertEqual(expected_carry, real_carry, code)
+ expected_carry32 = 1 if sim.spr['XER'][XER_bits['CA32']] else 0
+ real_carry32 = yield alu.n.data_o.xer_co.data[1] # XXX CO32
+ self.assertEqual(expected_carry, real_carry, code)