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):
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 disassemble(self, value, record, verbose=False):
raise NotImplementedError
+
@_dataclasses.dataclass(eq=True, frozen=True)
class DynamicOperand(Operand):
def disassemble(self, value, record, verbose=False):
else:
yield str(int(value))
+
+@_dataclasses.dataclass(eq=True, frozen=True)
+class ImmediateOperand(DynamicOperand):
+ pass
+
+
@_dataclasses.dataclass(eq=True, frozen=True)
class StaticOperand(Operand):
value: int
else:
yield str(int(value))
+
@_dataclasses.dataclass(eq=True, frozen=True)
class DynamicOperandTargetAddrLI(DynamicOperand):
@property
yield hex(int(_selectconcat(value,
_SelectableInt(value=0b00, bits=2))))
+
class DynamicOperandTargetAddrBD(DynamicOperand):
@property
def name(self):
yield hex(int(_selectconcat(value,
_SelectableInt(value=0b00, bits=2))))
+
@_dataclasses.dataclass(eq=True, frozen=True)
class DynamicOperandGPR(DynamicOperand):
def disassemble(self, value, record, verbose=False):
else:
yield f"r{str(int(value))}"
+
@_dataclasses.dataclass(eq=True, frozen=True)
class DynamicOperandFPR(DynamicOperand):
def disassemble(self, value, record, verbose=False):
yield f"f{str(int(value))}"
-class Operands:
- def __init__(self, insn, iterable):
+class Operands(tuple):
+ def __new__(cls, insn, iterable):
branches = {
"b": {"target_addr": DynamicOperandTargetAddrLI},
"ba": {"target_addr": DynamicOperandTargetAddrLI},
else:
if operand.endswith(")"):
operand = operand.replace("(", " ").replace(")", "")
- all_operands = operand.split(" ")
+ (immediate, _, operand) = operand.partition(" ")
else:
- all_operands = [operand]
+ immediate = None
- for operand in all_operands:
- if insn in branches and operand in branches[insn]:
- dynamic_cls = branches[insn][operand]
+ if immediate is not None:
+ operands.append(ImmediateOperand(name=immediate))
- if operand in _RegType.__members__:
- regtype = _RegType[operand]
- if regtype is _RegType.GPR:
- dynamic_cls = DynamicOperandGPR
- elif regtype is _RegType.FPR:
- dynamic_cls = DynamicOperandFPR
+ if insn in branches and operand in branches[insn]:
+ dynamic_cls = branches[insn][operand]
- operand = dynamic_cls(name=operand)
- operands.append(operand)
+ if operand in _RegType.__members__:
+ regtype = _RegType[operand]
+ if regtype is _RegType.GPR:
+ dynamic_cls = DynamicOperandGPR
+ elif regtype is _RegType.FPR:
+ dynamic_cls = DynamicOperandFPR
- self.__operands = operands
-
- return super().__init__()
-
- def __repr__(self):
- return self.__operands.__repr__()
+ operand = dynamic_cls(name=operand)
+ operands.append(operand)
- def __iter__(self):
- yield from self.__operands
+ return super().__new__(cls, operands)
def __contains__(self, key):
return self.__getitem__(key) is not None
def __getitem__(self, key):
- for operand in self.__operands:
+ for operand in self:
if operand.name == key:
return operand
return "".join(map(str, bits))
def spec(self, record):
+ immediate = ""
dynamic_operands = []
for operand in record.operands.dynamic:
- dynamic_operands.append(operand.name)
+ name = operand.name
+ if immediate:
+ name = f"{immediate}({name})"
+ immediate = ""
+ if isinstance(operand, ImmediateOperand):
+ immediate = operand.name
+ if not immediate:
+ dynamic_operands.append(name)
+
static_operands = []
for operand in record.operands.static:
static_operands.append(f"{operand.name}={operand.value}")
+
operands = ""
if dynamic_operands:
operands += f" {','.join(dynamic_operands)}"
if static_operands:
operands += f" ({' '.join(static_operands)})"
+
return f"{record.name}{operands}"
def opcode(self, record):
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))
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)