-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,
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 = """\
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}"
-
-
-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):
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 */"
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=";")
+
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, typedef="size_t"):
+class Size(Integer, c_typedef="size_t"):
pass
-class UInt32(Integer, typedef="uint32_t"):
+class UInt32(Integer, c_typedef="uint32_t"):
pass
-class Name(CType, str):
+class UInt64(Integer, c_typedef="uint64_t"):
+ pass
+
+
+@_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 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):
@_dataclasses.dataclass(eq=True, frozen=True)
-class Record(Struct):
- name: Name
- 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
+
+ def __lt__(self, other):
+ if not isinstance(other, self.__class__):
+ return NotImplemented
-Prefix = FieldsMapping("Prefix", base=_SVP64PrefixFields)
-RM = FieldsMapping("RM", base=_SVP64RMFields)
+ 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)
+ 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()
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, Record, Prefix, RM):
+ for cls in (Instruction, Desc, Opcode, Record):
yield from cls.c_decl()
yield ""
- yield "enum svp64_rm_field"
- yield "svp64_opindex_rm_field (const struct svp64_desc *desc, ppc_opindex_t opindex);"
+ 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.__class__.c_var("svp64_records",
+ 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 ""
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 ""
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[] = {"
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)
-
-
-ISA = _SVP64RM()
-FIELDS = {field.name:field.type for field in _dataclasses.fields(Desc)}
-
-def parse(path):
- visited = set()
-
- 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
-
- visited.add(name)
-
- return True
-
- for data in ISA.get_svp64_csv(path):
- comment = data.pop("comment")
- names = comment.split("=")[-1].split("/")
- names = set(filter(name_filter, names))
- if not names:
- continue
- rc = _RC[data["rc"] if data["rc"] else "NONE"]
- if rc is _RC.RC:
- names.update({f"{name}." for name in names})
+ }[self](opcodes, nr_opcodes, records, nr_records)
+
+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, value) in data.items():
- key = key.lower().replace(" ", "_")
- cls = FIELDS.get(key)
- if cls is None:
- continue
-
- if ((cls is EType and value == "NONE") or
- (cls is Extra and value == "Idx_1_2")):
- desc = {}
+
+ for (key, cls) in fields.items():
+ value = getattr(insn, key)
+
+ if (((cls is EType) and (value is _SVEType.NONE)) or
+ ((cls is Extra) and (value is _SVExtra.Idx_1_2))):
+ desc = None
break
- 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)
+ value = cls[value[0].name]
+ elif issubclass(cls, _enum.Enum):
+ value = cls[value.name]
+ else:
+ value = cls(value)
desc[key] = value
- if not desc:
+ 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)
- for name in map(Name, names):
- yield Record(name=name, 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):
- records = []
- 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:
- records.extend(parse(path))
- records = sorted(frozenset(records))
-
- for line in codegen.generate(records):
+ db = _Database(_find_wiki_dir())
+ (opcodes, records) = collect(db)
+ for line in codegen.generate(opcodes, records):
print(line)