In3Sel as _In3Sel,
OutSel as _OutSel,
CRInSel as _CRInSel,
+ CRIn2Sel as _CRIn2Sel,
CROutSel as _CROutSel,
LDSTLen as _LDSTLen,
LDSTMode as _LDSTMode,
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
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, "")):
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)
yield str(int(value))
+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)
class StaticOperand(Operand):
value: int
class RegisterOperand(DynamicOperand):
- def spec(self, insn, record, merge):
+ 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 = self.span(record=record)
if isinstance(insn, SVP64Instruction):
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)
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)
+
+ 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)
yield f"{vector}{prefix}{int(value)}"
-class GPRFPROperand(RegisterOperand):
- 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)
- # this is silly these should be in a general base class,
- # settable by constructor
- vshift = 2
- sshift = 5
- spshft = 0
- if vector:
- value = ((value << vshift) | (spec<<spshft))
- span = (span + spec_span)
- else:
- value = ((spec << sshift) | value)
- span = (spec_span + span)
-
- return (value, span)
-
- return super().spec(insn=insn, record=record, merge=merge)
-
-
-class GPROperand(GPRFPROperand):
+class GPROperand(RegisterOperand):
def disassemble(self, insn, record,
verbosity=Verbosity.NORMAL, indent=""):
prefix = "" if (verbosity <= Verbosity.SHORT) else "r"
verbosity=verbosity, indent=indent)
-class FPROperand(GPRFPROperand):
+class FPROperand(RegisterOperand):
def disassemble(self, insn, record,
verbosity=Verbosity.NORMAL, indent=""):
prefix = "" if (verbosity <= Verbosity.SHORT) else "f"
class CR3Operand(RegisterOperand):
- def spec(self, insn, record):
- def merge(vector, value, span, spec, spec_span):
- bits = (len(span) + len(spec_span))
- #print ("value", bin(value.value), value.bits)
- value = _SelectableInt(value=value.value, bits=bits)
- spec = _SelectableInt(value=spec.value, bits=bits)
- #print ("spec", bin(spec.value), spec.bits)
- #print ("value", bin(value.value), value.bits)
- #print ("lsbs", bin(lsbs.value), lsbs.bits)
- # this is silly these should be in a general base class,
- # settable by constructor
- vshift = 4
- sshift = 3
- spshft = 2
- lsbshf = 0
- if vector:
- value = ((value << vshift) | (spec<<spshft))
- span = (span[0:3] + spec_span + ('{0}', '{0}') + span[3:5])
- else:
- value = ((spec << sshift) | value)
- span = (('{0}', '{0}') + spec_span + span)
-
- # add the 2 LSBs back in
- #print ("after", bin(value.value), value.bits)
- return (value, span)
-
- return super().spec(insn=insn, record=record, merge=merge)
+ pass
-# exactly the same as CR3Operand, should be exactly the same base class
-# which should also be exactly the same base class as GPR and FPR operand
-# which sohuld be taking a constructor with prefix "r" and "f" as options
-# as well as vshift, sshift and spsft as parameters, and whether
-# to skip 2 LSBs and put them back on afterwards.
-# it's all the exact same scheme, so why on earth duplicate code?
class CR5Operand(RegisterOperand):
- def spec(self, insn, record):
- def merge(vector, value, span, spec, spec_span):
- # this is silly these should be in a general base class,
- # settable by constructor
- sshift = 3 # len(value) aka value.bits
- vshift = 4 # 7-sshift
- spshft = 2 # 5-sshift
- lsbshf = 0 # has to be set as a parameter
- lsbmsk = (1<<lsbshf)-1
- # record the 2 lsbs first
- lsbs = _SelectableInt(value=value.value&(lsbmsk), bits=lsbshf)
- bits = (len(span) + len(spec_span))
- #print ("value", bin(value.value), value.bits)
- value = _SelectableInt(value=value.value>>lsbshf, bits=bits)
- spec = _SelectableInt(value=spec.value, bits=bits)
- #print ("spec", bin(spec.value), spec.bits)
- #print ("value", bin(value.value), value.bits)
- #print ("lsbs", bin(lsbs.value), lsbs.bits)
- if vector:
- value = ((value << vshift) | (spec<<spshft))
- span = (span[0:3] + spec_span + spshft*('{0}',) + span[3:5])
- else:
- value = ((spec << sshift) | value)
- span = (spshft*('{0}',) + spec_span + span)
-
- # add the 2 LSBs back in
- v = (value.value<<lsbshf)+lsbs.value
- res = _SelectableInt(value=v, bits=bits+lsbshf)
- #print ("after", bin(value.value), value.bits)
- #print ("res", bin(res.value), res.bits)
- return (res, span)
-
- return super().spec(insn=insn, record=record, merge=merge)
-
-
-# this is silly, all of these should be the same base class
-class DynamicOperandCR(RegisterOperand):
- 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:
- dst_value = []
- dst_span = []
- table = (
- (value, span, (0, 1, 2)),
- (spec, spec_span, (0, 1)),
- (value, span, (3, 4)),
- )
- else:
- dst_value = [
- _SelectableInt(value=0, bits=1),
- _SelectableInt(value=0, bits=1),
- ]
- dst_span = ["{0}", "{0}"]
- table = (
- (spec, spec_span, (0, 1)),
- (value, span, (0, 1, 2, 3, 4)),
- )
+ def sv_spec_enter(self, value, span):
+ value = _SelectableInt(value=(value.value >> 2), bits=3)
+ return (value, span)
- for (src_value, src_span, sel) in table:
- for idx in sel:
- dst_value.append(src_value[idx])
- dst_span.append(src_span[idx])
-
- value = _selectconcat(dst_value)
- span = tuple(dst_span)
-
- return (value, span)
-
- return super().spec(insn=insn, record=record, merge=merge)
-
- def disassemble(self, insn, record, verbose=False, indent=""):
- yield from super().disassemble(prefix="cr",
- insn=insn, record=record, verbose=verbose, indent=indent)
+ 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):
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())
class TargetAddrOperandLI(TargetAddrOperand):
verbosity=verbosity, indent=indent)
-class DOperandDX(DynamicOperand):
+class DOperandDX(SignedOperand):
def span(self, record):
operands = map(DynamicOperand, ("d0", "d1", "d2"))
spans = map(lambda operand: operand.span(record=record), operands)
yield f"{indent}{indent}{indent}{int(value):0{value.bits}b}"
yield f"{indent}{indent}{indent}{', '.join(span)}"
else:
- yield str(int(value))
+ yield str(value.to_signed_int())
class Operands(tuple):
"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 custom_insns and operand in custom_insns[insn]:
- dynamic_cls = custom_insns[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]
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:
(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]
- def record(self, db):
- record = db[self.suffix]
- if record is None:
- raise KeyError(self)
- return record
+ class smr(BaseRM):
+ """normal: scalar reduce mode (mapreduce), SUBVL=1"""
+ RG: 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 pmr(BaseRM):
+ """normal: parallel reduce mode (mapreduce), SUBVL=1"""
+ pass
- def mode(self, db):
- record = self.record(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]
- Rc = False
- if record.mdwn.operands["Rc"] is not None:
- Rc = bool(self[record.fields["Rc"]])
+ simple: simple
+ smr: smr
+ pmr: pmr
+ svmr: svmr
+ pu: pu
+ ffrc1: ffrc1
+ ffrc0: ffrc0
+ sat: sat
+ satx: satx
+ satpu: satpu
+ prrc1: prrc1
+ prrc0: prrc0
- 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
- if record.svp64.mode is _SVMode.BRANCH:
- return (self.prefix.rm.mode, "branch")
+ 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)
- raise ValueError(self)
+ 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
+
+ @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 = db[self]
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}"
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.")
+
yield f"{indent}spec"
yield f"{indent}{indent}{spec}"
yield f"{indent}pcode"
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 ""
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].operands["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()
+ names = {}
+ opcodes = _collections.defaultdict(set)
+
for (name, mdwn) in mdwndb:
(section, ppc) = ppcdb[name]
if ppc is None:
section=section, ppc=ppc, svp64=svp64,
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:
+ 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, Opcode):
- for record in self:
- if record.opcode == key:
- return record
-
elif isinstance(key, str):
- for record in self:
- if record.name == key:
- return record
+ return self.__names[key]
return None