CryIn as _CryIn,
Form as _Form,
SVEtype as _SVEtype,
+ SVmask_src as _SVmask_src,
SVMode as _SVMode,
SVPtype as _SVPtype,
SVExtra as _SVExtra,
name: str
ptype: _SVPtype = _SVPtype.NONE
etype: _SVEtype = _SVEtype.NONE
+ msrc: _SVmask_src = _SVmask_src.NO # MASK_SRC is active
in1: _In1Sel = _In1Sel.NONE
in2: _In2Sel = _In2Sel.NONE
in3: _In3Sel = _In3Sel.NONE
"CONDITIONS": "conditions",
"Ptype": "ptype",
"Etype": "etype",
+ "SM": "msrc",
"CR in": "cr_in",
"CR out": "cr_out",
}
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
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 __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 RMBase(_Mapping):
+class BaseRM(_Mapping):
_: _Field = range(24)
mmode: _Field = (0,)
mask: _Field = range(1, 4)
subvl: _Field = range(8, 10)
mode: Mode.remap(range(19, 24))
smask: _Field = range(16, 19)
-
extra: Extra.remap(range(10, 19))
extra2: Extra2.remap(range(10, 19))
extra3: Extra3.remap(range(10, 19))
+ def specifiers(self, record):
+ subvl = int(self.subvl)
+ if subvl > 0:
+ yield {
+ 1: "vec2",
+ 2: "vec3",
+ 3: "vec4",
+ }[subvl]
+
+ 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))}"
+
+
+# ********************
+# Normal mode
+# https://libre-soc.org/openpower/sv/normal/
+
+class NormalLDSTBaseRM(BaseRM):
+ def specifiers(self, record):
+ widths = {
+ 0b11: "8",
+ 0b10: "16",
+ 0b01: "32",
+ }
+ predicates = {
+ # integer
+ (0, 0b001): "1<<r3",
+ (0, 0b010): "r3",
+ (0, 0b011): "~r3",
+ (0, 0b100): "r10",
+ (0, 0b101): "~r10",
+ (0, 0b110): "r30",
+ (0, 0b111): "~r30",
+ # CRs
+ (1, 0b000): "lt",
+ (1, 0b001): "ge",
+ (1, 0b010): "gt",
+ (1, 0b011): "le",
+ (1, 0b100): "eq",
+ (1, 0b101): "ne",
+ (1, 0b110): "so",
+ (1, 0b111): "ns",
+ }
+
+ mmode = int(self.mmode)
+ mask = int(self.mask)
+ if record.svp64.ptype is _SVPtype.P2:
+ (smask, dmask) = (int(self.smask), mask)
+ else:
+ (smask, dmask) = (mask, mask)
+ if all((smask, dmask)) and (smask == dmask):
+ yield f"m={predicates[(mmode, smask)]}"
+ else:
+ sw = predicates.get((mmode, smask))
+ dw = predicates.get((mmode, dmask))
+ if sw:
+ yield f"sm={sw}"
+ if dw:
+ yield f"dm={dw}"
+
+ dw = int(self.elwidth)
+ sw = int(self.ewsrc)
+ if all((dw, sw)) and (dw == sw):
+ yield f"w={widths[dw]}"
+ else:
+ if dw != 0b00:
+ yield f"dw={widths[dw]}"
+ if sw != 0b00:
+ yield f"sw={widths[sw]}"
+
+ yield from super().specifiers(record=record)
+
+
+class NormalBaseRM(NormalLDSTBaseRM):
+ pass
+
+
+class NormalSimpleRM(NormalBaseRM):
+ """normal: simple mode"""
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[4]
+
+ def specifiers(self, record):
+ if self.dz:
+ yield f"dz"
+ if self.sz:
+ yield f"sz"
+ yield from super().specifiers(record=record)
+
+
+class NormalScalarReduceRM(NormalBaseRM):
+ """normal: scalar reduce mode (mapreduce), SUBVL=1"""
+ RG: BaseRM.mode[4]
+
+ def specifiers(self, record):
+ if self.RG:
+ yield "mrr"
+
+ yield from super().specifiers(record=record)
+
+
+class NormalReservedRM(NormalBaseRM):
+ """normal: reserved"""
+ pass
+
+
+class NormalFailFirstRc1RM(NormalBaseRM):
+ """normal: Rc=1: ffirst CR sel"""
+ inv: BaseRM.mode[2]
+ CR: BaseRM.mode[3, 4]
+
+
+class NormalFailFirstRc0RM(NormalBaseRM):
+ """normal: Rc=0: ffirst z/nonz"""
+ inv: BaseRM.mode[2]
+ VLi: BaseRM.mode[3]
+ RC1: BaseRM.mode[4]
+
+ def specifiers(self, record):
+ if self.RC1:
+ inv = "~" if self.inv else ""
+ yield f"ff={inv}RC1"
+
+ yield from super().specifiers(record=record)
+
+
+class NormalSaturationRM(NormalBaseRM):
+ """normal: sat mode: N=0/1 u/s, SUBVL=1"""
+ N: BaseRM.mode[2]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[4]
+
+ def specifiers(self, record):
+ if self.dz:
+ yield f"dz"
+ if self.sz:
+ yield f"sz"
+ if self.N:
+ yield "sats"
+ else:
+ yield "satu"
+
+ yield from super().specifiers(record=record)
+
+
+class NormalPredResultRc1RM(NormalBaseRM):
+ """normal: Rc=1: pred-result CR sel"""
+ inv: BaseRM.mode[2]
+ CR: BaseRM.mode[3, 4]
+
+
+class NormalPredResultRc0RM(NormalBaseRM):
+ """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 specifiers(self, record):
+ if self.zz:
+ yield f"zz"
+ if self.RC1:
+ inv = "~" if self.inv else ""
+ yield f"pr={inv}RC1"
+
+ yield from super().specifiers(record=record)
+
+
+class NormalRM(NormalBaseRM):
+ simple: NormalSimpleRM
+ smr: NormalScalarReduceRM
+ reserved: NormalReservedRM
+ ffrc1: NormalFailFirstRc1RM
+ ffrc0: NormalFailFirstRc0RM
+ sat: NormalSaturationRM
+ prrc1: NormalPredResultRc1RM
+ prrc0: NormalPredResultRc0RM
+
+
+# ********************
+# LD/ST Immediate mode
+# https://libre-soc.org/openpower/sv/ldst/
+
+class LDSTImmBaseRM(NormalLDSTBaseRM):
+ pass
+
+
+class LDSTImmSimpleRM(LDSTImmBaseRM):
+ """ld/st immediate: simple mode"""
+ zz: BaseRM.mode[3]
+ els: BaseRM.mode[4]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[3]
+
+ def specifiers(self, record):
+ if self.zz:
+ yield f"zz"
+
+ yield from super().specifiers(record=record)
+
+
+class LDSTImmReservedRM(LDSTImmBaseRM):
+ """ld/st immediate: reserved"""
+ pass
+
+
+class LDSTImmFailFirstRc1RM(LDSTImmBaseRM):
+ """ld/st immediate: Rc=1: ffirst CR sel"""
+ inv: BaseRM.mode[2]
+ CR: BaseRM.mode[3, 4]
+
+
+class LDSTImmFailFirstRc0RM(LDSTImmBaseRM):
+ """ld/st immediate: Rc=0: ffirst z/nonz"""
+ inv: BaseRM.mode[2]
+ els: BaseRM.mode[3]
+ RC1: BaseRM.mode[4]
+
+ def specifiers(self, record):
+ if self.RC1:
+ inv = "~" if self.inv else ""
+ yield f"ff={inv}RC1"
+
+ yield from super().specifiers(record=record)
+
+class LDSTImmSaturationRM(LDSTImmBaseRM):
+ """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]
+
+ def specifiers(self, record):
+ if self.zz:
+ yield f"zz"
+ if self.N:
+ yield "sats"
+ else:
+ yield "satu"
+
+ yield from super().specifiers(record=record)
+
+
+class LDSTImmPredResultRc1RM(LDSTImmBaseRM):
+ """ld/st immediate: Rc=1: pred-result CR sel"""
+ inv: BaseRM.mode[2]
+ CR: BaseRM.mode[3, 4]
+
+
+class LDSTImmPredResultRc0RM(LDSTImmBaseRM):
+ """ld/st immediate: Rc=0: pred-result z/nonz"""
+ inv: BaseRM.mode[2]
+ els: BaseRM.mode[3]
+ RC1: BaseRM.mode[4]
+
+ def specifiers(self, record):
+ if self.RC1:
+ inv = "~" if self.inv else ""
+ yield f"pr={inv}RC1"
+
+ yield from super().specifiers(record=record)
+
+class LDSTImmRM(LDSTImmBaseRM):
+ simple: LDSTImmSimpleRM
+ reserved: LDSTImmReservedRM
+ ffrc1: LDSTImmFailFirstRc1RM
+ ffrc0: LDSTImmFailFirstRc0RM
+ sat: LDSTImmSaturationRM
+ prrc1: LDSTImmPredResultRc1RM
+ prrc0: LDSTImmPredResultRc0RM
-class RMNormal(RMBase):
- mode: NormalMode
+# ********************
+# LD/ST Indexed mode
+# https://libre-soc.org/openpower/sv/ldst/
-class RMLDSTImm(RMBase):
- mode: LDSTImmMode
+class LDSTIdxBaseRM(NormalLDSTBaseRM):
+ pass
+
+
+class LDSTIdxSimpleRM(LDSTIdxBaseRM):
+ """ld/st index: simple mode"""
+ SEA: BaseRM.mode[2]
+ sz: BaseRM.mode[3]
+ dz: BaseRM.mode[3]
+
+ def specifiers(self, record):
+ if self.dz:
+ yield f"dz"
+ if self.sz:
+ yield f"sz"
+
+ yield from super().specifiers(record=record)
+
+
+class LDSTIdxStrideRM(LDSTIdxBaseRM):
+ """ld/st index: strided (scalar only source)"""
+ SEA: BaseRM.mode[2]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[4]
+
+ def specifiers(self, record):
+ if self.dz:
+ yield f"dz"
+ if self.sz:
+ yield f"sz"
+
+ yield from super().specifiers(record=record)
+
+
+class LDSTIdxSaturationRM(LDSTIdxBaseRM):
+ """ld/st index: sat mode: N=0/1 u/s"""
+ N: BaseRM.mode[2]
+ dz: BaseRM.mode[3]
+ sz: BaseRM.mode[4]
+
+ def specifiers(self, record):
+ if self.dz:
+ yield f"dz"
+ if self.sz:
+ yield f"sz"
+ if self.N:
+ yield "sats"
+ else:
+ yield "satu"
+ yield from super().specifiers(record=record)
-class RMLDSTIdx(RMBase):
- mode: LDSTIdxMode
+class LDSTIdxPredResultRc1RM(LDSTIdxBaseRM):
+ """ld/st index: Rc=1: pred-result CR sel"""
+ inv: BaseRM.mode[2]
+ CR: BaseRM.mode[3, 4]
-class RM(RMBase):
- normal: RMNormal
- ldst_imm: RMLDSTImm
- ldst_idx: RMLDSTIdx
+
+class LDSTIdxPredResultRc0RM(LDSTIdxBaseRM):
+ """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]
+
+ def specifiers(self, record):
+ if self.zz:
+ yield f"zz"
+ if self.RC1:
+ inv = "~" if self.inv else ""
+ yield f"pr={inv}RC1"
+
+ yield from super().specifiers(record=record)
+
+
+class LDSTIdxRM(LDSTIdxBaseRM):
+ simple: LDSTIdxSimpleRM
+ stride: LDSTIdxStrideRM
+ sat: LDSTIdxSaturationRM
+ prrc1: LDSTIdxPredResultRc1RM
+ prrc0: LDSTIdxPredResultRc0RM
+
+
+
+# ********************
+# CR ops mode
+# https://libre-soc.org/openpower/sv/cr_ops/
+
+class CROpBaseRM(BaseRM):
+ pass
+
+
+class CROpSimpleRM(CROpBaseRM):
+ """cr_op: simple mode"""
+ SNZ: BaseRM[7]
+ RG: BaseRM[20]
+ sz: BaseRM[21]
+ dz: BaseRM[22]
+
+ def specifiers(self, record):
+ if self.dz:
+ yield f"dz"
+ if self.sz:
+ yield f"sz"
+ if self.RG:
+ yield "mrr"
+
+ yield from super().specifiers(record=record)
+
+
+class CROpScalarReduceRM(CROpBaseRM):
+ """cr_op: scalar reduce mode (mapreduce), SUBVL=1"""
+ SNZ: BaseRM[7]
+ RG: BaseRM[20]
+ sz: BaseRM[21]
+ dz: BaseRM[22]
+
+ def specifiers(self, record):
+ if self.sz:
+ yield f"sz"
+ if self.RG:
+ yield "mrr"
+
+ yield from super().specifiers(record=record)
+
+
+class CROpReservedRM(CROpBaseRM):
+ """cr_op: reserved"""
+ zz: BaseRM[6]
+ SNZ: BaseRM[7]
+ RG: BaseRM[20]
+ sz: BaseRM[6]
+ dz: BaseRM[6]
+
+ def specifiers(self, record):
+ if self.zz:
+ yield f"zz"
+ if self.RG:
+ yield "mrr"
+
+ yield from super().specifiers(record=record)
+
+
+class CROpFailFirst3RM(CROpBaseRM):
+ """cr_op: ffirst 3-bit mode"""
+ SNZ: BaseRM[7]
+ VLI: BaseRM[20]
+ inv: BaseRM[21]
+ CR: BaseRM[22, 23]
+ sz: BaseRM[21]
+ dz: BaseRM[22]
+
+ def specifiers(self, record):
+ if self.zz:
+ yield f"zz"
+ yield from super().specifiers(record=record)
+
+
+class CROpFailFirst5RM(CROpBaseRM):
+ """cr_op: ffirst 5-bit mode"""
+ sz: BaseRM[6]
+ SNZ: BaseRM[7]
+ VLI: BaseRM[20]
+ inv: BaseRM[21]
+ dz: BaseRM[22]
+
+ def specifiers(self, record):
+ if self.dz:
+ yield f"dz"
+ if self.sz:
+ yield f"sz"
+ yield from super().specifiers(record=record)
+
+
+class CROpRM(CROpBaseRM):
+ simple: CROpSimpleRM
+ smr: CROpScalarReduceRM
+ reserved: CROpReservedRM
+ ff3: CROpFailFirst3RM
+ ff5: CROpFailFirst5RM
+
+
+# ********************
+# Branches mode
+# https://libre-soc.org/openpower/sv/branches/
+
+
+class BranchBaseRM(BaseRM):
+ ALL: BaseRM[4]
+ SNZ: BaseRM[5]
+ SL: BaseRM[17]
+ SLu: BaseRM[18]
+ LRu: BaseRM[22]
+ sz: BaseRM[23]
+
+
+class BranchSimpleRM(BranchBaseRM):
+ """branch: simple mode"""
+ pass
+
+
+class BranchVLSRM(BranchBaseRM):
+ """branch: VLSET mode"""
+ VSb: BaseRM[7]
+ VLI: BaseRM[21]
+
+
+class BranchCTRRM(BranchBaseRM):
+ """branch: CTR-test mode"""
+ CTi: BaseRM[6]
+
+
+class BranchCTRVLSRM(BranchVLSRM, BranchCTRRM):
+ """branch: CTR-test+VLSET mode"""
+ pass
+
+
+class BranchRM(BranchBaseRM):
+ simple: BranchSimpleRM
+ vls: BranchVLSRM
+ ctr: BranchCTRRM
+ ctrvls: BranchCTRVLSRM
+
+
+class RM(BaseRM):
+ normal: NormalRM
+ ldst_imm: LDSTImmRM
+ ldst_idx: LDSTIdxRM
+ cr_op: CROpRM
+
+ def select(self, record, Rc):
+ rm = self
+
+ # the idea behind these tables is that they are now literally
+ # in identical format to insndb.csv and minor_xx.csv and can
+ # be done precisely as that. the only thing to watch out for
+ # is the insertion of Rc=1 as a "mask/value" bit and likewise
+ # regtype detection (3-bit BF/BFA, 5-bit BA/BB/BT) also inserted
+ # as the LSB.
+ table = None
+ if record.svp64.mode is _SVMode.NORMAL:
+ # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
+ # mode Rc mask Rc member
+ table = (
+ (0b000000, 0b111000, "simple"), # simple (no Rc)
+ (0b001000, 0b111000, "smr"), # mapreduce (no Rc)
+ (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
+ (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
+ (0b100000, 0b110000, "sat"), # saturation (no Rc)
+ (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
+ (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
+ )
+ rm = rm.normal
+ search = ((int(rm.mode) << 1) | Rc)
+
+ elif record.svp64.mode is _SVMode.LDST_IMM:
+ # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
+ # mode Rc mask Rc member
+ # ironically/coincidentally this table is identical to NORMAL
+ # mode except reserved in place of smr
+ table = (
+ (0b000000, 0b111000, "simple"), # simple (no Rc)
+ (0b001000, 0b111000, "reserved"), # rsvd (no Rc)
+ (0b010000, 0b110001, "ffrc0"), # ffirst, Rc=0
+ (0b010001, 0b110001, "ffrc1"), # ffirst, Rc=1
+ (0b100000, 0b110000, "sat"), # saturation (no Rc)
+ (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
+ (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
+ )
+ rm = rm.ldst_imm
+ search = ((int(rm.mode) << 1) | Rc)
+
+ elif record.svp64.mode is _SVMode.LDST_IDX:
+ # concatenate mode 5-bit with Rc (LSB) then do a mask/map search
+ # mode Rc mask Rc member
+ table = (
+ (0b000000, 0b111000, "simple"), # simple (no Rc)
+ (0b010000, 0b110000, "stride"), # strided, (no Rc)
+ (0b100000, 0b110000, "sat"), # saturation (no Rc)
+ (0b110000, 0b110001, "prrc0"), # predicate, Rc=0
+ (0b110001, 0b110001, "prrc1"), # predicate, Rc=1
+ )
+ rm = rm.ldst_idx
+ search = ((int(rm.mode) << 1) | Rc)
+
+ elif record.svp64.mode is _SVMode.CROP:
+ # concatenate mode 5-bit with regtype (LSB) then do mask/map search
+ # mode 3b mask 3b member
+ table = (
+ (0b000000, 0b111000, "simple"), # simple
+ (0b001000, 0b111000, "smr"), # mapreduce
+ (0b100000, 0b100000, "ff5"), # failfirst, 5-bit CR
+ (0b100001, 0b100001, "ff3"), # failfirst, 3-bit CR
+ )
+ # determine CR type, 5-bit (BA/BB/BT) or 3-bit Field (BF/BFA)
+ 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:
+ regtype = 0 # 5-bit
+ elif regtype is _RegType.CR_BIT:
+ regtype = 1 # 3-bit
+ else:
+ raise ValueError(record.svp64)
+ # finally provide info for search
+ rm = rm.cr_op
+ search = ((int(rm.mode) << 1) | (regtype or 0))
+
+ elif record.svp64.mode is _SVMode.BRANCH:
+ # just mode 5-bit. could be reduced down to 2, oh well.
+ # mode mask action(getattr)
+ table = [(0b00000, 0b11000, "simple"), # simple
+ (0b01000, 0b11000, "vls"), # VLset
+ (0b10000, 0b11000, "ctr"), # CTR mode
+ (0b11000, 0b11000, "ctrvls"), # CTR+VLset mode
+ ]
+ # slightly weird: doesn't have a 5-bit "mode" field like others
+ search = int(rm[19:23])
+
+ # look up in table
+ if table is not None:
+ for (value, mask, member) in table:
+ if ((value & search) == (mask & search)):
+ rm = getattr(rm, member)
+ break
+
+ if rm.__class__ is self.__class__:
+ raise ValueError(self)
+
+ return rm
class SVP64Instruction(PrefixedInstruction):
bits.append(bit)
return "".join(map(str, bits))
- def mode(self, db):
- record = self.record(db=db)
-
- Rc = False
- if record.mdwn.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
-
- if record.svp64.mode is _SVMode.BRANCH:
- return (self.prefix.rm.mode, "branch")
-
- elif record.svp64.mode is _SVMode.CROP:
- return (self.prefix.rm.mode, "crop")
-
- elif record.svp64.mode is _SVMode.NORMAL:
- mode = self.prefix.rm.normal.mode
- if sel == 0b00:
- if mode[2] == 0b0:
- mode = mode.simple
- else:
- if subvl == 0b00:
- if mode[3] == 0b0:
- mode = mode.smr
- else:
- mode = mode.pmr
- else:
- if mode[4] == 0b0:
- mode = mode.svmr
- else:
- mode = mode.pu
- elif sel == 0b01:
- if Rc:
- mode = mode.ffrc1
- else:
- mode = mode.ffrc0
- elif sel == 0b10:
- if subvl == 0b00:
- mode = mode.sat
- else:
- if mode[4]:
- mode = mode.satx
- else:
- mode = mode.satpu
- elif sel == 0b11:
- if Rc:
- mode = mode.prrc1
- else:
- mode = mode.prrc0
- elif record.svp64.mode is _SVMode.LDST_IMM:
- mode = self.prefix.rm.ldst_imm.mode
- if sel == 0b00:
- if mode[2] == 0b0:
- mode = mode.simple
- else:
- mode = mode.spu
- elif sel == 0b01:
- if Rc:
- mode = mode.ffrc1
- else:
- mode = mode.ffrc0
- elif sel == 0b10:
- mode = mode.sat
- elif sel == 0b11:
- if Rc:
- mode = mode.prrc1
- else:
- mode = mode.prrc0
- elif record.svp64.mode is _SVMode.LDST_IMM:
- mode = self.prefix.rm.ldst_idx.mode
- 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:
- if Rc:
- mode = mode.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)
-
- raise ValueError(self)
-
def disassemble(self, db,
byteorder="little",
verbosity=Verbosity.NORMAL):
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}"
return
+ name = f"sv.{record.name}"
+
+ Rc = False
+ if record.mdwn.operands["Rc"] is not None:
+ Rc = bool(record.mdwn.operands["Rc"].value)
+ rm = self.prefix.rm.select(record=record, Rc=Rc)
+
+ # convert specifiers to /x/y/z
+ specifiers = list(rm.specifiers(record=record))
+ if specifiers: # if any add one extra to get the extra "/"
+ specifiers = ['']+specifiers
+ specifiers = "/".join(specifiers)
+
+ # convert operands to " ,x,y,z"
operands = tuple(map(_operator.itemgetter(1),
self.dynamic_operands(db=db, verbosity=verbosity)))
- if operands:
- yield f"{blob_prefix}sv.{record.name} {','.join(operands)}"
- else:
- yield f"{blob_prefix}{record.name}"
+ operands = ','.join(operands)
+ if len(operands) > 0: # if any separate with a space
+ operands = " " + operands
+
+ yield f"{blob_prefix}{name}{specifiers}{operands}"
if blob_suffix:
yield f"{blob_suffix}"
- (mode, mode_desc) = self.mode(db=db)
-
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):
- return (key in record.names)
-
- def Rc_match(key, record):
- if not key.endswith("."):
- return False
-
- if record.Rc is _RCOE.NONE:
- 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: