temporary hack-revert, the original is now in branch "paths"
[openpower-isa.git] / src / openpower / sv / sv_binutils.py
index e9f4feb86023e1884475a5741b4f85bd00df9475..a6a7f10922f7f865955d43ca1188f772b2109eb3 100644 (file)
@@ -1,9 +1,11 @@
-import abc as _abc
 import argparse as _argparse
 import dataclasses as _dataclasses
 import enum as _enum
-import functools as _functools
-import operator as _operator
+
+import os as _os
+import sys as _sys
+
+_sys.path.append(_os.path.dirname(_os.path.realpath(__file__)) + "/../../")
 
 from openpower.decoder.power_enums import (
     In1Sel as _In1Sel,
@@ -11,18 +13,17 @@ 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,
-    RC as _RC,
+    SVMode as _SVMode,
     find_wiki_dir as _find_wiki_dir,
 )
 from openpower.consts import SVP64MODE as _SVP64MODE
-from openpower.decoder.power_insn import Database as _Database
-from openpower.decoder.isa.caller import SVP64RMFields as _SVP64RMFields
-from openpower.decoder.isa.caller import SVP64PrefixFields as _SVP64PrefixFields
-from openpower.decoder.selectable_int import SelectableIntMapping
+from openpower.insndb.core import Database as _Database
+from openpower.insndb.core import SVP64Instruction as _SVP64Instruction
 
 
 DISCLAIMER = """\
@@ -54,96 +55,85 @@ def indent(strings):
     return map(lambda string: ("  " + string), strings)
 
 
-class CTypeMeta(type):
-    def __new__(metacls, name, bases, attrs, typedef="void"):
-        cls = super().__new__(metacls, name, bases, attrs)
-        if typedef == "void":
+class ObjectMeta(type):
+    def __new__(metacls, clsname, bases, ns,
+            c_typedef="void", **kwargs):
+        if c_typedef == "void":
             for base in bases:
                 if (hasattr(base, "c_typedef") and
                         (base.c_typedef != "void")):
-                    typedef = base.c_typedef
+                    c_typedef = base.c_typedef
                     break
-        cls.__typedef = typedef
 
-        return cls
+        ns.setdefault("c_typedef", c_typedef)
+        ns.update(kwargs)
 
-    def __getitem__(cls, size):
-        name = f"{cls.__name__}[{'' if size is Ellipsis else size}]"
-        return type(name, (Array,), {}, type=cls, size=size)
+        return super().__new__(metacls, clsname, bases, ns)
 
-    @property
-    def c_typedef(cls):
-        return cls.__typedef
 
-    @_abc.abstractmethod
+class Object(metaclass=ObjectMeta):
+    @classmethod
     def c_decl(cls):
         yield from ()
 
+    @classmethod
     def c_var(cls, name, prefix="", suffix=""):
         return f"{prefix}{cls.c_typedef} {name}{suffix}"
 
+    def c_value(self, *, prefix="", suffix="", **kwargs):
+        yield from ()
 
-class ArrayMeta(CTypeMeta):
-    def __new__(metacls, name, bases, attrs, type, size, **kwargs):
-        cls = super().__new__(metacls, name, bases, attrs, **kwargs)
-        cls.__type = type
-        cls.__ellipsis = (size is Ellipsis)
-        cls.__size = 0 if cls.__ellipsis else size
-
-        return cls
-
-    def __len__(cls):
-        return cls.__size
 
-    def c_decl(cls):
-        size = "" if cls.__ellipsis else f"{cls.__size}"
-        yield f"{cls.__type.c_typedef}[{size}]"
+class ArrayMeta(ObjectMeta):
+    def __new__(metacls, clsname, bases, ns,
+            c_base, c_size, **kwargs):
+        if c_size is Ellipsis:
+            clsname = f"{clsname}[]"
+        else:
+            clsname = f"{clsname}[{c_size}]"
 
-    def c_var(cls, name, prefix="", suffix=""):
-        size = "" if cls.__ellipsis else f"{cls.__size}"
-        return f"{prefix}{cls.__type.c_typedef} {name}[{size}]{suffix}"
+        return super().__new__(metacls, clsname, bases, ns,
+            c_typedef=c_base.c_typedef, c_base=c_base, c_size=c_size, **kwargs)
 
+    def __getitem__(cls, key):
+        (c_base, c_size) = key
+        return cls.__class__(cls.__name__, (cls,), {},
+            c_base=c_base, c_size=c_size)
 
-class BitmapMeta(CTypeMeta):
-    def __new__(metacls, name, bases, attrs,
-            typedef="uint64_t", bits=0, **kwargs):
-        cls = super().__new__(metacls,
-            name, bases, attrs, typedef=typedef, **kwargs)
-        cls.__bits = bits
-        return cls
 
-    def __len__(cls):
-        return cls.__bits
+class Array(Object, tuple, metaclass=ArrayMeta,
+        c_base=Object, c_size=...):
+    @classmethod
+    def c_decl(cls):
+        if cls.c_size is Ellipsis:
+            size = ""
+        else:
+            size = f"{len(cls)}"
+        yield f"{cls.c_base.c_typedef}[{size}]"
 
+    @classmethod
     def c_var(cls, name, prefix="", suffix=""):
-        return f"{prefix}{cls.c_typedef} {name} : {cls.__bits}{suffix}"
-
-
-class CType(metaclass=CTypeMeta):
-    @_abc.abstractmethod
-    def c_value(self, *, prefix="", suffix="", **kwargs):
-        yield from ()
+        if cls.c_size is Ellipsis:
+            size = ""
+        else:
+            size = f"{len(cls)}"
+        return f"{prefix}{cls.c_base.c_typedef} {name}[{size}]{suffix}"
 
-
-class Array(CType, tuple, metaclass=ArrayMeta, type=CType, size=...):
     def c_value(self, *, prefix="", suffix="", **kwargs):
         yield f"{prefix}{{"
-        for (index, item) in enumerate(self):
+        for item in self:
             yield from indent(item.c_value(suffix=","))
         yield f"}}{suffix}"
 
 
-class Bitmap(metaclass=BitmapMeta):
-    pass
-
-
-class Void(CType, typedef="void"):
+class Void(Object, c_typedef="void"):
     def c_var(cls, name, prefix="", suffix=""):
         raise NotImplementedError
 
 
-class EnumMeta(_enum.EnumMeta, CTypeMeta):
-    def __call__(metacls, name, entries, tag=None, exclude=None, **kwargs):
+class EnumMeta(_enum.EnumMeta, ObjectMeta):
+    def __call__(cls, clsname, entries,
+            c_tag=None, c_typedef=None, exclude=None):
         if exclude is None:
             exclude = frozenset()
         if isinstance(entries, type) and issubclass(entries, _enum.Enum):
@@ -152,53 +142,52 @@ class EnumMeta(_enum.EnumMeta, CTypeMeta):
         if isinstance(entries, dict):
             entries = tuple(entries.items())
         entries = ((key, value) for (key, value) in entries if key not in exclude)
-        if tag is None:
-            tag = f"svp64_{name.lower()}"
 
-        cls = super().__call__(value=name, names=entries, **kwargs)
-        cls.__tag = tag
+        if c_tag is None:
+            c_tag = f"svp64_{clsname.lower()}"
+        if c_typedef is None:
+            c_typedef = f"enum {c_tag}"
 
-        return cls
+        base = ObjectMeta(cls.__name__, (), {},
+            c_tag=c_tag, c_typedef=c_typedef)
 
-    @property
-    def c_typedef(cls):
-        return f"enum {cls.c_tag}"
+        return super().__call__(value=clsname, names=entries, type=base)
 
+
+class Enum(Object, _enum.Enum, metaclass=EnumMeta):
     @property
-    def c_tag(cls):
-        return cls.__tag
+    def c_name(self):
+        return f"{self.c_tag.upper()}_{self.name.upper()}"
 
+    @classmethod
     def c_decl(cls):
         yield f"{cls.c_typedef} {{"
         for item in cls:
             yield from indent(item.c_value(suffix=","))
         yield f"}};"
 
-    def c_var(cls, name, prefix="", suffix=""):
-        return f"{prefix}{cls.c_typedef} {name}{suffix}"
-
-
-class Enum(CType, _enum.Enum, metaclass=EnumMeta):
-    @property
-    def c_name(self):
-        return f"{self.__class__.c_tag.upper()}_{self.name.upper()}"
-
     def c_value(self, *, prefix="", suffix="", **kwargs):
         yield f"{prefix}{self.c_name}{suffix}"
 
+    @classmethod
+    def c_var(cls, name, prefix="", suffix=""):
+        return f"{prefix}{cls.c_typedef} {name}{suffix}"
 
-In1Sel = Enum("In1Sel", _In1Sel, tag="svp64_in1_sel")
-In2Sel = Enum("In2Sel", _In2Sel, tag="svp64_in2_sel")
-In3Sel = Enum("In3Sel", _In3Sel, tag="svp64_in3_sel")
-OutSel = Enum("OutSel", _OutSel, tag="svp64_out_sel")
-CRInSel = Enum("CRInSel", _CRInSel, tag="svp64_cr_in_sel")
-CROutSel = Enum("CROutSel", _CROutSel, tag="svp64_cr_out_sel")
-PType = Enum("PType", _SVPtype, tag="svp64_ptype")
-EType = Enum("EType", _SVEtype, tag="svp64_etype", exclude="NONE")
-Extra = Enum("Extra", _SVExtra, tag="svp64_extra", exclude="Idx_1_2")
 
+In1Sel = Enum("In1Sel", _In1Sel, c_tag="svp64_in1_sel")
+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")
+Extra = Enum("Extra", _SVExtra, c_tag="svp64_extra", exclude="Idx_1_2")
+Mode = Enum("Mode", _SVMode, c_tag="svp64_mode")
 
-class Constant(CType, _enum.Enum, metaclass=EnumMeta):
+
+class Constant(_enum.Enum, metaclass=EnumMeta):
     @classmethod
     def c_decl(cls):
         yield f"/* {cls.c_tag.upper()} constants */"
@@ -209,28 +198,28 @@ class Constant(CType, _enum.Enum, metaclass=EnumMeta):
             yield f"#define {key} {value}"
 
     def c_value(self, *, prefix="", suffix="", **kwargs):
-        yield f"{prefix}{self.__class__.c_tag.upper()}_{self.c_name.upper()}{suffix}"
+        yield f"{prefix}{self.c_tag.upper()}_{self.c_name.upper()}{suffix}"
 
 
-Mode = Constant("Mode", _SVP64MODE)
+ModeConst = Constant("Mode", _SVP64MODE)
 
 
-class StructMeta(CTypeMeta):
-    def __new__(metacls, name, bases, attrs, tag=None, **kwargs):
-        if tag is None:
-            tag = f"svp64_{name.lower()}"
-        if "typedef" not in kwargs:
-            kwargs["typedef"] = f"struct {tag}"
+class StructMeta(ObjectMeta):
+    def __new__(metacls, clsname, bases, ns,
+            c_tag=None, c_typedef=None):
 
-        cls = super().__new__(metacls, name, bases, attrs, **kwargs)
-        cls.__tag = tag
+        if c_tag is None:
+            c_tag = f"svp64_{clsname.lower()}"
+        if c_typedef is None:
+            c_typedef = f"struct {c_tag}"
 
-        return cls
+        return super().__new__(metacls, clsname, bases, ns,
+            c_typedef=c_typedef, c_tag=c_tag)
 
-    @property
-    def c_tag(cls):
-        return cls.__tag
 
+@_dataclasses.dataclass(eq=True, frozen=True)
+class Struct(Object, metaclass=StructMeta):
+    @classmethod
     def c_decl(cls):
         def transform(field):
             return field.type.c_var(name=f"{field.name}", suffix=";")
@@ -239,9 +228,6 @@ class StructMeta(CTypeMeta):
         yield from indent(map(transform, _dataclasses.fields(cls)))
         yield f"}};"
 
-
-@_dataclasses.dataclass(eq=True, frozen=True)
-class Struct(CType, metaclass=StructMeta):
     def c_value(self, *, prefix="", suffix="", **kwargs):
         yield f"{prefix}{{"
         for field in _dataclasses.fields(self):
@@ -251,24 +237,95 @@ class Struct(CType, metaclass=StructMeta):
         yield f"}}{suffix}"
 
 
-class Integer(CType, str):
+class Integer(Object, str):
     def c_value(self, *, prefix="", suffix="", **kwargs):
         yield f"{prefix}{self}{suffix}"
 
 
-class Byte(Integer, typedef="uint8_t"):
+class Byte(Integer, c_typedef="uint8_t"):
+    pass
+
+
+class Size(Integer, c_typedef="size_t"):
     pass
 
 
-class Size(Integer, typedef="size_t"):
+class UInt32(Integer, c_typedef="uint32_t"):
     pass
 
 
-class UInt32(Integer, typedef="uint32_t"):
+class UInt64(Integer, c_typedef="uint64_t"):
     pass
 
 
-class Name(CType, str, typedef="const char *"):
+@_dataclasses.dataclass(eq=True, frozen=True)
+class Instruction(Struct, c_tag="svp64_insn"):
+    value: UInt64
+
+    @classmethod
+    def c_decl(cls):
+        def mangle(path, action):
+            if path.endswith("]"):
+                path = path[:-1]
+            for symbol in (".", "[", "]"):
+                path = path.replace(symbol, "_")
+            if path != "":
+                return f"{cls.c_tag}_{action}_{path}"
+            else:
+                return f"{cls.c_tag}_{action}"
+
+        def getter(path, field):
+            yield "static inline uint64_t"
+            yield f"{mangle(path, 'get')}(const {cls.c_typedef} *insn)"
+            yield "{"
+            yield from indent(["uint64_t value = insn->value;"])
+            yield from indent(["return ("])
+            actions = []
+            for (dst, src) in enumerate(reversed(field)):
+                src = (64 - (src + 1))
+                dst = f"UINT64_C({dst})"
+                src = f"UINT64_C({src})"
+                action = f"(((value >> {src}) & UINT64_C(1)) << {dst})"
+                actions.append(action)
+            for action in indent(indent(actions[:-1])):
+                yield f"{action} |"
+            yield from indent(indent([f"{actions[-1]}"]))
+            yield from indent([");"])
+            yield "}"
+            yield ""
+
+        def setter(path, field):
+            mask = ((2 ** 64) - 1)
+            for bit in field:
+                mask &= ~(1 << (64 - (bit + 1)))
+            action = mangle(path, "set")
+            yield "static inline void"
+            yield f"{mangle(path, 'set')}({cls.c_typedef} *insn, uint64_t value)"
+            yield "{"
+            yield from indent([f"insn->value &= UINT64_C(0x{mask:016x});"])
+            actions = []
+            for (src, dst) in enumerate(reversed(field)):
+                dst = (64 - (dst + 1))
+                dst = f"UINT64_C({dst})"
+                src = f"UINT64_C({src})"
+                action = f"(((value >> {src}) & UINT64_C(1)) << {dst})"
+                actions.append(action)
+            yield from indent(["insn->value |= ("])
+            for action in indent(indent(actions[:-1])):
+                yield f"{action} |"
+            yield from indent(indent([f"{actions[-1]}"]))
+            yield from indent([");"])
+            yield "}"
+            yield ""
+
+        yield from super().c_decl()
+        yield ""
+        for (path, field) in _SVP64Instruction.traverse(path=""):
+            yield from getter(path, field)
+            yield from setter(path, field)
+
+
+class Name(Object, str, c_typedef="const char *"):
     def __repr__(self):
         escaped = self.replace("\"", "\\\"")
         return f"\"{escaped}\""
@@ -281,42 +338,60 @@ class Name(CType, str, 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):
+    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):
@@ -333,176 +408,66 @@ class Desc(Struct):
 
 
 @_dataclasses.dataclass(eq=True, frozen=True)
-class Record(Struct):
-    name: Name
-    opcode: Opcode
-    desc: Desc
+class Opcode(Struct):
+    class Value(UInt32):
+        def __new__(cls, value):
+            if isinstance(value, int):
+                value = f"0x{value:08x}"
+            return super().__new__(cls, value)
 
-    def __lt__(self, other):
-        if not isinstance(other, self.__class__):
-            return NotImplemented
+    class Mask(UInt32):
+        def __new__(cls, value):
+            if isinstance(value, int):
+                value = f"0x{value:08x}"
+            return super().__new__(cls, value)
 
-        return self.name < other.name
+    value: Value
+    mask: Mask
 
 
-class FunctionMeta(CTypeMeta):
-    def __new__(metacls, name, bases, attrs, rv, args):
-        cls = super().__new__(metacls, name, bases, attrs)
-        cls.__rv = rv
-        cls.__args = args
+class Opcodes(Object, c_typedef="const struct svp64_opcode *"):
+    def __init__(self, offset):
+        self.__offset = offset
+        return super().__init__()
 
-        return cls
+    def __repr__(self):
+        return f"{self.__class__.__name__}({self.__offset})"
 
+    @classmethod
     def c_var(cls, name, prefix="", suffix=""):
-        rv = cls.__rv.c_typedef
-        args = ", ".join(arg_cls.c_var(arg_name) \
-                    for (arg_name, arg_cls) in cls.__args)
-        return f"{prefix}{rv} {name}({args}){suffix}"
-
-
-class FieldsMappingMeta(EnumMeta):
-    class HelperMeta(FunctionMeta):
-        def __new__(metacls, name, bases, attrs, rv, args, enum):
-            cls = super().__new__(metacls, name, bases, attrs, rv=rv, args=args)
-            cls.__enum = enum
-            return cls
-
-        def __iter__(cls):
-            short_c_tag = cls.__enum.c_tag[:-len("_field")]
-            # Use __members__, not __iter__, otherwise aliases are lost.
-            for (name, value) in cls.__enum.__members__.items():
-                yield (f"{short_c_tag}_{name}".upper(), value)
-
-    class GetterMeta(HelperMeta):
-        def __new__(metacls, name, bases, attrs, enum, struct):
-            return super().__new__(metacls, name, bases, attrs,
-                                    enum=enum, rv=UInt32, args=(
-                ("storage", struct),
-                ("field", enum),
-            ))
-
-    class SetterMeta(HelperMeta):
-        def __new__(metacls, name, bases, attrs, enum, struct):
-            return super().__new__(metacls, name, bases, attrs, enum=enum,
-                                   rv=Void, args=(
-                ("*storage", struct),
-                ("field", enum),
-                ("value", UInt32),
-            ))
-
-    def __call__(metacls, name, base=SelectableIntMapping, **kwargs):
-        def flatten(mapping, parent=""):
-            for (key, value) in mapping.items():
-                key = f"{parent}_{key}" if parent else key
-                if isinstance(value, dict):
-                    yield from flatten(mapping=value, parent=key)
-                else:
-                    value = map(lambda bit: bit, reversed(value))
-                    yield (key.upper(), tuple(value))
-
-        tag = f"svp64_{name.lower()}"
-        entries = dict(flatten(mapping=dict(base)))
-        bitmap = type(name, (Bitmap,), {}, typedef="uint32_t", bits=base.bits)
-        struct = _dataclasses.make_dataclass(name, (("value", bitmap),),
-            bases=(Struct,), frozen=True, eq=True)
-
-        cls = super().__call__(name=name,
-            entries=entries, tag=f"{tag}_field", **kwargs)
-
-        def c_value(entries, stmt):
-            yield "switch (field) {"
-            for (field_name, field_value) in entries:
-                yield from indent([f"case {field_name}:"])
-                yield from indent(indent(map(stmt,
-                                             enumerate(field_value.value))))
-                yield from indent(indent(["break;"]))
-            yield "}"
-
-        class Getter(metaclass=FieldsMappingMeta.GetterMeta,
-                enum=cls, struct=struct):
-            def c_value(self, prefix="", suffix=""):
-                yield f"{prefix}{{"
-                yield from indent([
-                    UInt32.c_var(name="result", suffix=" = UINT32_C(0);"),
-                    UInt32.c_var(name="origin", suffix=" = storage.value;"),
-                ])
-                yield ""
-                yield from indent(c_value(entries=self.__class__,
-                    stmt=lambda kv: f"result |= SVP64_FIELD_GET(origin, {kv[1]}, {kv[0]});"))
-                yield ""
-                yield from indent(["return result;"])
-                yield f"}}{suffix}"
-
-        class Setter(metaclass=FieldsMappingMeta.SetterMeta,
-                enum=cls, struct=struct):
-            def c_value(self, prefix="", suffix=""):
-                yield f"{prefix}{{"
-                yield from indent([
-                    UInt32.c_var(name="result", suffix=" = storage->value;"),
-                ])
-                yield ""
-                yield from indent(c_value(entries=self.__class__,
-                    stmt=lambda kv: f"SVP64_FIELD_SET(&result, value, {kv[0]}, {kv[1]});"))
-                yield ""
-                yield from indent(["storage->value = result;"])
-                yield f"}}{suffix}"
-
-        cls.__tag = tag
-        cls.__struct = struct
-        cls.__getter = Getter()
-        cls.__setter = Setter()
-
-        return cls
-
-    @property
-    def c_getter(cls):
-        return cls.__getter
-
-    @property
-    def c_setter(cls):
-        return cls.__setter
+        return f"{prefix}{cls.c_typedef}{name}{suffix}"
 
+    @classmethod
     def c_decl(cls):
-        yield f"{cls.c_typedef} {{"
-        for field_name in cls.__members__.keys():
-            short_c_tag = cls.c_tag[:-len("_field")]
-            yield from indent([f"{short_c_tag}_{field_name},".upper()])
-        yield f"}};"
-        yield from cls.__struct.c_decl()
-        yield cls.__getter.__class__.c_var(name=f"{cls.__tag}_get", suffix=";")
-        yield cls.__setter.__class__.c_var(name=f"{cls.__tag}_set", suffix=";")
+        yield "const struct svp64_opcode *opcodes;"
 
+    def c_value(self, *, prefix="", suffix="", **kwargs):
+        yield f"{prefix}&svp64_opcodes[{self.__offset}]{suffix}"
 
-class FieldsMapping(Enum, metaclass=FieldsMappingMeta):
-    @property
-    def c_name(self):
-        short_c_tag = self.__class__.c_tag[:-len("_field")]
-        return f"{short_c_tag}_{self.name}".upper()
 
+@_dataclasses.dataclass(eq=True, frozen=True)
+class Record(Struct):
+    name: Name
+    desc: Desc
+    opcodes: Opcodes
+    nr_opcodes: Size
 
-Prefix = FieldsMapping("Prefix", base=_SVP64PrefixFields)
-RM = FieldsMapping("RM", base=_SVP64RMFields)
+    def __lt__(self, other):
+        if not isinstance(other, self.__class__):
+            return NotImplemented
 
+        return self.name < other.name
 
-class Codegen(_enum.Enum):
-    PPC_SVP64_GEN_H = _enum.auto()
-    PPC_SVP64_OPC_GEN_C = _enum.auto()
 
-    @classmethod
-    def _missing_(cls, value):
-        return {
-            "ppc-svp64-gen.h": Codegen.PPC_SVP64_GEN_H,
-            "ppc-svp64-opc-gen.c": Codegen.PPC_SVP64_OPC_GEN_C,
-        }.get(value)
+class Codegen(_enum.Enum):
+    PPC_SVP64_GEN_H = "include/opcode/ppc-svp64-gen.h"
+    PPC_SVP64_OPC_GEN_C = "opcodes/ppc-svp64-opc-gen.c"
 
     def __str__(self):
-        return {
-            Codegen.PPC_SVP64_GEN_H: "ppc-svp64-gen.h",
-            Codegen.PPC_SVP64_OPC_GEN_C: "ppc-svp64-opc-gen.c",
-        }[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()
@@ -522,21 +487,27 @@ class Codegen(_enum.Enum):
 
             enums = (
                 In1Sel, In2Sel, In3Sel, OutSel,
-                CRInSel, CROutSel,
+                CRInSel, CRIn2Sel, CROutSel,
                 PType, EType, Extra,
-                Mode,
+                Mode, ModeConst,
             )
             for enum in enums:
                 yield from enum.c_decl()
                 yield ""
 
-            for cls in (Desc, Opcode, Record, Prefix, RM):
+            for cls in (Instruction, Desc, Opcode, Record):
                 yield from cls.c_decl()
                 yield ""
 
-            yield records.__class__.c_var("svp64_records",
+            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.__class__.c_var("svp64_num_records",
+            yield nr_records.c_var("svp64_nr_records",
                         prefix="extern const ", suffix=";")
             yield ""
 
@@ -550,14 +521,14 @@ class Codegen(_enum.Enum):
             yield ""
 
             yield f"#endif /* {self.name} */"
-            yield ""
 
-        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 ""
 
@@ -607,77 +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 records.__class__.c_var("svp64_records",
+            yield opcodes.c_var("svp64_opcodes",
                         prefix="const ", suffix=" = \\")
-            yield from records.c_value(prefix="", suffix=";")
+            yield from opcodes.c_value(prefix="", suffix=";")
             yield ""
-            yield num_records.__class__.c_var("svp64_num_records",
+            yield nr_opcodes.c_var("svp64_nr_opcodes",
                         prefix="const ", suffix=" = \\")
-            yield from indent(num_records.c_value(suffix=";"))
+            yield from indent(nr_opcodes.c_value(suffix=";"))
             yield ""
 
-            bit_shl = lambda val, pos: f"({val} << UINT32_C({pos}))"
-            bit_shr = lambda val, pos: f"({val} >> UINT32_C({pos}))"
-            bit_get = lambda val, pos: f"({bit_shr(val, pos)} & UINT32_C(1))"
-            bit_or = lambda lhs, rhs: f"({lhs} | {rhs})"
-            bit_and = lambda lhs, rhs: f"({lhs} & {rhs})"
-            bit_not = lambda val: f"~({val})"
-
-            macros = (
-                (
-                    "SVP64_FIELD_CLEAR",
-                    ("VALUE", "BIT"),
-                    bit_and("VALUE", bit_not(bit_shl("UINT32_C(1)", "BIT"))),
-                ),
-                (
-                    "SVP64_FIELD_REMAP",
-                    ("VALUE", "SRC", "DST"),
-                    bit_shl(bit_get("VALUE", "SRC"), "DST"),
-                ),
-                (
-                    "SVP64_FIELD_GET",
-                    ("ORIGIN", "SRC", "DST"),
-                    "SVP64_FIELD_REMAP(ORIGIN, SRC, DST)",
-                ),
-                (
-                    "SVP64_FIELD_SET",
-                    ("RESULT", "VALUE", "SRC", "DST"),
-                    ("do { (*RESULT) = " + bit_or(
-                        lhs="SVP64_FIELD_CLEAR(*(RESULT), DST)",
-                        rhs="SVP64_FIELD_REMAP(VALUE, SRC, DST)",
-                    ) + "; } while (0)"),
-                ),
-            )
-            for (name, args, body) in macros:
-                yield f"#define {name}({', '.join(args)}) \\"
-                yield from indent([body])
-                yield ""
-
-            for cls in (Prefix, RM):
-                table = {
-                    "get": cls.c_getter,
-                    "set": cls.c_setter,
-                }
-                for (mode, subcls) in table.items():
-                    yield subcls.__class__.c_var(name=f"svp64_{cls.__name__.lower()}_{mode}")
-                    yield from subcls.c_value()
-                    yield ""
-
-            for name in map(_operator.itemgetter(0), macros):
-                yield f"#undef {name}"
+            yield records.c_var("svp64_records",
+                        prefix="const ", suffix=" = \\")
+            yield from records.c_value(prefix="", suffix=";")
+            yield ""
+            yield nr_records.c_var("svp64_nr_records",
+                        prefix="const ", suffix=" = \\")
+            yield from indent(nr_records.c_value(suffix=";"))
             yield ""
 
             yield "const struct powerpc_pd_reg svp64_regs[] = {"
@@ -699,32 +633,38 @@ class Codegen(_enum.Enum):
             yield Size.c_var("svp64_num_regs",
                         prefix="const ", suffix=" = \\")
             yield from indent(num_regs.c_value(suffix=";"))
-            yield ""
 
+        opcodes = Array[Opcode, ...](opcodes)
+        nr_opcodes = Size("(sizeof (svp64_opcodes) / sizeof (svp64_opcodes[0]))")
 
-        records = Record[...](records)
-        num_records = Size("(sizeof (svp64_records) / sizeof (svp64_records[0]))")
+        records = Array[Record, ...](records)
+        nr_records = Size("(sizeof (svp64_records) / sizeof (svp64_records[0]))")
 
-        return {
+        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):
         desc = {}
 
         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)
@@ -734,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)