-import abc as _abc
import argparse as _argparse
import dataclasses as _dataclasses
import enum as _enum
-import re as _re
+
+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,
+ SVPType as _SVPType,
+ SVEType as _SVEType,
+ SVExtra as _SVExtra,
+ SVMode as _SVMode,
+ find_wiki_dir as _find_wiki_dir,
)
-from openpower.decoder.power_svp64 import SVP64RM as _SVP64RM
+from openpower.consts import SVP64MODE as _SVP64MODE
+from openpower.decoder.power_insn import Database as _Database
+from openpower.decoder.power_insn import SVP64Instruction as _SVP64Instruction
-DISCLAIMER = (
- "/*",
- " * this file is auto-generated, do not edit",
- " * https://git.libre-soc.org/?p=openpower-isa.git;a=blob;f=src/openpower/sv/sv_binutils.py",
- " * part of Libre-SOC, sponsored by NLnet",
- " */",
-)
+DISCLAIMER = """\
+/* {path} -- {desc}
+ Copyright (C) 2022 Free Software Foundation, Inc.
+ Written by Dmitry Selyutin (ghostmansd).
+ Sponsored by NLnet and NGI POINTER under EU Grants 871528 and 957073.
+
+ This file is part of the GNU opcodes library.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ It is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */\
+"""
def indent(strings):
- return map(lambda string: (" " + string), strings)
+ return map(lambda string: (" " + string), strings)
+
+
+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
+ ns.setdefault("c_typedef", c_typedef)
+ ns.update(kwargs)
+
+ return super().__new__(metacls, clsname, bases, ns)
+
+
+class Object(metaclass=ObjectMeta):
+ @classmethod
+ def c_decl(cls):
+ yield from ()
-class CType:
@classmethod
- @_abc.abstractmethod
- def c_decl(self, name):
- pass
+ 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(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}]"
- @_abc.abstractmethod
- def c_value(self, prefix="", suffix=""):
- pass
+ 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 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
- @_abc.abstractmethod
- def c_var(self, name):
- pass
+ def c_var(cls, name, prefix="", suffix=""):
+ if cls.c_size is Ellipsis:
+ size = ""
+ else:
+ size = f"{len(cls)}"
+ return f"{prefix}{cls.c_base.c_typedef} {name}[{size}]{suffix}"
+
+ def c_value(self, *, prefix="", suffix="", **kwargs):
+ yield f"{prefix}{{"
+ for item in self:
+ yield from indent(item.c_value(suffix=","))
+ yield f"}}{suffix}"
+
+class Void(Object, c_typedef="void"):
+ def c_var(cls, name, prefix="", suffix=""):
+ raise NotImplementedError
+
+
+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())
+ entries = ((key, value) for (key, value) in entries if key not in exclude)
+
+ if c_tag is None:
+ c_tag = f"svp64_{clsname.lower()}"
+ if c_typedef is None:
+ c_typedef = f"enum {c_tag}"
+
+ base = ObjectMeta(cls.__name__, (), {},
+ c_tag=c_tag, c_typedef=c_typedef)
+
+ return super().__call__(value=clsname, names=entries, type=base)
+
+
+class Enum(Object, _enum.Enum, metaclass=EnumMeta):
+ @property
+ def c_name(self):
+ return f"{self.c_tag.upper()}_{self.name.upper()}"
-class Enum(CType, _enum.Enum):
@classmethod
def c_decl(cls):
- c_tag = f"svp64_{cls.__name__.lower()}"
- yield f"enum {c_tag} {{"
+ yield f"{cls.c_typedef} {{"
for item in cls:
yield from indent(item.c_value(suffix=","))
yield f"}};"
- def c_value(self, prefix="", suffix=""):
- c_tag = f"svp64_{self.__class__.__name__.lower()}"
- yield f"{prefix}{c_tag.upper()}_{self.name.upper()}{suffix}"
+ def c_value(self, *, prefix="", suffix="", **kwargs):
+ yield f"{prefix}{self.c_name}{suffix}"
@classmethod
- def c_var(cls, name):
- c_tag = f"svp64_{cls.__name__.lower()}"
- yield f"enum {c_tag} {name}"
+ def c_var(cls, name, prefix="", suffix=""):
+ return f"{prefix}{cls.c_typedef} {name}{suffix}"
-# Python forbids inheriting from enum unless it's empty.
-In1Sel = Enum("In1Sel", {item.name:item.value for item in _In1Sel})
-In2Sel = Enum("In2Sel", {item.name:item.value for item in _In2Sel})
-In3Sel = Enum("In3Sel", {item.name:item.value for item in _In3Sel})
-OutSel = Enum("OutSel", {item.name:item.value for item in _OutSel})
-CRInSel = Enum("CRInSel", {item.name:item.value for item in _CRInSel})
-CROutSel = Enum("CROutSel", {item.name:item.value for item in _CROutSel})
-SVPType = Enum("SVPType", {item.name:item.value for item in _SVPtype})
-SVEType = Enum("SVEType", {item.name:item.value for item in _SVEtype})
-SVEXTRA = Enum("SVEXTRA", {item.name:item.value for item in _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 Opcode(CType):
- def __init__(self, value, mask, bits):
- self.__value = value
- self.__mask = mask
- self.__bits = bits
+class Constant(_enum.Enum, metaclass=EnumMeta):
+ @classmethod
+ def c_decl(cls):
+ yield f"/* {cls.c_tag.upper()} constants */"
+ # Use __members__, not __iter__, otherwise aliases are lost.
+ for (key, item) in cls.__members__.items():
+ key = f"{cls.c_tag.upper()}_{key.upper()}"
+ value = f"0x{item.value:08x}U"
+ yield f"#define {key} {value}"
- return super().__init__()
+ def c_value(self, *, prefix="", suffix="", **kwargs):
+ yield f"{prefix}{self.c_tag.upper()}_{self.c_name.upper()}{suffix}"
- @property
- def value(self):
- return self.__value
- @property
- def mask(self):
- return self.__mask
+ModeConst = Constant("Mode", _SVP64MODE)
- @property
- def bits(self):
- return self.__bits
- def __repr__(self):
- fmt = f"{{value:0{self.bits}b}}:{{mask:0{self.bits}b}}"
- return fmt.format(value=self.value, mask=self.mask)
+class StructMeta(ObjectMeta):
+ def __new__(metacls, clsname, bases, ns,
+ c_tag=None, c_typedef=None):
+
+ if c_tag is None:
+ c_tag = f"svp64_{clsname.lower()}"
+ if c_typedef is None:
+ c_typedef = f"struct {c_tag}"
+ return super().__new__(metacls, clsname, bases, ns,
+ c_typedef=c_typedef, c_tag=c_tag)
+
+
+@_dataclasses.dataclass(eq=True, frozen=True)
+class Struct(Object, metaclass=StructMeta):
@classmethod
def c_decl(cls):
- yield f"struct svp64_opcode {{"
- yield from indent([
- "uint32_t value;",
- "uint32_t mask;",
- ])
+ def transform(field):
+ return field.type.c_var(name=f"{field.name}", suffix=";")
+
+ yield f"{cls.c_typedef} {{"
+ yield from indent(map(transform, _dataclasses.fields(cls)))
yield f"}};"
- def c_value(self, prefix="", suffix=""):
+ def c_value(self, *, prefix="", suffix="", **kwargs):
yield f"{prefix}{{"
- yield from indent([
- f".value = UINT32_C(0x{self.value:08X}),",
- f".mask = UINT32_C(0x{self.mask:08X}),",
- ])
+ for field in _dataclasses.fields(self):
+ name = field.name
+ attr = getattr(self, name)
+ yield from indent(attr.c_value(prefix=f".{name} = ", suffix=","))
yield f"}}{suffix}"
- @classmethod
- def c_var(cls, name):
- yield f"struct svp64_opcode {name}"
+class Integer(Object, str):
+ def c_value(self, *, prefix="", suffix="", **kwargs):
+ yield f"{prefix}{self}{suffix}"
+
+
+class Byte(Integer, c_typedef="uint8_t"):
+ pass
+
+
+class Size(Integer, c_typedef="size_t"):
+ pass
-class IntegerOpcode(Opcode):
- def __init__(self, integer):
- value = int(integer, 0)
- bits = max(1, value.bit_length())
- mask = int(("1" * bits), 2)
- return super().__init__(value=value, mask=mask, bits=bits)
+class UInt32(Integer, c_typedef="uint32_t"):
+ pass
-class PatternOpcode(Opcode):
- def __init__(self, pattern):
- value = 0
- mask = 0
- bits = len(pattern)
- for bit in pattern:
- value |= (bit == "1")
- mask |= (bit != "-")
- value <<= 1
- mask <<= 1
- value >>= 1
- mask >>= 1
+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 ""
- return super().__init__(value=value, mask=mask, bits=bits)
+ 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(CType, str):
+class Name(Object, str, c_typedef="const char *"):
def __repr__(self):
escaped = self.replace("\"", "\\\"")
return f"\"{escaped}\""
- def c_value(self, prefix="", suffix=""):
+ def c_value(self, *, prefix="", suffix="", **kwargs):
yield f"{prefix}{self!r}{suffix}"
@classmethod
- def c_var(cls, name):
- yield f"const char *{name}"
+ def c_var(cls, name, prefix="", suffix=""):
+ 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 Entry(CType):
- name: Name
- opcode: Opcode
+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
-
- def __lt__(self, other):
- if not isinstance(other, self.__class__):
- return NotImplemented
- return self.name < other.name
+ 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_entry {{"
+ yield f"struct svp64_desc {{"
for field in _dataclasses.fields(cls):
- if issubclass(field.type, Enum):
- bits = len(field.type).bit_length()
- yield from indent([f"uint64_t {field.name} : {bits};"])
- bits_all += bits
- else:
- yield from indent(field.type.c_var(name=f"{field.name};"))
+ bits = len(field.type).bit_length()
+ yield from indent([f"uint64_t {field.name} : {bits};"])
+ bits_all += bits
bits_rsvd = (64 - (bits_all % 64))
if bits_rsvd:
yield from indent([f"uint64_t : {bits_rsvd};"])
yield f"}};"
- def c_value(self, prefix="", suffix=""):
- yield f"{prefix}{{"
- for field in _dataclasses.fields(self):
- name = field.name
- attr = getattr(self, name)
- yield from indent(attr.c_value(prefix=f".{name} = ", suffix=","))
- yield f"}}{suffix}"
- @classmethod
- def c_var(cls, name):
- yield f"struct svp64_entry {name}"
+@_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})"
-class Codegen(_enum.Enum):
- PPC_SVP64_H = _enum.auto()
- PPC_SVP64_OPC_C = _enum.auto()
+ @classmethod
+ def c_var(cls, name, prefix="", suffix=""):
+ return f"{prefix}{cls.c_typedef}{name}{suffix}"
@classmethod
- def _missing_(cls, value):
- return {
- "ppc-svp64.h": Codegen.PPC_SVP64_H,
- "ppc-svp64-opc.c": Codegen.PPC_SVP64_OPC_C,
- }.get(value)
+ 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
+ desc: Desc
+ opcodes: Opcodes
+ nr_opcodes: Size
+
+ 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 = "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]
-
- def generate(self, entries):
- def ppc_svp64_h(entries):
- yield from DISCLAIMER
+ return self.value
+
+ 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()
yield ""
yield f"#ifndef {self.name}"
yield "#endif"
yield ""
- yield from Opcode.c_decl()
- yield ""
-
enums = (
In1Sel, In2Sel, In3Sel, OutSel,
- CRInSel, CROutSel,
- SVPType, SVEType, SVEXTRA,
+ CRInSel, CRIn2Sel, CROutSel,
+ PType, EType, Extra,
+ Mode, ModeConst,
)
for enum in enums:
yield from enum.c_decl()
yield ""
- yield from Entry.c_decl()
+ for cls in (Instruction, Desc, Opcode, Record):
+ 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 "extern const struct svp64_entry svp64_entries[];"
- yield "extern const unsigned int svp64_num_entries;"
+ yield records.c_var("svp64_records",
+ prefix="extern const ", suffix=";")
+ 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):
- yield from DISCLAIMER
+ 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 ""
- yield "const struct svp64_entry svp64_entries[] = {"
- for (index, entry) in enumerate(entries):
- yield from indent(entry.c_value(prefix=f"[{index}] = ", suffix=","))
- yield f"}};"
+ def opindex(enum, name, table):
+ sep = (max(map(len, list(table.values()) + ["UNUSED"])) + 1)
+ c_tag = f"svp64_{enum.__name__.lower()}"
+ yield "static inline ppc_opindex_t"
+ yield f"svp64_desc_{name}_opindex(const struct svp64_desc *desc)"
+ yield "{"
+ yield from indent(["static const ppc_opindex_t table[] = {"])
+ for key in enum:
+ value = table.get(key, "UNUSED")
+ yield from indent(indent([f"{value:{sep}}, /* {key.c_name} */"]))
+ yield from indent(["};"])
+ yield ""
+ yield from indent([f"return table[desc->{name}];"])
+ yield "}"
+ yield ""
+
+ yield from opindex(In1Sel, "in1", {
+ In1Sel.RA: "RA",
+ In1Sel.RA_OR_ZERO: "RA0",
+ In1Sel.SPR: "SPR",
+ In1Sel.RS: "RS",
+ In1Sel.FRA: "FRA",
+ In1Sel.FRS: "FRS",
+ })
+ yield from opindex(In2Sel, "in2", {
+ In2Sel.RB: "RB",
+ In2Sel.SPR: "SPR",
+ In2Sel.RS: "RS",
+ In2Sel.FRB: "FRB",
+ })
+ yield from opindex(In3Sel, "in3", {
+ In3Sel.RS: "RS",
+ In3Sel.RB: "RB",
+ In3Sel.FRS: "FRS",
+ In3Sel.FRC: "FRC",
+ In3Sel.RC: "RC",
+ In3Sel.RT: "RT",
+ })
+ for name in ("out", "out2"):
+ 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 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 "const unsigned int svp64_num_entries = \\"
- yield " sizeof (svp64_entries) / sizeof (svp64_entries[0]);"
+ 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[] = {"
+ 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=";"))
+
+ opcodes = Array[Opcode, ...](opcodes)
+ nr_opcodes = Size("(sizeof (svp64_opcodes) / sizeof (svp64_opcodes[0]))")
+
+ 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)
+
+
+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
+ ((cls is Extra) and (value is _SVExtra.Idx_1_2))):
+ desc = None
+ break
+
+ 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)
+ 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)
+
+ record = Record(name=name, desc=desc,
+ opcodes=Opcodes(offset), nr_opcodes=Size(len(insn.opcodes)))
+ records.append(record)
- return {
- Codegen.PPC_SVP64_H: ppc_svp64_h,
- Codegen.PPC_SVP64_OPC_C: ppc_svp64_opc_c,
- }[self](entries)
-
-
-def regex_enum(enum):
- assert issubclass(enum, _enum.Enum)
- return "|".join(item.name for item in enum)
-
-
-PATTERN_VHDL_BINARY = r"(?:2#[01]+#)"
-PATTERN_DECIMAL = r"(?:[0-9]+)"
-PATTERN_PARTIAL_BINARY = r"(?:[01-]+)"
-
-# Examples of the entries to be caught by the pattern below:
-# 2 => (P2, EXTRA3, RA_OR_ZERO, NONE, NONE, RT, NONE, NONE, NONE, Idx1, NONE, NONE, Idx0, NONE, NONE, NONE), -- lwz
-# -----10110 => (P2, EXTRA3, NONE, FRB, NONE, FRT, NONE, NONE, CR1, NONE, Idx1, NONE, Idx0, NONE, NONE, Idx0), -- fsqrts
-# 2#0000000000# => (P2, EXTRA3, NONE, NONE, NONE, NONE, NONE, BFA, BF, NONE, NONE, NONE, NONE, NONE, Idx1, Idx0), -- mcrf
-PATTERN = "".join((
- r"^\s*",
- rf"(?P<opcode>{PATTERN_VHDL_BINARY}|{PATTERN_DECIMAL}|{PATTERN_PARTIAL_BINARY})",
- r"\s?=>\s?",
- r"\(",
- r",\s".join((
- rf"(?P<ptype>{regex_enum(_SVPtype)})",
- rf"(?P<etype>{regex_enum(_SVEtype)})",
- rf"(?P<in1>{regex_enum(_In1Sel)})",
- rf"(?P<in2>{regex_enum(_In2Sel)})",
- rf"(?P<in3>{regex_enum(_In3Sel)})",
- rf"(?P<out>{regex_enum(_OutSel)})",
- rf"(?P<out2>{regex_enum(_OutSel)})",
- rf"(?P<cr_in>{regex_enum(_CRInSel)})",
- rf"(?P<cr_out>{regex_enum(_CROutSel)})",
- rf"(?P<sv_in1>{regex_enum(_SVEXTRA)})",
- rf"(?P<sv_in2>{regex_enum(_SVEXTRA)})",
- rf"(?P<sv_in3>{regex_enum(_SVEXTRA)})",
- rf"(?P<sv_out>{regex_enum(_SVEXTRA)})",
- rf"(?P<sv_out2>{regex_enum(_SVEXTRA)})",
- rf"(?P<sv_cr_in>{regex_enum(_SVEXTRA)})",
- rf"(?P<sv_cr_out>{regex_enum(_SVEXTRA)})",
- )),
- r"\)",
- r",",
- r"\s?--\s?",
- r"(?P<name>[A-Za-z0-9_\./]+)",
- r"\s*$",
-))
-REGEX = _re.compile(PATTERN)
-
-
-ISA = _SVP64RM()
-FIELDS = {field.name:field for field in _dataclasses.fields(Entry)}
-def parse(path, opcode_cls):
- for entry in ISA.get_svp64_csv(path):
- # skip instructions that are not suitable
- names = entry.pop("comment").split("=")[-1]
- for name in map(Name, names.split("/")):
- if name.startswith("l") and name.endswith("br"):
- continue
- if name in {"mcrxr", "mcrxrx", "darn"}:
- continue
- if name in {"bctar", "bcctr"}:
- continue
- if "rfid" in name:
- continue
- if name in {"setvl"}:
- continue
-
- entry = {key.lower().replace(" ", "_"):value for (key, value) in entry.items()}
- for (key, value) in tuple(entry.items()):
- key = key.lower().replace(" ", "_")
- if key not in FIELDS:
- entry.pop(key)
- continue
-
- field = FIELDS[key]
- if not isinstance(value, field.type):
- if issubclass(field.type, _enum.Enum):
- value = {item.name:item for item in field.type}[value]
- elif issubclass(field.type, Opcode):
- value = opcode_cls(value)
- else:
- value = field.type(value)
- entry[key] = value
-
- yield Entry(name=name, **entry)
+ return (opcodes, records)
def main(codegen):
- entries = []
- table = {
- "minor_19.csv": IntegerOpcode,
- "minor_30.csv": IntegerOpcode,
- "minor_31.csv": IntegerOpcode,
- "minor_58.csv": IntegerOpcode,
- "minor_62.csv": IntegerOpcode,
- "minor_22.csv": IntegerOpcode,
- "minor_5.csv": PatternOpcode,
- "minor_63.csv": PatternOpcode,
- "minor_59.csv": PatternOpcode,
- "major.csv": IntegerOpcode,
- "extra.csv": PatternOpcode,
- }
- for (path, opcode_cls) in table.items():
- entries.extend(parse(path, opcode_cls))
- 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)
if __name__ == "__main__":
parser = _argparse.ArgumentParser()
- parser.add_argument("codegen", type=Codegen, choices=Codegen, help="code generator")
+ parser.add_argument("codegen",
+ type=Codegen, choices=Codegen,
+ help="code generator")
args = vars(parser.parse_args())
main(**args)