Add checks for CMPRB and CMPEQB instructions.

main
Jean-François Nguyen 2 years ago
parent d3546e4362
commit b3255def24

@ -4,11 +4,13 @@ from power_fv.check.insn import InsnCheck




__all__ = [ __all__ = [
"CMPI", "CMPLI", "CMP", "CMPL", "CMPI", "CMPLI", "CMP", "CMPL", "CMPRB", "CMPEQB",
] ]




class CMPI (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPI ): pass class CMPI (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPI ): pass
class CMPLI (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPLI): pass class CMPLI (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPLI ): pass
class CMP (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMP ): pass class CMP (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMP ): pass
class CMPL (InsnCheck, spec_cls=CompareSpec, insn_cls=const.CMPL ): 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

@ -32,7 +32,7 @@ class CompareSpec(InsnSpec, Elaboratable):
("so", 1), ("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 += [ m.d.comb += [
self.pfv.ra.index.eq(self.insn.RA), 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) m.d.comb += src_a.eq(self.pfv.ra.r_data)
with m.Else(): with m.Else():
m.d.comb += src_a.eq(self.pfv.ra.r_data[:32].as_unsigned()) 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: else:
assert False 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 += [ m.d.comb += [
self.pfv.rb.index.eq(self.insn.RB), self.pfv.rb.index.eq(self.insn.RB),
self.pfv.rb.r_stb.eq(1), 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) m.d.comb += src_b.eq(self.pfv.rb.r_data)
with m.Else(): with m.Else():
m.d.comb += src_b.eq(self.pfv.rb.r_data[:32].as_unsigned()) 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: else:
assert False assert False


# Result # Result


if isinstance(self.insn, (CMPI, CMP)): if isinstance(self.insn, (CMPI, CMP, CMPLI, CMPL)):
m.d.comb += result.lt.eq(src_a.as_signed() < src_b.as_signed()) if isinstance(self.insn, (CMPI, CMP)):
elif isinstance(self.insn, (CMPLI, CMPL)): m.d.comb += result.lt.eq(src_a.as_signed() < src_b.as_signed())
m.d.comb += result.lt.eq(src_a.as_unsigned() < src_b.as_unsigned()) 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: else:
assert False assert False


m.d.comb += [ m.d.comb += [
result.gt .eq(~(result.lt | result.eq_)), self.pfv.cr.w_mask.word_select(7-self.insn.BF, width=4).eq(0xf),
result.eq_.eq(src_a == src_b), self.pfv.cr.w_data.word_select(7-self.insn.BF, width=4).eq(result),
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),
] ]


return m return m

Loading…
Cancel
Save