X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fopenpower%2Fdecoder%2Fpower_insn.py;h=ec70efce65dae6ebe16af3c4478b1976734a3e9c;hb=439dfd50906008cc32691cd0b4ade6d89fa58ef6;hp=f17447281b90d8c792b4d40a2e1dd1d3dfbb07b0;hpb=851d055f60243396075499e8681a8218111c7ead;p=openpower-isa.git diff --git a/src/openpower/decoder/power_insn.py b/src/openpower/decoder/power_insn.py index f1744728..ec70efce 100644 --- a/src/openpower/decoder/power_insn.py +++ b/src/openpower/decoder/power_insn.py @@ -1276,13 +1276,11 @@ class BaseRM(_Mapping): 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)) - @property - def specifiers(self): + def specifiers(self, record): subvl = int(self.subvl) if subvl > 0: yield { @@ -1300,26 +1298,64 @@ class BaseRM(_Mapping): yield f"{indent}{', '.join(map(str, members))}" +# ******************** +# Normal mode +# https://libre-soc.org/openpower/sv/normal/ + class NormalLDSTBaseRM(BaseRM): - @property - def specifiers(self): - width = { + def specifiers(self, record): + widths = { 0b11: "8", 0b10: "16", 0b01: "32", } + predicates = { + # integer + (0, 0b001): "1<1""" - N: BaseRM.mode[2] - zz: BaseRM.mode[3] - dz: BaseRM.mode[3] - sz: BaseRM.mode[3] - - @property - def specifiers(self): - if self.zz: - yield f"zz" - if self.N: - yield "sats" - else: - yield "satu" - yield from super().specifiers + yield from super().specifiers(record=record) class NormalPredResultRc1RM(NormalBaseRM): @@ -1421,11 +1444,14 @@ class NormalPredResultRc0RM(NormalBaseRM): dz: BaseRM.mode[3] sz: BaseRM.mode[3] - @property - def specifiers(self): + def specifiers(self, record): if self.zz: yield f"zz" - yield from super().specifiers + if self.RC1: + inv = "~" if self.inv else "" + yield f"pr={inv}RC1" + + yield from super().specifiers(record=record) class NormalRM(NormalBaseRM): @@ -1435,11 +1461,14 @@ class NormalRM(NormalBaseRM): ffrc1: NormalFailFirstRc1RM ffrc0: NormalFailFirstRc0RM sat: NormalSaturationRM - satx: NormalSaturationExtRM prrc1: NormalPredResultRc1RM prrc0: NormalPredResultRc0RM +# ******************** +# LD/ST Immediate mode +# https://libre-soc.org/openpower/sv/ldst/ + class LDSTImmBaseRM(NormalLDSTBaseRM): pass @@ -1451,11 +1480,11 @@ class LDSTImmSimpleRM(LDSTImmBaseRM): dz: BaseRM.mode[3] sz: BaseRM.mode[3] - @property - def specifiers(self): + def specifiers(self, record): if self.zz: yield f"zz" - yield from super().specifiers + + yield from super().specifiers(record=record) class LDSTImmReservedRM(LDSTImmBaseRM): @@ -1475,6 +1504,12 @@ class LDSTImmFailFirstRc0RM(LDSTImmBaseRM): 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""" @@ -1484,15 +1519,15 @@ class LDSTImmSaturationRM(LDSTImmBaseRM): dz: BaseRM.mode[3] sz: BaseRM.mode[3] - @property - def specifiers(self): + def specifiers(self, record): if self.zz: yield f"zz" if self.N: yield "sats" else: yield "satu" - yield from super().specifiers + + yield from super().specifiers(record=record) class LDSTImmPredResultRc1RM(LDSTImmBaseRM): @@ -1507,6 +1542,12 @@ class LDSTImmPredResultRc0RM(LDSTImmBaseRM): 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 @@ -1518,6 +1559,10 @@ class LDSTImmRM(LDSTImmBaseRM): prrc0: LDSTImmPredResultRc0RM +# ******************** +# LD/ST Indexed mode +# https://libre-soc.org/openpower/sv/ldst/ + class LDSTIdxBaseRM(NormalLDSTBaseRM): pass @@ -1528,13 +1573,13 @@ class LDSTIdxSimpleRM(LDSTIdxBaseRM): sz: BaseRM.mode[3] dz: BaseRM.mode[3] - @property - def specifiers(self): + def specifiers(self, record): if self.dz: yield f"dz" if self.sz: yield f"sz" - yield from super().specifiers + + yield from super().specifiers(record=record) class LDSTIdxStrideRM(LDSTIdxBaseRM): @@ -1543,13 +1588,13 @@ class LDSTIdxStrideRM(LDSTIdxBaseRM): dz: BaseRM.mode[3] sz: BaseRM.mode[4] - @property - def specifiers(self): + def specifiers(self, record): if self.dz: yield f"dz" if self.sz: yield f"sz" - yield from super().specifiers + + yield from super().specifiers(record=record) class LDSTIdxSaturationRM(LDSTIdxBaseRM): @@ -1558,8 +1603,7 @@ class LDSTIdxSaturationRM(LDSTIdxBaseRM): dz: BaseRM.mode[3] sz: BaseRM.mode[4] - @property - def specifiers(self): + def specifiers(self, record): if self.dz: yield f"dz" if self.sz: @@ -1568,7 +1612,8 @@ class LDSTIdxSaturationRM(LDSTIdxBaseRM): yield "sats" else: yield "satu" - yield from super().specifiers + + yield from super().specifiers(record=record) class LDSTIdxPredResultRc1RM(LDSTIdxBaseRM): @@ -1585,11 +1630,14 @@ class LDSTIdxPredResultRc0RM(LDSTIdxBaseRM): dz: BaseRM.mode[3] sz: BaseRM.mode[3] - @property - def specifiers(self): + def specifiers(self, record): if self.zz: yield f"zz" - yield from super().specifiers + if self.RC1: + inv = "~" if self.inv else "" + yield f"pr={inv}RC1" + + yield from super().specifiers(record=record) class LDSTIdxRM(LDSTIdxBaseRM): @@ -1600,19 +1648,23 @@ class LDSTIdxRM(LDSTIdxBaseRM): prrc0: LDSTIdxPredResultRc0RM + +# ******************** +# CR ops mode +# https://libre-soc.org/openpower/sv/cr_ops/ + class CROpBaseRM(BaseRM): pass class CROpSimpleRM(CROpBaseRM): """cr_op: simple mode""" - sz: BaseRM[6] SNZ: BaseRM[7] RG: BaseRM[20] + sz: BaseRM[21] dz: BaseRM[22] - @property - def specifiers(self): + def specifiers(self, record): if self.dz: yield f"dz" if self.sz: @@ -1620,23 +1672,23 @@ class CROpSimpleRM(CROpBaseRM): if self.RG: yield "mrr" - yield from super().specifiers + yield from super().specifiers(record=record) class CROpScalarReduceRM(CROpBaseRM): """cr_op: scalar reduce mode (mapreduce), SUBVL=1""" - sz: BaseRM[6] SNZ: BaseRM[7] RG: BaseRM[20] + sz: BaseRM[21] + dz: BaseRM[22] - @property - def specifiers(self): + def specifiers(self, record): if self.sz: yield f"sz" if self.RG: yield "mrr" - yield from super().specifiers + yield from super().specifiers(record=record) class CROpReservedRM(CROpBaseRM): @@ -1644,34 +1696,31 @@ class CROpReservedRM(CROpBaseRM): zz: BaseRM[6] SNZ: BaseRM[7] RG: BaseRM[20] - dz: BaseRM[6] sz: BaseRM[6] + dz: BaseRM[6] - @property - def specifiers(self): + def specifiers(self, record): if self.zz: yield f"zz" if self.RG: yield "mrr" - yield from super().specifiers + yield from super().specifiers(record=record) class CROpFailFirst3RM(CROpBaseRM): """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] + sz: BaseRM[21] + dz: BaseRM[22] - @property - def specifiers(self): + def specifiers(self, record): if self.zz: yield f"zz" - yield from super().specifiers + yield from super().specifiers(record=record) class CROpFailFirst5RM(CROpBaseRM): @@ -1682,13 +1731,12 @@ class CROpFailFirst5RM(CROpBaseRM): inv: BaseRM[21] dz: BaseRM[22] - @property - def specifiers(self): + def specifiers(self, record): if self.dz: yield f"dz" if self.sz: yield f"sz" - yield from super().specifiers + yield from super().specifiers(record=record) class CROpRM(CROpBaseRM): @@ -1699,6 +1747,11 @@ class CROpRM(CROpBaseRM): ff5: CROpFailFirst5RM +# ******************** +# Branches mode +# https://libre-soc.org/openpower/sv/branches/ + + class BranchBaseRM(BaseRM): ALL: BaseRM[4] SNZ: BaseRM[5] @@ -1745,92 +1798,102 @@ class RM(BaseRM): 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 action(getattr) - 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 - ] - + # 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 - for (val, mask, action) in table: - if (val&search) == (mask&search): - rm = getattr(rm, action) - break + 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 - if rm.mode[0:2] == 0b00: - if rm.mode[2] == 0b0: - rm = rm.simple - else: - rm = rm.reserved - elif rm.mode[0:2] == 0b01: - if Rc: - rm = rm.ffrc1 - else: - rm = rm.ffrc0 - elif rm.mode[0:2] == 0b10: - rm = rm.sat - elif rm.mode[0:2] == 0b11: - if Rc: - rm = rm.prrc1 - else: - rm = rm.prrc0 + search = ((int(rm.mode) << 1) | Rc) - elif record.svp64.mode is _SVMode.LDST_IMM: + 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 - 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: - rm = rm.prrc1 - else: - rm = rm.prrc0 + search = ((int(rm.mode) << 1) | Rc) elif record.svp64.mode is _SVMode.CROP: - rm = rm.cr_op - if rm[19] == 0b0: - if rm[21] == 0b0: - rm = rm.simple - else: - rm = rm.smr + # 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: - 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(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: - 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 + # 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) @@ -1883,21 +1946,21 @@ class SVP64Instruction(PrefixedInstruction): Rc = False if record.mdwn.operands["Rc"] is not None: - Rc = bool(self.suffix[record.fields["Rc"]]) + Rc = bool(record.mdwn.operands["Rc"].value) rm = self.prefix.rm.select(record=record, Rc=Rc) - specifiers = tuple(rm.specifiers) - if specifiers: - specifiers = f"/{'/'.join(specifiers)}" - else: - specifiers = "" + # 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: - operands = f" {','.join(operands)}" - else: - operands = "" + 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: