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)
return self.__mapping.get(key, None)
-class Operands:
- @_dataclasses.dataclass(eq=True, frozen=True)
- class Operand:
- name: str
+@_dataclasses.dataclass(eq=True, frozen=True)
+class Operand:
+ name: str
- def disassemble(self, value, record, verbose=False):
- raise NotImplementedError
+ 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):
+ span = record.fields[self.name]
+ value = value[span]
+ if verbose:
+ yield f"{int(value):0{value.bits}b}"
+ yield repr(span)
+ 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
+
+ def disassemble(self, value, record, verbose=False):
+ span = record.fields[self.name]
+ value = value[span]
+ if verbose:
+ yield f"{int(value):0{value.bits}b}"
+ yield repr(span)
+ else:
+ yield str(int(value))
+
+
+@_dataclasses.dataclass(eq=True, frozen=True)
+class DynamicOperandTargetAddrLI(DynamicOperand):
+ @property
+ def name(self):
+ return "LI"
+
+ @name.setter
+ def name(self, _):
+ pass
+
+ def disassemble(self, value, record, verbose=False):
+ span = record.fields["LI"]
+ value = value[span]
+ if verbose:
+ yield f"{int(value):0{value.bits}b}"
+ yield repr(span)
+ yield "target_addr = EXTS(LI || 0b00))"
+ else:
+ yield hex(int(_selectconcat(value,
+ _SelectableInt(value=0b00, bits=2))))
- @_dataclasses.dataclass(eq=True, frozen=True)
- class DynamicOperand(Operand):
- def disassemble(self, value, record, verbose=False):
- span = record.fields[self.name]
- value = value[span]
- if verbose:
- yield f"{int(value):0{value.bits}b}"
- yield repr(span)
- else:
- yield str(int(value))
-
- @_dataclasses.dataclass(eq=True, frozen=True)
- class StaticOperand(Operand):
- value: int
-
- def disassemble(self, value, record, verbose=False):
- span = record.fields[self.name]
- value = value[span]
- if verbose:
- yield f"{int(value):0{value.bits}b}"
- yield repr(span)
- else:
- yield str(int(value))
-
- @_dataclasses.dataclass(eq=True, frozen=True)
- class DynamicOperandIFormLI(DynamicOperand):
- @property
- def name(self):
- return "LI"
-
- @name.setter
- def name(self, _):
- pass
-
- def disassemble(self, value, record, verbose=False):
- span = record.fields["LI"]
- value = value[span]
- if verbose:
- yield f"{int(value):0{value.bits}b}"
- yield repr(span)
- yield "target_addr = EXTS(LI || 0b00))"
- else:
- yield hex(int(_selectconcat(value,
- _SelectableInt(value=0b00, bits=2))))
-
- class DynamicOperandBFormBD(DynamicOperand):
- @property
- def name(self):
- return "BD"
-
- @name.setter
- def name(self, _):
- pass
-
- def disassemble(self, value, record, verbose=False):
- span = record.fields["BD"]
- value = value[span]
- if verbose:
- yield f"{int(value):0{value.bits}b}"
- yield repr(span)
- yield "target_addr = EXTS(BD || 0b00))"
- else:
- 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):
- span = record.fields[self.name]
- value = value[span]
- if verbose:
- yield f"{int(value):0{value.bits}b}"
- yield repr(span)
- else:
- yield f"r{str(int(value))}"
-
- @_dataclasses.dataclass(eq=True, frozen=True)
- class DynamicOperandFPR(DynamicOperand):
- def disassemble(self, value, record, verbose=False):
- span = record.fields[self.name]
- value = value[span]
- if verbose:
- yield f"{int(value):0{value.bits}b}"
- yield repr(span)
- else:
- yield f"f{str(int(value))}"
- def __init__(self, insn, iterable):
+class DynamicOperandTargetAddrBD(DynamicOperand):
+ @property
+ def name(self):
+ return "BD"
+
+ @name.setter
+ def name(self, _):
+ pass
+
+ def disassemble(self, value, record, verbose=False):
+ span = record.fields["BD"]
+ value = value[span]
+ if verbose:
+ yield f"{int(value):0{value.bits}b}"
+ yield repr(span)
+ yield "target_addr = EXTS(BD || 0b00))"
+ else:
+ 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):
+ span = record.fields[self.name]
+ value = value[span]
+ if verbose:
+ yield f"{int(value):0{value.bits}b}"
+ yield repr(span)
+ else:
+ yield f"r{str(int(value))}"
+
+
+@_dataclasses.dataclass(eq=True, frozen=True)
+class DynamicOperandFPR(DynamicOperand):
+ def disassemble(self, value, record, verbose=False):
+ span = record.fields[self.name]
+ value = value[span]
+ if verbose:
+ yield f"{int(value):0{value.bits}b}"
+ yield repr(span)
+ else:
+ yield f"f{str(int(value))}"
+
+
+class Operands(tuple):
+ def __new__(cls, insn, iterable):
branches = {
- "b": {"LI": self.__class__.DynamicOperandIFormLI},
- "ba": {"LI": self.__class__.DynamicOperandIFormLI},
- "bl": {"LI": self.__class__.DynamicOperandIFormLI},
- "bla": {"LI": self.__class__.DynamicOperandIFormLI},
- "bc": {"BD": self.__class__.DynamicOperandBFormBD},
- "bca": {"BD": self.__class__.DynamicOperandBFormBD},
- "bcl": {"BD": self.__class__.DynamicOperandBFormBD},
- "bcla": {"BD": self.__class__.DynamicOperandBFormBD},
+ "b": {"target_addr": DynamicOperandTargetAddrLI},
+ "ba": {"target_addr": DynamicOperandTargetAddrLI},
+ "bl": {"target_addr": DynamicOperandTargetAddrLI},
+ "bla": {"target_addr": DynamicOperandTargetAddrLI},
+ "bc": {"target_addr": DynamicOperandTargetAddrBD},
+ "bca": {"target_addr": DynamicOperandTargetAddrBD},
+ "bcl": {"target_addr": DynamicOperandTargetAddrBD},
+ "bcla": {"target_addr": DynamicOperandTargetAddrBD},
}
operands = []
for operand in iterable:
- dynamic_cls = self.__class__.DynamicOperand
- static_cls = self.__class__.StaticOperand
+ dynamic_cls = DynamicOperand
+ static_cls = StaticOperand
if "=" in operand:
(name, value) = operand.split("=")
operand = static_cls(name=name, value=int(value))
+ operands.append(operand)
else:
+ if operand.endswith(")"):
+ operand = operand.replace("(", " ").replace(")", "")
+ (immediate, _, operand) = operand.partition(" ")
+ else:
+ immediate = None
+
+ if immediate is not None:
+ operands.append(ImmediateOperand(name=immediate))
+
if insn in branches and operand in branches[insn]:
dynamic_cls = branches[insn][operand]
if operand in _RegType.__members__:
regtype = _RegType[operand]
if regtype is _RegType.GPR:
- dynamic_cls = self.__class__.DynamicOperandGPR
+ dynamic_cls = DynamicOperandGPR
elif regtype is _RegType.FPR:
- dynamic_cls = self.__class__.DynamicOperandFPR
+ dynamic_cls = DynamicOperandFPR
operand = dynamic_cls(name=operand)
+ operands.append(operand)
- operands.append(operand)
-
- self.__operands = operands
-
- return super().__init__()
-
- def __repr__(self):
- return self.__operands.__repr__()
-
- 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
@property
def dynamic(self):
for operand in self:
- if isinstance(operand, self.__class__.DynamicOperand):
+ if isinstance(operand, DynamicOperand):
yield operand
@property
def static(self):
for operand in self:
- if isinstance(operand, self.__class__.StaticOperand):
+ if isinstance(operand, StaticOperand):
yield 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)