diff --git a/power_fv/check/insn/compare.py b/power_fv/check/insn/compare.py index 142af87..e50837e 100644 --- a/power_fv/check/insn/compare.py +++ b/power_fv/check/insn/compare.py @@ -4,11 +4,13 @@ from power_fv.check.insn import InsnCheck __all__ = [ - "CMPI", "CMPLI", "CMP", "CMPL", + "CMPI", "CMPLI", "CMP", "CMPL", "CMPRB", "CMPEQB", ] -class CMPI (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPI ): pass -class CMPLI (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPLI): pass -class CMP (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMP ): pass -class CMPL (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPL ): pass +class CMPI (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPI ): pass +class CMPLI (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPLI ): pass +class CMP (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMP ): pass +class CMPL (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPL ): pass +class CMPRB (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPRB ): pass +class CMPEQB (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPEQB): pass diff --git a/power_fv/insn/spec/compare.py b/power_fv/insn/spec/compare.py index 29d6d6e..afc0b21 100644 --- a/power_fv/insn/spec/compare.py +++ b/power_fv/insn/spec/compare.py @@ -32,7 +32,7 @@ class CompareSpec(InsnSpec, Elaboratable): ("so", 1), ]) - # Operand A : (RA) or [(RA)(32:63) sign-extended or zero-extended] + # Operand A : (RA) or EXTS((RA)(32:63)) or EXTZ((RA)(32:63)) or EXTZ((RA)(56:63)) m.d.comb += [ self.pfv.ra.index.eq(self.insn.RA), @@ -49,12 +49,14 @@ class CompareSpec(InsnSpec, Elaboratable): m.d.comb += src_a.eq(self.pfv.ra.r_data) with m.Else(): m.d.comb += src_a.eq(self.pfv.ra.r_data[:32].as_unsigned()) + elif isinstance(self.insn, (CMPRB, CMPEQB)): + m.d.comb += src_a.eq(self.pfv.ra.r_data[:8].as_unsigned()) else: assert False - # Operand B : SI or UI or (RB) or [(RB)(32:63) sign-extended or zero-extended] + # Operand B : SI or UI or (RB) or EXTS((RB)(32:63)) or EXTZ((RB)(32:63)) - if isinstance(self.insn, (CMP, CMPL)): + if isinstance(self.insn, (CMP, CMPL, CMPRB, CMPEQB)): m.d.comb += [ self.pfv.rb.index.eq(self.insn.RB), self.pfv.rb.r_stb.eq(1), @@ -74,27 +76,61 @@ class CompareSpec(InsnSpec, Elaboratable): m.d.comb += src_b.eq(self.pfv.rb.r_data) with m.Else(): m.d.comb += src_b.eq(self.pfv.rb.r_data[:32].as_unsigned()) + elif isinstance(self.insn, CMPRB): + m.d.comb += src_b.eq(self.pfv.rb.r_data[:32].as_unsigned()) + elif isinstance(self.insn, CMPEQB): + m.d.comb += src_b.eq(self.pfv.rb.r_data) else: assert False # Result - if isinstance(self.insn, (CMPI, CMP)): - m.d.comb += result.lt.eq(src_a.as_signed() < src_b.as_signed()) - elif isinstance(self.insn, (CMPLI, CMPL)): - m.d.comb += result.lt.eq(src_a.as_unsigned() < src_b.as_unsigned()) + if isinstance(self.insn, (CMPI, CMP, CMPLI, CMPL)): + if isinstance(self.insn, (CMPI, CMP)): + m.d.comb += result.lt.eq(src_a.as_signed() < src_b.as_signed()) + if isinstance(self.insn, (CMPLI, CMPL)): + m.d.comb += result.lt.eq(src_a.as_unsigned() < src_b.as_unsigned()) + + m.d.comb += [ + result.gt .eq(~(result.lt | result.eq_)), + result.eq_.eq(src_a == src_b), + result.so .eq(self.pfv.xer.r_data.so), + ] + + elif isinstance(self.insn, CMPRB): + src1 = Signal(unsigned(8)) + src21hi = Signal(unsigned(8)) + src21lo = Signal(unsigned(8)) + src22hi = Signal(unsigned(8)) + src22lo = Signal(unsigned(8)) + in_range = Signal() + + m.d.comb += [ + src1.eq(src_a[:8]), + Cat(src22lo, src22hi, src21lo, src21hi).eq(src_b[:32]), + ] + + with m.If(~self.insn.L): + m.d.comb += in_range.eq( (src22lo <= src1) & (src1 <= src22hi)) + with m.Else(): + m.d.comb += in_range.eq( (src21lo <= src1) & (src1 <= src21hi) + | (src22lo <= src1) & (src1 <= src22hi)) + + m.d.comb += result.eq(Cat(Const(0, 2), in_range, Const(0, 1))) + + elif isinstance(self.insn, CMPEQB): + _match = 0 + for i in range(64//8): + _match |= (src_a == src_b.word_select(i, width=8)) + + m.d.comb += result.eq(Cat(Const(0, 2), _match, Const(0, 1))) + else: assert False m.d.comb += [ - result.gt .eq(~(result.lt | result.eq_)), - result.eq_.eq(src_a == src_b), - result.so .eq(self.pfv.xer.r_data.so), - ] - - m.d.comb += [ - self.pfv.cr.w_mask[::-1].word_select(self.insn.BF, width=4).eq(0b1111), - self.pfv.cr.w_data[::-1].word_select(self.insn.BF, width=4).eq(result), + self.pfv.cr.w_mask.word_select(7-self.insn.BF, width=4).eq(0xf), + self.pfv.cr.w_data.word_select(7-self.insn.BF, width=4).eq(result), ] return m