pysvp64asm: avoid empty fields
[openpower-isa.git] / src / openpower / sv / sv_binutils.py
index 99d969b5f8affb6ec2a5c22958118c5c9e8e37d7..b4dea0acf62ed1419fb36cda661c99f2b702d3ee 100644 (file)
@@ -13,11 +13,12 @@ from openpower.decoder.power_enums import (
     In3Sel as _In3Sel,
     OutSel as _OutSel,
     CRInSel as _CRInSel,
+    CRIn2Sel as _CRIn2Sel,
     CROutSel as _CROutSel,
-    SVPtype as _SVPtype,
-    SVEtype as _SVEtype,
+    SVPType as _SVPType,
+    SVEType as _SVEType,
     SVExtra as _SVExtra,
-    Function as _Function,
+    SVMode as _SVMode,
     find_wiki_dir as _find_wiki_dir,
 )
 from openpower.consts import SVP64MODE as _SVP64MODE
@@ -178,11 +179,12 @@ In2Sel = Enum("In2Sel", _In2Sel, c_tag="svp64_in2_sel")
 In3Sel = Enum("In3Sel", _In3Sel, c_tag="svp64_in3_sel")
 OutSel = Enum("OutSel", _OutSel, c_tag="svp64_out_sel")
 CRInSel = Enum("CRInSel", _CRInSel, c_tag="svp64_cr_in_sel")
+CRIn2Sel = Enum("CRIn2Sel", _CRIn2Sel, c_tag="svp64_cr_in2_sel")
 CROutSel = Enum("CROutSel", _CROutSel, c_tag="svp64_cr_out_sel")
-PType = Enum("PType", _SVPtype, c_tag="svp64_ptype")
-EType = Enum("EType", _SVEtype, c_tag="svp64_etype", exclude="NONE")
+PType = Enum("PType", _SVPType, c_tag="svp64_ptype")
+EType = Enum("EType", _SVEType, c_tag="svp64_etype", exclude="NONE")
 Extra = Enum("Extra", _SVExtra, c_tag="svp64_extra", exclude="Idx_1_2")
-Function = Enum("Function", _Function, c_tag="svp64_function")
+Mode = Enum("Mode", _SVMode, c_tag="svp64_mode")
 
 
 class Constant(_enum.Enum, metaclass=EnumMeta):
@@ -199,7 +201,7 @@ class Constant(_enum.Enum, metaclass=EnumMeta):
         yield f"{prefix}{self.c_tag.upper()}_{self.c_name.upper()}{suffix}"
 
 
-Mode = Constant("Mode", _SVP64MODE)
+ModeConst = Constant("Mode", _SVP64MODE)
 
 
 class StructMeta(ObjectMeta):
@@ -277,7 +279,6 @@ class Instruction(Struct, c_tag="svp64_insn"):
             yield f"{mangle(path, 'get')}(const {cls.c_typedef} *insn)"
             yield "{"
             yield from indent(["uint64_t value = insn->value;"])
-            yield ""
             yield from indent(["return ("])
             actions = []
             for (dst, src) in enumerate(reversed(field)):
@@ -286,9 +287,9 @@ class Instruction(Struct, c_tag="svp64_insn"):
                 src = f"UINT64_C({src})"
                 action = f"(((value >> {src}) & UINT64_C(1)) << {dst})"
                 actions.append(action)
-            for action in indent(indent(actions)):
+            for action in indent(indent(actions[:-1])):
                 yield f"{action} |"
-            yield from indent(indent(["UINT64_C(0)"]))
+            yield from indent(indent([f"{actions[-1]}"]))
             yield from indent([");"])
             yield "}"
             yield ""
@@ -310,16 +311,16 @@ class Instruction(Struct, c_tag="svp64_insn"):
                 action = f"(((value >> {src}) & UINT64_C(1)) << {dst})"
                 actions.append(action)
             yield from indent(["insn->value |= ("])
-            for action in indent(indent(actions)):
+            for action in indent(indent(actions[:-1])):
                 yield f"{action} |"
-            yield from indent(indent(["UINT64_C(0)"]))
+            yield from indent(indent([f"{actions[-1]}"]))
             yield from indent([");"])
             yield "}"
             yield ""
 
         yield from super().c_decl()
         yield ""
-        for (path, field) in _SVP64Instruction.traverse():
+        for (path, field) in _SVP64Instruction.traverse(path=""):
             yield from getter(path, field)
             yield from setter(path, field)
 
@@ -337,43 +338,60 @@ class Name(Object, str, c_typedef="const char *"):
         return f"{prefix}const char *{name}{suffix}"
 
 
-@_dataclasses.dataclass(eq=True, frozen=True)
-class Opcode(Struct):
-    class Value(UInt32):
-        def __new__(cls, value):
-            if isinstance(value, int):
-                value = f"0x{value:08x}"
-            return super().__new__(cls, value)
+class BooleanMeta(ObjectMeta):
+    def __len__(cls):
+        return 1
 
-    class Mask(UInt32):
-        def __new__(cls, value):
-            if isinstance(value, int):
-                value = f"0x{value:08x}"
-            return super().__new__(cls, value)
 
-    value: Value
-    mask: Mask
+class Boolean(Object, metaclass=BooleanMeta):
+    def __init__(self, value):
+        self.__state = bool(value)
+        return super().__init__()
+
+    def __bool__(self):
+        return self.__state
+
+    def __repr__(self):
+        return self.__state.__repr__()
+
+    @property
+    def name(self):
+        return "true" if self else "false"
+
+    @property
+    def value(self):
+        return "true" if self else "false"
+
+    def c_value(self, *, prefix="", suffix="", **kwargs):
+        yield f"{prefix}{self.value}{suffix}"
+
+    @classmethod
+    def c_var(cls, name, prefix="", suffix=""):
+        return f"{prefix}bool {name}{suffix}"
 
 
 @_dataclasses.dataclass(eq=True, frozen=True)
 class Desc(Struct):
-    function: Function
+    mode: Mode
     in1: In1Sel
     in2: In2Sel
     in3: In3Sel
     out: OutSel
     out2: OutSel
     cr_in: CRInSel
+    cr_in2: CRIn2Sel
     cr_out: CROutSel
-    sv_ptype: PType
-    sv_etype: EType
-    sv_in1: Extra
-    sv_in2: Extra
-    sv_in3: Extra
-    sv_out: Extra
-    sv_out2: Extra
-    sv_cr_in: Extra
-    sv_cr_out: Extra
+    ptype: PType
+    etype: EType
+    extra_idx_in1: Extra
+    extra_idx_in2: Extra
+    extra_idx_in3: Extra
+    extra_idx_out: Extra
+    extra_idx_out2: Extra
+    extra_idx_cr_in: Extra
+    extra_idx_cr_in2: Extra
+    extra_idx_cr_out: Extra
+    Rc: Boolean
 
     @classmethod
     def c_decl(cls):
@@ -389,11 +407,50 @@ class Desc(Struct):
         yield f"}};"
 
 
+@_dataclasses.dataclass(eq=True, frozen=True)
+class Opcode(Struct):
+    class Value(UInt32):
+        def __new__(cls, value):
+            if isinstance(value, int):
+                value = f"0x{value:08x}"
+            return super().__new__(cls, value)
+
+    class Mask(UInt32):
+        def __new__(cls, value):
+            if isinstance(value, int):
+                value = f"0x{value:08x}"
+            return super().__new__(cls, value)
+
+    value: Value
+    mask: Mask
+
+
+class Opcodes(Object, c_typedef="const struct svp64_opcode *"):
+    def __init__(self, offset):
+        self.__offset = offset
+        return super().__init__()
+
+    def __repr__(self):
+        return f"{self.__class__.__name__}({self.__offset})"
+
+    @classmethod
+    def c_var(cls, name, prefix="", suffix=""):
+        return f"{prefix}{cls.c_typedef}{name}{suffix}"
+
+    @classmethod
+    def c_decl(cls):
+        yield "const struct svp64_opcode *opcodes;"
+
+    def c_value(self, *, prefix="", suffix="", **kwargs):
+        yield f"{prefix}&svp64_opcodes[{self.__offset}]{suffix}"
+
+
 @_dataclasses.dataclass(eq=True, frozen=True)
 class Record(Struct):
     name: Name
-    opcode: Opcode
     desc: Desc
+    opcodes: Opcodes
+    nr_opcodes: Size
 
     def __lt__(self, other):
         if not isinstance(other, self.__class__):
@@ -409,8 +466,8 @@ class Codegen(_enum.Enum):
     def __str__(self):
         return self.value
 
-    def generate(self, records):
-        def ppc_svp64_h(records, num_records):
+    def generate(self, opcodes, records):
+        def ppc_svp64_h(opcodes, nr_opcodes, records, nr_records):
             disclaimer = DISCLAIMER.format(path=str(self),
                 desc="Header file for PowerPC opcode table (SVP64 extensions)")
             yield from disclaimer.splitlines()
@@ -430,9 +487,9 @@ class Codegen(_enum.Enum):
 
             enums = (
                 In1Sel, In2Sel, In3Sel, OutSel,
-                CRInSel, CROutSel,
+                CRInSel, CRIn2Sel, CROutSel,
                 PType, EType, Extra,
-                Mode, Function,
+                Mode, ModeConst,
             )
             for enum in enums:
                 yield from enum.c_decl()
@@ -442,9 +499,15 @@ class Codegen(_enum.Enum):
                 yield from cls.c_decl()
                 yield ""
 
+            yield opcodes.c_var("svp64_opcodes",
+                        prefix="extern const ", suffix=";")
+            yield nr_opcodes.c_var("svp64_nr_opcodes",
+                        prefix="extern const ", suffix=";")
+            yield ""
+
             yield records.c_var("svp64_records",
                         prefix="extern const ", suffix=";")
-            yield num_records.c_var("svp64_num_records",
+            yield nr_records.c_var("svp64_nr_records",
                         prefix="extern const ", suffix=";")
             yield ""
 
@@ -459,12 +522,13 @@ class Codegen(_enum.Enum):
 
             yield f"#endif /* {self.name} */"
 
-        def ppc_svp64_opc_c(records, num_records):
+        def ppc_svp64_opc_c(opcodes, nr_opcodes, records, nr_records):
             disclaimer = DISCLAIMER.format(path=str(self),
                 desc="PowerPC opcode list (SVP64 extensions)")
             yield from disclaimer.splitlines()
             yield ""
 
+            yield "#include <stdbool.h>"
             yield "#include \"opcode/ppc-svp64.h\""
             yield ""
 
@@ -514,26 +578,40 @@ class Codegen(_enum.Enum):
                     OutSel.RT_OR_ZERO: "RT",
                     OutSel.FRT: "FRT",
                     OutSel.FRS: "FRS",
+                    OutSel.RS: "RS",
                 })
             yield from opindex(CRInSel, "cr_in", {
                 CRInSel.BI: "BI",
                 CRInSel.BFA: "BFA",
                 CRInSel.BC: "BC",
+                CRInSel.BA: "BA",
                 CRInSel.WHOLE_REG: "FXM",
             })
+            yield from opindex(CRIn2Sel, "cr_in2", {
+                CRIn2Sel.BB: "BB",
+            })
             yield from opindex(CROutSel, "cr_out", {
                 CROutSel.BF: "BF",
                 CROutSel.BT: "BT",
                 CROutSel.WHOLE_REG: "FXM",
             })
 
+            yield opcodes.c_var("svp64_opcodes",
+                        prefix="const ", suffix=" = \\")
+            yield from opcodes.c_value(prefix="", suffix=";")
+            yield ""
+            yield nr_opcodes.c_var("svp64_nr_opcodes",
+                        prefix="const ", suffix=" = \\")
+            yield from indent(nr_opcodes.c_value(suffix=";"))
+            yield ""
+
             yield records.c_var("svp64_records",
                         prefix="const ", suffix=" = \\")
             yield from records.c_value(prefix="", suffix=";")
             yield ""
-            yield num_records.c_var("svp64_num_records",
+            yield nr_records.c_var("svp64_nr_records",
                         prefix="const ", suffix=" = \\")
-            yield from indent(num_records.c_value(suffix=";"))
+            yield from indent(nr_records.c_value(suffix=";"))
             yield ""
 
             yield "const struct powerpc_pd_reg svp64_regs[] = {"
@@ -556,16 +634,21 @@ class Codegen(_enum.Enum):
                         prefix="const ", suffix=" = \\")
             yield from indent(num_regs.c_value(suffix=";"))
 
+        opcodes = Array[Opcode, ...](opcodes)
+        nr_opcodes = Size("(sizeof (svp64_opcodes) / sizeof (svp64_opcodes[0]))")
+
         records = Array[Record, ...](records)
-        num_records = Size("(sizeof (svp64_records) / sizeof (svp64_records[0]))")
+        nr_records = Size("(sizeof (svp64_records) / sizeof (svp64_records[0]))")
 
         yield from {
             Codegen.PPC_SVP64_GEN_H: ppc_svp64_h,
             Codegen.PPC_SVP64_OPC_GEN_C: ppc_svp64_opc_c,
-        }[self](records, num_records)
+        }[self](opcodes, nr_opcodes, records, nr_records)
 
 
-def records(db):
+def collect(db):
+    opcodes = []
+    records = []
     fields = {field.name:field.type for field in _dataclasses.fields(Desc)}
 
     for insn in filter(lambda insn: insn.svp64 is not None, db):
@@ -574,12 +657,14 @@ def records(db):
         for (key, cls) in fields.items():
             value = getattr(insn, key)
 
-            if (((cls is EType) and (value is _SVEtype.NONE)) or
+            if (((cls is EType) and (value is _SVEType.NONE)) or
                     ((cls is Extra) and (value is _SVExtra.Idx_1_2))):
                 desc = None
                 break
 
-            if issubclass(cls, _enum.Enum):
+            if issubclass(cls, Boolean):
+                value = Boolean(value)
+            elif issubclass(cls, _enum.Enum):
                 value = cls[value.name]
             else:
                 value = cls(value)
@@ -589,17 +674,25 @@ def records(db):
             continue
 
         name = Name(f"sv.{insn.name}")
-        value = Opcode.Value(insn.opcode.value)
-        mask = Opcode.Mask(insn.opcode.mask)
-        opcode = Opcode(value=value, mask=mask)
+        offset = len(opcodes)
+        for opcode in insn.opcodes:
+            value = Opcode.Value(opcode.value)
+            mask = Opcode.Mask(opcode.mask)
+            opcode = Opcode(value=value, mask=mask)
+            opcodes.append(opcode)
         desc = Desc(**desc)
 
-        yield Record(name=name, opcode=opcode, desc=desc)
+        record = Record(name=name, desc=desc,
+            opcodes=Opcodes(offset), nr_opcodes=Size(len(insn.opcodes)))
+        records.append(record)
+
+    return (opcodes, records)
 
 
 def main(codegen):
     db = _Database(_find_wiki_dir())
-    for line in codegen.generate(records(db)):
+    (opcodes, records) = collect(db)
+    for line in codegen.generate(opcodes, records):
         print(line)