def disassemble(self, verbosity=Verbosity.NORMAL):
if verbosity >= Verbosity.VERBOSE:
indent = (" " * 4)
- for (name, value, members) in self.traverse(path="RM"):
+ for (name, span) in self.traverse(path="RM"):
+ value = self.storage[span]
yield f"{name}"
yield f"{indent}{int(value):0{value.bits}b}"
- yield f"{indent}{', '.join(map(str, members))}"
+ yield f"{indent}{', '.join(map(str, span))}"
class FFPRRc1BaseRM(BaseRM):
def specifiers(self, record, mode):
inv = _SelectableInt(value=int(self.inv), bits=1)
CR = _SelectableInt(value=int(self.CR), bits=2)
- mask = int(_selectconcat(inv, CR))
- predicate = { # exactly same table as in NormalLDSTBaseRM
- 0b000: "lt",
- 0b001: "ge",
- 0b010: "gt",
- 0b011: "le",
- 0b100: "eq",
- 0b101: "ne",
- 0b110: "so",
- 0b111: "ns",
- }[mask]
+ mask = int(_selectconcat(CR, inv))
+ predicate = PredicateBaseRM.predicate(True, mask)
yield f"{mode}={predicate}"
yield from super().specifiers(record=record)
yield from super().specifiers(record=record)
-class NormalLDSTBaseRM(BaseRM):
+class ElsBaseRM(BaseRM):
def specifiers(self, record):
- # these go in inverse order. calculable as: "8<<(3-width)"
- # TODO later: fp operations would be ew=fp16 ew=bf16 ew=fp32
- widths = {
+ if self.els:
+ yield "els"
+
+ yield from super().specifiers(record=record)
+
+
+class WidthBaseRM(BaseRM):
+ @staticmethod
+ def width(FP, width):
+ width = {
0b11: "8",
0b10: "16",
0b01: "32",
- }
- predicates = {
+ }.get(width)
+ if width is None:
+ return None
+ if FP:
+ width = ("fp" + width)
+ return width
+
+ def specifiers(self, record):
+ # elwidths: use "w=" if same otherwise dw/sw
+ # FIXME this should consider FP instructions
+ FP = False
+ dw = WidthBaseRM.width(FP, int(self.elwidth))
+ sw = WidthBaseRM.width(FP, int(self.ewsrc))
+ if dw == sw and dw:
+ yield ("w=" + dw)
+ else:
+ if dw:
+ yield ("dw=" + dw)
+ if sw:
+ yield ("sw=" + sw)
+
+ yield from super().specifiers(record=record)
+
+
+class PredicateBaseRM(BaseRM):
+ @staticmethod
+ def predicate(CR, mask):
+ return {
# integer
- (0, 0b001): "1<<r3",
- (0, 0b010): "r3",
- (0, 0b011): "~r3",
- (0, 0b100): "r10",
- (0, 0b101): "~r10",
- (0, 0b110): "r30",
- (0, 0b111): "~r30",
- # CRs - exactly the same table as in FFPRRc1BaseRM
- (1, 0b000): "lt",
- (1, 0b001): "ge",
- (1, 0b010): "gt",
- (1, 0b011): "le",
- (1, 0b100): "eq",
- (1, 0b101): "ne",
- (1, 0b110): "so",
- (1, 0b111): "ns",
- }
+ (False, 0b001): "1<<r3",
+ (False, 0b010): "r3",
+ (False, 0b011): "~r3",
+ (False, 0b100): "r10",
+ (False, 0b101): "~r10",
+ (False, 0b110): "r30",
+ (False, 0b111): "~r30",
+ # CRs
+ (True, 0b000): "lt",
+ (True, 0b001): "ge",
+ (True, 0b010): "gt",
+ (True, 0b011): "le",
+ (True, 0b100): "eq",
+ (True, 0b101): "ne",
+ (True, 0b110): "so",
+ (True, 0b111): "ns",
+ }.get((CR, mask))
- # predication - single and twin. use "m=" if same otherwise sm/dm
- mmode = int(self.mmode)
+ def specifiers(self, record):
+ # predication - single and twin
+ # use "m=" if same otherwise sm/dm
+ CR = (int(self.mmode) == 1)
mask = int(self.mask)
- sw = dw = predicates.get((mmode, mask))
+ sm = dm = PredicateBaseRM.predicate(CR, mask)
if record.svp64.ptype is _SVPtype.P2:
smask = int(self.smask)
- sw = predicates.get((mmode, smask))
- if sw == dw and dw:
- yield ("m=" + dw)
+ sm = PredicateBaseRM.predicate(CR, smask)
+ if sm == dm and dm:
+ yield ("m=" + dm)
else:
- if sw:
- yield ("sm=" + sw)
- if dw:
- yield ("dm=" + dw)
-
- # elwidths: use "w=" if same otherwise dw/sw
- dws = widths.get(int(self.elwidth))
- sws = widths.get(int(self.ewsrc))
- if dws == sws and dws:
- yield ("w=" + dws)
- else:
- if dws:
- yield ("dw=" + dws)
- if sws:
- yield ("sw=" + sws)
+ if sm:
+ yield ("sm=" + sm)
+ if dm:
+ yield ("dm=" + dm)
yield from super().specifiers(record=record)
-class NormalBaseRM(NormalLDSTBaseRM):
+class PredicateWidthBaseRM(WidthBaseRM, PredicateBaseRM):
+ pass
+
+
+class NormalBaseRM(PredicateWidthBaseRM):
"""
Normal mode
https://libre-soc.org/openpower/sv/normal/
RC1: BaseRM.mode[4]
def specifiers(self, record):
+ if self.VLi:
+ yield "vli"
+
yield from super().specifiers(record=record, mode="ff")
prrc0: NormalPRRc0RM
-class LDSTImmBaseRM(NormalLDSTBaseRM):
+class LDSTImmBaseRM(PredicateWidthBaseRM):
"""
LD/ST Immediate mode
https://libre-soc.org/openpower/sv/ldst/
pass
-class LDSTImmSimpleRM(ZZBaseRM, LDSTImmBaseRM):
+class LDSTImmSimpleRM(ElsBaseRM, ZZBaseRM, LDSTImmBaseRM):
"""ld/st immediate: simple mode"""
zz: BaseRM.mode[3]
els: BaseRM.mode[4]
yield from super().specifiers(record=record, mode="ff")
-class LDSTImmFFRc0RM(FFPRRc0BaseRM, LDSTImmBaseRM):
+class LDSTImmFFRc0RM(FFPRRc0BaseRM, ElsBaseRM, LDSTImmBaseRM):
"""ld/st immediate: Rc=0: ffirst z/nonz"""
inv: BaseRM.mode[2]
els: BaseRM.mode[3]
yield from super().specifiers(record=record, mode="ff")
-class LDSTImmSatRM(SatBaseRM, ZZBaseRM, LDSTImmBaseRM):
+class LDSTImmSatRM(ElsBaseRM, SatBaseRM, ZZBaseRM, LDSTImmBaseRM):
"""ld/st immediate: sat mode: N=0/1 u/s"""
N: BaseRM.mode[2]
zz: BaseRM.mode[3]
yield from super().specifiers(record=record, mode="pr")
-class LDSTImmPRRc0RM(FFPRRc0BaseRM, LDSTImmBaseRM):
+class LDSTImmPRRc0RM(FFPRRc0BaseRM, ElsBaseRM, LDSTImmBaseRM):
"""ld/st immediate: Rc=0: pred-result z/nonz"""
inv: BaseRM.mode[2]
els: BaseRM.mode[3]
prrc0: LDSTImmPRRc0RM
-class LDSTIdxBaseRM(NormalLDSTBaseRM):
+class LDSTIdxBaseRM(PredicateWidthBaseRM):
"""
LD/ST Indexed mode
https://libre-soc.org/openpower/sv/ldst/
SLu: BaseRM[18]
LRu: BaseRM[22]
sz: BaseRM[23]
+ CTR: BaseRM[19]
+ VLS: BaseRM[20]
+
+ def specifiers(self, record):
+ if self.ALL:
+ yield "all"
+
+ # /sz
+ # branch.sz=1
+ # branch.snz=0
+ # /snz
+ # branch.sz=1
+ # branch.snz=1
+ if self.SNZ:
+ if not self.sz:
+ raise ValueError(self.sz)
+ yield "snz"
+ elif self.sz:
+ yield "sz"
+
+ if self.SL:
+ yield "sl"
+ if self.SLu:
+ yield "slu"
+ if self.LRu:
+ yield "lru"
+
+ # Branch modes lack source mask.
+ # Therefore a custom code is needed.
+ CR = (int(self.mmode) == 1)
+ mask = int(self.mask)
+ m = PredicateBaseRM.predicate(CR, mask)
+ if m is not None:
+ yield ("m=" + m)
+
+ yield from super().specifiers(record=record)
class BranchSimpleRM(BranchBaseRM):
VSb: BaseRM[7]
VLI: BaseRM[21]
+ def specifiers(self, record):
+ yield {
+ (0b0, 0b0): "vs",
+ (0b0, 0b1): "vsi",
+ (0b1, 0b0): "vsb",
+ (0b1, 0b1): "vsbi",
+ }[int(self.VSb), int(self.VLI)]
+
+ yield from super().specifiers(record=record)
+
class BranchCTRRM(BranchBaseRM):
"""branch: CTR-test mode"""
CTi: BaseRM[6]
+ def specifiers(self, record):
+ if self.CTi:
+ yield "cti"
+ else:
+ yield "ctr"
+
+ yield from super().specifiers(record=record)
+
class BranchCTRVLSRM(BranchVLSRM, BranchCTRRM):
"""branch: CTR-test+VLSET mode"""
ldst_imm: LDSTImmRM
ldst_idx: LDSTIdxRM
cr_op: CROpRM
+ branch: BranchRM
def select(self, record, Rc):
rm = self
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 member
+ # just mode 2-bit
+ # mode mask member
table = (
- (0b00000, 0b11000, "simple"), # simple
- (0b01000, 0b11000, "vls"), # VLset
- (0b10000, 0b11000, "ctr"), # CTR mode
- (0b11000, 0b11000, "ctrvls"), # CTR+VLset mode
+ (0b00, 0b11, "simple"), # simple
+ (0b01, 0b11, "vls"), # VLset
+ (0b10, 0b11, "ctr"), # CTR mode
+ (0b11, 0b11, "ctrvls"), # CTR+VLset mode
)
# slightly weird: doesn't have a 5-bit "mode" field like others
- search = int(rm[19:23])
+ rm = rm.branch
+ search = int(rm.mode[0, 1])
# look up in table
if table 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))
+ # convert specifiers to /x/y/z (sorted lexicographically)
+ specifiers = sorted(rm.specifiers(record=record))
if specifiers: # if any add one extra to get the extra "/"
specifiers = ([""] + specifiers)
specifiers = "/".join(specifiers)