power_insn: support verbosity levels
authorDmitry Selyutin <ghostmansd@gmail.com>
Fri, 9 Sep 2022 16:27:59 +0000 (19:27 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Fri, 9 Sep 2022 16:27:59 +0000 (19:27 +0300)
src/openpower/decoder/power_insn.py
src/openpower/sv/trans/pysvp64dis.py

index 018eaddfb158f6a0a4bfb72e768a07a69b4c060a..2c28fc9e466df07d88201c29097a28bc20d5b754 100644 (file)
@@ -47,6 +47,18 @@ from openpower.decoder.power_fields import (
 from openpower.decoder.pseudo.pagereader import ISA as _ISA
 
 
+@_functools.total_ordering
+class Verbosity(_enum.Enum):
+    SHORT = _enum.auto()
+    NORMAL = _enum.auto()
+    VERBOSE = _enum.auto()
+
+    def __lt__(self, other):
+        if not isinstance(other, self.__class__):
+            return NotImplemented
+        return (self.value < other.value)
+
+
 def dataclass(cls, record, keymap=None, typemap=None):
     if keymap is None:
         keymap = {}
@@ -506,20 +518,20 @@ class Operand:
     name: str
 
     def disassemble(self, insn, record,
-            short=False, verbose=False, indent=""):
+            verbosity=Verbosity.NORMAL, indent=""):
         raise NotImplementedError
 
 
 @_dataclasses.dataclass(eq=True, frozen=True)
 class DynamicOperand(Operand):
     def disassemble(self, insn, record,
-            short=False, verbose=False, indent=""):
+            verbosity=Verbosity.NORMAL, indent=""):
         span = record.fields[self.name]
         if isinstance(insn, SVP64Instruction):
             span = tuple(map(lambda bit: (bit + 32), span))
         value = insn[span]
 
-        if verbose:
+        if verbosity >= Verbosity.VERBOSE:
             span = map(str, span)
             yield f"{indent}{self.name}"
             yield f"{indent}{indent}{int(value):0{value.bits}b}"
@@ -600,10 +612,10 @@ class DynamicOperandReg(DynamicOperand):
         return _SVExtra.NONE
 
     def disassemble(self, insn, record,
-            short=False, verbose=False, prefix="", indent=""):
+            verbosity=Verbosity.NORMAL, prefix="", indent=""):
         (vector, value, span) = self.spec(insn=insn, record=record)
 
-        if verbose:
+        if verbosity >= Verbosity.VERBOSE:
             yield f"{indent}{self.name}"
             yield f"{indent}{indent}{int(value):0{value.bits}b}"
             yield f"{indent}{indent}{', '.join(span)}"
@@ -631,13 +643,13 @@ class StaticOperand(Operand):
     value: int
 
     def disassemble(self, insn, record,
-            short=False, verbose=False, indent=""):
+            verbosity=Verbosity.NORMAL, indent=""):
         span = record.fields[self.name]
         if isinstance(insn, SVP64Instruction):
             span = tuple(map(lambda bit: (bit + 32), span))
         value = insn[span]
 
-        if verbose:
+        if verbosity >= Verbosity.VERBOSE:
             span = map(str, span)
             yield f"{indent}{self.name}"
             yield f"{indent}{indent}{int(value):0{value.bits}b}"
@@ -649,13 +661,13 @@ class StaticOperand(Operand):
 @_dataclasses.dataclass(eq=True, frozen=True)
 class DynamicOperandTargetAddr(DynamicOperandReg):
     def disassemble(self, insn, record, field,
-            short=False, verbose=False, indent=""):
+            verbosity=Verbosity.NORMAL, indent=""):
         span = record.fields[field]
         if isinstance(insn, SVP64Instruction):
             span = tuple(map(lambda bit: (bit + 32), span))
         value = insn[span]
 
-        if verbose:
+        if verbosity >= Verbosity.VERBOSE:
             span = tuple(map(str, span))
             yield f"{indent}{self.name}"
             yield f"{indent}{indent}{int(value):0{value.bits}b}00"
@@ -669,38 +681,38 @@ class DynamicOperandTargetAddr(DynamicOperandReg):
 @_dataclasses.dataclass(eq=True, frozen=True)
 class DynamicOperandTargetAddrLI(DynamicOperandTargetAddr):
     def disassemble(self, insn, record,
-            short=False, verbose=False, indent=""):
+            verbosity=Verbosity.NORMAL, indent=""):
         return super().disassemble(field="LI",
             insn=insn, record=record,
-            short=short, verbose=verbose, indent=indent)
+            verbosity=verbosity, indent=indent)
 
 
 class DynamicOperandTargetAddrBD(DynamicOperandTargetAddr):
     def disassemble(self, insn, record,
-            short=False, verbose=False, indent=""):
+            verbosity=Verbosity.NORMAL, indent=""):
         return super().disassemble(field="BD",
             insn=insn, record=record,
-            short=short, verbose=verbose, indent=indent)
+            verbosity=verbosity, indent=indent)
 
 
 @_dataclasses.dataclass(eq=True, frozen=True)
 class DynamicOperandGPR(DynamicOperandReg):
     def disassemble(self, insn, record,
-            short=False, verbose=False, indent=""):
-        prefix = "" if short else "r"
+            verbosity=Verbosity.NORMAL, indent=""):
+        prefix = "" if (verbosity <= Verbosity.SHORT) else "r"
         yield from super().disassemble(prefix=prefix,
             insn=insn, record=record,
-            short=short, verbose=verbose, indent=indent)
+            verbosity=verbosity, indent=indent)
 
 
 @_dataclasses.dataclass(eq=True, frozen=True)
 class DynamicOperandFPR(DynamicOperandReg):
     def disassemble(self, insn, record,
-            short=False, verbose=False, indent=""):
-        prefix = "" if short else "f"
+            verbosity=Verbosity.NORMAL, indent=""):
+        prefix = "" if (verbosity <= Verbosity.SHORT) else "f"
         yield from super().disassemble(prefix=prefix,
             insn=insn, record=record,
-            short=short, verbose=verbose, indent=indent)
+            verbosity=verbosity, indent=indent)
 
 
 class Operands(tuple):
@@ -905,7 +917,7 @@ class Instruction(_Mapping):
 
         return f"{prefix}{record.name}{operands}"
 
-    def dynamic_operands(self, db, short=False):
+    def dynamic_operands(self, db, verbosity=Verbosity.NORMAL):
         record = self.record(db=db)
 
         imm = False
@@ -914,7 +926,7 @@ class Instruction(_Mapping):
         for operand in record.operands.dynamic:
             name = operand.name
             dis = operand.disassemble(insn=self, record=record,
-                short=short, verbose=False)
+                verbosity=min(verbosity, Verbosity.NORMAL))
             value = " ".join(dis)
             if imm:
                 name = f"{imm_name}({name})"
@@ -932,8 +944,9 @@ class Instruction(_Mapping):
         for operand in record.operands.static:
             yield (operand.name, operand.value)
 
-    def disassemble(self, db, byteorder="little",
-            short=False, verbose=False):
+    def disassemble(self, db,
+            byteorder="little",
+            verbosity=Verbosity.NORMAL):
         raise NotImplementedError
 
 
@@ -961,10 +974,11 @@ class WordInstruction(Instruction):
         record = self.record(db=db)
         return f"0x{record.opcode.mask:08x}"
 
-    def disassemble(self, db, byteorder="little",
-            verbose=False, short=False):
+    def disassemble(self, db,
+            byteorder="little",
+            verbosity=Verbosity.NORMAL):
         integer = int(self)
-        if short:
+        if verbosity <= Verbosity.SHORT:
             blob = ""
         else:
             blob = integer.to_bytes(length=4, byteorder=byteorder)
@@ -977,13 +991,13 @@ class WordInstruction(Instruction):
             return
 
         operands = tuple(map(_operator.itemgetter(1),
-            self.dynamic_operands(db=db, short=short)))
+            self.dynamic_operands(db=db, verbosity=verbosity)))
         if operands:
             yield f"{blob}{record.name} {','.join(operands)}"
         else:
             yield f"{blob}{record.name}"
 
-        if verbose:
+        if verbosity >= Verbosity.VERBOSE:
             indent = (" " * 4)
             binary = self.binary
             spec = self.spec(db=db, prefix="")
@@ -1002,7 +1016,7 @@ class WordInstruction(Instruction):
             yield f"{indent}{indent}{mask}"
             for operand in record.operands:
                 yield from operand.disassemble(insn=self, record=record,
-                    short=short, verbose=True, indent=indent)
+                    verbosity=verbosity, indent=indent)
             yield ""
 
 
@@ -1413,33 +1427,36 @@ class SVP64Instruction(PrefixedInstruction):
 
         raise ValueError(self)
 
-    def disassemble(self, db, byteorder="little",
-            short=False, 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))
+    def disassemble(self, db,
+            byteorder="little",
+            verbosity=Verbosity.NORMAL):
+        def blob(integer):
+            if verbosity <= Verbosity.SHORT:
+                return ""
+            else:
+                blob = integer.to_bytes(length=4, byteorder=byteorder)
+                blob = " ".join(map(lambda byte: f"{byte:02x}", blob))
+                return f"{blob}    "
 
+        blob_prefix = blob(int(self.prefix))
+        blob_suffix = blob(int(self.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}"
+            yield f"{blob_prefix}.long 0x{int(self.prefix):08x}"
+            yield f"{blob_suffix}.long 0x{int(self.suffix):08x}"
             return
 
         operands = tuple(map(_operator.itemgetter(1),
-            self.dynamic_operands(db=db, short=short)))
+            self.dynamic_operands(db=db, verbosity=verbosity)))
         if operands:
-            yield f"{blob_prefix}    sv.{record.name} {','.join(operands)}"
+            yield f"{blob_prefix}sv.{record.name} {','.join(operands)}"
         else:
-            yield f"{blob_prefix}    {record.name}"
+            yield f"{blob_prefix}{record.name}"
         yield f"{blob_suffix}"
 
         (mode, mode_desc) = self.mode(db=db)
 
-        if verbose:
+        if verbosity >= Verbosity.VERBOSE:
             indent = (" " * 4)
             binary = self.binary
             spec = self.spec(db=db, prefix="sv.")
@@ -1462,7 +1479,7 @@ class SVP64Instruction(PrefixedInstruction):
             yield f"{indent}{indent}{mask}"
             for operand in record.operands:
                 yield from operand.disassemble(insn=self, record=record,
-                    short=short, verbose=True, indent=indent)
+                    verbosity=verbosity, indent=indent)
 
             yield f"{indent}mode"
             yield f"{indent}{indent}{mode_desc}"
index 135d9c0c8d3d119fa6dd114980680ab84f69a80a..837041da1ac9edbfeab150a4f3a272911b10aa9e 100644 (file)
@@ -7,6 +7,7 @@ from openpower.decoder.power_enums import (
     find_wiki_dir as _find_wiki_dir,
 )
 from openpower.decoder.power_insn import (
+    Verbosity as _Verbosity,
     Database as _Database,
     WordInstruction as _WordInstruction,
     PrefixedInstruction as _PrefixedInstruction,
@@ -53,10 +54,10 @@ def load(ifile, byteorder=ByteOrder.LITTLE, **_):
     ifile.seek(curpos) # restore position so that generator can be reused
 
 
-def dump(insns, verbose, short=False, **_):
+def dump(insns, verbosity, **_):
     db = _Database(_find_wiki_dir())
     for insn in insns:
-        yield from insn.disassemble(db=db, verbose=verbose, short=short)
+        yield from insn.disassemble(db=db, verbosity=verbosity)
 
 
 # this is the entry-point for the console-script pysvp64dis
@@ -68,10 +69,12 @@ def main():
         type=_argparse.FileType("w"), default=_sys.stdout)
     parser.add_argument("-b", "--byteorder",
         type=ByteOrder, default=ByteOrder.LITTLE)
-    parser.add_argument("-v", "--verbose",
-        action="store_true", default=False)
     parser.add_argument("-s", "--short",
-        action="store_true", default=False)
+        dest="verbosity", default=_Verbosity.NORMAL,
+        action="store_const", const=_Verbosity.SHORT)
+    parser.add_argument("-v", "--verbose",
+        dest="verbosity", default=_Verbosity.NORMAL,
+        action="store_const", const=_Verbosity.VERBOSE)
     parser.add_argument("-l", "--log",
         action="store_true", default=False)