power_insn: add support for a trivial assembly
authorDmitry Selyutin <ghostmansd@gmail.com>
Sun, 6 Nov 2022 09:29:55 +0000 (12:29 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Sun, 15 Jan 2023 19:47:22 +0000 (22:47 +0300)
src/openpower/decoder/power_insn.py

index 4aa2fff95f8b8ac88762f6b1be58f5b1e0780e9e..5a89a7ebfb9f867205099a13fa0759a5757b88ae 100644 (file)
@@ -532,6 +532,14 @@ class Operand:
     def span(self, record):
         return record.fields[self.name]
 
+    def assemble(self, value, insn, record):
+        span = self.span(record=record)
+        if isinstance(insn, SVP64Instruction):
+            span = tuple(map(lambda bit: (bit + 32), span))
+        if isinstance(value, str):
+            value = int(value, 0)
+        insn[span] = value
+
     def disassemble(self, insn, record,
             verbosity=Verbosity.NORMAL, indent=""):
         raise NotImplementedError
@@ -575,6 +583,10 @@ class SignedOperand(DynamicOperand):
 class StaticOperand(Operand):
     value: int
 
+    def assemble(self, insn, record):
+        return super().assemble(value=self.value,
+            insn=insn, record=record)
+
     def disassemble(self, insn, record,
             verbosity=Verbosity.NORMAL, indent=""):
         span = self.span(record=record)
@@ -1176,6 +1188,10 @@ class Instruction(_Mapping):
         for operand in record.mdwn.operands.static:
             yield (operand.name, operand.value)
 
+    @classmethod
+    def assemble(cls, db, opcode, arguments):
+        raise NotImplementedError(f"{cls.__name__}.assemble")
+
     def disassemble(self, db,
             byteorder="little",
             verbosity=Verbosity.NORMAL):
@@ -1186,6 +1202,25 @@ class WordInstruction(Instruction):
     _: _Field = range(0, 32)
     po: _Field = range(0, 6)
 
+    @classmethod
+    def assemble(cls, db, opcode, arguments):
+        value = 0
+        mask = 0
+        record = db[opcode]
+        for opcode in record.opcodes:
+            value |= int(opcode.value)
+            mask |= int(opcode.mask)
+        insn = cls.integer(value=(value & mask))
+
+        operands = tuple(record.mdwn.operands.dynamic)
+        if len(operands) != len(arguments):
+            raise ValueError("operands count mismatch")
+        for (index, operand) in enumerate(operands):
+            value = arguments[index]
+            operand.assemble(value=value, insn=insn, record=record)
+
+        return insn
+
     @classmethod
     def integer(cls, value, byteorder="little"):
         return super().integer(bits=32, value=value, byteorder=byteorder)