From: Dmitry Selyutin Date: Sun, 6 Nov 2022 09:29:55 +0000 (+0300) Subject: power_insn: fix XO static operand X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=632396c02940f227f5a03dd2cd8c15650a3fd1a4;p=openpower-isa.git power_insn: fix XO static operand --- diff --git a/src/openpower/decoder/power_insn.py b/src/openpower/decoder/power_insn.py index b632051a..c7f856bc 100644 --- a/src/openpower/decoder/power_insn.py +++ b/src/openpower/decoder/power_insn.py @@ -161,6 +161,11 @@ class Opcode: return "".join(pattern(self.value, self.mask, self.value.bit_length())) + def match(self, key): + if isinstance(key, Instruction): + key = int(key) + return ((self.value & self.mask) == (key & self.mask)) + class IntegerOpcode(Opcode): def __init__(self, value): @@ -643,6 +648,9 @@ class Operands: return super().__init__() + def __repr__(self): + return self.__mapping.__repr__() + def __contains__(self, key): return self.__mapping.__contains__(key) @@ -705,11 +713,24 @@ class Record: opcode = ppc.opcode value |= opcode.value mask |= opcode.mask + value = Opcode.Value(value) + mask = Opcode.Mask(mask) XO = Opcode(value=value, mask=mask) + PO = self.section.opcode if PO is None: PO = XO XO = None + + PO = POStaticOperand(record=self, + name="PO", value=int(PO.value), mask=int(PO.mask)) + if XO is None: + XO = XOStaticOperand(record=self, + name="XO", value=0, mask=0) + else: + XO = XOStaticOperand(record=self, + name="XO", value=int(XO.value), mask=int(XO.mask)) + return (PO, XO) @cached_property @@ -720,20 +741,12 @@ class Record: def XO(self): return self.PO_XO[1] - @cached_property + @property def static_operands(self): - operands = [] - (PO, XO) = self.PO_XO + yield from self.PO_XO - operands.append(POStaticOperand(record=self, - name="PO", value=(PO.value & PO.mask))) - if XO is not None: - operands.append(XOStaticOperand(record=self, - name="XO", value=(XO.value & XO.mask))) for (cls, kwargs) in self.mdwn.operands.static: - operands.append(cls(record=self, **kwargs)) - - return tuple(operands) + yield cls(record=self, **kwargs) @cached_property def dynamic_operands(self): @@ -764,9 +777,9 @@ class Record: def match(self, key): for opcode in self.opcodes: - if ((opcode.value & opcode.mask) == - (key & opcode.mask)): + if opcode.match(key): return True + return False @property @@ -929,6 +942,8 @@ class StaticOperand(Operand): @_dataclasses.dataclass(eq=True, frozen=True) class POStaticOperand(StaticOperand): + mask: int + @cached_property def span(self): return tuple(range(0, 6)) @@ -936,18 +951,37 @@ class POStaticOperand(StaticOperand): @_dataclasses.dataclass(eq=True, frozen=True) class XOStaticOperand(StaticOperand): + mask: int + def __post_init__(self): - assert self.record.section.opcode is not None + if self.record.section.opcode is None: + assert self.value == 0 + assert self.mask == 0 + object.__setattr__(self, "span", ()) + return + bits = self.record.section.bitsel value = _SelectableInt(value=self.value, bits=len(bits)) span = dict(zip(bits, range(len(bits)))) + span_rev = {value:key for (key, value) in span.items()} + # This part is tricky: we could have used self.record.static_operands, # but this would cause an infinite recursion, since this code is called # from the self.record.static_operands method already. for (cls, kwargs) in self.record.mdwn.operands.static: operand = cls(record=self.record, **kwargs) for idx in operand.span: - span.pop(idx, None) + rev = span.pop(idx, None) + if rev is not None: + span_rev.pop(rev, None) + + # This part is simpler: we drop bits which are not in the mask. + for bit in tuple(span.values()): + rev = (len(bits) - bit - 1) + if ((self.mask & (1 << bit)) == 0): + idx = span_rev.pop(rev, None) + if idx is not None: + span.pop(idx, None) value = int(_selectconcat(*(value[bit] for bit in span.values()))) span = tuple(span.keys())