power_insn: postpone operands initialization
authorDmitry Selyutin <ghostmansd@gmail.com>
Sun, 6 Nov 2022 09:29:55 +0000 (12:29 +0300)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 2 Jun 2023 18:51:16 +0000 (19:51 +0100)
src/openpower/decoder/power_insn.py
src/openpower/sv/sv_binutils_fptrans.py

index 63597660dccf9e70b5a218f0590fe433ee712d1f..abf340192a50d2d3ce31b5e2802d7c866b20905a 100644 (file)
@@ -900,8 +900,8 @@ class DOperandDX(SignedOperand):
             yield str(value.to_signed_int())
 
 
-class Operands(tuple):
-    def __new__(cls, insn, iterable):
+class Operands:
+    def __init__(self, insn, iterable):
         custom_insns = {
             "b": {"target_addr": TargetAddrOperandLI},
             "ba": {"target_addr": TargetAddrOperandLI},
@@ -935,71 +935,78 @@ class Operands(tuple):
             "DS": EXTSOperandDS,
         }
 
-        operands = []
+        mapping = {}
         for operand in iterable:
-            dynamic_cls = DynamicOperand
-            static_cls = StaticOperand
+            cls = DynamicOperand
 
             if "=" in operand:
                 (name, value) = operand.split("=")
-                operand = static_cls(name=name, value=int(value))
-                operands.append(operand)
+                mapping[name] = (StaticOperand, {"value": int(value)})
             else:
-                if operand.endswith(")"):
-                    operand = operand.replace("(", " ").replace(")", "")
-                    (immediate, _, operand) = operand.partition(" ")
+                name = operand
+                if name.endswith(")"):
+                    name = name.replace("(", " ").replace(")", "")
+                    (immediate, _, name) = name.partition(" ")
                 else:
                     immediate = None
 
                 if immediate is not None:
-                    if immediate in custom_immediates:
-                        dynamic_cls = custom_immediates[immediate]
-                        operands.append(dynamic_cls(name=immediate))
-                    else:
-                        operands.append(ImmediateOperand(name=immediate))
+                    cls = custom_immediates.get(immediate, ImmediateOperand)
+                    mapping[name] = (cls, {})
 
-                if operand in custom_fields:
-                    dynamic_cls = custom_fields[operand]
-                if insn in custom_insns and operand in custom_insns[insn]:
-                    dynamic_cls = custom_insns[insn][operand]
+                if insn in custom_insns and name in custom_insns[insn]:
+                    cls = custom_insns[insn][name]
+                elif name in custom_fields:
+                    cls = custom_fields[name]
 
-                if operand in _RegType.__members__:
-                    regtype = _RegType[operand]
+                if name in _RegType.__members__:
+                    regtype = _RegType[name]
                     if regtype is _RegType.GPR:
-                        dynamic_cls = GPROperand
+                        cls = GPROperand
                     elif regtype is _RegType.FPR:
-                        dynamic_cls = FPROperand
+                        cls = FPROperand
                     if regtype is _RegType.CR_BIT: # 5-bit
-                        dynamic_cls = CR5Operand
+                        cls = CR5Operand
                     if regtype is _RegType.CR_REG: # actually CR Field, 3-bit
-                        dynamic_cls = CR3Operand
+                        cls = CR3Operand
+
+                mapping[name] = (cls, {})
+
+        static = []
+        dynamic = []
+        for (name, (cls, kwargs)) in mapping.items():
+            kwargs = dict(kwargs)
+            kwargs["name"] = name
+            if issubclass(cls, StaticOperand):
+                static.append((cls, kwargs))
+            elif issubclass(cls, DynamicOperand):
+                dynamic.append((cls, kwargs))
+            else:
+                raise ValueError(name)
 
-                operand = dynamic_cls(name=operand)
-                operands.append(operand)
+        self.__mapping = mapping
+        self.__static = tuple(static)
+        self.__dynamic = tuple(dynamic)
 
-        return super().__new__(cls, operands)
+        return super().__init__()
 
     def __contains__(self, key):
-        return self.__getitem__(key) is not None
+        return self.__mapping.__contains__(key)
 
     def __getitem__(self, key):
-        for operand in self:
-            if operand.name == key:
-                return operand
+        (cls, kwargs) = self.__mapping.__getitem__(key)
+        kwargs = dict(kwargs)
+        kwargs["name"] = key
 
-        return None
+        return (cls, kwargs)
 
     @property
-    def dynamic(self):
-        for operand in self:
-            if isinstance(operand, DynamicOperand):
-                yield operand
+    def static(self):
+        return self.__static
 
     @property
-    def static(self):
-        for operand in self:
-            if isinstance(operand, StaticOperand):
-                yield operand
+    def dynamic(self):
+        return self.__dynamic
 
 
 class PCode:
@@ -1054,7 +1061,8 @@ class Record:
                 value[dst] = int((XO.value & (1 << src)) != 0)
                 mask[dst] = int((XO.mask & (1 << src)) != 0)
 
-            for operand in self.mdwn.operands.static:
+            for (cls, kwargs) in self.mdwn.operands.static:
+                operand = cls(**kwargs)
                 for (src, dst) in enumerate(reversed(operand.span(record=self))):
                     value[dst] = int((operand.value & (1 << src)) != 0)
                     mask[dst] = 1
@@ -1128,7 +1136,8 @@ class Record:
 
     @cached_property
     def Rc(self):
-        Rc = self.mdwn.operands["Rc"]
+        (cls, kwargs) = self.mdwn.operands["Rc"]
+        Rc = cls(**kwargs)
         if Rc is None:
             return False
         return bool(Rc.value)
@@ -1205,7 +1214,8 @@ class Instruction(_Mapping):
         imm = False
         imm_name = ""
         imm_value = ""
-        for operand in record.mdwn.operands.dynamic:
+        for (cls, kwargs) in record.mdwn.operands.dynamic:
+            operand = cls(**kwargs)
             name = operand.name
             value = " ".join(operand.disassemble(insn=self,
                 record=record, verbosity=min(verbosity, Verbosity.NORMAL)))
@@ -1222,7 +1232,8 @@ class Instruction(_Mapping):
 
     def static_operands(self, db):
         record = self.record(db=db)
-        for operand in record.mdwn.operands.static:
+        for (cls, kwargs) in record.mdwn.operands.static:
+            operand = cls(**kwargs)
             yield (operand.name, operand.value)
 
     @classmethod
@@ -1252,7 +1263,8 @@ class WordInstruction(Instruction):
         operands = tuple(record.mdwn.operands.dynamic)
         if len(operands) != len(arguments):
             raise ValueError("operands count mismatch")
-        for (index, operand) in enumerate(operands):
+        for (index, (cls, kwargs)) in enumerate(operands):
+            operand = cls(**kwargs)
             value = arguments[index]
             operand.assemble(value=value, insn=insn, record=record)
 
@@ -1311,7 +1323,8 @@ class WordInstruction(Instruction):
             yield f"{indent}opcodes"
             for opcode in record.opcodes:
                 yield f"{indent}{indent}{opcode!r}"
-            for operand in record.mdwn.operands:
+            for (cls, kwargs) in record.mdwn.operands:
+                operand = cls(**kwargs)
                 yield from operand.disassemble(insn=self, record=record,
                     verbosity=verbosity, indent=indent)
             yield ""
@@ -2174,7 +2187,8 @@ class SVP64Instruction(PrefixedInstruction):
             yield f"{indent}opcodes"
             for opcode in record.opcodes:
                 yield f"{indent}{indent}{opcode!r}"
-            for operand in record.mdwn.operands:
+            for (cls, kwargs) in record.mdwn.operands:
+                operand = cls(**kwargs)
                 yield from operand.disassemble(insn=self, record=record,
                     verbosity=verbosity, indent=indent)
             yield f"{indent}RM"
@@ -2296,8 +2310,7 @@ class PPCDatabase:
             record = records[alias]
             if record.intop not in {_MicrOp.OP_B, _MicrOp.OP_BC}:
                 raise ValueError(record)
-            operands = mdwndb[name].operands["AA"]
-            if operands is None:
+            if "AA" not in mdwndb[name].operands:
                 raise ValueError(record)
             return alias
 
index d6aec3afe82cc416c50a3dd77de860fc103b43ee..e7d4b9b5e5e4040c05beef3c8653bbb07d2ea876 100644 (file)
@@ -82,33 +82,36 @@ def collect(db):
 
         @_dataclasses.dataclass(eq=True, frozen=True)
         class POStaticOperand(_StaticOperand):
-            def __init__(self, PO):
-                value = (PO.value & PO.mask)
-                return super().__init__(name="PO", value=value)
-
             def span(self, record):
                 return tuple(range(0, 6))
 
         @_dataclasses.dataclass(eq=True, frozen=True)
         class XOStaticOperand(_StaticOperand):
-            def __init__(self, XO):
-                value = (XO.value & XO.mask)
-                return super().__init__(name="XO", value=value)
-
             def span(self, record):
                 return tuple(record.section.bitsel)
 
-        static_operands = [POStaticOperand(PO=PO)]
+        static_operands = [(POStaticOperand, {
+            "name": "PO",
+            "value": (PO.value & PO.mask)
+        })]
         if XO is not None:
-            static_operands.append(XOStaticOperand(XO=XO))
+            static_operands.append((XOStaticOperand, {
+                "name": "XO",
+                "value": (XO.value & XO.mask)
+            }))
+
         static_operands.extend(record.mdwn.operands.static)
         dynamic_operands = record.mdwn.operands.dynamic
 
         def static_operand(operand):
+            (cls, kwargs) = operand
+            operand = cls(**kwargs)
             return StaticOperand(name=operand.name,
                 value=operand.value, span=operand.span(record=record))
 
         def dynamic_operand(operand):
+            (cls, kwargs) = operand
+            operand = cls(**kwargs)
             return DynamicOperand(name=operand.name,
                 span=operand.span(record=record))