-import abc as _abc
import argparse as _argparse
import dataclasses as _dataclasses
import enum as _enum
-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,
In3Sel as _In3Sel,
OutSel as _OutSel,
CRInSel as _CRInSel,
+ CRIn2Sel as _CRIn2Sel,
CROutSel as _CROutSel,
- SVPtype as _SVPtype,
- SVEtype as _SVEtype,
- SVEXTRA as _SVEXTRA,
- RC as _RC,
+ SVPType as _SVPType,
+ SVEType as _SVEType,
+ SVExtra as _SVExtra,
+ SVMode as _SVMode,
+ find_wiki_dir as _find_wiki_dir,
)
from openpower.consts import SVP64MODE as _SVP64MODE
-from openpower.decoder.power_svp64 import SVP64RM as _SVP64RM
-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.decoder.power_insn import Database as _Database
+from openpower.decoder.power_insn import SVP64Instruction as _SVP64Instruction
DISCLAIMER = """\
def indent(strings):
- return map(lambda string: (" " + string), strings)
+ return map(lambda string: (" " + string), strings)
-class CTypeMeta(type):
- def __new__(metacls, name, bases, attrs, typedef=None):
- cls = super().__new__(metacls, name, bases, attrs)
- cls.__typedef = typedef
+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")):
+ c_typedef = base.c_typedef
+ break
- 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}"
+ if cls.c_size is Ellipsis:
+ size = ""
+ else:
+ size = f"{len(cls)}"
+ return f"{prefix}{cls.c_base.c_typedef} {name}[{size}]{suffix}"
-
-class CType(metaclass=CTypeMeta):
- @_abc.abstractmethod
- def c_value(self, *, prefix="", suffix="", **kwargs):
- yield from ()
-
-
-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):
- yield from indent(item.c_value(prefix=f"[{index}] = ", suffix=","))
+ 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, **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):
# Use __members__, not __iter__, otherwise aliases are lost.
entries = dict(entries.__members__)
if isinstance(entries, dict):
entries = tuple(entries.items())
- if tag is None:
- tag = f"svp64_{name.lower()}"
+ entries = ((key, value) for (key, value) in entries if key not in exclude)
- 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)
+
+ return super().__call__(value=clsname, names=entries, type=base)
- @property
- def c_typedef(cls):
- return f"enum {cls.c_tag}"
+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)
-In2Sel = Enum("In2Sel", _In2Sel)
-In3Sel = Enum("In3Sel", _In3Sel)
-OutSel = Enum("OutSel", _OutSel)
-CRInSel = Enum("CRInSel", _CRInSel)
-CROutSel = Enum("CROutSel", _CROutSel)
-SVPType = Enum("SVPType", _SVPtype)
-SVEType = Enum("SVEType", _SVEtype)
-SVEXTRA = Enum("SVEXTRA", _SVEXTRA)
+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 */"
yield f"#define {key} {value}"
def c_value(self, *, prefix="", suffix="", **kwargs):
- yield f"{prefix}{self.__class__.c_tag.upper()}_{self.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=";")
+
yield f"{cls.c_typedef} {{"
- for field in _dataclasses.fields(cls):
- yield from indent([field.type.c_var(name=f"{field.name}",
- suffix=";")])
+ 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):
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):
+@_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}\""
return f"{prefix}const char *{name}{suffix}"
+class BooleanMeta(ObjectMeta):
+ def __len__(cls):
+ return 1
+
+
+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 Record(Struct):
+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: SVPType
- sv_etype: SVEType
- sv_in1: SVEXTRA
- sv_in2: SVEXTRA
- sv_in3: SVEXTRA
- sv_out: SVEXTRA
- sv_out2: SVEXTRA
- sv_cr_in: SVEXTRA
- sv_cr_out: SVEXTRA
+ 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):
bits_all = 0
- yield f"struct svp64_record {{"
+ yield f"struct svp64_desc {{"
for field in _dataclasses.fields(cls):
bits = len(field.type).bit_length()
yield from indent([f"uint64_t {field.name} : {bits};"])
@_dataclasses.dataclass(eq=True, frozen=True)
-class Entry(Struct):
- name: Name
- record: Record
+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))
- # value = map(lambda bit: ((base.bits - 1) - bit),
- # reversed(value))
- yield (key.upper(), tuple(value))
-
- tag = f"svp64_{name.lower()}"
- fields = 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=fields, tag=f"{tag}_field",
- **kwargs)
-
- def c_value(fields, stmt):
- yield "switch (field) {"
- for (field_name, field_value) in fields:
- 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(fields=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(fields=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_H = _enum.auto()
- PPC_SVP64_OPC_C = _enum.auto()
- @classmethod
- def _missing_(cls, value):
- return {
- "ppc-svp64.h": Codegen.PPC_SVP64_H,
- "ppc-svp64-opc.c": Codegen.PPC_SVP64_OPC_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_H: "ppc-svp64.h",
- Codegen.PPC_SVP64_OPC_C: "ppc-svp64-opc.c",
- }[self]
+ return self.value
- def generate(self, entries):
- def ppc_svp64_h(entries, num_entries):
+ 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()
enums = (
In1Sel, In2Sel, In3Sel, OutSel,
- CRInSel, CROutSel,
- SVPType, SVEType, SVEXTRA,
- Mode,
+ CRInSel, CRIn2Sel, CROutSel,
+ PType, EType, Extra,
+ Mode, ModeConst,
)
for enum in enums:
yield from enum.c_decl()
yield ""
- for cls in (Record, Entry, Prefix, RM):
+ for cls in (Instruction, Desc, Opcode, Record):
yield from cls.c_decl()
yield ""
- for name in ("in1", "in2", "in3", "out", "out2", "cr_in", "cr_out"):
- yield "unsigned char"
- yield f"svp64_record_{name}_opsel(const struct svp64_record *record);"
- 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 entries.__class__.c_var("svp64_entries",
+ yield records.c_var("svp64_records",
prefix="extern const ", suffix=";")
- yield num_entries.__class__.c_var("svp64_num_entries",
+ yield nr_records.c_var("svp64_nr_records",
prefix="extern const ", suffix=";")
yield ""
- yield f"#define SVP64_NAME_MAX {max(map(lambda entry: len(entry.name), entries))}"
+ yield "extern const struct powerpc_pd_reg svp64_regs[];"
+ yield Size.c_var("svp64_num_regs", prefix="extern const ", suffix=";")
yield ""
yield "#ifdef __cplusplus"
yield ""
yield f"#endif /* {self.name} */"
- yield ""
- def ppc_svp64_opc_c(entries, num_entries):
+ 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 ""
- def opsel(enum, name, table):
+ def opindex(enum, name, table):
sep = (max(map(len, list(table.values()) + ["UNUSED"])) + 1)
c_tag = f"svp64_{enum.__name__.lower()}"
- yield "unsigned char"
- yield f"svp64_record_{name}_opsel(const struct svp64_record *record)"
+ yield "static inline ppc_opindex_t"
+ yield f"svp64_desc_{name}_opindex(const struct svp64_desc *desc)"
yield "{"
- yield from indent(["static const unsigned char table[] = {"])
+ yield from indent(["static const ppc_opindex_t table[] = {"])
for key in enum:
value = table.get(key, "UNUSED")
- c_value = f"{c_tag.upper()}_{key.name.upper()}"
- yield from indent(indent([f"{value:{sep}}, /* {c_value} */"]))
+ yield from indent(indent([f"{value:{sep}}, /* {key.c_name} */"]))
yield from indent(["};"])
yield ""
- yield from indent([f"return table[record->{name}];"])
+ yield from indent([f"return table[desc->{name}];"])
yield "}"
yield ""
- yield from opsel(In1Sel, "in1", {
+ yield from opindex(In1Sel, "in1", {
In1Sel.RA: "RA",
- In1Sel.RA_OR_ZERO: "RA",
+ In1Sel.RA_OR_ZERO: "RA0",
In1Sel.SPR: "SPR",
In1Sel.RS: "RS",
In1Sel.FRA: "FRA",
In1Sel.FRS: "FRS",
})
- yield from opsel(In2Sel, "in2", {
+ yield from opindex(In2Sel, "in2", {
In2Sel.RB: "RB",
In2Sel.SPR: "SPR",
In2Sel.RS: "RS",
In2Sel.FRB: "FRB",
})
- yield from opsel(In3Sel, "in3", {
+ yield from opindex(In3Sel, "in3", {
In3Sel.RS: "RS",
In3Sel.RB: "RB",
In3Sel.FRS: "FRS",
In3Sel.RT: "RT",
})
for name in ("out", "out2"):
- yield from opsel(OutSel, name, {
+ yield from opindex(OutSel, name, {
OutSel.RT: "RT",
OutSel.RA: "RA",
OutSel.SPR: "SPR",
OutSel.RT_OR_ZERO: "RT",
OutSel.FRT: "FRT",
OutSel.FRS: "FRS",
+ OutSel.RS: "RS",
})
- yield from opsel(CRInSel, "cr_in", {
+ yield from opindex(CRInSel, "cr_in", {
CRInSel.BI: "BI",
CRInSel.BFA: "BFA",
- CRInSel.BC: "CRB",
+ CRInSel.BC: "BC",
+ CRInSel.BA: "BA",
CRInSel.WHOLE_REG: "FXM",
})
- yield from opsel(CROutSel, "cr_out", {
+ 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 entries.__class__.c_var("svp64_entries",
+ yield opcodes.c_var("svp64_opcodes",
prefix="const ", suffix=" = \\")
- yield from entries.c_value(prefix="", suffix=";")
+ yield from opcodes.c_value(prefix="", suffix=";")
yield ""
- yield num_entries.__class__.c_var("svp64_num_entries",
+ yield nr_opcodes.c_var("svp64_nr_opcodes",
prefix="const ", suffix=" = \\")
- yield from indent(num_entries.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 ""
+ 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 ""
- 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 "const struct powerpc_pd_reg svp64_regs[] = {"
+ regs = {}
+ for (category, count, flags) in sorted((
+ ("r", 128, "PPC_OPERAND_GPR"),
+ ("f", 128, "PPC_OPERAND_FPR"),
+ ("cr", 128, "PPC_OPERAND_CR_REG"),
+ )):
+ for index in range(count):
+ regs[f"{category}{index}"] = (index, flags)
+ regs[f"{category}.{index}"] = (index, flags)
+ for (name, (index, flags)) in sorted(regs.items()):
+ yield from indent([f"{{\"{name}\", {index}, {flags}}},"])
+ yield "};"
yield ""
+ num_regs = Size("(sizeof (svp64_regs) / sizeof (svp64_regs[0]))")
+ yield Size.c_var("svp64_num_regs",
+ prefix="const ", suffix=" = \\")
+ yield from indent(num_regs.c_value(suffix=";"))
- entries = Entry[...](entries)
- num_entries = Size("(sizeof (svp64_entries) / sizeof (svp64_entries[0]))")
+ opcodes = Array[Opcode, ...](opcodes)
+ nr_opcodes = Size("(sizeof (svp64_opcodes) / sizeof (svp64_opcodes[0]))")
- return {
- Codegen.PPC_SVP64_H: ppc_svp64_h,
- Codegen.PPC_SVP64_OPC_C: ppc_svp64_opc_c,
- }[self](entries, num_entries)
+ records = Array[Record, ...](records)
+ 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](opcodes, nr_opcodes, records, nr_records)
-ISA = _SVP64RM()
-FIELDS = {field.name:field.type for field in _dataclasses.fields(Record)}
-FIELDS.update({field.name:field.type for field in _dataclasses.fields(Entry)})
-def parse(path):
- visited = set()
+def collect(db):
+ opcodes = []
+ records = []
+ fields = {field.name:field.type for field in _dataclasses.fields(Desc)}
- def name_filter(name):
- if name.startswith("l") and name.endswith("br"):
- return False
- if name in {"mcrxr", "mcrxrx", "darn"}:
- return False
- if name in {"bctar", "bcctr"}:
- return False
- if "rfid" in name:
- return False
- if name in {"setvl"}:
- return False
- if name in visited:
- return False
+ for insn in filter(lambda insn: insn.svp64 is not None, db):
+ desc = {}
- visited.add(name)
+ for (key, cls) in fields.items():
+ value = getattr(insn, key)
- return True
+ if (((cls is EType) and (value is _SVEType.NONE)) or
+ ((cls is Extra) and (value is _SVExtra.Idx_1_2))):
+ desc = None
+ break
- def item_mapper(item):
- (key, value) = item
- key = key.lower().replace(" ", "_")
- cls = FIELDS.get(key, object)
- if not isinstance(value, cls):
- if issubclass(cls, _enum.Enum):
- value = {item.name:item for item in cls}[value]
+ if issubclass(cls, Boolean):
+ value = Boolean(value)
+ elif issubclass(cls, Extra):
+ value = tuple(value)
+ if not value:
+ value = cls["NONE"]
+ else:
+ value = cls[value[0].name]
+ elif issubclass(cls, _enum.Enum):
+ value = cls[value.name]
else:
value = cls(value)
- return (key, value)
+ desc[key] = value
+
+ if desc is None:
+ continue
+
+ name = Name(f"sv.{insn.name}")
+ 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)
- def item_filter(item):
- (key, _) = item
- return (key in FIELDS)
+ record = Record(name=name, desc=desc,
+ opcodes=Opcodes(offset), nr_opcodes=Size(len(insn.opcodes)))
+ records.append(record)
- for record in ISA.get_svp64_csv(path):
- names = record.pop("comment").split("=")[-1].split("/")
- names = set(filter(name_filter, names))
- if names:
- rc = _RC[record["rc"] if record["rc"] else "NONE"]
- if rc is _RC.RC:
- names.update({f"{name}." for name in names})
- record = dict(filter(item_filter, map(item_mapper, record.items())))
- for name in map(Name, names):
- yield Entry(name=name, record=Record(**record))
+ return (opcodes, records)
def main(codegen):
- entries = []
- paths = (
- "minor_19.csv",
- "minor_30.csv",
- "minor_31.csv",
- "minor_58.csv",
- "minor_62.csv",
- "minor_22.csv",
- "minor_5.csv",
- "minor_63.csv",
- "minor_59.csv",
- "major.csv",
- "extra.csv",
- )
- for path in paths:
- entries.extend(parse(path))
- entries = sorted(frozenset(entries))
-
- for line in codegen.generate(entries):
+ db = _Database(_find_wiki_dir())
+ (opcodes, records) = collect(db)
+ for line in codegen.generate(opcodes, records):
print(line)