flags.add(flag)
record["flags"] = PPCRecord.Flags(flags)
- return dataclass(cls, record, keymap=PPCRecord.__KEYMAP, typemap=typemap)
+ return dataclass(cls, record,
+ keymap=PPCRecord.__KEYMAP,
+ typemap=typemap)
@cached_property
def names(self):
return frozenset(self.comment.split("=")[-1].split("/"))
-class PPCMultiRecord(tuple):
+class PPCMultiRecord(frozenset):
@cached_property
def unified(self):
def merge(lhs, rhs):
value |= (vstate << bit)
mask |= (mstate << bit)
- return _dataclasses.replace(lhs, opcode=Opcode(value=value, mask=mask))
+ opcode = opcode=Opcode(value=value, mask=mask)
+
+ return _dataclasses.replace(lhs, opcode=opcode)
return _functools.reduce(merge, self)
if value == "0":
record[key] = "NONE"
- record["extra"] = cls.ExtraMap(record.pop(f"{index}") for index in range(0, 4))
+ extra = []
+ for idx in range(0, 4):
+ extra.append(record.pop(f"{idx}"))
+
+ record["extra"] = cls.ExtraMap(extra)
return dataclass(cls, record, keymap=cls.__KEYMAP)
def __hash__(self):
return hash(int(self))
+ def record(self, db):
+ record = db[self]
+ if record is None:
+ raise KeyError(self)
+ return record
+
def disassemble(self, db, byteorder="little", verbose=False):
raise NotImplementedError
bits.append(bit)
return "".join(map(str, bits))
- def spec(self, record):
+ def spec(self, db):
+ record = self.record(db=db)
+
immediate = ""
dynamic_operands = []
for operand in record.operands.dynamic:
return f"{record.name}{operands}"
- def opcode(self, record):
+ def opcode(self, db):
+ record = self.record(db=db)
return f"0x{record.opcode.value:08x}"
- def mask(self, record):
+ def mask(self, db):
+ record = self.record(db=db)
return f"0x{record.opcode.mask:08x}"
def disassemble(self, db, byteorder="little", verbose=False):
blob = integer.to_bytes(length=4, byteorder=byteorder)
blob = " ".join(map(lambda byte: f"{byte:02x}", blob))
- record = db[self]
+ record = self.record(db=db)
if record is None:
yield f"{blob} .long 0x{integer:08x}"
return
if verbose:
indent = (" " * 4)
binary = self.binary
- spec = self.spec(record=record)
- opcode = self.opcode(record=record)
- mask = self.mask(record=record)
+ spec = self.spec(db=db)
+ opcode = self.opcode(db=db)
+ mask = self.mask(db=db)
yield f"{indent}spec"
yield f"{indent}{indent}{spec}"
yield f"{indent}binary"
bits.append(bit)
return "".join(map(str, bits))
- def spec(self, record):
- return f"sv.{self.suffix.spec(record=record)}"
-
- def opcode(self, record):
- return self.suffix.opcode(record=record)
-
- def mask(self, record):
- return self.suffix.mask(record=record)
+ def spec(self, db):
+ return f"sv.{self.suffix.spec(db=db)}"
- def disassemble(self, db, byteorder="little", verbose=False):
- integer_prefix = int(self.prefix)
- blob_prefix = integer_prefix.to_bytes(length=4, byteorder=byteorder)
- blob_prefix = " ".join(map(lambda byte: f"{byte:02x}", blob_prefix))
+ def opcode(self, db):
+ return self.suffix.opcode(db=db)
- integer_suffix = int(self.suffix)
- blob_suffix = integer_suffix.to_bytes(length=4, byteorder=byteorder)
- blob_suffix = " ".join(map(lambda byte: f"{byte:02x}", blob_suffix))
+ def mask(self, db):
+ return self.suffix.mask(db=db)
- record = db[self.suffix]
- if record is None or record.svp64 is None:
- yield f"{blob_prefix} .long 0x{int(self.prefix):08x}"
- yield f"{blob_suffix} .long 0x{int(self.suffix):08x}"
- return
+ def mode(self, db):
+ record = self.record(db=db)
Rc = False
if record.operands["Rc"] is not None:
Rc = bool(self[record.fields["Rc"]])
+ record = self.record(db=db)
subvl = self.prefix.rm.subvl
mode = self.prefix.rm.mode
sel = mode.sel
else:
mode = mode.prrc0
- if type(mode) is Mode:
- raise NotImplementedError
+ modes = {
+ NormalMode.simple: "normal: simple",
+ NormalMode.smr: "normal: smr",
+ NormalMode.pmr: "normal: pmr",
+ NormalMode.svmr: "normal: svmr",
+ NormalMode.pu: "normal: pu",
+ NormalMode.ffrc1: "normal: ffrc1",
+ NormalMode.ffrc0: "normal: ffrc0",
+ NormalMode.sat: "normal: sat",
+ NormalMode.satx: "normal: satx",
+ NormalMode.satpu: "normal: satpu",
+ NormalMode.prrc1: "normal: prrc1",
+ NormalMode.prrc0: "normal: prrc0",
+ LDSTImmMode.simple: "ld/st imm: simple",
+ LDSTImmMode.spu: "ld/st imm: spu",
+ LDSTImmMode.ffrc1: "ld/st imm: ffrc1",
+ LDSTImmMode.ffrc0: "ld/st imm: ffrc0",
+ LDSTImmMode.sat: "ld/st imm: sat",
+ LDSTImmMode.prrc1: "ld/st imm: prrc1",
+ LDSTImmMode.prrc0: "ld/st imm: prrc0",
+ LDSTIdxMode.simple: "ld/st idx simple",
+ LDSTIdxMode.stride: "ld/st idx stride",
+ LDSTIdxMode.sat: "ld/st idx sat",
+ LDSTIdxMode.prrc1: "ld/st idx prrc1",
+ LDSTIdxMode.prrc0: "ld/st idx prrc0",
+ }
+ for (cls, desc) in modes.items():
+ if isinstance(mode, cls):
+ return (mode, desc)
+
+ raise NotImplementedError
+
+ def disassemble(self, db, byteorder="little", verbose=False):
+ integer_prefix = int(self.prefix)
+ blob_prefix = integer_prefix.to_bytes(length=4, byteorder=byteorder)
+ blob_prefix = " ".join(map(lambda byte: f"{byte:02x}", blob_prefix))
+
+ integer_suffix = int(self.suffix)
+ blob_suffix = integer_suffix.to_bytes(length=4, byteorder=byteorder)
+ blob_suffix = " ".join(map(lambda byte: f"{byte:02x}", blob_suffix))
+
+ record = self.record(db=db)
+ if record is None or record.svp64 is None:
+ yield f"{blob_prefix} .long 0x{int(self.prefix):08x}"
+ yield f"{blob_suffix} .long 0x{int(self.suffix):08x}"
+ return
yield f"{blob_prefix} sv.{record.name}"
yield f"{blob_suffix}"
+ (mode, mode_desc) = self.mode(db=db)
+
if verbose:
indent = (" " * 4)
binary = self.binary
- spec = self.spec(record=record)
- opcode = self.opcode(record=record)
- mask = self.mask(record=record)
+ spec = self.spec(db=db)
+ opcode = self.opcode(db=db)
+ mask = self.mask(db=db)
yield f"{indent}spec"
yield f"{indent}{indent}{spec}"
yield f"{indent}binary"
record=record, verbose=True)
for part in parts:
yield f"{indent}{indent}{part}"
+
+ yield f"{indent}mode"
+ yield f"{indent}{indent}{mode_desc}"
yield ""
def parse(stream, factory):
+ def match(entry):
+ return ("TODO" not in frozenset(entry.values()))
+
lines = filter(lambda line: not line.strip().startswith("#"), stream)
entries = _csv.DictReader(lines)
- entries = filter(lambda entry: "TODO" not in frozenset(entry.values()), entries)
+ entries = filter(match, entries)
return tuple(map(factory, entries))
class PPCDatabase:
- def __init__(self, root, mdwndb, fieldsdb):
+ def __init__(self, root, mdwndb):
# The code below groups the instructions by section:identifier.
# We use the comment as an identifier, there's nothing better.
# The point is to capture different opcodes for the same instruction.
section.Mode.INTEGER: IntegerOpcode,
section.Mode.PATTERN: PatternOpcode,
}[section.mode]
- factory = _functools.partial(PPCRecord.CSV, opcode_cls=opcode_cls)
+ factory = _functools.partial(
+ PPCRecord.CSV, opcode_cls=opcode_cls)
with open(path, "r", encoding="UTF-8") as stream:
for insn in parse(stream, factory):
records[section][insn.comment].add(insn)
self.__db = db
self.__mdwndb = mdwndb
- self.__fieldsdb = fieldsdb
return super().__init__()
for (section, records) in self.__db.items():
for record in records:
- if (exact_match(key, record) or
- Rc_match(key, record) or
+ if exact_match(key, record):
+ return (section, record)
+
+ for record in records:
+ if (Rc_match(key, record) or
LK_match(key, record) or
AA_match(key, record)):
return (section, record)
mdwndb = MarkdownDatabase()
fieldsdb = FieldsDatabase()
- ppcdb = PPCDatabase(root=root, mdwndb=mdwndb, fieldsdb=fieldsdb)
+ ppcdb = PPCDatabase(root=root, mdwndb=mdwndb)
svp64db = SVP64Database(root=root, ppcdb=ppcdb)
db = set()