import dataclasses as _dataclasses
import enum as _enum
import functools as _functools
+import itertools as _itertools
import os as _os
import operator as _operator
import pathlib as _pathlib
In3Sel as _In3Sel,
OutSel as _OutSel,
CRInSel as _CRInSel,
+ CRIn2Sel as _CRIn2Sel,
CROutSel as _CROutSel,
LDSTLen as _LDSTLen,
LDSTMode as _LDSTMode,
@_functools.total_ordering
@_dataclasses.dataclass(eq=True, frozen=True)
class Opcode:
- class Value(int):
- def __repr__(self):
- if self.bit_length() <= 32:
- return f"0x{self:08x}"
- else:
- return f"0x{self:016x}"
+ class Integer(int):
+ def __new__(cls, value):
+ if isinstance(value, str):
+ value = int(value, 0)
+ if not isinstance(value, int):
+ raise ValueError(value)
+
+ if value.bit_length() > 64:
+ raise ValueError(value)
+
+ return super().__new__(cls, value)
+
+ def __str__(self):
+ return super().__repr__()
- class Mask(int):
def __repr__(self):
- if self.bit_length() <= 32:
- return f"0x{self:08x}"
- else:
- return f"0x{self:016x}"
+ return f"{self:0{self.bit_length()}b}"
+
+ def bit_length(self):
+ if super().bit_length() > 32:
+ return 64
+ return 32
+
+ class Value(Integer):
+ pass
+
+ class Mask(Integer):
+ pass
value: Value
- mask: Mask = None
+ mask: Mask
def __lt__(self, other):
if not isinstance(other, Opcode):
return ((self.value, self.mask) < (other.value, other.mask))
def __post_init__(self):
- (value, mask) = (self.value, self.mask)
-
- if isinstance(value, Opcode):
- if mask is not None:
- raise ValueError(mask)
- (value, mask) = (value.value, value.mask)
- elif isinstance(value, str):
- if mask is not None:
- raise ValueError(mask)
- value = int(value, 0)
-
- if not isinstance(value, int):
- raise ValueError(value)
- if mask is None:
- mask = value
- if not isinstance(mask, int):
- raise ValueError(mask)
+ if self.value.bit_length() != self.mask.bit_length():
+ raise ValueError("bit length mismatch")
- object.__setattr__(self, "value", self.__class__.Value(value))
- object.__setattr__(self, "mask", self.__class__.Mask(mask))
+ def __repr__(self):
+ def pattern(value, mask, bit_length):
+ for bit in range(bit_length):
+ if ((mask & (1 << (bit_length - bit - 1))) == 0):
+ yield "-"
+ elif (value & (1 << (bit_length - bit - 1))):
+ yield "1"
+ else:
+ yield "0"
+
+ return "".join(pattern(self.value, self.mask, self.value.bit_length()))
class IntegerOpcode(Opcode):
def __init__(self, value):
- if isinstance(value, str):
- value = int(value, 0)
- return super().__init__(value=value, mask=None)
+ if value.startswith("0b"):
+ mask = int(("1" * len(value[2:])), 2)
+ else:
+ mask = 0b111111
+
+ value = Opcode.Value(value)
+ mask = Opcode.Mask(mask)
+
+ return super().__init__(value=value, mask=mask)
class PatternOpcode(Opcode):
- def __init__(self, value):
- (pattern, value, mask) = (value, 0, 0)
+ def __init__(self, pattern):
+ if not isinstance(pattern, str):
+ raise ValueError(pattern)
+ (value, mask) = (0, 0)
for symbol in pattern:
if symbol not in {"0", "1", "-"}:
raise ValueError(pattern)
value >>= 1
mask >>= 1
- return super().__init__(value=value, mask=mask)
-
-
-class FieldsOpcode(Opcode):
- def __init__(self, fields):
- def field(opcode, field):
- (value, mask) = opcode
- (field, bits) = field
- shifts = map(lambda bit: (31 - bit), reversed(tuple(bits)))
- for (index, shift) in enumerate(shifts):
- bit = ((field & (1 << index)) != 0)
- value |= (bit << shift)
- mask |= (1 << shift)
- return (value, mask)
-
- (value, mask) = _functools.reduce(field, fields, (0, 0))
+ value = Opcode.Value(value)
+ mask = Opcode.Mask(mask)
return super().__init__(value=value, mask=mask)
in3: _In3Sel = _In3Sel.NONE
out: _OutSel = _OutSel.NONE
cr_in: _CRInSel = _CRInSel.NONE
+ cr_in2: _CRIn2Sel = _CRIn2Sel.NONE
cr_out: _CROutSel = _CROutSel.NONE
cry_in: _CryIn = _CryIn.ZERO
ldst_len: _LDSTLen = _LDSTLen.NONE
}
@classmethod
- def CSV(cls, record, opcode_cls=Opcode):
+ def CSV(cls, record, opcode_cls):
typemap = {field.name:field.type for field in _dataclasses.fields(cls)}
typemap["opcode"] = opcode_cls
+ if record["CR in"] == "BA_BB":
+ record["cr_in"] = "BA"
+ record["cr_in2"] = "BB"
+ del record["CR in"]
+
flags = set()
for flag in frozenset(PPCRecord.Flags):
if bool(record.pop(flag, "")):
return frozenset(self.comment.split("=")[-1].split("/"))
-class PPCMultiRecord(frozenset):
- @cached_property
- def unified(self):
- def merge(lhs, rhs):
- value = 0
- mask = 0
- lvalue = lhs.opcode.value
- rvalue = rhs.opcode.value
- lmask = lhs.opcode.mask
- rmask = rhs.opcode.mask
- bits = max(lmask.bit_length(), rmask.bit_length())
- for bit in range(bits):
- lvstate = ((lvalue & (1 << bit)) != 0)
- rvstate = ((rvalue & (1 << bit)) != 0)
- lmstate = ((lmask & (1 << bit)) != 0)
- rmstate = ((rmask & (1 << bit)) != 0)
- vstate = lvstate
- mstate = True
- if (not lmstate or not rmstate) or (lvstate != rvstate):
- vstate = 0
- mstate = 0
- value |= (vstate << bit)
- mask |= (mstate << bit)
-
- opcode = opcode=Opcode(value=value, mask=mask)
-
- return _dataclasses.replace(lhs, opcode=opcode)
-
- return _functools.reduce(merge, self)
-
+class PPCMultiRecord(tuple):
def __getattr__(self, attr):
- return getattr(self.unified, attr)
+ if attr == "opcode":
+ raise AttributeError(attr)
+ return getattr(self[0], attr)
@_dataclasses.dataclass(eq=True, frozen=True)
out: _OutSel = _OutSel.NONE
out2: _OutSel = _OutSel.NONE
cr_in: _CRInSel = _CRInSel.NONE
+ cr_in2: _CRIn2Sel = _CRIn2Sel.NONE
cr_out: _CROutSel = _CROutSel.NONE
extra: ExtraMap = ExtraMap()
conditions: str = ""
@classmethod
def CSV(cls, record):
- for key in ("in1", "in2", "in3", "out", "out2", "CR in", "CR out"):
+ for key in frozenset({
+ "in1", "in2", "in3", "CR in",
+ "out", "out2", "CR out",
+ }):
value = record[key]
if value == "0":
record[key] = "NONE"
+ if record["CR in"] == "BA_BB":
+ record["cr_in"] = "BA"
+ record["cr_in2"] = "BB"
+ del record["CR in"]
+
extra = []
for idx in range(0, 4):
extra.append(record.pop(f"{idx}"))
)
if key not in frozenset({
- "in1", "in2", "in3", "cr_in",
+ "in1", "in2", "in3", "cr_in", "cr_in2",
"out", "out2", "cr_out",
}):
raise KeyError(key)
def __iter__(self):
yield from range(self.start, (self.end + 1))
+ def __reversed__(self):
+ return tuple(reversed(tuple(self)))
+
@property
def start(self):
return self.__start
return (bin(self) if self else "None")
path: _pathlib.Path
- opcode: Opcode
bitsel: BitSel
suffix: Suffix
mode: Mode
+ opcode: IntegerOpcode = None
@classmethod
def CSV(cls, record):
- return dataclass(cls, record)
+ typemap = {field.name:field.type for field in _dataclasses.fields(cls)}
+ if record["opcode"] == "NONE":
+ typemap["opcode"] = lambda _: None
+
+ return dataclass(cls, record, typemap=typemap)
class Fields:
class Operand:
name: str
+ def span(self, record):
+ return record.fields[self.name]
+
def disassemble(self, insn, record,
verbosity=Verbosity.NORMAL, indent=""):
raise NotImplementedError
-@_dataclasses.dataclass(eq=True, frozen=True)
class DynamicOperand(Operand):
def disassemble(self, insn, record,
verbosity=Verbosity.NORMAL, indent=""):
- span = record.fields[self.name]
+ span = self.span(record=record)
if isinstance(insn, SVP64Instruction):
span = tuple(map(lambda bit: (bit + 32), span))
value = insn[span]
yield str(int(value))
-@_dataclasses.dataclass(eq=True, frozen=True)
-class ImmediateOperand(DynamicOperand):
- pass
+class SignedOperand(DynamicOperand):
+ def disassemble(self, insn, record,
+ verbosity=Verbosity.NORMAL, indent=""):
+ span = self.span(record=record)
+ if isinstance(insn, SVP64Instruction):
+ span = tuple(map(lambda bit: (bit + 32), span))
+ value = insn[span]
+
+ if verbosity >= Verbosity.VERBOSE:
+ span = map(str, span)
+ yield f"{indent}{self.name}"
+ yield f"{indent}{indent}{int(value):0{value.bits}b}"
+ yield f"{indent}{indent}{', '.join(span)}"
+ else:
+ yield str(value.to_signed_int())
@_dataclasses.dataclass(eq=True, frozen=True)
def disassemble(self, insn, record,
verbosity=Verbosity.NORMAL, indent=""):
- span = record.fields[self.name]
+ span = self.span(record=record)
if isinstance(insn, SVP64Instruction):
span = tuple(map(lambda bit: (bit + 32), span))
value = insn[span]
yield str(int(value))
-@_dataclasses.dataclass(eq=True, frozen=True)
-class DynamicOperandReg(DynamicOperand):
- def spec(self, insn, record, merge):
+class ImmediateOperand(DynamicOperand):
+ pass
+
+
+class NonZeroOperand(DynamicOperand):
+ def disassemble(self, insn, record,
+ verbosity=Verbosity.NORMAL, indent=""):
+ span = self.span(record=record)
+ if isinstance(insn, SVP64Instruction):
+ span = tuple(map(lambda bit: (bit + 32), span))
+ value = insn[span]
+
+ if verbosity >= Verbosity.VERBOSE:
+ span = map(str, span)
+ yield f"{indent}{self.name}"
+ yield f"{indent}{indent}{int(value):0{value.bits}b}"
+ yield f"{indent}{indent}{', '.join(span)}"
+ else:
+ yield str(int(value) + 1)
+
+
+class RegisterOperand(DynamicOperand):
+ def sv_spec_enter(self, value, span):
+ return (value, span)
+
+ def sv_spec_leave(self, value, span, origin_value, origin_span):
+ return (value, span)
+
+ def spec(self, insn, record):
vector = False
- span = record.fields[self.name]
+ span = self.span(record=record)
if isinstance(insn, SVP64Instruction):
span = tuple(map(lambda bit: (bit + 32), span))
value = insn[span]
+ span = tuple(map(str, span))
if isinstance(insn, SVP64Instruction):
+ (origin_value, origin_span) = (value, span)
+ (value, span) = self.sv_spec_enter(value=value, span=span)
+
extra_idx = self.extra_idx(record=record)
+ if extra_idx is _SVExtra.NONE:
+ return (vector, value, span)
if record.etype is _SVEtype.EXTRA3:
spec = insn.prefix.rm.extra3[extra_idx]
if spec != 0:
vector = bool(spec[0])
- span = tuple(map(str, span))
spec_span = spec.__class__
if record.etype is _SVEtype.EXTRA3:
spec_span = tuple(map(str, spec_span[1, 2]))
else:
raise ValueError(record.etype)
- (value, span) = merge(vector, value, span, spec, spec_span)
+ vector_shift = (2 + (5 - value.bits))
+ scalar_shift = value.bits
+ spec_shift = (5 - value.bits)
- span = tuple(map(str, span))
+ bits = (len(span) + len(spec_span))
+ value = _SelectableInt(value=value.value, bits=bits)
+ spec = _SelectableInt(value=spec.value, bits=bits)
+ if vector:
+ value = ((value << vector_shift) | (spec << spec_shift))
+ span = (span + spec_span + ((spec_shift * ('{0}',))))
+ else:
+ value = ((spec << scalar_shift) | value)
+ span = ((spec_shift * ('{0}',)) + spec_span + span)
+
+ (value, span) = self.sv_spec_leave(value=value, span=span,
+ origin_value=origin_value, origin_span=origin_span)
return (vector, value, span)
def extra_idx(self, record):
for key in frozenset({
- "in1", "in2", "in3", "cr_in",
+ "in1", "in2", "in3", "cr_in", "cr_in2",
"out", "out2", "cr_out",
}):
extra_reg = record.svp64.extra_reg(key=key)
(vector, value, span) = self.spec(insn=insn, record=record)
if verbosity >= Verbosity.VERBOSE:
- yield f"{indent}{self.name}"
+ mode = "vector" if vector else "scalar"
+ yield f"{indent}{self.name} ({mode})"
yield f"{indent}{indent}{int(value):0{value.bits}b}"
yield f"{indent}{indent}{', '.join(span)}"
if isinstance(insn, SVP64Instruction):
else:
etype = repr(record.etype).lower()
yield f"{indent}{indent}{etype}{extra_idx!r}"
- yield f"{indent}type"
- yield f"{indent}{indent}{'vector' if vector else 'scalar'}"
else:
vector = "*" if vector else ""
yield f"{vector}{prefix}{int(value)}"
-class DynamicOperandGPRFPR(DynamicOperandReg):
- def spec(self, insn, record):
- def merge(vector, value, span, spec, spec_span):
- bits = (len(span) + len(spec_span))
- value = _SelectableInt(value=value.value, bits=bits)
- spec = _SelectableInt(value=spec.value, bits=bits)
- if vector:
- value = ((value << 2) | spec)
- span = (span + spec_span)
- else:
- value = ((spec << 5) | value)
- span = (spec_span + span)
-
- value = _SelectableInt(value=value, bits=bits)
-
- return (value, span)
-
- return super().spec(insn=insn, record=record, merge=merge)
-
-
-class DynamicOperandGPR(DynamicOperandGPRFPR):
+class GPROperand(RegisterOperand):
def disassemble(self, insn, record,
verbosity=Verbosity.NORMAL, indent=""):
prefix = "" if (verbosity <= Verbosity.SHORT) else "r"
verbosity=verbosity, indent=indent)
-@_dataclasses.dataclass(eq=True, frozen=True)
-class DynamicOperandFPR(DynamicOperandGPRFPR):
+class FPROperand(RegisterOperand):
def disassemble(self, insn, record,
verbosity=Verbosity.NORMAL, indent=""):
prefix = "" if (verbosity <= Verbosity.SHORT) else "f"
verbosity=verbosity, indent=indent)
-@_dataclasses.dataclass(eq=True, frozen=True)
-class DynamicOperandTargetAddr(DynamicOperandReg):
+class CR3Operand(RegisterOperand):
+ pass
+
+
+class CR5Operand(RegisterOperand):
+ def sv_spec_enter(self, value, span):
+ value = _SelectableInt(value=(value.value >> 2), bits=3)
+ return (value, span)
+
+ def sv_spec_leave(self, value, span, origin_value, origin_span):
+ value = _selectconcat(value, origin_value[3:5])
+ span += origin_span
+ return (value, span)
+
+
+class TargetAddrOperand(RegisterOperand):
def disassemble(self, insn, record, field,
verbosity=Verbosity.NORMAL, indent=""):
- span = record.fields[field]
+ span = self.span(record=record)
if isinstance(insn, SVP64Instruction):
span = tuple(map(lambda bit: (bit + 32), span))
value = insn[span]
if verbosity >= Verbosity.VERBOSE:
span = tuple(map(str, span))
- yield f"{indent}{self.name}"
- yield f"{indent}{indent}{int(value):0{value.bits}b}00"
- yield f"{indent}{indent}{', '.join(span + ('{0}', '{0}'))}"
- yield f"{indent}{indent}target_addr = EXTS({field} || 0b00))"
+ yield f"{indent}{self.name} = EXTS({field} || 0b00))"
+ yield f"{indent}{indent}{field}"
+ yield f"{indent}{indent}{indent}{int(value):0{value.bits}b}00"
+ yield f"{indent}{indent}{indent}{', '.join(span + ('{0}', '{0}'))}"
else:
- yield hex(int(_selectconcat(value,
- _SelectableInt(value=0b00, bits=2))))
+ yield hex(_selectconcat(value,
+ _SelectableInt(value=0b00, bits=2)).to_signed_int())
-@_dataclasses.dataclass(eq=True, frozen=True)
-class DynamicOperandTargetAddrLI(DynamicOperandTargetAddr):
+class TargetAddrOperandLI(TargetAddrOperand):
+ def span(self, record):
+ return record.fields["LI"]
+
def disassemble(self, insn, record,
verbosity=Verbosity.NORMAL, indent=""):
return super().disassemble(field="LI",
verbosity=verbosity, indent=indent)
-class DynamicOperandTargetAddrBD(DynamicOperandTargetAddr):
+class TargetAddrOperandBD(TargetAddrOperand):
+ def span(self, record):
+ return record.fields["BD"]
+
def disassemble(self, insn, record,
verbosity=Verbosity.NORMAL, indent=""):
return super().disassemble(field="BD",
verbosity=verbosity, indent=indent)
+class DOperandDX(SignedOperand):
+ def span(self, record):
+ operands = map(DynamicOperand, ("d0", "d1", "d2"))
+ spans = map(lambda operand: operand.span(record=record), operands)
+ return sum(spans, tuple())
+
+ def disassemble(self, insn, record,
+ verbosity=Verbosity.NORMAL, indent=""):
+ span = self.span(record=record)
+ if isinstance(insn, SVP64Instruction):
+ span = tuple(map(lambda bit: (bit + 32), span))
+ value = insn[span]
+
+ if verbosity >= Verbosity.VERBOSE:
+ yield f"{indent}D"
+ mapping = {
+ "d0": "[0:9]",
+ "d1": "[10:15]",
+ "d2": "[16]",
+ }
+ for (subname, subspan) in mapping.items():
+ operand = DynamicOperand(name=subname)
+ span = operand.span(record=record)
+ if isinstance(insn, SVP64Instruction):
+ span = tuple(map(lambda bit: (bit + 32), span))
+ value = insn[span]
+ span = map(str, span)
+ yield f"{indent}{indent}{operand.name} = D{subspan}"
+ yield f"{indent}{indent}{indent}{int(value):0{value.bits}b}"
+ yield f"{indent}{indent}{indent}{', '.join(span)}"
+ else:
+ yield str(value.to_signed_int())
+
+
class Operands(tuple):
def __new__(cls, insn, iterable):
- branches = {
- "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},
+ custom_insns = {
+ "b": {"target_addr": TargetAddrOperandLI},
+ "ba": {"target_addr": TargetAddrOperandLI},
+ "bl": {"target_addr": TargetAddrOperandLI},
+ "bla": {"target_addr": TargetAddrOperandLI},
+ "bc": {"target_addr": TargetAddrOperandBD},
+ "bca": {"target_addr": TargetAddrOperandBD},
+ "bcl": {"target_addr": TargetAddrOperandBD},
+ "bcla": {"target_addr": TargetAddrOperandBD},
+ "addpcis": {"D": DOperandDX},
+ "fishmv": {"D": DOperandDX},
+ "fmvis": {"D": DOperandDX},
+ }
+ custom_fields = {
+ "SVi": NonZeroOperand,
+ "SVd": NonZeroOperand,
+ "SVxd": NonZeroOperand,
+ "SVyd": NonZeroOperand,
+ "SVzd": NonZeroOperand,
+ "BD": SignedOperand,
+ "D": SignedOperand,
+ "DQ": SignedOperand,
+ "DS": SignedOperand,
+ "SI": SignedOperand,
+ "IB": SignedOperand,
+ "LI": SignedOperand,
+ "SIM": SignedOperand,
+ "SVD": SignedOperand,
+ "SVDS": SignedOperand,
}
operands = []
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 custom_fields:
+ dynamic_cls = custom_fields[operand]
+ if insn in custom_insns and operand in custom_insns[insn]:
+ dynamic_cls = custom_insns[insn][operand]
if operand in _RegType.__members__:
regtype = _RegType[operand]
if regtype is _RegType.GPR:
- dynamic_cls = DynamicOperandGPR
+ dynamic_cls = GPROperand
elif regtype is _RegType.FPR:
- dynamic_cls = DynamicOperandFPR
+ dynamic_cls = FPROperand
+ if regtype is _RegType.CR_BIT: # 5-bit
+ dynamic_cls = CR5Operand
+ if regtype is _RegType.CR_REG: # actually CR Field, 3-bit
+ dynamic_cls = CR3Operand
operand = dynamic_cls(name=operand)
operands.append(operand)
yield operand
+class PCode:
+ def __init__(self, iterable):
+ self.__pcode = tuple(iterable)
+ return super().__init__()
+
+ def __iter__(self):
+ yield from self.__pcode
+
+ def __repr__(self):
+ return self.__pcode.__repr__()
+
+
+@_dataclasses.dataclass(eq=True, frozen=True)
+class MarkdownRecord:
+ pcode: PCode
+ operands: Operands
+
+
@_functools.total_ordering
@_dataclasses.dataclass(eq=True, frozen=True)
class Record:
section: Section
ppc: PPCRecord
fields: Fields
- operands: Operands
+ mdwn: MarkdownRecord
svp64: SVP64Record = None
def __lt__(self, other):
if not isinstance(other, Record):
return NotImplemented
- return (self.opcode < other.opcode)
+ return (min(self.opcodes) < min(other.opcodes))
- @cached_property
- def opcode(self):
- fields = []
- if self.section.opcode:
- fields += [(self.section.opcode.value, BitSel((0, 5)))]
- fields += [(self.ppc.opcode.value, self.section.bitsel)]
- else:
- fields += [(self.ppc.opcode.value, self.section.bitsel)]
+ @property
+ def opcodes(self):
+ def opcode(ppc):
+ value = ([0] * 32)
+ mask = ([0] * 32)
- for operand in self.operands.static:
- fields += [(operand.value, self.fields[operand.name])]
+ PO = self.section.opcode
+ if PO is not None:
+ for (src, dst) in enumerate(reversed(BitSel((0, 5)))):
+ value[dst] = int((PO.value & (1 << src)) != 0)
+ mask[dst] = int((PO.mask & (1 << src)) != 0)
- return FieldsOpcode(fields)
+ XO = ppc.opcode
+ for (src, dst) in enumerate(reversed(self.section.bitsel)):
+ value[dst] = int((XO.value & (1 << src)) != 0)
+ mask[dst] = int((XO.mask & (1 << src)) != 0)
+
+ for operand in self.mdwn.operands.static:
+ for (src, dst) in enumerate(reversed(operand.span(record=self))):
+ value[dst] = int((operand.value & (1 << src)) != 0)
+ mask[dst] = 1
+
+ value = Opcode.Value(int(("".join(map(str, value))), 2))
+ mask = Opcode.Mask(int(("".join(map(str, mask))), 2))
+
+ return Opcode(value=value, mask=mask)
+
+ return tuple(sorted(map(opcode, self.ppc)))
+
+ def match(self, key):
+ for opcode in self.opcodes:
+ if ((opcode.value & opcode.mask) ==
+ (key & opcode.mask)):
+ return True
+ return False
@property
def function(self):
def cr_in(self):
return self.ppc.cr_in
+ @property
+ def cr_in2(self):
+ return self.ppc.cr_in2
+
@property
def cr_out(self):
return self.ppc.cr_out
def __hash__(self):
return hash(int(self))
+ def __getitem__(self, key):
+ return self.storage.__getitem__(key)
+
+ def __setitem__(self, key, value):
+ return self.storage.__setitem__(key, value)
+
+ def bytes(self, byteorder="little"):
+ nr_bytes = (self.storage.bits // 8)
+ return int(self).to_bytes(nr_bytes, byteorder=byteorder)
+
def record(self, db):
record = db[self]
if record is None:
imm = False
imm_name = ""
imm_value = ""
- for operand in record.operands.dynamic:
+ for operand in record.mdwn.operands.dynamic:
name = operand.name
dis = operand.disassemble(insn=self, record=record,
verbosity=min(verbosity, Verbosity.NORMAL))
def static_operands(self, db):
record = self.record(db=db)
- for operand in record.operands.static:
+ for operand in record.mdwn.operands.static:
yield (operand.name, operand.value)
def disassemble(self, db,
bits.append(bit)
return "".join(map(str, bits))
- def opcode(self, db):
- record = self.record(db=db)
- return f"0x{record.opcode.value:08x}"
-
- def mask(self, db):
- record = self.record(db=db)
- return f"0x{record.opcode.mask:08x}"
-
def disassemble(self, db,
byteorder="little",
verbosity=Verbosity.NORMAL):
blob = " ".join(map(lambda byte: f"{byte:02x}", blob))
blob += " "
- record = self.record(db=db)
+ record = db[self]
if record is None:
yield f"{blob}.long 0x{integer:08x}"
return
indent = (" " * 4)
binary = self.binary
spec = self.spec(db=db, prefix="")
- opcode = self.opcode(db=db)
- mask = self.mask(db=db)
yield f"{indent}spec"
yield f"{indent}{indent}{spec}"
+ yield f"{indent}pcode"
+ for stmt in record.mdwn.pcode:
+ yield f"{indent}{indent}{stmt}"
yield f"{indent}binary"
yield f"{indent}{indent}[0:8] {binary[0:8]}"
yield f"{indent}{indent}[8:16] {binary[8:16]}"
yield f"{indent}{indent}[16:24] {binary[16:24]}"
yield f"{indent}{indent}[24:32] {binary[24:32]}"
- yield f"{indent}opcode"
- yield f"{indent}{indent}{opcode}"
- yield f"{indent}mask"
- yield f"{indent}{indent}{mask}"
- for operand in record.operands:
+ yield f"{indent}opcodes"
+ for opcode in record.opcodes:
+ yield f"{indent}{indent}{opcode!r}"
+ for operand in record.mdwn.operands:
yield from operand.disassemble(insn=self, record=record,
verbosity=verbosity, indent=indent)
yield ""
(prefix, suffix) = map(transform, (prefix, suffix))
value = _selectconcat(prefix, suffix)
- return super().integer(value=value)
+ return super().integer(bits=64, value=value)
class Mode(_Mapping):
_: _Field = range(0, 5)
- sel: _Field = range(0, 2)
-
-
-class NormalMode(Mode):
- class simple(Mode):
- """simple mode"""
- dz: Mode[3]
- sz: Mode[4]
-
- class smr(Mode):
- """scalar reduce mode (mapreduce), SUBVL=1"""
- RG: Mode[4]
-
- class pmr(Mode):
- """parallel reduce mode (mapreduce), SUBVL=1"""
- pass
-
- class svmr(Mode):
- """subvector reduce mode, SUBVL>1"""
- SVM: Mode[3]
-
- class pu(Mode):
- """Pack/Unpack mode, SUBVL>1"""
- SVM: Mode[3]
-
- class ffrc1(Mode):
- """Rc=1: ffirst CR sel"""
- inv: Mode[2]
- CRbit: Mode[3, 4]
-
- class ffrc0(Mode):
- """Rc=0: ffirst z/nonz"""
- inv: Mode[2]
- VLi: Mode[3]
- RC1: Mode[4]
-
- class sat(Mode):
- """sat mode: N=0/1 u/s, SUBVL=1"""
- N: Mode[2]
- dz: Mode[3]
- sz: Mode[4]
-
- class satx(Mode):
- """sat mode: N=0/1 u/s, SUBVL>1"""
- N: Mode[2]
- zz: Mode[3]
- dz: Mode[3]
- sz: Mode[3]
-
- class satpu(Mode):
- """Pack/Unpack sat mode: N=0/1 u/s, SUBVL>1"""
- N: Mode[2]
- zz: Mode[3]
- dz: Mode[3]
- sz: Mode[3]
-
- class prrc1(Mode):
- """Rc=1: pred-result CR sel"""
- inv: Mode[2]
- CRbit: Mode[3, 4]
-
- class prrc0(Mode):
- """Rc=0: pred-result z/nonz"""
- inv: Mode[2]
- zz: Mode[3]
- RC1: Mode[4]
- dz: Mode[3]
- sz: Mode[3]
-
- simple: simple
- smr: smr
- pmr: pmr
- svmr: svmr
- pu: pu
- ffrc1: ffrc1
- ffrc0: ffrc0
- sat: sat
- satx: satx
- satpu: satpu
- prrc1: prrc1
- prrc0: prrc0
-
-
-class LDSTImmMode(Mode):
- class simple(Mode):
- """simple mode"""
- zz: Mode[3]
- els: Mode[4]
- dz: Mode[3]
- sz: Mode[3]
-
- class spu(Mode):
- """Structured Pack/Unpack"""
- zz: Mode[3]
- els: Mode[4]
- dz: Mode[3]
- sz: Mode[3]
-
- class ffrc1(Mode):
- """Rc=1: ffirst CR sel"""
- inv: Mode[2]
- CRbit: Mode[3, 4]
-
- class ffrc0(Mode):
- """Rc=0: ffirst z/nonz"""
- inv: Mode[2]
- els: Mode[3]
- RC1: Mode[4]
-
- class sat(Mode):
- """sat mode: N=0/1 u/s"""
- N: Mode[2]
- zz: Mode[3]
- els: Mode[4]
- dz: Mode[3]
- sz: Mode[3]
-
- class prrc1(Mode):
- """Rc=1: pred-result CR sel"""
- inv: Mode[2]
- CRbit: Mode[3, 4]
-
- class prrc0(Mode):
- """Rc=0: pred-result z/nonz"""
- inv: Mode[2]
- els: Mode[3]
- RC1: Mode[4]
-
- simple: simple
- spu: spu
- ffrc1: ffrc1
- ffrc0: ffrc0
- sat: sat
- prrc1: prrc1
- prrc0: prrc0
-
-
-class LDSTIdxMode(Mode):
- class simple(Mode):
- """simple mode"""
- SEA: Mode[2]
- sz: Mode[3]
- dz: Mode[3]
-
- class stride(Mode):
- """strided (scalar only source)"""
- SEA: Mode[2]
- dz: Mode[3]
- sz: Mode[4]
-
- class sat(Mode):
- """sat mode: N=0/1 u/s"""
- N: Mode[2]
- dz: Mode[3]
- sz: Mode[4]
-
- class prrc1(Mode):
- """Rc=1: pred-result CR sel"""
- inv: Mode[2]
- CRbit: Mode[3, 4]
-
- class prrc0(Mode):
- """Rc=0: pred-result z/nonz"""
- inv: Mode[2]
- zz: Mode[3]
- RC1: Mode[4]
- dz: Mode[3]
- sz: Mode[3]
-
- simple: simple
- stride: stride
- sat: sat
- prrc1: prrc1
- prrc0: prrc0
class Extra(_Mapping):
self[key].assign(value)
-class RM(_Mapping):
- class Mode(Mode):
- normal: NormalMode
- ldst_imm: LDSTImmMode
- ldst_idx: LDSTIdxMode
-
+class BaseRM(_Mapping):
_: _Field = range(24)
mmode: _Field = (0,)
mask: _Field = range(1, 4)
extra2: Extra2.remap(range(10, 19))
extra3: Extra3.remap(range(10, 19))
+ def disassemble(self, verbosity=Verbosity.NORMAL):
+ if verbosity >= Verbosity.VERBOSE:
+ indent = (" " * 4)
+ for (name, value, members) in self.traverse(path="RM"):
+ yield f"{name}"
+ yield f"{indent}{int(value):0{value.bits}b}"
+ yield f"{indent}{', '.join(map(str, members))}"
-class SVP64Instruction(PrefixedInstruction):
- """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
- class Prefix(PrefixedInstruction.Prefix):
- id: _Field = (7, 9)
- rm: RM.remap((6, 8) + tuple(range(10, 32)))
- prefix: Prefix
+class NormalRM(BaseRM):
+ class simple(BaseRM):
+ """normal: simple mode"""
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[4]
- @property
- def binary(self):
- bits = []
- for idx in range(64):
- bit = int(self[idx])
- bits.append(bit)
- return "".join(map(str, bits))
+ class smr(BaseRM):
+ """normal: scalar reduce mode (mapreduce), SUBVL=1"""
+ RG: BaseRM.mode[4]
- def opcode(self, db):
- return self.suffix.opcode(db=db)
+ class pmr(BaseRM):
+ """normal: parallel reduce mode (mapreduce), SUBVL=1"""
+ pass
- def mask(self, db):
- return self.suffix.mask(db=db)
+ class svmr(BaseRM):
+ """normal: subvector reduce mode, SUBVL>1"""
+ SVM: BaseRM.mode[3]
+
+ class pu(BaseRM):
+ """normal: Pack/Unpack mode, SUBVL>1"""
+ SVM: BaseRM.mode[3]
+
+ class ffrc1(BaseRM):
+ """normal: Rc=1: ffirst CR sel"""
+ inv: BaseRM.mode[2]
+ CR: BaseRM.mode[3, 4]
+
+ class ffrc0(BaseRM):
+ """normal: Rc=0: ffirst z/nonz"""
+ inv: BaseRM.mode[2]
+ VLi: BaseRM.mode[3]
+ RC1: BaseRM.mode[4]
+
+ class sat(BaseRM):
+ """normal: sat mode: N=0/1 u/s, SUBVL=1"""
+ N: BaseRM.mode[2]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[4]
+
+ class satx(BaseRM):
+ """normal: sat mode: N=0/1 u/s, SUBVL>1"""
+ N: BaseRM.mode[2]
+ zz: BaseRM.mode[3]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[3]
+
+ class satpu(BaseRM):
+ """normal: Pack/Unpack sat mode: N=0/1 u/s, SUBVL>1"""
+ N: BaseRM.mode[2]
+ zz: BaseRM.mode[3]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[3]
+
+ class prrc1(BaseRM):
+ """normal: Rc=1: pred-result CR sel"""
+ inv: BaseRM.mode[2]
+ CR: BaseRM.mode[3, 4]
+
+ class prrc0(BaseRM):
+ """normal: Rc=0: pred-result z/nonz"""
+ inv: BaseRM.mode[2]
+ zz: BaseRM.mode[3]
+ RC1: BaseRM.mode[4]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[3]
- def mode(self, db):
- record = self.record(db=db)
+ simple: simple
+ smr: smr
+ pmr: pmr
+ svmr: svmr
+ pu: pu
+ ffrc1: ffrc1
+ ffrc0: ffrc0
+ sat: sat
+ satx: satx
+ satpu: satpu
+ prrc1: prrc1
+ prrc0: prrc0
- 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
+class LDSTImmRM(BaseRM):
+ class simple(BaseRM):
+ """ld/st immediate: simple mode"""
+ zz: BaseRM.mode[3]
+ els: BaseRM.mode[4]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[3]
+
+ class spu(BaseRM):
+ """ld/st immediate: Structured Pack/Unpack"""
+ zz: BaseRM.mode[3]
+ els: BaseRM.mode[4]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[3]
+
+ class ffrc1(BaseRM):
+ """ld/st immediate: Rc=1: ffirst CR sel"""
+ inv: BaseRM.mode[2]
+ CR: BaseRM.mode[3, 4]
+
+ class ffrc0(BaseRM):
+ """ld/st immediate: Rc=0: ffirst z/nonz"""
+ inv: BaseRM.mode[2]
+ els: BaseRM.mode[3]
+ RC1: BaseRM.mode[4]
+
+ class sat(BaseRM):
+ """ld/st immediate: sat mode: N=0/1 u/s"""
+ N: BaseRM.mode[2]
+ zz: BaseRM.mode[3]
+ els: BaseRM.mode[4]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[3]
+
+ class prrc1(BaseRM):
+ """ld/st immediate: Rc=1: pred-result CR sel"""
+ inv: BaseRM.mode[2]
+ CR: BaseRM.mode[3, 4]
+
+ class prrc0(BaseRM):
+ """ld/st immediate: Rc=0: pred-result z/nonz"""
+ inv: BaseRM.mode[2]
+ els: BaseRM.mode[3]
+ RC1: BaseRM.mode[4]
+
+ simple: simple
+ spu: spu
+ ffrc1: ffrc1
+ ffrc0: ffrc0
+ sat: sat
+ prrc1: prrc1
+ prrc0: prrc0
+
+
+class LDSTIdxRM(BaseRM):
+ class simple(BaseRM):
+ """ld/st index: simple mode"""
+ SEA: BaseRM.mode[2]
+ sz: BaseRM.mode[3]
+ dz: BaseRM.mode[3]
+
+ class stride(BaseRM):
+ """ld/st index: strided (scalar only source)"""
+ SEA: BaseRM.mode[2]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[4]
+
+ class sat(BaseRM):
+ """ld/st index: sat mode: N=0/1 u/s"""
+ N: BaseRM.mode[2]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[4]
+
+ class prrc1(BaseRM):
+ """ld/st index: Rc=1: pred-result CR sel"""
+ inv: BaseRM.mode[2]
+ CR: BaseRM.mode[3, 4]
+
+ class prrc0(BaseRM):
+ """ld/st index: Rc=0: pred-result z/nonz"""
+ inv: BaseRM.mode[2]
+ zz: BaseRM.mode[3]
+ RC1: BaseRM.mode[4]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[3]
+
+ simple: simple
+ stride: stride
+ sat: sat
+ prrc1: prrc1
+ prrc0: prrc0
+
+
+class CROpRM(BaseRM):
+ class simple(BaseRM):
+ """cr_op: simple mode"""
+ sz: BaseRM[6]
+ SNZ: BaseRM[7]
+ RG: BaseRM[20]
+ dz: BaseRM[22]
+
+ class smr(BaseRM):
+ """cr_op: scalar reduce mode (mapreduce), SUBVL=1"""
+ sz: BaseRM[6]
+ SNZ: BaseRM[7]
+ RG: BaseRM[20]
+
+ class svmr(BaseRM):
+ """cr_op: subvector reduce mode, SUBVL>1"""
+ zz: BaseRM[6]
+ SNZ: BaseRM[7]
+ RG: BaseRM[20]
+ SVM: BaseRM[22]
+ dz: BaseRM[6]
+ sz: BaseRM[6]
+
+ class reserved(BaseRM):
+ """cr_op: reserved"""
+ zz: BaseRM[6]
+ SNZ: BaseRM[7]
+ RG: BaseRM[20]
+ dz: BaseRM[6]
+ sz: BaseRM[6]
+
+ class ff3(BaseRM):
+ """cr_op: ffirst 3-bit mode"""
+ zz: BaseRM[6]
+ SNZ: BaseRM[7]
+ VLI: BaseRM[20]
+ inv: BaseRM[21]
+ CR: BaseRM[22, 23]
+ dz: BaseRM[6]
+ sz: BaseRM[6]
+
+ class ff5(BaseRM):
+ """cr_op: ffirst 5-bit mode"""
+ zz: BaseRM[6]
+ SNZ: BaseRM[7]
+ VLI: BaseRM[20]
+ inv: BaseRM[21]
+ dz: BaseRM[22]
+ dz: BaseRM[6]
+ sz: BaseRM[6]
+
+ simple: simple
+ smr: smr
+ svmr: svmr
+ reserved: reserved
+ ff3: ff3
+ ff5: ff5
+
+
+class BranchBaseRM(BaseRM):
+ ALL: BaseRM[4]
+ SNZ: BaseRM[5]
+ SL: BaseRM[17]
+ SLu: BaseRM[18]
+ LRu: BaseRM[22]
+ sz: BaseRM[23]
+
+
+class BranchRM(BranchBaseRM):
+ class simple(BranchBaseRM):
+ """branch: simple mode"""
+ pass
+
+ class vls(BranchBaseRM):
+ """branch: VLSET mode"""
+ VSb: BaseRM[7]
+ VLI: BaseRM[21]
+
+ class ctr(BranchBaseRM):
+ """branch: CTR-test mode"""
+ CTi: BaseRM[6]
+
+ class ctrvls(vls, ctr):
+ """branch: CTR-test+VLSET mode"""
+ pass
+
+
+class RM(BaseRM):
+ normal: NormalRM
+ ldst_imm: LDSTImmRM
+ ldst_idx: LDSTIdxRM
+ cr_op: CROpRM
+
+ def select(self, record, Rc):
+ rm = self
if record.svp64.mode is _SVMode.NORMAL:
- mode = mode.normal
- if sel == 0b00:
- if mode[2] == 0b0:
- mode = mode.simple
+ rm = rm.normal
+ if rm.mode[0:2] == 0b00:
+ if rm.mode[2] == 0b0:
+ rm = rm.simple
else:
- if subvl == 0b00:
- if mode[3] == 0b0:
- mode = mode.smr
+ if self.subvl == 0b00:
+ if rm.mode[3] == 0b0:
+ rm = rm.smr
else:
- mode = mode.pmr
+ rm = rm.pmr
else:
- if mode[4] == 0b0:
- mode = mode.svmr
+ if rm.mode[4] == 0b0:
+ rm = rm.svmr
else:
- mode = mode.pu
- elif sel == 0b01:
+ rm = rm.pu
+ elif rm.mode[0:2] == 0b01:
if Rc:
- mode = mode.ffrc1
+ rm = rm.ffrc1
else:
- mode = mode.ffrc0
- elif sel == 0b10:
- if subvl == 0b00:
- mode = mode.sat
+ rm = rm.ffrc0
+ elif rm.mode[0:2] == 0b10:
+ if self.subvl == 0b00:
+ rm = rm.sat
else:
- if mode[4]:
- mode = mode.satx
+ if rm.mode[4]:
+ rm = rm.satx
else:
- mode = mode.satpu
- elif sel == 0b11:
+ rm = rm.satpu
+ elif rm.mode[0:2] == 0b11:
if Rc:
- mode = mode.prrc1
+ rm = rm.prrc1
else:
- mode = mode.prrc0
+ rm = rm.prrc0
+
elif record.svp64.mode is _SVMode.LDST_IMM:
- mode = mode.ldst_imm
- if sel == 0b00:
- if mode[2] == 0b0:
- mode = mode.simple
+ rm = rm.ldst_imm
+ if rm.mode[0:2] == 0b00:
+ if rm.mode[2] == 0b0:
+ rm = rm.simple
else:
- mode = mode.spu
- elif sel == 0b01:
+ rm = rm.spu
+ elif rm.mode[0:2] == 0b01:
if Rc:
- mode = mode.ffrc1
+ rm = rm.ffrc1
else:
- mode = mode.ffrc0
- elif sel == 0b10:
- mode = mode.sat
- elif sel == 0b11:
+ rm = rm.ffrc0
+ elif rm.mode[0:2] == 0b10:
+ rm = rm.sat
+ elif rm.mode[0:2] == 0b11:
if Rc:
- mode = mode.prrc1
+ rm = rm.prrc1
else:
- mode = mode.prrc0
+ rm = rm.prrc0
+
elif record.svp64.mode is _SVMode.LDST_IMM:
- mode = mode.ldst_idx
- if mode.sel == 0b00:
- mode = mode.simple
- elif mode.sel == 0b01:
- mode = mode.stride
- elif mode.sel == 0b10:
- mode = mode.sat
- elif mode.sel == 0b11:
+ rm = rm.ldst_idx
+ if rm.mode[0:2] == 0b00:
+ rm = rm.simple
+ elif rm.mode[0:2] == 0b01:
+ rm = rm.stride
+ elif rm.mode[0:2] == 0b10:
+ rm = rm.sat
+ elif rm.mode[0:2] == 0b11:
if Rc:
- mode = mode.prrc1
+ rm = rm.prrc1
else:
- mode = mode.prrc0
-
- 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)
+ rm = rm.prrc0
+
+ elif record.svp64.mode is _SVMode.CROP:
+ rm = rm.cr_op
+ if rm[19] == 0b0:
+ if rm[21] == 0b0:
+ rm = rm.simple
+ else:
+ if self.subvl == 0:
+ rm = rm.smr
+ else:
+ if rm[23] == 0b0:
+ rm = rm.svmr
+ else:
+ rm = rm.reserved
+ else:
+ regtype = None
+ for idx in range(0, 4):
+ for entry in record.svp64.extra[idx]:
+ if entry.regtype is _SVExtraRegType.DST:
+ if regtype is not None:
+ raise ValueError(record.svp64)
+ regtype = _RegType(entry.reg)
+ if regtype is _RegType.CR_REG:
+ rm = rm.ff5
+ elif regtype is _RegType.CR_BIT:
+ rm = rm.ff3
+ else:
+ raise ValueError(record.svp64)
- if record.svp64.mode is _SVMode.BRANCH:
- return (self.prefix.rm.mode, "branch")
+ elif record.svp64.mode is _SVMode.BRANCH:
+ if rm[19] == 0b0:
+ if rm[20] == 0b0:
+ rm = rm.simple
+ else:
+ rm = rm.vls
+ else:
+ if rm[20] == 0b0:
+ rm = rm.ctr
+ else:
+ rm = rm.ctrvls
+
+ if rm.__class__ is self.__class__:
+ raise ValueError(self)
+
+ return rm
+
+
+class SVP64Instruction(PrefixedInstruction):
+ """SVP64 instruction: https://libre-soc.org/openpower/sv/svp64/"""
+ class Prefix(PrefixedInstruction.Prefix):
+ id: _Field = (7, 9)
+ rm: RM.remap((6, 8) + tuple(range(10, 32)))
+
+ prefix: Prefix
+
+ def record(self, db):
+ record = db[self.suffix]
+ if record is None:
+ raise KeyError(self)
+ return record
- raise ValueError(self)
+ @property
+ def binary(self):
+ bits = []
+ for idx in range(64):
+ bit = int(self[idx])
+ bits.append(bit)
+ return "".join(map(str, bits))
def disassemble(self, db,
byteorder="little",
blob = " ".join(map(lambda byte: f"{byte:02x}", blob))
return f"{blob} "
+ record = self.record(db=db)
blob_prefix = blob(int(self.prefix))
blob_suffix = blob(int(self.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}"
yield f"{blob_prefix}sv.{record.name} {','.join(operands)}"
else:
yield f"{blob_prefix}{record.name}"
- yield f"{blob_suffix}"
+ if blob_suffix:
+ yield f"{blob_suffix}"
- (mode, mode_desc) = self.mode(db=db)
+ Rc = False
+ if record.mdwn.operands["Rc"] is not None:
+ Rc = bool(self.suffix[record.fields["Rc"]])
+ rm = self.prefix.rm.select(record=record, Rc=Rc)
if verbosity >= Verbosity.VERBOSE:
indent = (" " * 4)
binary = self.binary
spec = self.spec(db=db, prefix="sv.")
- opcode = self.opcode(db=db)
- mask = self.mask(db=db)
+
yield f"{indent}spec"
yield f"{indent}{indent}{spec}"
+ yield f"{indent}pcode"
+ for stmt in record.mdwn.pcode:
+ yield f"{indent}{indent}{stmt}"
yield f"{indent}binary"
yield f"{indent}{indent}[0:8] {binary[0:8]}"
yield f"{indent}{indent}[8:16] {binary[8:16]}"
yield f"{indent}{indent}[40:48] {binary[40:48]}"
yield f"{indent}{indent}[48:56] {binary[48:56]}"
yield f"{indent}{indent}[56:64] {binary[56:64]}"
- yield f"{indent}opcode"
- yield f"{indent}{indent}{opcode}"
- yield f"{indent}mask"
- yield f"{indent}{indent}{mask}"
- for operand in record.operands:
+ yield f"{indent}opcodes"
+ for opcode in record.opcodes:
+ yield f"{indent}{indent}{opcode!r}"
+ for operand in record.mdwn.operands:
yield from operand.disassemble(insn=self, record=record,
verbosity=verbosity, indent=indent)
-
- yield f"{indent}mode"
- yield f"{indent}{indent}{mode_desc}"
+ yield f"{indent}RM"
+ yield f"{indent}{indent}{rm.__doc__}"
+ for line in rm.disassemble(verbosity=verbosity):
+ yield f"{indent}{indent}{line}"
yield ""
(dynamic, *static) = desc.regs
operands.extend(dynamic)
operands.extend(static)
- db[name] = Operands(insn=name, iterable=operands)
+ pcode = PCode(iterable=desc.pcode)
+ operands = Operands(insn=name, iterable=operands)
+ db[name] = MarkdownRecord(pcode=pcode, operands=operands)
+
self.__db = db
+
return super().__init__()
def __iter__(self):
yield from self.__db.items()
+ def __contains__(self, key):
+ return self.__db.__contains__(key)
+
def __getitem__(self, key):
return self.__db.__getitem__(key)
for insn in parse(stream, factory):
records[section][insn.comment].add(insn)
- db = dd(set)
+ sections = dd(set)
for (section, group) in records.items():
for records in group.values():
- db[section].add(PPCMultiRecord(records))
+ sections[section].add(PPCMultiRecord(records))
+
+ db = {}
+ for (section, records) in sections.items():
+ for record in records:
+ def exact_match(names):
+ for name in names:
+ if name in mdwndb:
+ yield name
+
+ def Rc_match(names):
+ for name in names:
+ if f"{name}." in mdwndb:
+ yield f"{name}."
+ yield name
+
+ def LK_match(names):
+ if "lk" not in record.flags:
+ yield from names
+ return
+
+ for name in names:
+ if f"{name}l" in mdwndb:
+ yield f"{name}l"
+ yield name
+
+ def AA_match(names):
+ if record.intop not in {_MicrOp.OP_B, _MicrOp.OP_BC}:
+ yield from names
+ return
+
+ for name in names:
+ operands = mdwndb[name].operands["AA"]
+ if ((operands is not None) and
+ (f"{name}a" in mdwndb)):
+ yield f"{name}a"
+ yield name
+
+ def reductor(names, match):
+ return match(names)
+
+ matches = (exact_match, Rc_match, LK_match, AA_match)
+
+ names = _functools.reduce(reductor, matches, record.names)
+ for name in names:
+ db[name] = (section, record)
self.__db = db
self.__mdwndb = mdwndb
return super().__init__()
+ @_functools.lru_cache(maxsize=512, typed=False)
def __getitem__(self, key):
- def exact_match(key, record):
- for name in record.names:
- if name == key:
- return True
-
- return False
-
- def Rc_match(key, record):
- if not key.endswith("."):
- return False
-
- if not record.Rc is _RCOE.RC:
- return False
-
- return exact_match(key[:-1], record)
-
- def LK_match(key, record):
- if not key.endswith("l"):
- return False
-
- if "lk" not in record.flags:
- return False
-
- return exact_match(key[:-1], record)
-
- def AA_match(key, record):
- if not key.endswith("a"):
- return False
-
- if record.intop not in {_MicrOp.OP_B, _MicrOp.OP_BC}:
- return False
-
- if self.__mdwndb[key]["AA"] is None:
- return False
-
- return (exact_match(key[:-1], record) or
- LK_match(key[:-1], record))
-
- for (section, records) in self.__db.items():
- for record in records:
- 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)
-
- return (None, None)
+ return self.__db.get(key, (None, None))
class SVP64Database:
class Database:
def __init__(self, root):
root = _pathlib.Path(root)
-
mdwndb = MarkdownDatabase()
fieldsdb = FieldsDatabase()
ppcdb = PPCDatabase(root=root, mdwndb=mdwndb)
svp64db = SVP64Database(root=root, ppcdb=ppcdb)
db = set()
- for (name, operands) in mdwndb:
+ names = {}
+ opcodes = _collections.defaultdict(set)
+
+ for (name, mdwn) in mdwndb:
(section, ppc) = ppcdb[name]
if ppc is None:
continue
fields = fieldsdb[ppc.form]
record = Record(name=name,
section=section, ppc=ppc, svp64=svp64,
- operands=operands, fields=fields)
+ mdwn=mdwn, fields=fields)
db.add(record)
+ names[record.name] = record
+ PO = section.opcode
+ if PO is None:
+ PO = ppc[0].opcode
+ opcodes[PO.value].add(record)
- self.__db = tuple(sorted(db))
+ self.__db = db
+ self.__names = names
+ self.__opcodes = opcodes
return super().__init__()
def __getitem__(self, key):
if isinstance(key, (int, Instruction)):
key = int(key)
- for record in self:
- opcode = record.opcode
- if ((opcode.value & opcode.mask) ==
- (key & opcode.mask)):
- return record
- return None
- elif isinstance(key, Opcode):
- for record in self:
- if record.opcode == key:
- return record
+ XO = int(_SelectableInt(value=int(key), bits=32)[0:6])
+ for record in self.__opcodes[XO]:
+ if record.match(key=key):
+ return record
+
elif isinstance(key, str):
- for record in self:
- if record.name == key:
- return record
+ return self.__names[key]
+
return None