use log function for warnings about .mdwn files in pagereader.py
[openpower-isa.git] / src / openpower / decoder / power_insn.py
index 92ebf4d041d98d8262a748f5b78c543186585781..6ea7f58d37e5ed5091f4d8cd032f4d8936ff8d9e 100644 (file)
@@ -227,14 +227,16 @@ class PPCRecord:
                 flags.add(flag)
         record["flags"] = PPCRecord.Flags(flags)
 
-        return dataclass(cls, record, keymap=PPCRecord.__KEYMAP, typemap=typemap)
+        return dataclass(cls, record,
+            keymap=PPCRecord.__KEYMAP,
+            typemap=typemap)
 
     @cached_property
     def names(self):
         return frozenset(self.comment.split("=")[-1].split("/"))
 
 
-class PPCMultiRecord(tuple):
+class PPCMultiRecord(frozenset):
     @cached_property
     def unified(self):
         def merge(lhs, rhs):
@@ -258,7 +260,9 @@ class PPCMultiRecord(tuple):
                 value |= (vstate << bit)
                 mask |= (mstate << bit)
 
-            return _dataclasses.replace(lhs, opcode=Opcode(value=value, mask=mask))
+            opcode = opcode=Opcode(value=value, mask=mask)
+
+            return _dataclasses.replace(lhs, opcode=opcode)
 
         return _functools.reduce(merge, self)
 
@@ -335,7 +339,11 @@ class SVP64Record:
             if value == "0":
                 record[key] = "NONE"
 
-        record["extra"] = cls.ExtraMap(record.pop(f"{index}") for index in range(0, 4))
+        extra = []
+        for idx in range(0, 4):
+            extra.append(record.pop(f"{idx}"))
+
+        record["extra"] = cls.ExtraMap(extra)
 
         return dataclass(cls, record, keymap=cls.__KEYMAP)
 
@@ -762,6 +770,12 @@ class Instruction(_Mapping):
     def __hash__(self):
         return hash(int(self))
 
+    def record(self, db):
+        record = db[self]
+        if record is None:
+            raise KeyError(self)
+        return record
+
     def disassemble(self, db, byteorder="little", verbose=False):
         raise NotImplementedError
 
@@ -782,7 +796,9 @@ class WordInstruction(Instruction):
             bits.append(bit)
         return "".join(map(str, bits))
 
-    def spec(self, record):
+    def spec(self, db):
+        record = self.record(db=db)
+
         immediate = ""
         dynamic_operands = []
         for operand in record.operands.dynamic:
@@ -807,10 +823,12 @@ class WordInstruction(Instruction):
 
         return f"{record.name}{operands}"
 
-    def opcode(self, record):
+    def opcode(self, db):
+        record = self.record(db=db)
         return f"0x{record.opcode.value:08x}"
 
-    def mask(self, record):
+    def mask(self, db):
+        record = self.record(db=db)
         return f"0x{record.opcode.mask:08x}"
 
     def disassemble(self, db, byteorder="little", verbose=False):
@@ -818,7 +836,7 @@ class WordInstruction(Instruction):
         blob = integer.to_bytes(length=4, byteorder=byteorder)
         blob = " ".join(map(lambda byte: f"{byte:02x}", blob))
 
-        record = db[self]
+        record = self.record(db=db)
         if record is None:
             yield f"{blob}    .long 0x{integer:08x}"
             return
@@ -839,9 +857,9 @@ class WordInstruction(Instruction):
         if verbose:
             indent = (" " * 4)
             binary = self.binary
-            spec = self.spec(record=record)
-            opcode = self.opcode(record=record)
-            mask = self.mask(record=record)
+            spec = self.spec(db=db)
+            opcode = self.opcode(db=db)
+            mask = self.mask(db=db)
             yield f"{indent}spec"
             yield f"{indent}{indent}{spec}"
             yield f"{indent}binary"
@@ -1113,34 +1131,23 @@ class SVP64Instruction(PrefixedInstruction):
             bits.append(bit)
         return "".join(map(str, bits))
 
-    def spec(self, record):
-        return f"sv.{self.suffix.spec(record=record)}"
-
-    def opcode(self, record):
-        return self.suffix.opcode(record=record)
-
-    def mask(self, record):
-        return self.suffix.mask(record=record)
+    def spec(self, db):
+        return f"sv.{self.suffix.spec(db=db)}"
 
-    def disassemble(self, db, byteorder="little", verbose=False):
-        integer_prefix = int(self.prefix)
-        blob_prefix = integer_prefix.to_bytes(length=4, byteorder=byteorder)
-        blob_prefix = " ".join(map(lambda byte: f"{byte:02x}", blob_prefix))
+    def opcode(self, db):
+        return self.suffix.opcode(db=db)
 
-        integer_suffix = int(self.suffix)
-        blob_suffix = integer_suffix.to_bytes(length=4, byteorder=byteorder)
-        blob_suffix = " ".join(map(lambda byte: f"{byte:02x}", blob_suffix))
+    def mask(self, db):
+        return self.suffix.mask(db=db)
 
-        record = db[self.suffix]
-        if record is None or record.svp64 is None:
-            yield f"{blob_prefix}    .long 0x{int(self.prefix):08x}"
-            yield f"{blob_suffix}    .long 0x{int(self.suffix):08x}"
-            return
+    def mode(self, db):
+        record = self.record(db=db)
 
         Rc = False
         if record.operands["Rc"] is not None:
             Rc = bool(self[record.fields["Rc"]])
 
+        record = self.record(db=db)
         subvl = self.prefix.rm.subvl
         mode = self.prefix.rm.mode
         sel = mode.sel
@@ -1212,18 +1219,64 @@ class SVP64Instruction(PrefixedInstruction):
                 else:
                     mode = mode.prrc0
 
-        if type(mode) is Mode:
-            raise NotImplementedError
+        modes = {
+            NormalMode.simple: "normal: simple",
+            NormalMode.smr: "normal: smr",
+            NormalMode.pmr: "normal: pmr",
+            NormalMode.svmr: "normal: svmr",
+            NormalMode.pu: "normal: pu",
+            NormalMode.ffrc1: "normal: ffrc1",
+            NormalMode.ffrc0: "normal: ffrc0",
+            NormalMode.sat: "normal: sat",
+            NormalMode.satx: "normal: satx",
+            NormalMode.satpu: "normal: satpu",
+            NormalMode.prrc1: "normal: prrc1",
+            NormalMode.prrc0: "normal: prrc0",
+            LDSTImmMode.simple: "ld/st imm: simple",
+            LDSTImmMode.spu: "ld/st imm: spu",
+            LDSTImmMode.ffrc1: "ld/st imm: ffrc1",
+            LDSTImmMode.ffrc0: "ld/st imm: ffrc0",
+            LDSTImmMode.sat: "ld/st imm: sat",
+            LDSTImmMode.prrc1: "ld/st imm: prrc1",
+            LDSTImmMode.prrc0: "ld/st imm: prrc0",
+            LDSTIdxMode.simple: "ld/st idx simple",
+            LDSTIdxMode.stride: "ld/st idx stride",
+            LDSTIdxMode.sat: "ld/st idx sat",
+            LDSTIdxMode.prrc1: "ld/st idx prrc1",
+            LDSTIdxMode.prrc0: "ld/st idx prrc0",
+        }
+        for (cls, desc) in modes.items():
+            if isinstance(mode, cls):
+                return (mode, desc)
+
+        raise NotImplementedError
+
+    def disassemble(self, db, byteorder="little", verbose=False):
+        integer_prefix = int(self.prefix)
+        blob_prefix = integer_prefix.to_bytes(length=4, byteorder=byteorder)
+        blob_prefix = " ".join(map(lambda byte: f"{byte:02x}", blob_prefix))
+
+        integer_suffix = int(self.suffix)
+        blob_suffix = integer_suffix.to_bytes(length=4, byteorder=byteorder)
+        blob_suffix = " ".join(map(lambda byte: f"{byte:02x}", blob_suffix))
+
+        record = self.record(db=db)
+        if record is None or record.svp64 is None:
+            yield f"{blob_prefix}    .long 0x{int(self.prefix):08x}"
+            yield f"{blob_suffix}    .long 0x{int(self.suffix):08x}"
+            return
 
         yield f"{blob_prefix}    sv.{record.name}"
         yield f"{blob_suffix}"
 
+        (mode, mode_desc) = self.mode(db=db)
+
         if verbose:
             indent = (" " * 4)
             binary = self.binary
-            spec = self.spec(record=record)
-            opcode = self.opcode(record=record)
-            mask = self.mask(record=record)
+            spec = self.spec(db=db)
+            opcode = self.opcode(db=db)
+            mask = self.mask(db=db)
             yield f"{indent}spec"
             yield f"{indent}{indent}{spec}"
             yield f"{indent}binary"
@@ -1246,13 +1299,19 @@ class SVP64Instruction(PrefixedInstruction):
                     record=record, verbose=True)
                 for part in parts:
                     yield f"{indent}{indent}{part}"
+
+            yield f"{indent}mode"
+            yield f"{indent}{indent}{mode_desc}"
             yield ""
 
 
 def parse(stream, factory):
+    def match(entry):
+        return ("TODO" not in frozenset(entry.values()))
+
     lines = filter(lambda line: not line.strip().startswith("#"), stream)
     entries = _csv.DictReader(lines)
-    entries = filter(lambda entry: "TODO" not in frozenset(entry.values()), entries)
+    entries = filter(match, entries)
     return tuple(map(factory, entries))
 
 
@@ -1297,7 +1356,7 @@ class FieldsDatabase:
 
 
 class PPCDatabase:
-    def __init__(self, root, mdwndb, fieldsdb):
+    def __init__(self, root, mdwndb):
         # The code below groups the instructions by section:identifier.
         # We use the comment as an identifier, there's nothing better.
         # The point is to capture different opcodes for the same instruction.
@@ -1311,7 +1370,8 @@ class PPCDatabase:
                     section.Mode.INTEGER: IntegerOpcode,
                     section.Mode.PATTERN: PatternOpcode,
                 }[section.mode]
-                factory = _functools.partial(PPCRecord.CSV, opcode_cls=opcode_cls)
+                factory = _functools.partial(
+                    PPCRecord.CSV, opcode_cls=opcode_cls)
                 with open(path, "r", encoding="UTF-8") as stream:
                     for insn in parse(stream, factory):
                         records[section][insn.comment].add(insn)
@@ -1323,7 +1383,6 @@ class PPCDatabase:
 
         self.__db = db
         self.__mdwndb = mdwndb
-        self.__fieldsdb = fieldsdb
 
         return super().__init__()
 
@@ -1368,8 +1427,11 @@ class PPCDatabase:
 
         for (section, records) in self.__db.items():
             for record in records:
-                if (exact_match(key, record) or
-                        Rc_match(key, record) or
+                if exact_match(key, record):
+                    return (section, record)
+
+            for record in records:
+                if (Rc_match(key, record) or
                         LK_match(key, record) or
                         AA_match(key, record)):
                     return (section, record)
@@ -1412,7 +1474,7 @@ class Database:
 
         mdwndb = MarkdownDatabase()
         fieldsdb = FieldsDatabase()
-        ppcdb = PPCDatabase(root=root, mdwndb=mdwndb, fieldsdb=fieldsdb)
+        ppcdb = PPCDatabase(root=root, mdwndb=mdwndb)
         svp64db = SVP64Database(root=root, ppcdb=ppcdb)
 
         db = set()