import abc as _abc
import argparse as _argparse
-import codecs as _codecs
import dataclasses as _dataclasses
import enum as _enum
-import pathlib as _pathlib
import re as _re
-import sys as _sys
from openpower.decoder.power_enums import (
In1Sel as _In1Sel,
SVEtype as _SVEtype,
SVEXTRA as _SVEXTRA,
)
+from openpower.decoder.power_svp64 import SVP64RM as _SVP64RM
DISCLAIMER = (
@classmethod
def c_var(cls, name):
c_tag = f"svp64_{cls.__name__.lower()}"
- yield f"enum {c_tag} {name};"
+ yield f"enum {c_tag} {name}"
# Python forbids inheriting from enum unless it's empty.
SVEXTRA = Enum("SVEXTRA", {item.name:item.value for item in _SVEXTRA})
-class Opcode(Field, str):
+class Opcode(Field):
+ def __init__(self, value, mask, bits):
+ self.__value = value
+ self.__mask = mask
+ self.__bits = bits
+
+ return super().__init__()
+
+ @property
+ def value(self):
+ return self.__value
+
+ @property
+ def mask(self):
+ return self.__mask
+
+ @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)
+
+ @classmethod
+ def c_decl(cls):
+ yield f"struct svp64_opcode {{"
+ yield from indent([
+ "uint32_t value;",
+ "uint32_t mask;",
+ ])
+ yield f"}};"
+
def c_value(self, prefix="", suffix=""):
- yield f"{prefix}\"{self}\"{suffix}"
+ yield f"{prefix}{{"
+ yield from indent([
+ f".value = UINT32_C(0x{self.value:08X}),",
+ f".mask = UINT32_C(0x{self.mask:08X}),",
+ ])
+ yield f"}}{suffix}"
@classmethod
def c_var(cls, name):
- yield f"const char *{name};"
+ yield f"struct svp64_opcode {name}"
+
+
+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 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
+
+ return super().__init__(value=value, mask=mask, bits=bits)
class Name(Field, str):
@classmethod
def c_var(cls, name):
- yield f"const char *{name};"
+ yield f"const char *{name}"
@_dataclasses.dataclass(eq=True, frozen=True)
-class Entry:
+class Entry(Field):
name: Name
opcode: Opcode
in1: In1Sel
out2: OutSel
cr_in: CRInSel
cr_out: CROutSel
- ptype: SVPType
- etype: SVEType
+ sv_ptype: SVPType
+ sv_etype: SVEType
sv_in1: SVEXTRA
sv_in2: SVEXTRA
sv_in3: 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
+
@classmethod
def c_decl(cls):
+ bits_all = 0
yield f"struct svp64_entry {{"
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=field.name))
+ yield from indent(field.type.c_var(name=f"{field.name};"))
+ 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=""):
@classmethod
def c_var(cls, name):
- yield f"struct svp64_entry {name};"
+ yield f"struct svp64_entry {name}"
class Codegen(_enum.Enum):
yield f"#define {self.name}"
yield ""
+ yield from Opcode.c_decl()
+ yield ""
+
enums = (
- PType, EType,
In1Sel, In2Sel, In3Sel, OutSel,
CRInSel, CROutSel,
- SVEXTRA,
+ SVPType, SVEType, SVEXTRA,
)
for enum in enums:
yield from enum.c_decl()
REGEX = _re.compile(PATTERN)
-def parse(stream):
- for line in stream:
- match = REGEX.match(line)
- if match is not None:
- entry = match.groupdict()
- for field in _dataclasses.fields(Entry):
- key = field.name
- value = entry[key]
+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
+ name = entry["name"] = entry.pop("comment").split("=")[-1]
+ 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)
+ else:
+ field = FIELDS[key]
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(**entry)
+
+ yield Entry(**entry)
def main(codegen):
- entries = tuple(parse(_sys.stdin))
+ 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(entries)
+
for line in codegen.generate(entries):
print(line)